I am trying to craft a linker-command script to be bootable by legacy grub (using multiboot). I am having difficulty getting the multiboot header in the required location (within the first 8192 bytes). My script looks something like:
SECTIONS
{
.multiboot :
{
__multiboot_header = .;
*(.multiboot)
}
.text 0x00100000 :
{
*(.text*)
*(.rodata)
}
/* ... remainder of script ... */
}
Overall, my objective is to have my custom executable loaded by the bootloader after the first 1MiB of physical memory; the address as part of the .text section declaration seems to have done this as I expected. Reading the ELF header gives the entry point as:
$ readelf -h kernel.elf | grep Entry
Entry point address: 0x100000
However, in doing so I seem to have also increased the file by this much.
$ ls -l file.elf
-rwxr-xr-x 1 user user 1049960 May 13 02:20 file.elf
The area between the ELF header and the .text section is initialized to zeros.
$ hexdump -C file.elf
00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 03 00 01 00 00 00 00 00 10 00 34 00 00 00 |............4...|
00000020 00 04 10 00 00 00 00 00 34 00 20 00 02 00 28 00 |........4. ...(.|
00000030 09 00 08 00 01 00 00 00 00 00 00 00 00 00 00 00 |................|
00000040 00 00 00 00 f8 00 10 00 f8 f0 4e 00 07 00 00 00 |..........N.....|
00000050 00 00 20 00 51 e5 74 64 00 00 00 00 00 00 00 00 |.. .Q.td........|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 |................|
00000070 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
00100000 8b 25 f8 f0 4e 00 50 53 e8 66 00 00 00 fa f4 eb |.%..N.PS.f......|
00100010 fc 55 89 e5 53 83 ec 10 c7 45 f8 00 00 00 00 eb |.U..S....E......|
00100020 38 a1 f4 00 10 00 8b 55 f8 01 d2 01 d0 8b 15 f4 |8......U........|
Also, although readelf -s
reports that __multiboot_header
has a value of 0x0 (which should be the address of the structure since it was defined at the same point it was mentioned in the linker file, right?):
$ readelf -s kernel.elf | grep multiboot
22: 00000000 0 NOTYPE GLOBAL DEFAULT 1 __multiboot_header
The output of readelf -S
seems to conflict:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 1] .multiboot PROGBITS 00000000 1000f8 00000c 00 0 0 1
[ 2] .text PROGBITS 00100000 100000 000096 00 AX 0 0 1
Which implies that the .multiboot section is actually inside the .text section.
If I offset into the file by 0x1000f8 then I can find the structure, however, I am not sure where the offset came from.
tl;dr
1) How can I ensure a specific data structure is within the first 8192 bytes of the output file?
2) How can I specify the load address without inflating the output binary with large gaps of zero-initialized blocks?