gcc cross compiler with optimisation

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
IRBMe

gcc cross compiler with optimisation

Post by IRBMe »

Here's the situation.

I have a fresh install of cygwin set up. So I followed the instructions in the FAQ about building a cross compiler exactly. It all compiled fine and seems to work good. I built gcc-3.4.0 and binutils 2.15

However, after turning on optimisation with the -O flag (any level -O1, -O2, -O3, even -Os), then something crazy happens.

The compiler spits out a small object file, as you would expect. However, once I try to link it with ld, the binary ends up being 1MB in size! Looking at it, there's some text at the beginning (a data section if some sort?) followed by thousands of null characters which pad it up to just under 1MB, then the actual kernel code, which fills it up to 1MB exactly.

I suspected that the 1MB value was coming from the linker script, where 1MB is the address the kernel is loaded at (0x100000). So I changed this to 0x10000 (65K) and tried rebuilding, and as I expected, this time the kernel was 65K.

Without turning on optimisation, it builds as expected, with just a binary that's well under 1KB.

I could live without the optimisation feature by adding the always-inline attribute and working around it etc, but really I shouldn't have to do that. I'd rather figure out what's going on here and solve it.....so What's going on here!?

Here's the command I use to compile and lnik:

Code: Select all

i586-elf-gcc -c -O3 -nostdlib -fno-builtin -fno-rtti -fno-exceptions -nostartfiles -mno-stack-arg-probe -Wall src/*.cpp

i586-elf-ld -T link.ld -o bin\kernel.bin 
And here's my linker script:

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
INPUT(kernel_asm.o)
INPUT(kernel.o)
SECTIONS
{
    . = 0x00100000;

    .text :
    {
        *(.text)
        *(.rodata)
    }

    .data :
    {
        start_ctors = .;
        *(.ctor*)
        end_ctors = .;
        *(.data)
    }

    .bss :
    {
        _sbss = .;
        *(COMMON)
        *(.bss)
        _ebss = .;
    }
}
The kernel itself is just a very simple, protected mode, run of the mill hello world kernel.

Any ideas? Seems like a VERY VERY strange thing to happen......especially with -Os - optimize for size! heh.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:gcc cross compiler with optimisation

Post by Pype.Clicker »

this is common result of a missing section in the linker script. (e.g. you tell the .text to go at 0x100000, and .data and .bss from there, but any section not describe still goes at 0x00000, hence the padding)

You also need to know that later versions of GCC uses ".rodata32" or things alike to differentiate long strings (that worth cache-alignment) from short strings.

To make sure, try an Objdump on files before you link and see if there's any section you miss, but imho, just replacing ".rodata" by ".rodata*" should make it ...
IRBMe

Re:gcc cross compiler with optimisation

Post by IRBMe »

ah yeh. that solved it. Thanks once again Pype. It's little "gotchas" like these that always trip up us newbs ;)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:gcc cross compiler with optimisation

Post by Pype.Clicker »

90% of linker errors magically get sense when you run 'objdump' on the input files ;)
IRBMe

Re:gcc cross compiler with optimisation

Post by IRBMe »

I've been putting it off for a while, but I guess now would be a good time to learn what all the output of objdump means. Off to the documentation I go.
Post Reply