Linker 使用链接器脚本制作ELF文件,节之间没有初始化块
我正在尝试创建一个链接器命令脚本,以便通过使用multiboot的遗留grub进行引导。在前8192字节内,我很难将multiboot头放在所需的位置。我的脚本看起来像:Linker 使用链接器脚本制作ELF文件,节之间没有初始化块,linker,ld,elf,grub,Linker,Ld,Elf,Grub,我正在尝试创建一个链接器命令脚本,以便通过使用multiboot的遗留grub进行引导。在前8192字节内,我很难将multiboot头放在所需的位置。我的脚本看起来像: SECTIONS { .multiboot : { __multiboot_header = .; *(.multiboot) } .text 0x00100000 : { *(.text*) *(.rodata)
SECTIONS
{
.multiboot :
{
__multiboot_header = .;
*(.multiboot)
}
.text 0x00100000 :
{
*(.text*)
*(.rodata)
}
/* ... remainder of script ... */
}
总的来说,我的目标是让引导加载程序在第一个1MB物理内存之后加载我的自定义可执行文件;作为.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报告uuu multiboot_头的值为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文件格式描述了此布局。。。您需要一个支持elf的加载程序将各个部分加载到目标位置
要获得可以1:1加载到内存中的平面二进制文件,请使用objcopy,例如类似于objcopy-O binary myfile.elf myfile.bin的东西。该文件的布局直接受链接器脚本的影响,.multiboot部分的内容实际上应该在偏移量0处。我不同意您的结论,这意味着.multiboot部分实际上在.text部分内。。根据Addr值,.multiboot从00000000开始,大小为00000c,.text从00100000开始,因此前者不在后者内…@falstaff,我根据Off字段得出结论。multiboot是超过.text的0xf8字节。由于multiboot是首先定义的,所以我希望它会出现在文件的前面。我知道Offset指的是ELF文件,但我不明白为什么它放在文本部分之后。根据grub参考,加载ELF是受支持的。实际上,如果加载的映像是正确的ELF文件,则无需指定multiboot头中的其他字段(如加载地址)。根据您的注释,如果有正确的ELF加载程序,物理内存将如何布局?multiboot头是否放在物理地址0x00,而.text部分的第一个字节是否放在0x00100000?我正在考虑objcopy路由,但我必须完成multiboot头的所有字段。我可能仍然会这样做,但我想首先解决的是链接器/精灵的关系。我理解您的上述评论,但我不理解额外的1MiB零初始化内存来自何处,也就是说,在使用移动位置计数器之后。=0x00100000,为什么生成的ELF文件的大小增加了这么多?。这些字节不是任何节的一部分。我的目标是简单地指定.text的第一个字节的加载地址。