如何读取目标文件的重定位记录

7
我正在尝试理解C工具链中的链接阶段。我编写了一个示例程序并分析了生成的目标文件。虽然这帮助我更好地理解了涉及的过程,但还有一些事情对我来说仍然不清楚。
以下是:

第1部分:处理已初始化变量。

这些重定位表条目是否正确...

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
0000002b dir32             .data
00000035 dir32             .data
0000003f dir32             .data

基本上,您告诉链接器,从.text偏移量2b353f处存储的地址不是绝对地址,而是相对于.data的偏移量。我理解这样做是为了使链接器能够:

  • 将这些相对地址转换为绝对地址以创建不可重定位的目标文件;
  • 或者在将目标文件与其他目标文件链接时适当地进行调整。

第二部分:处理未初始化的变量。

我不明白为什么未初始化的变量与初始化的变量处理方式如此不同。为什么寄存器地址存储在操作码中,

  • 对于所有未初始化的变量(0x0、0x0和0x0)都是相等的,而对于所有初始化的变量(0x0、0x4和0x8)都是不同的?

另外,它们的重定位表条目的值字段完全不清楚。我原本希望在那里引用.bss部分。

RELOCATION RECORDS FOR [.text]:
OFFSET   TYPE              VALUE
0000000d dir32             _var1_zeroed-0x00000004
00000017 dir32             _var2_zeroed-0x00000004
00000021 dir32             _var3_zeroed-0x00000004
1个回答

3
基本上是告诉链接器在偏移量处存储的地址……不,链接器已经不再参与了。重定位表告诉加载程序——操作系统的部分负责将可执行映像加载到内存中——有关地址的信息。链接器基于一初始的前提条件构建可执行映像,即映像可以被加载到预期的地址上。如果是这种情况,那么一切都很顺利,不需要进行任何操作。然而,如果有冲突,虚拟地址空间已经被其他进程使用,那么映像就需要重新定位到另一个地址。这就需要对地址进行修补,必须添加理想加载地址和实际加载地址之间的偏移量。因此,如果.data节最终位于.text+0x2b、.text+0x35等其他地址,则必须更改相应的地址,未初始化变量也同样如此。链接器已经为它们选择了一个地址,但如果_var1_zeroed-0x00000004最终位于.text+0x0d、.text+0x17等其他地址,则必须更改相应的地址。

连接器根据一切都理想和图像可以在预期地址加载的假设构建可执行映像。然而,这似乎并不适用于问题中提到的目标文件。请注意,操作码中存储的寄存器文件地址对所有未初始化变量都相等。你能详细说明一下吗? - Multisync
哎呀,糟糕,目标文件在前一步。链接器分配地址。 - Hans Passant
嗯...那么相比之下,为什么已经由编译器分配了初始化变量的地址呢? - Multisync
编译器必须选择一个偏移量在.data中使变量匹配初始值。链接器合并.data部分,因此仍会更改地址。 - Hans Passant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接