为何GCC-7.5.0编译同一代码生成不同重定位条目类型?
ELF重定位类型差异的原因分析
核心结论
决定R_X86_64_PC32与R_X86_64_PLT32重定位类型差异的核心因素是GCC的编译配置与默认选项,内核版本对此没有直接影响。
关键差异点解析
1. GCC默认PIE配置差异
学校容器中的GCC编译时启用了--enable-default-pie配置,这会让GCC默认添加-fpie选项,生成位置无关目标文件(PIE)。在PIE模式下,编译器对同一编译单元内的函数调用会生成直接的PC相对地址重定位,对应R_X86_64_PC32类型,无需经过PLT(过程链接表)。
而你自定义编译的GCC未启用--enable-default-pie,默认生成位置相关代码,此时编译器默认生成通过PLT的函数调用,对应R_X86_64_PLT32类型。
2. Binutils版本的次要影响
学校容器使用GNU汇编器2.30,另一台服务器使用2.38。新版本Binutils在重定位处理逻辑上可能存在细微差异,但这是次要因素,核心仍由GCC的默认配置决定。
验证方法
- 在自定义GCC的机器上,添加
-fpie选项编译,重定位类型会变为R_X86_64_PC32:gcc -v -c -fpie -o main.o main.c - 在学校容器中,添加
-fno-pie -fplt选项编译,重定位类型会变为R_X86_64_PLT32:gcc -v -c -fno-pie -fplt -o main.o main.c
总结
两种重定位类型的差异本质是GCC的PIE默认配置导致的代码生成策略不同:
- PIE模式下,优先使用直接PC相对重定位,避免PLT的额外开销;
- 非PIE模式下,默认生成PLT调用(即使是同一编译单元内的函数)。
内容的提问来源于stack exchange,提问作者季子墨
相关产品推荐
相关产品推荐

