为何objdump对-fPIC与非-fPIC生成的目标文件输出一致?
为啥-fPIC编译的目标文件和普通编译的反汇编看起来一样?
嘿,这个问题我刚接触PIC机制的时候也困惑过,咱们一步步拆解清楚~
首先得明确一个关键:你现在查看的是编译生成的目标文件(.o),不是最终链接后的可执行文件,-fPIC的核心差异并不会直接体现在反汇编的指令偏移上,而是藏在目标文件的重定位信息里。
1. 反汇编里的callq只是临时占位偏移
你看到的callq 15 <a+0x15>,本质上是编译器给printf调用留的一个相对偏移占位符。在目标文件阶段,所有外部函数(比如标准库的printf)的地址都是未确定的,所以这个偏移只是当前函数内的临时数值,只有在链接时才会被替换成真正的跳转地址。不管用不用-fPIC,这个临时偏移都不会有区别。
2. 真正的差异在重定位表
要看到-fPIC的实际影响,你得用objdump -r查看目标文件的重定位条目:
- 不用
-fPIC编译的a.o里,对printf的调用对应的重定位类型是R_X86_64_PC32,这是普通的PC相对重定位; - 用
-fPIC编译的a.o里,对应的重定位类型是R_X86_64_PLT32,这表示会通过**过程链接表(PLT)**来间接调用printf——这正是PIC实现位置无关的关键机制之一。
3. -no-pie是链接阶段选项,编译阶段加了没用
你提到的-no-pie是给链接器用的,用来生成非位置无关的可执行文件。如果只是编译成目标文件,这个选项不会产生任何效果。你需要在链接时加上它(比如gcc -no-pie a.o -o a_nonpie),然后对比PIC和非PIC的可执行文件反汇编,才能看到明显的差异:
- 非PIC的可执行文件里,
printf的调用会直接跳转到绝对地址; - PIC的可执行文件里,会先跳转到PLT表的
printf条目,再间接调用真正的函数。
总结一下
目标文件阶段的反汇编指令偏移看起来一致是正常的,因为真正的位置无关逻辑藏在重定位信息和链接后的PLT/GOT结构里。想看差异,要么查重定位表,要么链接成可执行文件后再反汇编~
内容的提问来源于stack exchange,提问作者user3132457
相关产品推荐
相关产品推荐

