链接器在链接时是否生成绝对虚拟地址

Joe*_*Joe 5 macos assembly linker executable virtual-memory

假设一个简单的 hello world in C,编译gcc -c为目标文件并反汇编为objdump如下所示:

_main:
       0:   55  pushq   %rbp
       1:   48 89 e5    movq    %rsp, %rbp
       4:   c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
       b:   c7 45 f8 05 00 00 00    movl    $5, -8(%rbp)
      12:   8b 05 00 00 00 00   movl    (%rip), %eax
Run Code Online (Sandbox Code Playgroud)

如您所见,内存地址是0, 1, 4, ..等等。它们不是实际地址。

链接目标文件并反汇编它看起来像这样:

_main:
100000f90:  55  pushq   %rbp
100000f91:  48 89 e5    movq    %rsp, %rbp
100000f94:  c7 45 fc 00 00 00 00    movl    $0, -4(%rbp)
100000f9b:  c7 45 f8 05 00 00 00    movl    $5, -8(%rbp)
100000fa2:  8b 05 58 00 00 00   movl    88(%rip), %eax
Run Code Online (Sandbox Code Playgroud)

我的问题是,是100000f90虚拟内存字节的实际地址还是偏移量?

链接器如何在执行前给出实际地址?如果该内存地址在执行时不可用怎么办?如果我在另一台内存少得多的机器上执行它怎么办(也许分页在这里开始)。

分配实际地址不是加载程序的工作吗?

链接器是否为最终的可执行文件生成实际地址?

prl*_*prl 7

(以下答案假定链接器未创建与位置无关的可执行文件。)

我的问题是,100000f90 是虚拟内存字节的实际地址还是偏移量?

这是实际的虚拟地址。严格来说,它是代码段基址的偏移量,但由于现代操作系统总是将代码段基址设置为 0,因此它实际上是实际的虚拟地址。

链接器如何在执行前给出实际地址?如果该内存地址在执行时不可用怎么办?如果我在另一台内存少得多的机器上执行它怎么办(也许分页在这里开始)。

每个进程都有自己独立的虚拟地址空间。因为它是虚拟内存,所以机器中的物理内存量并不重要。分页是虚拟地址映射到物理地址的过程。

分配实际地址不是加载程序的工作吗?

是的,在创建进程时,操作系统加载程序会为进程分配物理页框并将页面映射到进程的虚拟地址空间。但是虚拟地址是由链接器分配的。