WeHack BBS
判断一个目标文件是否用-fPIC编译 - 可打印的版本

+- WeHack BBS (https://bbs.wehack.space)
+-- 版块: 计算机技术 (https://bbs.wehack.space/forum-5.html)
+--- 版块: 程序设计讨论区 (https://bbs.wehack.space/forum-14.html)
+--- 主题: 判断一个目标文件是否用-fPIC编译 (/thread-362.html)



判断一个目标文件是否用-fPIC编译 - vimacs - 04-07-2023

构建动态库所用的目标文件都必须是位置无关的,因此编译动态库的源文件的时候都会加-fPIC. 如果构建这个动态库需要通过链接外部的静态库,而外部的静态库不是用-fPIC编译的,那么就会链接失败。为了调试这类问题,需要知道怎么判断一个静态库,更具体的是静态库内的目标文件,是不是用-fPIC构建的。

在Bing问了一下,找到一个stackoverflow[1]链接,里面说可以用 readelf --relocs 查看,它的方法是找 PLT, GOT, JUMP_SLOT 这些字符串。然而不用 -fPIC 构建的静态库也会有 R_X86_64_PLT32 这样的重定位,似乎这方法不太行。另外可以用 nm 找 _GLOBAL_OFFSET_TABLE_, 似乎也有同样的问题。

之后我点进这个问题的一个相关问题[2],然后想明白是怎么回事了。这个方法也是用 readelf --relocs, 但是它找某些不符合位置无关这个性质的重定位,即 R_X86_64_32 等。

代码:
readelf --relocs /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.a |\
      awk '$3~/^R_/ && $5!~/^\.debug/{print $3}' |sort -u

找到了 R_X86_64_32 或者 R_X86_64_32S 就表明不是用 -fPIC 构建了。同时我也明白链接时报的错误信息是什么意思了,其实就是说遇到了不满足位置无关的重定位。

(后来我查到了为什么我构建某个动态库链接失败,原因是构建一个外部静态库的时候虽然加了-fPIC,但后来又被覆盖了。)

[1] https://stackoverflow.com/questions/1340402/how-can-i-tell-with-something-like-objdump-if-an-object-file-has-been-built-wi
[2] https://unix.stackexchange.com/questions/89211/how-to-test-whether-a-linux-binary-was-compiled-as-position-independent-code