You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GAS为何为外部符号调用生成R_X86_64_PLT32重定位?链接后为何表现如PC32?

关于GAS汇编重定位类型的两个问题

问题1

汇编以下代码(使用GNU汇编器GAS):

.extern foo

.global bar
.section .text
bar:
    call foo
    ret

生成的目标文件中,调用foo的位置存在类型为R_X86_64_PLT32的重定位项,该重定位项通过公式L + A - P解析(其中L为符号的PLT条目地址,A为加数,P为重定位项引用的位置)。由于该文件未定义PLT,请问GAS为何选择此类重定位?

问题2

将上述目标文件与汇编以下代码生成的目标模块链接时:

.global foo
.section .text
foo:
    ret

上述R_X86_64_PLT32重定位项的解析行为与R_X86_64_PC32类型一致,这是为什么?


解答

针对问题1的解释

GAS选择R_X86_64_PLT32重定位,核心是为了兼容动态链接场景:

  • 汇编器处理.extern foo时,无法提前判断foo是程序内部符号还是动态库中的外部符号。为了避免后续链接时出现兼容性问题,汇编器默认采用PLT相关的重定位类型——这种类型既能支持动态链接时的延迟绑定(通过PLT跳转表实现),也能在静态链接场景下正常工作。
  • PLT是链接阶段才会生成的结构,汇编器只需要标记出需要PLT重定位的位置,后续链接器会根据符号的实际来源(本地/动态库)决定是否生成对应的PLT条目。

针对问题2的解释

当链接时发现foo是当前可执行文件内的本地符号(非动态库符号),链接器会对R_X86_64_PLT32重定位做优化处理:

  • 此时不需要通过PLT跳转,链接器会直接计算foo的实际地址与重定位位置P的偏移,逻辑和R_X86_64_PC32完全一致(后者公式为S + A - P,S为符号实际地址)。
  • 在静态链接场景下,PLT条目地址L会直接指向foo的实际地址S,因此L + A - P和S + A - P的计算结果完全相同,表现出的解析行为就和R_X86_64_PC32一致。

内容的提问来源于stack exchange,提问作者mdjukan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 20:22:11