68

我怎样才能知道objdump,如果一个目标文件是用 构建的-fPIC

4

6 回答 6

77

答案取决于平台。在大多数平台上,如果从

readelf --relocs foo.o | egrep '(GOT|PLT|JU?MP_SLOT)'

为空,则要么foo.o未使用 编译-fPIC,要么foo.o不包含任何-fPIC重要的代码。

于 2009-08-29T16:02:50.103 回答
16

我只需要在 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

于 2009-11-25T01:42:03.213 回答
3

我假设,您真正想知道的是共享库是否由使用 -fPIC 编译的目标文件组成。

如前所述,如果有 TEXTREL,则不使用 -fPIC。

有一个很棒的工具叫做 scanelf,它可以显示导致 .text 重定位的符号。

更多信息可以在HOWTO Locate and Fix .text Relocations TEXTRELs中找到。

于 2012-06-13T15:31:43.877 回答
2
readelf -a *.so | grep 标志
  标志:0x50001007,noreorder,pic,cpic,o32,mips32

这应该在大多数情况下都有效。

于 2014-12-11T10:51:36.910 回答
2

-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}
于 2015-06-19T15:43:19.383 回答
0

区分您的程序是否使用 -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 的预请求。

于 2010-06-26T08:32:03.723 回答