作为链接器输入的文件称为Object File。链接器生成一个Image 文件,该文件又用作加载程序的输入。
“ Microsoft Portable Executable and Common Object File Format Specification ”的简介
RVA(相对虚拟地址)。在图像文件中,项目加载到内存后的地址,减去图像文件的基地址。一个项目的 RVA 几乎总是不同于它在磁盘上文件中的位置(文件指针)。
在目标文件中,RVA 的意义不大,因为没有分配内存位置。在这种情况下,RVA 将是一个段内的地址(稍后在此表中描述),稍后在链接期间对其应用重定位。为简单起见,编译器只需将每个部分中的第一个 RVA 设置为零。
VA(虚拟地址)。与 RVA 相同,只是不减去图像文件的基地址。该地址被称为“VA”,因为 Windows 为每个进程创建了一个不同的 VA 空间,独立于物理内存。对于几乎所有目的,一个 VA 应该被认为只是一个地址。VA 不像 RVA 那样可预测,因为加载器可能不会在其首选位置加载图像。
即使读了这篇文章,我仍然不明白。我有很多问题。任何人都可以用实际的方式解释它。Object File
请按照说明遵守&的术语Image File
。
我所知道的地址是
- 在目标文件和图像文件中,我们都不知道确切的内存位置,所以,
- 汇编器在生成目标文件时计算相对于部分
.data
&的地址.text
(对于函数名称)。 - 将多个目标文件作为输入的链接器会生成一个图像文件。在生成时,它首先合并每个目标文件的所有部分,并在合并时重新计算相对于每个部分的地址偏移量。而且,没有什么比全局偏移量更好的了。
如果我所知道的有什么不对的地方,请纠正我。
编辑:
在阅读了弗朗西斯的回答后,我很清楚什么是物理地址、VA 和 RVA 以及它们之间的关系。
所有变量和方法的 RVA 必须在重定位期间由链接器计算。那么,(方法/变量的 RVA 值)==(它与文件开头的偏移量)?一定是真的。但令人惊讶的是,它不是。为什么这样?
我通过使用PEView检查 了这一点c:\WINDOWS\system32\kernel32.dll
,发现:
- RVA 和 FileOffset 直到 Sections 的开头都是相同的。(
.text
是这个 dll 中的第一部分)。 - 从
.text
through的开始.data
,.rsrc
到最后一个部分的最后一个字节 (.reloc
) RVA 和 FileOffset 是不同的。&第一部分的第一个字节的 RVA 也“总是”显示为0x1000
- 有趣的是,每个部分的字节在 FileOffset 中是连续的。我的意思是另一个部分从一个部分的最后一个字节的下一个字节开始。但是,如果我在 RVA 中看到同样的情况,那么这就是一节最后一个字节的 RVA 和下一节的第一个字节之间的巨大差距。
我猜:
所有,在第一个(此处)部分之前的数据字节
.text
实际上“没有”加载到进程的 VA 空间中,这些数据字节仅用于定位和描述这些部分。它们可以称为“元节数据”。因为它们没有加载到进程的 VA 空间中。术语 RVA 的使用也毫无意义,这就是
RVA == FileOffset
这些字节的原因。自从,
- RVA 术语仅对将实际加载到 VA 空间的字节有效。
.text
,.data
,.rsrc
,的字节.reloc
就是这样的字节。0x00000
PEView 软件不是从 RVA开始,而是从0x1000
.
我不明白为什么第三次观察。我无法解释。