Ubuntu GCC默认隐含-fPIC,openSUSE则否:是配置还是二进制差异?
GCC默认-fPIC参数的发行版差异问题
实验环境
- Ubuntu 18.04,gcc 7.5.0,binutils 2.30(2019-05-08)
- openSUSE Leap 15.5,gcc 7.5.0,binutils 2.39(2022-10-25)
问题复现
编译基于foo1.c的共享库时出现跨发行版差异:foo1.c代码如下:
#include <stdio.h> extern void FooX(int); void Foo1(int i) { printf("foo1(%d)\n", i); i++; FooX(i); }
在openSUSE上执行编译命令:
gcc -g -c foo1.c gcc -shared foo1.o -o libfoo1.so
第二条链接命令报错:
ld: foo1.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
添加-fPIC参数重新编译后链接成功,但Ubuntu 18.04无需显式指定该参数就能正常构建共享库。
差异验证
对比目标文件后确认:
- openSUSE环境下,有无
-fPIC参数编译出的foo1.o机器码存在明显差异; - Ubuntu环境下,有无
-fPIC参数编译出的foo1.o完全一致,且与openSUSE带-fPIC编译的结果相同,说明Ubuntu的GCC默认隐含了-fPIC参数。
问题解答
这种差异不是GCC二进制的内置特性,而是由发行版的GCC配置文件控制的。
具体控制文件是/usr/lib/gcc/<目标架构>/<gcc版本>/specs——Ubuntu在打包GCC时,针对x86_64架构默认添加了-fPIC编译参数;而openSUSE的默认配置中未包含该参数,因此需要用户显式指定才能编译共享库。
内容的提问来源于stack exchange,提问作者Jimm Chen
相关产品推荐
相关产品推荐

