bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ELF LOAD header generation inconsistency.


From: Luciann Bennet
Subject: ELF LOAD header generation inconsistency.
Date: Sun, 6 Jun 2010 02:16:06 -0400

Hi:

I have a cross compiling LD from binutils 2.20 which targets i586-elf,
and was compiled using a my native ubuntu pre-installed GCC 4.4.1
toolchain. I use the cross compiler to generate ELF binaries for a
freestanding environment.

Here is the output of objdump as run on two output final binaries from
the same project:

address@hidden:/osdev/zbz$ objdump -p -h zambezii.zxe tmp/zambezii.zxe

zambezii.zxe:     file format elf32-i386

Program Header:
   LOAD off    0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
        filesz 0x00000030 memsz 0x00000030 flags rw-
   LOAD off    0x00002000 vaddr 0xc0005000 paddr 0x00105000 align 2**12
        filesz 0x000000b1 memsz 0x000000b1 flags r-x
   LOAD off    0x00003000 vaddr 0xc0006000 paddr 0x00106000 align 2**12
        filesz 0x00007138 memsz 0x00014690 flags rwx
  STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
        filesz 0x00000000 memsz 0x00000000 flags rwx

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 0 .__kheaders   00000030  00100000  00100000  00001000  2**2
                 CONTENTS, ALLOC, LOAD, DATA
 1 .__ksetup     00004000  00101000  00101000  0000b000  2**12
                 CONTENTS, READONLY
 2 .__korientation 000000b1  c0005000  00105000  00002000  2**4
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 3 .ctor         00000010  c0006000  00106000  00003000  2**2
                 CONTENTS, ALLOC, LOAD, DATA
 4 .text         000059ab  c0007000  00107000  00004000  2**4
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 5 .data         00000138  c000d000  0010d000  0000a000  2**3
                 CONTENTS, ALLOC, LOAD, DATA
 6 .bss          0000c690  c000e000  0010e000  0000a138  2**5
                 ALLOC

tmp/zambezii.zxe:     file format elf32-i386

Program Header:
   LOAD off    0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
        filesz 0x00005000 memsz 0x00005000 flags rw-
   LOAD off    0x00006000 vaddr 0xc0005000 paddr 0x00105000 align 2**12
        filesz 0x000000b1 memsz 0x000000b1 flags r-x
   LOAD off    0x00007000 vaddr 0xc0006000 paddr 0x00106000 align 2**12
        filesz 0x00007138 memsz 0x00014690 flags rwx
  STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
        filesz 0x00000000 memsz 0x00000000 flags rwx

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 0 .__kheaders   00000030  00100000  00100000  00001000  2**2
                 CONTENTS, ALLOC, LOAD, DATA
 1 .__ksetup     00004000  00101000  00101000  00002000  2**12
                 CONTENTS, ALLOC, LOAD, DATA
 2 .__korientation 000000b1  c0005000  00105000  00006000  2**4
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 3 .ctor         00000014  c0006000  00106000  00007000  2**2
                 CONTENTS, ALLOC, LOAD, DATA
 4 .text         00005a5b  c0007000  00107000  00008000  2**4
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 5 .data         00000138  c000d000  0010d000  0000e000  2**3
                 CONTENTS, ALLOC, LOAD, DATA
 6 .bss          0000c690  c000e000  0010e000  0000e138  2**5
                 ALLOC

----------------------------------------

The first file is the one which is generated as of this email. The
second is the one which used to be generated before I made a minor
change in my source. The problem is this:

I generate page tables statically in my kernel image, and have them
placed in a section '.__ksetup', which is set, by my custom linker
script, to link to the same virtual address as the physical load
address. The rest of the sections (other than .__kheaders) are linked
to 0xC0000000.

As you can see, .__ksetup section is of size 16KB in the final image
of both files, and should be loaded with the rest of the file into
memory, and the LOAD header in the second (the former output) reflects
this. However, as of this writing, the output binary excludes the
.__ksetup section from the LOAD headers, even though .__ksetup section
is actually included in the kernel binary. I have verified this with a
hexdump. Both output files are created with the same cross compiler.

The simple change I made to the source of my project was that I had
been generating a top level table in ASM, and several lower tables
which were pointed to by the top level table in C++. There are four
tables in all, each 4KB, (thus 16KB). I found that G++ seemed to think
that the linker could do with some 'help', and G++ tended to, instead
of inserting references to symbols in a relocation table for the
linker to resolve, it would generate a constructor for any relocations
to be done on symbols for data relocations. So the G++ compiler would
generate a constructor to do the relocation at runtime before the
program started. Needless to say, this is undesirable in a kernel.

So I replaced the tables which were done in C++ with their equivalents
in assembly, and ensured that they linked. They did. I ensured they
linked and were relocated at link time properly with a hexdump. You
can rest assured that the page tables are in the kernel image since I
had to do extensive debugging to find out why my kernel was triple
faulting on code that used to work. You can see for yourself: the
.__ksetup section in the final image of both files is 16KB large.

To conclude: For some reason, LD has decided that a section should not
be placed into the LOAD headers, *even though* ALL of the tables are
referenced externally and would need to be resolved and copied into
the final image (which is WHY they appear there. They are not
optimized out.).

Note that the problem has several hacky fixes: but this IS strange
behaviour, and I can see no cogent reason why the linker just randomly
decided to exclude a section from being loaded, so I thought it a good
idea to let the dev team know instead of just quietly fixing the
problem for myself with a hack and moving on.

As per 
(http://web.mit.edu/~sdavies/MacData/afs/athena/project/rhel-doc/3/rhel-ld-en-3/bug-reporting.html),
I am giving environment info here:

Invocation:
i586-elf-ld  -T platform/__klinkScript.ld -o ../zambezii.zxe \
-\( __kthreads.a kernel.a platform.a memoryTrib.a numaTrib.a cpuTrib.a
firmware.a chipset.a arch.a __kclasses.a __kcxxabi.a __kstdlib.a
__kcxxlib.a __kclib.a lang.a -\)
make[1]: Leaving directory `/osdev/zbz/core'

I use an HP G71t notebook, with an Intel T4300 processor, and have 3GB
of RAM. I would have liked to paste in the tables I generate,
but...they are pretty large in source form. About 120KB. Lots of lines
of scrolling for something that is not the problem: I can vouch that
those tables are relocated properly and that they appear, properly
resolved, in the final image.

-------------------------------------

I debugged the problem, and have got LD to stop cutting out the page
tables from the program headers. What I did was redo the page tables
in C++, then look that the output asm from i586-elf-g++ -S (assmbly
output), and the only difference was that GCC placed these lines above
the tables:

        .file   "__kpagingLevel1Hll.cpp"
.globl __kpagingLevel1Tables
        .section        .__ksetupDataS,"aw",@progbits
        .align 4096
        .type   __kpagingLevel1Tables, @object
        .size   __kpagingLevel1Tables, 12288

It goes without saying that I had the .globl pseudo op in my
hand-written ASM, so that wasn't the issue. It's probably the .type or
.size directives. Anyway, I placed that into mine, and now LD behaves
itself. But this is still abnormal behaviour, so I've sent in the bug
report. There's no reason why LD should leave out a section in the
program header when it's clearly referenced in the program.

Hope I helped stamp something bad out.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]