当前位置: 代码迷 >> 综合 >> gcc编译选项-fPIC
  详细解决方案

gcc编译选项-fPIC

热度:56   发布时间:2023-12-08 16:03:35.0

-fPIC选项指定编译器应该生成位置独立的代码,这会改变编译器生成执行特定操作的代码的方式,包括访问全局、静态和外部变量,访问字符串常量,以及获取函数的地址。这些变更使得代码可以在运行时被放置在任意一个虚拟地址处。这一点对于共享库来讲是必需的,因为在链接的时候是无法知道共享库代码位于内存的何处的。(一个共享库在运行时所处的内存位置依赖于很多因素,如加载这个库的程序已经占用的内存数量和这个程序已经加载的其他共享库。)

在Linux/x86-32上,可以使用不加-fPIC选项编译的模块来创建共享库。但这样做的话会丢失共享库的一些优点,因为包含依赖于位置的内存引用的程序文本页面不会在进程间共享。在一些架构上是无法在不加-fPIC选项的情况下构建共享库的。

为了确定一个既有目标文件在编译时是否使用了-fPIC选项,可以使用下面两个命令中的一个来检查目标文件符号表中是否存在名称_GLOBAL_OFFSET_TABLE_。

$nm mod1.o | grep _GLOBAL_OFFSET_TABLE_

$readelf -s mod1.o | grep _GLOBAL_OFFSET_TABLE_

相应的,如果下面两个相互等价的命令中的任意一个产生了任何输出,那么指定的共享库中至少存在一个目标模块在编译时没有指定-fPIC选项

$objdump --all-headers libfoo.so | grep TEXTREL

$readelf -d libmyzk_api.so | grep TEXTREL

字符串TEXTREL表示存在一个目标模块,其文本段中包含需要运行时重定位的引用。