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

Clang中x86-64平台PLT32的含义及动态链接相关疑问

x86-64平台R_X86_64_PLT32重定位解析

问题背景

测试代码

#include <stdio.h>

__attribute__((noinline)) 
int add(int a, int b)
{
        return a + b;
}

int add_external_def(int a, int b);

int main() 
{
        printf("5 + 5 = %d\n", add(5, 5));
        printf("5 + 5 = %d\n", add_external_def(5, 5));
        return 0;
}

编译结果对比

使用Clang 17.0.1针对x86-64平台以-O3编译为可执行文件时,生成的函数调用汇编片段如下:

call add
call printf@PLT
call add_external_def@PLT

当仅编译为二进制目标文件(.o)时,这些调用的汇编形式变为:

call   20 <main+0x10>
    R_X86_64_PLT32 add-0x4
call   33 <main+0x23>
    R_X86_64_PLT32 printf-0x4
call   42 <main+0x32>
    R_X86_64_PLT32 add_external_def-0x4

用户疑问

  • R_X86_64_PLT32 ...-0x4部分的含义是什么?
  • “该函数是否通过PLT解析”的信息去哪里了?

解答

1. R_X86_64_PLT32 ...-0x4的含义

  • **R_X86_64_PLT32**是x86-64平台的一种重定位类型,作用是告知链接器:在最终链接阶段,要将当前call指令的目标地址修正为对应函数的PLT(过程链接表)项地址,用于实现动态链接的延迟绑定。
  • ...-0x4是指令地址计算的必然要求:x86-64的call指令使用32位相对偏移,偏移值是从当前call指令的下一条指令开始计算的。而call指令本身长度为4字节,所以重定位时需要用目标PLT项地址减去当前call指令地址,再减去4,才能得到正确的偏移量。汇编中的add-0x4是这个计算逻辑的简化表示,链接器会自动完成最终的偏移计算。

2. “是否通过PLT解析”的信息位置

在目标文件(.o)阶段,R_X86_64_PLT32这个重定位类型本身就是“该调用将通过PLT解析”的明确标记。

你在可执行文件中看到的不同调用形式,是链接完成后的最终优化结果:

  • 对于add这种内部定义且未导出的函数,链接器可以直接将调用地址指向函数实际入口,无需经过PLT;
  • 对于printf这种动态库提供的函数,链接器必须保留PLT调用以实现动态绑定;
  • 对于add_external_def这种外部未定义函数,若最终链接时它被解析为动态库函数,则保留PLT调用;若被解析为同一可执行文件内的函数,链接器会自动优化掉PLT,改为直接调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:43:27