Page 1 of 1
long mode, loading a binary
Posted: Sat Oct 10, 2015 2:46 am
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
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 3:51 am
by mariuszp
Is it a flat binary, and the OS has a pre-determined address space structure?
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 5:35 am
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.
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 7:25 am
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.
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 9:44 am
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
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 2:52 pm
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.
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 5:22 pm
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:
while things works with:
For some reason, on 32 bit, using eax, this was working.
Thanks again.
Angelo
Re: long mode, loading a binary
Posted: Sat Oct 10, 2015 5:47 pm
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:
while things works with:
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;