链接器如何知道可执行文件的特定部分将映射到进程地址 space 的位置?

How does the linker know where a particular section of an executable will be mapped into the address space of a process?

我正在阅读有关程序如何加载到内存中的内容。我想了解 PE/ELF 文件的不同部分(如文本、数据、rodata 等)如何映射到进程虚拟地址 space 中的不同位置。我特别想了解链接器如何知道特定部分(例如 rodata)将映射到地址 space 的位置,以便它可以在创建可执行文件之前解析所有符号的正确地址。

操作系统(例如 Windows)是否有一个固定范围的虚拟地址用于它们 load/map 特定部分的进程?如果不是,那么链接器将如何解析不同部分中符号的正确地址?

没有。链接器只能建议将可执行映像加载到某个VA,通常PE为0x00400000,DLL为0x10000000。部分的虚拟地址(.text、.rodata、.data 等)按部分对齐方式(通常是0x00001000)对齐,并且因此,他们建议的 VA 是 0x004010000x00402000 等。链接器然后将符号地址固定到那些假定的 VA。
默认 ImageBase 地址(取自链接器脚本或链接器参数)不需要 OS 加载程序,但我没有看到一个改变它的理由,在调试过程中看到漂亮的四舍五入地址是一个好习惯。

在极少数情况下,Windows 加载程序可能会发现建议地址 space 的一部分已被占用,因此它将 在不同的 VA[=27] 加载图像=] 并修复对其新 VA 的位置相关(绝对)引用。 特殊 PE 部分 relocs 包含对需要在加载时重定位的程序符号的引用地址。