2

我只是用来objdump -x ...检查 PE 文件的部分。

大约有 90,000 行 reloc 条目:

reloc   92 offset  bc0 [524bc0] HIGHLOW
reloc   93 offset  bc4 [524bc4] HIGHLOW
    ....

大多数 PE 文件的大部分空间都是由上面的 reloc 条目组成的,这是否成立?

这些条目是做什么用的?

更新

任何人都可以解释重定位条目如何像上面那样工作?

4

1 回答 1

12

当内存中存在基本冲突时,需要重新定位。如果一个动态链接库想要将它的代码段加载到某个内存空间,但是当它已经被另一个模块占用时,它必须被加载到不同的地方。但是,通过将其加载到不同的地址空间中,它会弄乱库引用的所有绝对引用。例如,假设可执行文件有一个名为的全局变量int dummy;,该变量位于 0x602315。每当访问/写入此变量时,程序都会执行以下操作码(假设代码位于 0x524BBE,与您提到的条目相同):

0x524BBE: MOV EAX, DWORD PTR DS:[0x602315];//move dummy to eax register to do stuff

当库加载到不同的空间时,0x602315 将不会指向变量,因为地址空间 0x602315 已经被其他模块占用。因此,要解决此问题,您必须告诉 PE 加载程序将位移 ( |new base address-expected base address|) 添加/减去此值 (0x602315)。为此,每个 PE 都包含一个称为重定位表的表,该表包含代码中引用此变量的所有偏移量。

因此,假设库在 0x700000 处加载,而不是 0x524000(预期的基本偏移量)。然后,PE 加载器将做的是查找表中的条目并将位移(0x700000-0x524000=0x1DC000)添加到偏移量(0x602315),这样您加载的代码将如下所示:

0x700BBE: MOV EAX, DWORD PTR DS:[0x7DE315];//move dummy to eax register to do stuff

它将运行良好,因为它指向变量的正确位置dummy

回到您的问题,objdump 的输出显示了该表的每个条目。92 可能表示条目的索引,BC0 是您访问变量的代码的相对地址,[524BC0] 将是相对地址 + 预期基址偏移的结果。并且 HIGHLOW 只是一种重定位(这基本上是为将来使用而保留的。目前,只有一种重定位(HIGHLOW)正在使用,因此您不必担心其他类型)。当加载器读取此条目时,它将更改 0x524BC0 的值以反映此更改。

关于您关于由.reloc表组成的 PE 的多数空间的问题,答案是取决于。如果你的程序频繁访问全局变量和常量,它将有一个巨大的重定位表,因为加载器必须更新的地方太多了。

于 2011-05-23T04:16:42.143 回答