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

i386与x86-64平台多ELF重定位行为差异原因探究

同一地址ELF重定位行为差异的原因分析

先看测试代码和实际现象:

汇编代码

#ifdef __x86_64__
#define R(N) R_X86_64_##N
#else
#define R(N) R_386_##N
#endif

     .globl foo
foo: .int 0
     .reloc foo, R(32), bar
     .reloc foo, R(32), baz

C代码

#include <stdio.h>

__asm__(
    ".globl bar\n\t"
    "bar = 0x42\n\t"
    ".globl baz\n\t"
    "baz = 0x57"
);

extern unsigned foo;
int main(void) {
    printf("%X\n", foo);
    return 0;
}

测试结果:

  • 32位x86环境下用GCC编译链接,输出99(0x42+0x57),两个重定位累加生效;
  • x86-64环境下编译链接,输出57,仅最后一个重定位生效。

原因解析

这本质是不同架构ELF重定位类型的语义设计差异:

  • 32位x86的R_386_32重定位类型,链接器实现严格遵循System V gABI的“连续重定位组合生效”规则,每个重定位都会把符号值累加到目标地址的当前值上。foo初始为0,先加bar的0x42,再加baz的0x57,最终得到0x99。
  • x86-64的R_X86_64_32重定位类型,其设计语义是生成单个32位绝对地址绑定,链接器默认认为同一地址的多个该类型重定位是冗余输入,因此采用覆盖式处理——只保留最后一次重定位的结果,直接用baz的0x57覆盖foo的初始值,所以输出57。

虽然AMD64 psABI没有明确提及这个行为,但GCC、Clang搭配ld、gold等主流链接器都统一遵循这个实现逻辑,属于架构特定重定位类型的隐含处理规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 07:07:31