67
votes

6 Answers

76
votes

The answer depends on the platform. On most platforms, if output from

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

is empty, then either foo.o was not compiled with -fPIC, or foo.o doesn't contain any code where -fPIC matters.

16
votes

I just had to do this on a PowerPC target to find which shared object (.so) was being built without -fPIC. What I did was run readelf -d libMyLib1.so and look for TEXTREL. If you see TEXTREL, one or more source files that make up your .so were not built with -fPIC. You can substitute readelf with elfdump if necessary.

E.g.,

[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]$

And to help people searching for solutions, the error I was getting when I ran my executable was this:

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

I don't know whether this info applies to all architectures.

Source: blogs.oracle.com/rie

3
votes

I assume, what you really want to know is whether or not a shared library is composed from object files compiled with -fPIC.

As already mentioned, if there are TEXTRELs, then -fPIC was not used.

There is a great tool called scanelf which can show you the symbols that caused .text relocations.

More information can be found at HOWTO Locate and Fix .text Relocations TEXTRELs.

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

This should work most of the time.

2
votes

-fPIC means that code will be able to execute in addresses different form the address that was compile for.

To do it , disasambler will look like this....

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

now in ax we have an offset that we need to add to any access to memory.

load bx, [ax + var_address}
0
votes

Another option to distinguish whether your program is generated wit -fPIC option:

provided that your code has -g3 -gdwarf-2 option enabled when compiling.

other gcc debug format may also contains the macro info:

Note the following $'..' syntax is assumes 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__

such a method works because gcc manual declares that if -fpic is used, PIC is defined to 1, and if -fPIC used, PIC is 2.

The above answers by checking the GOT is the better way. Because the prerequest of -g3 -gdwarf-2 I guess seldom being used.