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

为何.rela.plt是PIC函数地址解析的必需结构?

ELF动态链接中.rela.plt段的核心作用解答

.rela.plt不存在任何冗余设计,动态链接的地址解析流程(无论是否启用懒绑定)都无法脱离它独立运行。你观测到的PLT指令中硬编码计算出的GOT偏移,仅服务于CPU执行指令的场景,完全无法覆盖动态链接器做重定位需要的全部信息。

核心原因拆解

  • PLT指令携带的信息存在本质缺失
    你看到的jmpq *0x200b92(%rip)指令确实能算出对应GOT表项地址0x601018,但动态链接器仅拿到这个地址没有任何意义:它无法得知这个内存位置需要填入哪个函数的地址、该函数来自哪个依赖共享库、该重定位项需要遵循哪种修正规则、是否需要附加地址偏移。如果没有独立的元信息存储,动态链接器只能反汇编整个代码段扫描跳转指令反向推导对应关系,不仅效率极低,还会因为不同编译器生成的PLT指令序列差异完全丧失兼容性。
  • 懒绑定场景下.rela.plt是解析流程的核心信息源
    启用懒绑定(默认配置)时,函数第一次被调用前,对应GOT表项存储的不是真实函数地址,而是PLT公共桩的入口地址;触发解析时,动态链接器会拿到当前待解析项的索引,直接到.rela.plt表中匹配对应条目,从中获取完整的重定位元数据:

    以你贴出的条目为例:重定位目标偏移为0x601018、类型为R_X86_64_JUMP_SLO、待解析符号为_Z7ml_funcii、地址加值为0
    动态链接器只有拿到这些信息,才能到全局符号表中匹配函数的实际加载地址,最终写回对应GOT表项完成绑定。

  • 非懒绑定场景下.rela.plt是唯一的重定位依据
    如果编译时开启-z now选项、或者运行时设置LD_BIND_NOW=1,动态链接器会在程序启动阶段、主逻辑执行前完成所有函数地址的绑定,这个过程中根本不会执行PLT中的代码,只能通过遍历.rela.plt段的所有条目,按条目中记录的偏移、类型、符号信息挨个完成GOT表修正,没有其他信息渠道。

对你的两个猜测的验证

  • 适配不同重定位类型确实是.rela.plt的设计目标之一:不同CPU架构、不同安全加固选项下的重定位规则差异极大,仅x86_64架构下就存在多种跳转相关的重定位类型,这些处理逻辑的分支判断完全依赖重定位表中的类型字段,不可能硬编码在代码段指令中。
  • 从代码段外部提取GOT地址的可靠性极低的判断也符合实际:.text段是只读可执行段,不同编译器版本、不同编译选项生成的PLT指令序列长度、编码方式都可能变化(比如支持Intel CET防护的PLT和传统PLT结构差异极大),依赖解析代码段指令获取重定位信息会直接导致兼容性崩溃,而独立存储的.rela.plt段遵循统一的ELF标准格式,和具体的指令生成逻辑解耦,稳定性和通用性更强。

最后补充一个容易混淆的认知:PLT指令中硬编码的GOT偏移是给CPU执行指令用的,.rela.plt存储的元数据是给动态链接器做重定位用的,二者服务的对象完全不同,不存在重复设计的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:27:18