我正在尝试制作一个链接器命令脚本,以便由遗留的grub(使用multiboot)引导。我无法在所需位置(在前 8192 字节内)获取多重引导标头。我的脚本看起来像这样:
SECTIONS
{
.multiboot :
{
__multiboot_header = .;
*(.multiboot)
}
.text 0x00100000 :
{
*(.text*)
*(.rodata)
}
/* ... remainder of script ... */
}
总的来说,我的目标是在物理内存的第一个 1MiB 之后由引导加载程序加载我的自定义可执行文件;作为.text部分声明一部分的地址似乎已经按照我的预期完成了此操作。读取 ELF 标头给出的入口点为:
$ readelf -h kernel.elf | grep Entry
Entry point address: 0x100000
但是,在这样做的过程中,我似乎也增加了文件这么多。
$ ls -l file.elf
-rwxr-xr-x 1 user user 1049960 May 13 02:20 file.elf
ELF 标头和.text部分之间的区域初始化为零。
$ 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........|
此外,尽管readelf -s
报告__multiboot_header
的值为 0x0(这应该是结构的地址,因为它是在链接器文件中提到的同一点定义的,对吧?
$ readelf -s kernel.elf | grep multiboot
22: 00000000 0 NOTYPE GLOBAL DEFAULT 1 __multiboot_header
readelf -S
的输出似乎相互冲突:
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
这意味着.multiboot部分实际上位于.text部分内。
如果我按 0x1000f8 偏移到文件中,那么我可以找到结构,但是,我不确定偏移量来自哪里。
tl;博士
1) 如何确保特定数据结构在输出文件的前 8192 字节内?
2) 如何在不膨胀具有较大零初始化块间隙的输出二进制文件的情况下指定加载地址?
elf 文件格式由其自己的规则生成,它存储信息的方式不受链接器文件的直接影响(例如,存储部分的偏移量不得与它们在内存中的位置相关联)。这是链接器文件中的SECTIONS
命令描述的内存布局,elf 文件格式描述了此布局......您需要一个具有精灵功能的装载机将各个部分加载到目标位置。
要获取可以 1:1 加载到内存中的平面二进制文件,请使用objcopy
(例如objcopy -O binary myfile.elf myfile.bin
之类的东西)。该文件的布局直接受链接器脚本的影响,.multiboot部分的内容应该真正处于偏移0
。