1

The multiboot2 header can't be found in my final ELF, because inside the binary file it stands at offset 0x334e0, but the multiboot2 spec tells only the first 32KiB, i.e. 0x8000 bytes, are checked. Therefore it comes "too late".

I don't know how I can solve this. Is the ELF header too bloated? The multiboot2 header itself is correct, i.e. several tools to check multiboot2 headers tell it is correct. It is only not working, when I link the header together with the other code. If I adjust tools to verify multiboot2 headers, i.e. bootimage[1] to look at more than the first 32KiB, it works too.

My linker script (for GNU ld):

/** The "start"-symbol from start.asm. */
ENTRY(start)

SECTIONS {

    /* Multiboot2-Header must be 64-bit (8 byte) aligned according to spec. */
    . = ALIGN(8);
    .multiboot2_header :
    {
        /* ensure that the multiboot header is at the beginning */
        *(.multiboot2_header)
    }

    .text :
    {
        *(.text)
    }
}

readelf -WSl <my-elf> tells, that the .multiboot2_header section is indeed the first one:

There are 1526 section headers, starting at offset 0x3ca8d8:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .multiboot2_header PROGBITS        0000000000000000 0334e8 000048 00      0   0  8
  [ 2] .debug_abbrev     PROGBITS        0000000000000000 033530 00ecea 00      0   0  1
  [ 3] .debug_info       PROGBITS        0000000000000000 04221a 0f0391 00      0   0  1
  [ 4] .debug_aranges    PROGBITS        0000000000000000 1325ab 019f40 00      0   0  1
  [ 5] .debug_ranges     PROGBITS        0000000000000000 14c4eb 0301d0 00      0   0  1
  [ 6] .debug_str        PROGBITS        0000000000000000 17c6bb 0c5de1 01  MS  0   0  1
  [ 7] .debug_pubnames   PROGBITS        0000000000000000 24249c 035215 00      0   0  1
  [ 8] .debug_pubtypes   PROGBITS        0000000000000000 2776b1 058c44 00      0   0  1
  [ 9] .debug_frame      PROGBITS        0000000000000000 2d02f8 033b60 00      0   0  8
  [10] .debug_line       PROGBITS        0000000000000000 303e58 08390a 00      0   0  1
  [11] .debug_loc        PROGBITS        0000000000000000 387762 0038d8 00      0   0  1
  [12] .comment          PROGBITS        0000000000000000 38b03a 000013 01  MS  0   0  1
  [13] .symtab           SYMTAB          0000000000000000 38b050 0089d0 18     15 803  8
  [14] .shstrtab         STRTAB          0000000000000000 393a20 01cec9 00      0   0  1
  [15] .strtab           STRTAB          0000000000000000 3b08e9 019fee 00      0   0  1
  [16] .rodata._ZN137_$LT$rust_multiboot2_64_bit_kernel..logger..BootStageAwareLogger$u20$as$u20$rust_multiboot2_64_bit_kernel..boot_stage..BootStageAware$GT$15next_boot_stage17h5918ecf04a4f1232E PROGBITS        0000000000000000 000160 000010 00   A  0   0  4
  ...
  [179] .rodata..L__unnamed_94 PROGBITS        00000000000045a8 004708 00007f 00   A  0   0  1
  [180] .eh_frame_hdr     PROGBITS        0000000000004628 004788 00000c 00   A  0   0  4
  [181] .eh_frame         PROGBITS        0000000000004638 004798 00001c 00   A  0   0  8
  [182] .text             PROGBITS        0000000000004654 0047b4 00001b 00  AX  0   0  4
  [183] .text._ZN29rust_multiboot2_64_bit_kernel6logger20BootStageAwareLogger13apply_to_each17h77f9f12abd1f054eE PROGBITS        0000000000004670 0047d0 000130 00  AX  0   0 16
  ...
  [1388] .text._ZN54_$LT$u32$u20$as$u20$core..ops..bit..Shl$LT$i32$GT$$GT$3shl17h0ba8101e5b58ae12E PROGBITS        0000000000030390 0304f0 000049 00  AX  0   0 16
  [1389] .text._ZN58_$LT$$RF$u32$u20$as$u20$core..ops..bit..Shl$LT$i32$GT$$GT$3shl17h518033907a793365E PROGBITS        00000000000303e0 030540 000021 00  AX  0   0 16
  [1390] .text.memcpy      PROGBITS        0000000000030410 030570 00004e 00  AX  0   0 16
  [1391] .text.memset      PROGBITS        0000000000030460 0305c0 0000a4 00  AX  0   0 16
  [1392] .text.memcmp      PROGBITS        0000000000030510 030670 000179 00  AX  0   0 16
  [1393] .data.rel.ro..L__unnamed_1 PROGBITS        0000000000030690 0307f0 0002c0 00  WA  0   0  8
  [1394] .data.rel.ro..L__unnamed_2 PROGBITS        0000000000030950 030ab0 000300 00  WA  0   0  8
  ...
  [1515] .data.rel.ro..L__unnamed_169 PROGBITS        00000000000332e0 033440 000018 00  WA  0   0  8
  [1516] .got              PROGBITS        00000000000332f8 033458 000090 00  WA  0   0  8
  [1517] .bss._ZN29rust_multiboot2_64_bit_kernel6logger6LOGGER17h0a7e2a9a53f2b5ddE NOBITS          0000000000033388 0334e8 000018 00  WA  0   0  8
  [1518] .bss              NOBITS          00000000000333a0 0334e8 020000 00  WA  0   0  8
  [1519] .bss._ZN29rust_multiboot2_64_bit_kernel3mb225MULTIBOOT2_INFO_STRUCTURE17h67db2667e3bd19ceE NOBITS          00000000000533a0 0334e8 000018 00  WA  0   0  8
  [1520] .bss._ZN29rust_multiboot2_64_bit_kernel5panic13PANIC_HANDLER17h02bbbbc17c579b55E NOBITS          00000000000533b8 0334e8 00000c 00  WA  0   0  4
  [1521] .bss._ZN29rust_multiboot2_64_bit_kernel5xuefi10UEFI_ST_BS17ha7c24b049d2b76abE NOBITS          00000000000533c8 0334e8 000008 00  WA  0   0  8
  [1522] .bss._ZN29rust_multiboot2_64_bit_kernel10boot_stage10BOOT_STAGE17he05c77811885a1c6E NOBITS          00000000000533d0 0334e8 000001 00  WA  0   0  1
  [1523] .bss._ZN29rust_multiboot2_64_bit_kernel11kernelalloc9ALLOCATOR17h93bce260f0439187E NOBITS          00000000000533d1 0334e8 000001 00  WA  0   0  1
  [1524] .bss._ZN3log5STATE17hdfa5c64bc29aed3eE NOBITS          00000000000533d8 0334e8 000008 00  WA  0   0  8
  [1525] .bss._ZN3log20MAX_LOG_LEVEL_FILTER17h84bf10c3ec44ab54E NOBITS          00000000000533e0 0334e8 000008 00  WA  0   0  8
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Elf file type is EXEC (Executable file)
Entry point 0x4654
There are 5 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000160 0x0000000000000000 0x0000000000000000 0x004654 0x004654 R   0x10
  LOAD           0x0047b4 0x0000000000004654 0x0000000000004654 0x02c035 0x02c035 R E 0x10
  LOAD           0x0307f0 0x0000000000030690 0x0000000000030690 0x002cf8 0x022d58 RW  0x8
  GNU_EH_FRAME   0x004788 0x0000000000004628 0x0000000000004628 0x00000c 0x00000c R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0

 Section to Segment mapping:
  Segment Sections...
   00     .rodata._ZN137_$LT$rust_multib...
   01     .text .text._ZN29rust_multiboot2_64_bit_kernel6logger2...
   02     .data.rel.ro..L__unnamed_1 .data.rel.ro..L__unnamed_2 ...
   03     .eh_frame_hdr 
   04     

There you can see the header comes "too late" in the file. How can I solve this? How can I move it to a smaller offset in the ELF file, i.e. closer to the file begin?

PS: The ELF get's assembled by cargo/rustc/llvm, which uses GNU ld with a custom link script in my case.

phip1611
  • 5,460
  • 4
  • 30
  • 57

1 Answers1

0
 Section to Segment mapping:
  Segment Sections...
   00     .rodata._ZN137_$LT$rust_multib...
   01     .text .text._ZN29rust_multiboot2_64_bit_kernel6logger2...
...

It's clear that the .rodata._ZN.... sections are at lower offsets in the file, and the .text is not in fact the very first.

You need to move .rodata... into a separate segment (by adjusting the linker script), or you need to disable separate RO segment for the ELF header (which would allow .text to be in the first segment). See this answer.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Even with `.rodata : { *(.rodata .rodata.* ) }` as additional section after `.text` and `.multiboot2_header`, the problem exists. – phip1611 Jul 28 '21 at 10:55
  • My only working solution is to add the multiboot2 header to the begin of the `.text` segment. This works but I'd still like to understand how I can achieve this with a separate section. – phip1611 Jul 28 '21 at 11:06