我如何使用 objdump 之类的东西来判断是不是使用 -fPIC 构建了目标文件?
Posted
技术标签:
【中文标题】我如何使用 objdump 之类的东西来判断是不是使用 -fPIC 构建了目标文件?【英文标题】:How can I tell, with something like objdump, if an object file has been built with -fPIC?我如何使用 objdump 之类的东西来判断是否使用 -fPIC 构建了目标文件? 【发布时间】:2010-11-23 08:20:58 【问题描述】:我怎样才能通过objdump
之类的内容来判断是否使用-fPIC
构建了目标文件?
【问题讨论】:
相关unix.stackexchange.com/questions/89211/… 【参考方案1】:答案取决于平台。在大多数平台上,如果输出来自
readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'
为空,则要么foo.o
没有使用-fPIC
编译,要么foo.o
不包含任何-fPIC
重要的代码。
【讨论】:
我测试了我的 PIC/no-PIC 对象,但这个测试不起作用。事实上 --reloc 什么也没列出。 @teambob 抱歉,objdump
不理解 --relocs
标志,readelf
可以。
这不是一个很有帮助的测试。如果它不为空,这并不能证明任何事情。考虑一个由 2 个目标文件组成的共享库。一个目标文件用-fPIC 编译,另一个不用-fPIC 编译。输出不会为空,但库与位置无关。
@Vanuan 该测试不适用于共享库,是的。但问题是关于目标文件,而不是共享库。
您介意解释一下为什么这个测试有意义,或者它背后的原因是什么?一个 grepping 是为了什么?为什么没有 -fPIC 就找不到这些东西?【参考方案2】:
我只需要在 PowerPC 目标上执行此操作即可找到在没有 -fPIC 的情况下正在构建的共享对象 (.so)。我所做的是运行 readelf -d libMyLib1.so 并寻找 TEXTREL。如果您看到 TEXTREL,则构成您的 .so 的一个或多个源文件不是使用 -fPIC 构建的。如有必要,您可以将 readelf 替换为 elfdump。
例如,
[user@host lib]$ readelf -d libMyLib1.so | grep TEXT # Bad, not -fPIC
0x00000016 (TEXTREL)
[user@host lib]$ readelf -d libMyLib2.so | grep TEXT # Good, -fPIC
[user@host lib]$
为了帮助人们寻找解决方案,我在运行可执行文件时遇到的错误是:
root@target:/# ./program: error while loading shared libraries: /usr/lib/libMyLi
b1.so: R_PPC_REL24 relocation at 0x0fc5987c for symbol 'memcpy' out of range
我不知道此信息是否适用于所有架构。
来源:blogs.oracle.com/rie
【讨论】:
【参考方案3】:我假设,您真正想知道的是共享库是否由使用 -fPIC 编译的目标文件组成。
如前所述,如果有 TEXTREL,则不使用 -fPIC。
有一个很棒的工具叫做 scanelf,它可以显示导致 .text 重定位的符号。
更多信息请访问HOWTO Locate and Fix .text Relocations TEXTRELs。
【讨论】:
【参考方案4】: readelf -a *.so | grep 标志 标志:0x50001007,noreorder,pic,cpic,o32,mips32这应该在大部分时间都有效。
【讨论】:
这看起来很简单,但是我面前的库是可重定位的,它的 .rel.plt 表中有很多 R_386_JUMP_SLOT 条目,但标志为 0x0。也许它只适用于 mips32。【参考方案5】:-fPIC 意味着代码将能够在与编译地址不同的地址中执行。
要做到这一点,disasambler 看起来像这样......
call get_offset_from_compilation_address
get_offset_from_compilation_address: pop ax
sub ax, ax , &get_offset_from_compilation_address
现在在 ax 中,我们有一个偏移量,我们需要添加到任何对内存的访问中。
load bx, [ax + var_address
【讨论】:
【参考方案6】:另一个区分你的程序是否是用 -fPIC 选项生成的选项:
前提是您的代码在编译时启用了 -g3 -gdwarf-2 选项。
其他 gcc 调试格式也可能包含宏信息:
注意下面的 $'..' 语法是假定 bash
echo $' main() printf("%d\\n", \n#ifdef __PIC__\n__PIC__\n#else\n0\n#endif\n); ' | gcc -fPIC -g3
-gdwarf-2 -o test -x c -
readelf --debug-dump=macro ./test | grep __PIC__
这样的方法是有效的,因为 gcc 手册声明如果使用 -fpic,PIC 被定义为 1,并且 如果使用 -fPIC,PIC 为 2。
以上通过检查GOT的答案是更好的方法。因为 -g3 -gdwarf-2 的 prerequest 我猜很少被使用。
【讨论】:
以上是关于我如何使用 objdump 之类的东西来判断是不是使用 -fPIC 构建了目标文件?的主要内容,如果未能解决你的问题,请参考以下文章
如果没有文件、objdump 或 gdb,如何知道二进制文件是不是包含调试符号?
让 objdump 在每个助记符上使用像 l 这样的操作数大小的后缀,即使它不是模棱两可的?