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

时间:2019-03-16 17:27:15

标签: macos assembly linker executable virtual-memory

假设C中的一个简单的hello世界,使用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

如您所见,内存地址为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

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

  

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

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

  

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

每个进程都有自己的单独虚拟地址空间。因为它是虚拟内存,所以计算机中的物理内存量无关紧要。分页是将虚拟地址映射到物理地址的过程。

  

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

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

答案 1 :(得分:-1)

  

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

这取决于链接器设置和输入源。对于常规编程,链接器通常会努力创建位置无关的代码。

  

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

很可能是偏移量。

  

链接器如何在执行之前提供实际地址?

考虑操作系统的加载程序。它期望事物位于特定的地址位置。任何体面的链接器都将允许程序员以某种方式指定绝对地址。

  

如果执行时该内存地址不可用怎么办?如果我在内存少得多的另一台机器上执行它(也许在这里启动分页)。

这是位置相关代码的问题。

  

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

加载程序的工作是按照可执行文件中提供的说明进行操作。在创建可执行文件时,链接器可以在某些情况下指定地址或推迟到加载程序。