Page 1 of 1

Executable file format

Posted: Mon Apr 29, 2013 4:44 am
by mark3094
Hello,

I've done a little OS development on x86 in Visual Studio, but I would like to move over to GCC/Cygwin (this is because I've also recently looked into the OS dev tutorials for the Raspberry Pi, and I would like to use a similar environment for each).

My bootloader is custom written and loads the kernel (which is a PE file) to 0x100000, finds the 'AddressofEntryPoint' field in the PE headers, and begins execution there.

I can compile 'kernel.c' straight into 'kernel.img' without linking (ie, using 'gcc -c'), and the kernel loads correctly. When I use any form of linking, it no longer loads.
I've used objdump and 'PE Explorer' to analyse the executable, and both report that the entry point is 0x100000, which is the same as the image base. This explains why the bootloader can't load it.

So, what has happened to the headers? I'm guessing that I've done something wrong in the linker script, or there is a special consideration with cygwin that I'm not yet aware of.
Can anyone suggest where I may have gone wrong? Or is it better to use some other file format, such as ELF, and rewrite sections of the bootloader? I think I'd prefer to stay with PE if possible, as I have more understanding of how it works than ELF (which is zero).

Any suggestions?



I have tried several linker scripts, including the one on the bare bones page. Here is one example that I've tried:

Code: Select all

ENTRY (_kmain)

BASEADDRESS = 0x100000;

SECTIONS
{
    . = BASEADDRESS;

    .text : AT(ADDR(.text))
    {
        *(.text)
    }

    .data : AT(ADDR(.data) - BASEADDRESS)
    {
        *(.data)
    }
}

Re: Executable file format

Posted: Mon Apr 29, 2013 6:21 am
by Owen
Is "_kmain" the correct entry point symbol?

If you're using C++, is it marked extern "C"? If you're using C, what calling convention is it? In particular, is the name mangling correct?

I'd recommend using objdump or nm to inspect the list of symbols kernel.o exports and make sure the linker script matches

Re: Executable file format

Posted: Mon Apr 29, 2013 6:51 am
by Combuster
I've used objdump and 'PE Explorer' to analyse the executable, and both report that the entry point is 0x100000, which is the same as the image base. This explains why the bootloader can't load it.
Why not? The situation is perfectly valid: the first byte of actual code is the entry point.

Sounds like you're blaming the wrong tool.

Re: Executable file format

Posted: Mon Apr 29, 2013 7:10 am
by Owen
(IIRC), for PE, the image base points at the headers

Re: Executable file format

Posted: Mon Apr 29, 2013 3:48 pm
by mark3094
Owen wrote:Is "_kmain" the correct entry point symbol?

If you're using C++, is it marked extern "C"? If you're using C, what calling convention is it? In particular, is the name mangling correct?
kmain is the entry point, and I'm writing in C. I think name mangling is correct, but I'll look into it further just in case. If I use 'kmain' instead of '_kmain' it spits out an error something like 'Cannot find kmain symbol, defaulting to 001000000'.
Combuster wrote:Why not? The situation is perfectly valid: the first byte of actual code is the entry point.

Sounds like you're blaming the wrong tool.
Unfortunately, no. As Owen goes on to say, the PE headers should be at the image base. There should be a field in there called 'AddressOfEntryPoint', which is where kmain should be. At least, this is how Visual C does it. If I use PE Explorer on my other Kernel, the image base is at 0x100000, but the entry point is 0x104BE0.

Here is an example of an older Kernel written in Visual Studio:
VC_PE_Analysis.PNG
And here is what I'm seeing when using GCC/Cygwin
GCC_PE_Analysis.PNG
This link explains using the Address of Entry field when loading a PE file:
http://wiki.osdev.org/PE#Loading_a_PE_file

Re: Executable file format

Posted: Tue Apr 30, 2013 2:42 am
by linguofreak
It looks to me like your linker script clobbers your headers with the .text section. You define BASEADDRESS to be 0x100000, you then define the location counter to be equal to BASEADDRESS, and then you define your .text section, which the linker places at the location counter.