2009-08-27 108 views

回答

48

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

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

是空的,那么无论foo.o没有与-fPIC编译或foo.o并不其中-fPIC事项包含任何代码。

+1

我测试了我的PIC /非PIC对象而这个测试不起作用。事实上--reloc没有列出任何东西。 – teambob

+0

这个测试为我在PPC架构上工作。 –

+1

@teambob对不起,'objdump'不理解'--relocs'标志,'readelf'。 –

8

我只需要在PowerPC目标上执行此操作来查找哪个共享对象(.so)正在构建而没有-fPIC。我所做的是运行readelf -d libMyLib1.so并寻找TEXTREL。如果您看到TEXTREL,构成您的.so的一个或多个源文件不是用-fPIC构建的。如有必要,您可以用readelf替换为elfdump

例如,

[[email protected] lib]$ readelf -d libMyLib1.so | grep TEXT # Bad, not -fPIC 
0x00000016 (TEXTREL) 
[[email protected] lib]$ readelf -d libMyLib2.so | grep TEXT # Good, -fPIC 
[[email protected] lib]$ 

,帮助人们寻找解决方案,当我跑我的可执行文件是这样的,我得到的错误:

[email protected]:/# ./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

0

另一种选择来区分你的程序是否生成带有-fPIC选项:

前提是你的代码有编译时启用-g3 -gdwarf-2选项。

其他海湾合作委员会调试格式也可能包含宏信息:

注意以下$“..”语法是假设的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的预先请求我很少被使用。

2

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

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

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

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

1
 
readelf -a *.so | grep Flags 
    Flags:        0x50001007, noreorder, pic, cpic, o32, mips32 

这应该在大多数情况下工作。

+1

这看起来很简单,但我前面的库是可重定位的,它的.rel.plt表中有大量的R_386_JUMP_SLOT条目,但标志为0x0。也许它只适用于mips32。 – James

1

-fPIC意味着代码将能够以不同于编译地址的地址执行。

要做到这一点,disasambler看起来像这样....

call get_offset_from_compilation_address 
get_offset_from_compilation_address: pop ax 
sub ax, ax , &get_offset_from_compilation_address 

现在斧头我们已经偏移,我们需要增加内存的任何访问。

load bx, [ax + var_address} 
相关问题