long mode, loading a binary

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
spectrum
Member
Member
Posts: 37
Joined: Wed Jun 13, 2007 7:06 am

long mode, loading a binary

Post by spectrum »

Dear all,

i have modified mi 32 bit os to 64bit long mode.

I am now up and running with GDT, IDT, paging, and trying to load a binary to execute it.

In 32bit i was using this method:
Building a small binary linking with -T 0x100000, and linking with a "loader.o" that was containing a _start label.
Then i was
- loading binary from SD into 0x100000,
- setting 0x100000 into %eax,
- and call *(%eax). It was working.

On 64 bit long mode this doesn't work anymore.
I get General Protection fault, RIP non-canonical error, or page fault read,
error seems depending on compiling options.

Maybe there is some link on how i can learn how to load and execute a binary ?
Every help is appreciated.

thanks
A
mariuszp
Member
Member
Posts: 593
Joined: Sat Oct 16, 2010 3:38 pm

Re: long mode, loading a binary

Post by mariuszp »

Is it a flat binary, and the OS has a pre-determined address space structure?
spectrum
Member
Member
Posts: 37
Joined: Wed Jun 13, 2007 7:06 am

Re: long mode, loading a binary

Post by spectrum »

hi,

it's something as an initial rough test actually, the binary is just a flat binary, and os just have a predefined memory place for a single binary.
mariuszp
Member
Member
Posts: 593
Joined: Sat Oct 16, 2010 3:38 pm

Re: long mode, loading a binary

Post by mariuszp »

spectrum wrote:hi,

it's something as an initial rough test actually, the binary is just a flat binary, and os just have a predefined memory place for a single binary.
Did you map the virtual memory pages for the binary?

Also I think x86_64 GNU linker align all pages on 2MB boundaries.
spectrum
Member
Member
Posts: 37
Joined: Wed Jun 13, 2007 7:06 am

Re: long mode, loading a binary

Post by spectrum »

yes they are mapped.

0x100000 is inside the ranges i mapped into the PT (i mapped 2MB).
I want to build the binary i load separately, so i use -T 0x100000 linking it. Its it also a org 0x100000 needed ?

As additional info, just jumping to 0x100000 i get

Code: Select all

0018235756e[HD   ] IO read(0x01f0) with drq == 0: last command was 20h
00018235794e[CPU0 ] CALL_Eq: canonical RIP violation
00845256000p[XGUI ] >>PANIC<< POWER button turned off.
00845256000i[CPU0 ] CPU is in long mode (active)
00845256000i[CPU0 ] CS.mode = 64 bit
00845256000i[CPU0 ] SS.mode = 64 bit
00845256000i[CPU0 ] EFER   = 0x00000500
00845256000i[CPU0 ] | RAX=000000000000afe0  RBX=0000000000006500
00845256000i[CPU0 ] | RCX=000000000000a927  RDX=00000000000003d5
00845256000i[CPU0 ] | RSP=000000000003dd80  RBP=000000000003dda0
00845256000i[CPU0 ] | RSI=000000000000000c  RDI=000000000000a90f
00845256000i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00845256000i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00845256000i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00845256000i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00845256000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
00845256000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00845256000i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 00000000 0 0
00845256000i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00845256000i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00845256000i[CPU0 ] | RIP=0000000000008d56 (0000000000008d56)
00845256000i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000
00845256000i[CPU0 ] | CR3=0x00001000 CR4=0x00000020
(0).[845256000] [0x0000000000008d56] 0008:0000000000008d56 (unk. ctxt): jmp .-2 (0x0000000000008d56) ; ebfe
00845256000i[CMOS ] Last time is 1444492172 (Sat Oct 10 17:49:32 2015)
00845256000i[XGUI ] Exit
00845256000i[CTRL ] quit_sim called with exit code 1
mariuszp
Member
Member
Posts: 593
Joined: Sat Oct 16, 2010 3:38 pm

Re: long mode, loading a binary

Post by mariuszp »

Code: Select all

00845256000i[CPU0 ] | RIP=0000000000008d56 (0000000000008d56)
This does not look right. I'd suggest trapping before the jump (using "xchg bx, bx" and then the jmp), and single-stepping in bochs to see at which point it goes wrong.

Furthermore, I am pretty sure that if you tell the linker that the load address is at 1MB, it will actually move it to 2MB because of alignment, on the x86_64. This happens with the linker targetting my OS, as well as the x86_64-elf linker.
spectrum
Member
Member
Posts: 37
Joined: Wed Jun 13, 2007 7:06 am

Re: long mode, loading a binary

Post by spectrum »

A special thanks.

As always here i find high competence and fast resolutions.

Don't know from where i copied this syntax, but mainly i was calling 0x100000 in a wrong way:

Code: Select all

mov 0x100000, %%rax
call  *(%%rax)
while things works with:

Code: Select all

call %%rax
For some reason, on 32 bit, using eax, this was working.

Thanks again.
Angelo
mariuszp
Member
Member
Posts: 593
Joined: Sat Oct 16, 2010 3:38 pm

Re: long mode, loading a binary

Post by mariuszp »

spectrum wrote:A special thanks.

As always here i find high competence and fast resolutions.

Don't know from where i copied this syntax, but mainly i was calling 0x100000 in a wrong way:

Code: Select all

mov 0x100000, %%rax
call  *(%%rax)
while things works with:

Code: Select all

call %%rax
For some reason, on 32 bit, using eax, this was working.

Thanks again.
Angelo
"call *(%rax)" interprets the value of RAX as the address of a function pointer. So it does:

Code: Select all

U64 *func = (U64*) rax;
rip = *func;
Post Reply