我怎样才能知道objdump
,如果一个目标文件是用 构建的-fPIC
?
6 回答
答案取决于平台。在大多数平台上,如果从
readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'
为空,则要么foo.o
未使用 编译-fPIC
,要么foo.o
不包含任何-fPIC
重要的代码。
我只需要在 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
我假设,您真正想知道的是共享库是否由使用 -fPIC 编译的目标文件组成。
如前所述,如果有 TEXTREL,则不使用 -fPIC。
有一个很棒的工具叫做 scanelf,它可以显示导致 .text 重定位的符号。
readelf -a *.so | grep 标志 标志:0x50001007,noreorder,pic,cpic,o32,mips32
这应该在大多数情况下都有效。
-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}
区分您的程序是否使用 -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 的预请求。