这将是一个很长的时间,所以拿一些咖啡/茶/yerba。
概括
如何告诉/强制 GNU ld 将部分/符号放入输出 ELF 文件的特定部分?
具体来说,我不是在询问符号的物理/加载地址,而是询问文件中的偏移量。
背景
我正在尝试采用真实世界的 BSD 内核并使其与 Multiboot 兼容并可由 GRUB 引导。为了使 ELF 映像与 Multiboot 兼容并可由 GRUB 识别,需要0x1BADB002
在文件的前 8KiB 中嵌入一个幻数 ( )。
我指的是Multiboot 0.6.96。
由于原始内核是相当大的一段代码,我将使用基于来自 OSDev wiki 的 Bare Bones 内核的示例。由于该内核已经与 Multiboot 兼容,因此我将使用
extra_symbol
with value0xCAFEBABE
作为我的问题的示例。
boot.s
包含:
.set CAFEBABE, 0xCAFEBABE
; ... snip ...
.section .extras
extra_symbol:
.long CAFEBABE
中的额外符号.text
最简单的选择是将具有该值的符号放在.text
其他任何部分之前:
.text BLOCK(4K) : ALIGN(4K)
{
*(.extras)
*(.multiboot)
*(.text)
}
这个例子很好,但如果真正的 BSD 内核.text
在文件中的 0x2000 (8KiB) 之后启动。这种方法不是一种选择。
之前的额外部分.text
?
另一种选择是将整个.extras
部分放在.text
. 在我的天真中,我希望.text
在链接描述文件之前放置这样一个部分也会使其更早地出现在输出 ELF 中:
SECTIONS
{
// ... some stuff ...
.extras : { *(.extras) }
.text BLOCK(4K) : ALIGN(4K)
{
*(.multiboot)
*(.text)
}
// ... more stuff ...
}
但事实并非如此:
$ i586-elf-readelf -S myos.bin
There are 10 section headers, starting at offset 0x6078:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .extras PROGBITS 00100000 006010 000004 00 0 0 1
[ 2] .comment PROGBITS 00000000 006014 000011 01 MS 0 0 1
[ 3] .text PROGBITS 00001000 001000 0001e4 00 AX 0 0 4096
[ 4] .rodata.str1.1 PROGBITS 000011e4 0011e4 000016 01 AMS 0 0 1
[ 5] .eh_frame PROGBITS 000011fc 0011fc 000104 00 A 0 0 4
[ 6] .bss PROGBITS 00002000 002000 004010 00 WA 0 0 4096
[ 7] .shstrtab STRTAB 00000000 006025 000050 00 0 0 1
[ 8] .symtab SYMTAB 00000000 006208 000210 10 9 19 4
[ 9] .strtab STRTAB 00000000 006418 000130 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
实际上,节在节头表中排在第一位,但它在文件 ( 0x6010
)中的偏移量在.text
. 事实上,它甚至在.bss
.
问题
ELF 规范明确指出:
虽然图中显示了紧接在 ELF 头之后的程序头表,以及紧随节之后的节头表,但实际文件可能会有所不同。此外,节和段没有指定的顺序。只有 ELF 标头在文件中具有固定位置。
我如何利用它并告诉 GNU ld 将我的extra_symbol
(可能是整个.extras
部分)放在文件中的任何其他部分之前,最好是在 ELF 标头之后?