C 地址是由objdump final addresses显示的还是仅由偏移量显示的?

C 地址是由objdump final addresses显示的还是仅由偏移量显示的?,c,linker,objdump,C,Linker,Objdump,假设此C代码是用gcc file.C编译的: int main(){ return 0; } 使用objdump生成的输出: 0000000000000660 <main>: 660: 55 push %rbp 661: 48 89 e5 mov %rsp,%rbp 664: b8 00 00 00 00 mov $0x0,%eax 669: 5d

假设此
C
代码是用
gcc file.C
编译的:

int main(){
 return 0;
}
使用
objdump
生成的输出:

0000000000000660 <main>:
660:    55                      push   %rbp
661:    48 89 e5                mov    %rsp,%rbp
664:    b8 00 00 00 00          mov    $0x0,%eax
669:    5d                      pop    %rbp
66a:    c3                      retq   
66b:    0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
注意在每个地址的左侧添加了
5s

以下是我的问题:

1-左侧的
5s
是什么?为什么objdump没有它们

2-这些只是偏移量吗?或最终地址硬编码为二进制,将加载到虚拟内存中

3-如果这些偏移量大于常规可执行文件和
饼图
之间的差异是什么?我认为只有饼图代码是位置独立的,并且在加载期间为其分配了随机地址,我没有使用
-fpie
选项进行编译。我还使用了
-fno-pie
,没有任何区别

1-左边的5是什么?为什么objdump没有它们

555…55516是1000…00016的三分之一。你看到的是多个五,仅仅是因为有人把某个特定的记忆区域分成了三部分
objdump
没有它们,因为它只是显示偏移量

2-这些只是偏移量吗?或最终地址硬编码为二进制,将加载到虚拟内存中

它们是相对于它们所在程序段的开始的偏移量

3-如果这些是偏移量,那么常规可执行文件和饼图之间的区别是什么?我认为只有饼图代码是位置独立的,并且在加载期间为其分配了随机地址,我没有使用-fpie选项编译。我也用过-fno派,没什么区别

与位置无关的可执行文件在程序执行期间计算其地址。它使用基址寄存器或提供给它的其他信息来定位对象,或使用相对于程序计数器的地址,或独立于程序位置的其他形式的寻址

相反,一个不独立于位置的程序可以使用绝对形式的寻址。但是,绝对地址不一定内置在对象模块中。对象模块中的地址仍然可以是相对于程序段或其他参考点的偏移量。加载程序时,加载器选择将程序节放在何处,并调整指令中内置的所有地址,将它们从偏移量更改为绝对地址。对象模块和最终的可执行文件包含描述所有需要这些“修复”的位置的数据结构


位置无关代码可以同时在两个不同进程中的两个不同虚拟内存地址上使用。因为它使用相对的寻址形式构造所有地址,所以代码的位置是不相关的。使用加载器固定地址的代码绑定到特定地址;加载程序完成后,代码的指令中嵌入了特定的地址,因此无法将其移动到其他位置。

感谢提供详细信息。可以安全地说,GDB显示的地址是最终地址(在加载程序调整了所有内容之后),而objdump只显示偏移量吗?@Dan:是的,在运行的程序中,GDB显示实际的虚拟内存地址。而objdump只显示偏移量。
0x555555554660 <main>                   push   %rbp
0x555555554661 <main+1>                 mov    %rsp,%rbp
0x555555554664 <main+4>                 mov    $0x0,%eax
0x555555554669 <main+9>                 pop    %rbp
0x55555555466a <main+10>                retq