Why does GNU ld include a section that does not appear in the linker script?
Asked Answered
S

0

1

I'm trying to create a minimal C example on a boot sector for educational purposes.

However, I noticed that my example was not being recognized as a boot sector because he magic 0x55aa bytes were not present as the 511th and 512th bytes.

Then, I investigated further, and it seems that this is because the .eh_frame section was getting included in the image, even though it was never mentioned in the linker script.

Why is that?

The exact setup is present here and reproduced below

build.sh:

as -ggdb3 -o entry.o entry.S
gcc -c -ggdb3 -nostartfiles -nostdlib -o main.o main.c
ld                  -o main.elf -T linker.ld entry.o main.o
ld --oformat binary -o main.img -T linker.ld entry.o main.o
qemu-system-x86_64 -hda main.img

linker.ld

ENTRY(mystart)
SECTIONS
{
  .text : {
    entry.o(.text)
    *(.text)
    *(.rodata)
    *(.data)
    /**(.eh_frame)*/
    . = 0x1FE;
    SHORT(0xAA55)
  }
  /* Reserve 16 MiB of stack. */
  __stack_bottom = .;
  . = . + 0x1000000;
  __stack_top = .;
}

entry.S:

.text
.global mystart
mystart:
    mov %rsp, __stack_top
    call main
    jmp .

main.c:

void main(void) {
    while (1);
}

If I uncomment the .eh_frame frame above, then it gets included at the specified location, and things work, although it is not ideal and I would rather ignore that section completely.

But why does it try to include the .eh_frame in the final image if I never mention it?

I found out about .eh_frame by doing:

hd main.img

which gives:

00000000  14 00 00 00 00 00 00 00  01 7a 52 00 01 78 10 01  |.........zR..x..|
00000010  1b 0c 07 08 90 01 00 00  1c 00 00 00 1c 00 00 00  |................|
00000020  27 00 00 00 06 00 00 00  00 41 0e 10 86 02 43 0d  |'........A....C.|
00000030  06 00 00 00 00 00 00 00  48 89 24 25 38 02 00 01  |........H.$%8...|
00000040  e8 02 00 00 00 eb fe 55  48 89 e5 eb fe 66 2e 0f  |.......UH....f..|
00000050  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000060  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000070  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000080  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000090  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000000a0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000000b0  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
000000c0  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
000000d0  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
000000e0  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000000f0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000100  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000110  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000120  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000130  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
00000140  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
00000150  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000160  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000170  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000180  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
00000190  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000001a0  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
000001b0  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
000001c0  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
000001d0  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 2e 0f  |...f.........f..|
000001e0  1f 84 00 00 00 00 00 66  2e 0f 1f 84 00 00 00 00  |.......f........|
000001f0  00 66 2e 0f 1f 84 00 00  00 00 00 66 2e 0f 1f 84  |.f.........f....|
00000200  00 00 00 00 00 66 2e 0f  1f 84 00 00 00 00 00 66  |.....f.........f|
00000210  2e 0f 1f 84 00 00 00 00  00 66 2e 0f 1f 84 00 00  |.........f......|
00000220  00 00 00 66 2e 0f 1f 84  00 00 00 00 00 66 0f 1f  |...f.........f..|
00000230  84 00 00 00 00 00 55 aa                           |......U.|
00000238

and then:

objdump -D main.o

which contains:

Disassembly of section .eh_frame:

0000000000000000 <.eh_frame>:
   0:   14 00                   adc    $0x0,%al
   2:   00 00                   add    %al,(%rax)
   4:   00 00                   add    %al,(%rax)
   6:   00 00                   add    %al,(%rax)
   8:   01 7a 52                add    %edi,0x52(%rdx)
   b:   00 01                   add    %al,(%rcx)
   d:   78 10                   js     1f <.eh_frame+0x1f>
   f:   01 1b                   add    %ebx,(%rbx)
  11:   0c 07                   or     $0x7,%al
  13:   08 90 01 00 00 1c       or     %dl,0x1c000001(%rax)
  19:   00 00                   add    %al,(%rax)
  1b:   00 1c 00                add    %bl,(%rax,%rax,1)
  1e:   00 00                   add    %al,(%rax)
  20:   00 00                   add    %al,(%rax)
  22:   00 00                   add    %al,(%rax)
  24:   06                      (bad)  
  25:   00 00                   add    %al,(%rax)
  27:   00 00                   add    %al,(%rax)
  29:   41 0e                   rex.B (bad) 
  2b:   10 86 02 43 0d 06       adc    %al,0x60d4302(%rsi)
  31:   00 00                   add    %al,(%rax)
  33:   00 00                   add    %al,(%rax)
  35:   00 00                   add    %al,(%rax)
        ...

so we can see that in the hd main.img, the first bytes are exactly the same as those in .eh_frame, and the image size is 512 + sizeof(.eh_frame) instead of the expected 512.

Tested on Ubuntu 18.04, GCC 7.3.0, binutils 2.30.

Screak answered 2/12, 2018 at 21:11 Comment(8)
Because any input section that is encountered while producing an output section that isn't specifically mentioned is still output in the order they are first encountered after the other sections you processed. You are running into this issue because you put your boot signature inside another section you are processing. To avoid this create a separate output section for the boot signature like . = 0x1FE; .bootsig : { SHORT(0xAA55) } .This file as an example: capp-sysware.com/misc/stackoverflow/linker.ld.53584666Delafuente
@MichaelPetch thanks! Your solution does produce the right signature. But I noticed that eh_frame is still there in the binary, is there any way to completely remove it? Also consider answering the question.Screak
If you don't want .eh_frame to appear you have two choices. Compile your C code with -fno-asynchronous-unwind-tables, or you can you DISCARD to eliminate it with the linker script. I usually strip .comment and .eh_frame with /DISCARD/ : { *(.eh_frame); *(.comment); }Delafuente
On an unrelated note you may wish to change *(.rodata) to *(.rodata*) . There may be more than one .rodata sections that appear as .rodata.XXX where XXX makes a unique section name.Delafuente
@MichaelPetch thanks again! As a followup... :-) I was trying to keep it minimal, but now I noticed that I also need to tell the linker about the 0x7c00 entry address. I tried: gist.github.com/cirosantilli/b2f269fdf1dd755b88c019a71364c512 but it seems to increase the image size beyond 512 if I do that. How to get both of them working?Screak
Ah, I think AT is the answer :-)Screak
AT is the answer yes. I have a sample here: capp-sysware.com/misc/osdev/linkedboot . You can cut out what you don't need.. That accounts for the kernel size i sectors, and also zeros the BSS section so has linker symbols for that.Delafuente
However the quick fix for the code you showed (github link) is . = 0x7DFE; before the boot signature. That is instead of . = 0x1FE; . The link I put to my sample also allows you to dovetail the kernel with the bootloader so is more complex than what you are looking for, but if you ever want add the kernel in and change the VMA of the kernel that sample may have some valueDelafuente

© 2022 - 2024 — McMap. All rights reserved.