Memos Electron
Memos Electron

Reputation: 660

My bootloader can't be compiled with gcc 4.6 and 4.7 ... only 4.5

I created my bootloader before 2 years under debian squeeze/stable with gcc 4.5. Now in debian wheezy/sid can't be compiled with 4.6 and 4.7 because creates bigger sections from these i expecting to produce the final binary by hand. This is not problem for me now since in debian wheezy/sid the gcc 4.5 is still there but i 'd like to make it possible to be compiled with gcc 4.6 and 4.7.

I produce the final binary like this:

the source files are compiled with:

gcc-4.5 -Wall -O3 -c -m32 -I. -o assemblybin-objects/vga_pm.S.o vga_pm.S

linked with:

ld -nostdlib -T binary.ld assemblybin-objects/vga_pm.S.o ... and other objects here ... -o bootloader.bin

the contents of the binary.ld is:

OUTPUT_FORMAT("binary","binary","binary")
OUTPUT_ARCH(i386)

SECTIONS
{
. = 0;
.bootloader : {
    . = 0x600;
    *(.bootstrap);
    . = 0x7fa;
    BYTE(0x11);
    BYTE(0x33);
    BYTE(0x55);
    BYTE(0x77);
    BYTE(0x55);
    BYTE(0xaa);
    _bootstrap_end = .;
    . = 0x800;
    *(.sysinit);
    _sysinit_end = .;
    . = 0x1000;
    *(.pages);
    _pages_end = .;
    . = 0x5000;
    *(.sysconf);
    *(.presystem);
    *(.system);
    *(.library);
    *(.text);
    *(.data);
    *(.bss);
    *(.rodata);
    *(.rodata.*);
    . = 0xeffc;
    BYTE(0x11);
    BYTE(0x33);
    BYTE(0x55);
    BYTE(0x77);
    _system_end = .;
}

. = ASSERT(_bootstrap_end <= 0x800,"Bootstrap section big!");
. = ASSERT(_sysinit_end <= 0x1000,"Sysinit section big!");
. = ASSERT(_pages_end <= 0x5000,"Pages section big!");
. = ASSERT(_system_end <= 0xf000,"System initialization section big!");
}

at last creating the final binary with dd.

I saw that when compiled with gcc 4.6 and 4.7 the linker adds some bytes (250-300) at the begin of the bootloader.bin.

I'm using the ld from binutils 2.22 and cook with my own recipes for the build process.

My actual questions are:

What are the differences between these versions of the gcc compiler and they produce bigger sections or instructing the linker through the elf object files to add these bytes at the begin of the bootloader.bin file?

Is there any command line argument for gcc 4.6 and/or 4.7 which will turn off a feature that may produce bigger sections than the gcc 4.5 or to remove the instructions those saying the linker to add these bytes at the begin of the bootloader.bin file?

edit 17-08-2012: I'm lil busy these days but soon i 'll update with the results of tests i did.

Answer to @strnk and @Dan Aloni: when i saw this problem the first i did is to exclude useless sections but the results are the same ... i think because the bootloader.bin is a simple binary with the linked code of the needed sections at the right position as the linker instructed to do, without section names, relocation and debug informations and symbols ... bootloader.bin file is not an elf object file.

Please consider the changes of the actual questions. Thanks for everything ... i 'll be back soon

edit 31-08-2012: Okay guys thanks for your help. The answer given by @Dan Aloni and accomplished with ldscript as @strnk shows

/DISCARD/ : {
    *(.eh_frame)
    *(.eh_frame_hdr)
}

after the asserts.

Upvotes: 10

Views: 782

Answers (4)

Dan Aloni
Dan Aloni

Reputation: 4098

By compiling a trivial C file with the flags you provided, between gcc-4.5 and gcc-4.6, and using objdump -h to examine the output, it seems that the .eh_frame section is introduced in gcc-4.6.

The ld script you provided does not take care of that section, and it probably should. You can use strip -R .eh_frame -R .eh_frame_hdr to remove that section and others from the object files prior to linking.

Anyway, since the linker is the same for both gcc versions, objdump -h on the object files will hint at the difference that causes this problem.

Upvotes: 8

DevSolar
DevSolar

Reputation: 70213

You might want to note that you are not actually using GCC at all.

vga_pm.S, judging from the file extension, is assembler source containing preprocessor directives, so you need the cpp preprocessor to turn that into preprocessed (.s) source. Note that the GNU assembler (as) has all the necessary native directives, e.g. for file inclusion, to make this step unnecessary.

"Compiling" .s source to .o object file doesn't require GCC either, as this can be done just as well using as directly (which is part of the binutils package).

Then you use ld for linking the object file into a binary. Again, ld is part of the binutils package.

Using GCC as a frontend confuses the issue, has little to no benefit, and might actually be at the root of your problem. Point in case, you told us which GCC versions you used, but you didn't tell us which binutils versions you used...

I recommend not depending on tools that are not strictly necessary, to keep your build process as simple as possible. In this case, drop GCC from your bootloader build step.

Upvotes: 2

strnk
strnk

Reputation: 2063

GCC adds some unwanted debug sections to its binary output (use objdump -h <file> to see them), I usually put those I don't want in a /DISCARD/ rule in my ld scripts to get rid of them :

/DISCARD/ : {
        *(.debug_*)
        *(.note*)
        *(.indent)
        *(.comment)
        *(.stab)
        *(.stabstr)
        *(.eh_frame)
}

Upvotes: 3

Employed Russian
Employed Russian

Reputation: 213385

Is there any command line argument which will turn off a feature that may produce bigger sections

Yes: if you care about size, you should build with -Os. The -O3 explicitly enables optimizations which could lead to larger code size. Since the bootloader executes once, using -O3 for it is almost certainly wrong.

Edit:

"Optimization in assembly is meaningless ...
... and other objects here ..."

Is all of your code in assembly? If so, optimization level is indeed meaningless, but then you should be able to simply compare output from readelf -S vga_pm.S.o built with both compilers, and see exactly which sections are different.

But it appears more likely that some of your objects are not in assembly, in which case the difference between -O3 and -Os will be quite meaningful.

Upvotes: 4

Related Questions