为目标文件中的指令分配地址

时间:2014-04-04 05:37:07

标签: c linux process ld loader

当我们使用gcc -c编译任何c代码并执行objdump -d <filename>.o时,我们会看到

Disassembly of section .text:
0000000000000000 <main>:
 0:   55                      push   %rbp
 1:   48 89 e5                mov    %rsp,%rbp
 4:   48 83 ec 10             sub    $0x10,%rsp
 8:   48 8d 45 fc             lea    -0x4(%rbp),%rax
 c:   48 89 c7                mov    %rax,%rdi
 f:   b8 00 00 00 00          mov    $0x0,%eax
 . . .

但在链接后,偏移量会更改为gcc -o prog -L/library/path -llibrary *.o

0000000000400644 <main>:
400644:       55                      push   %rbp
400645:       48 89 e5                mov    %rsp,%rbp
400648:       48 83 ec 10             sub    $0x10,%rsp
40064c:       48 8d 45 fc             lea    -0x4(%rbp),%rax
400650:       48 89 c7                mov    %rax,%rdi
400653:       b8 00 00 00 00          mov    $0x0,%eax

链接完成后如何计算偏移量?

我们基本上得到3组地址,     1.编译完成后     2.链接后     3.加载后

以上地址如何相关?

3 个答案:

答案 0 :(得分:2)

您必须记住,目标文件仅包含您的代码,因此它始终位于零偏移处。

链接时,添加其他来源的模块,如运行时初始化和库函数。您不知道这些对象的大小,或者它们将被放置在生成的可执行文件中的位置,因此无法自己计算代码不同部分的偏移量。此外,如果您有多个目标文件,链接器可能会根据需要重新排列它们。

代码在运行时最终会出现什么虚拟地址,部分取决于链接器,但主要取决于操作系统和地址空间随机化等等。

答案 1 :(得分:1)

gcc -c将运行compiler正确(某些cc1)生成汇编代码,然后运行assembleras)。请与gcc -v -c核实,了解究竟发生了什么。

编译器(实际上cc1)正在将您的C代码转换为汇编代码。

然后汇编程序(as)将汇编代码转换为object fileExecutable & Linkable Format,a.k.a。ELF)。

ELF目标文件包含带有relocation指令或指令的字节段(例如代码或.text段或.data段),并定义(和使用)符号引用。重定位取决于处理器,参见例如this list of relocation typesx86-64 ABI spec - application binary interface。这些重定位由linker(由ld启动的gcc处理。阅读Levine's Linkers and loaders book。因此,ELF目标文件包含具有重定位指令和symbol tables的字节。

链接器将根据重定位代码修改某些机器指令(或其他数据)。

答案 2 :(得分:0)

每个平台/体系结构都有其可执行文件所需的特定内存布局。链接器的任务是以适合您的平台/体系结构的方式组合/重定位目标文件。

使用gcc工具链,这种适应是通过链接描述文件完成的。如果您很好奇,可以查看实现(默认链接脚本通常位于名为ldscripts的目录中,文件扩展名为.xbn