views:

669

answers:

4

How can I tell, with something like objdump, if an object file has been built with -fPIC?

Thanks, -Crazy Chenz

A: 

Updated: please see comments for clarified information.

The --reloc and --dynamic-reloc options should list the relocation information. If it is not empty it has been compiled with -fPIC

teambob
Actually, they both have stuff... the only difference I can see is that sometimes in the .rodata section (with -fPIC) there is a _GLOBAL_OFFSET_TABLE_ symbol and other times there is not, so this isn't such a clear cut answer yet.
Crazy Chenz
Sorry it has been a few months since I dealt with fPIC. When you create a relocatable object there needs to be a list of fix-up locations for function calls and variables. This is true for both static libraries and dynamic libraries.In ELF format the GLOBAL_OFFSET_TABLE (GOT) is rewritten on link to point to the variables. There is a PLT header as well which is used to point to the functions - but since Intel processors have a relative jump instruction there is no need to rewrite this table.I found some information which may be more helpful: http://people.redhat.com/drepper/dsohowto.pdf
teambob
relocatable objects (foo.o) never contain any dynamic relocations, and most do contain "normal" relocations. So your answer is just plain wrong. Instead of clarifying what you meant in comments, you should probably edit it so it is at least not incorrect. Or vote for my correct answer instead :-)
Employed Russian
A: 

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

objdump --reloc 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.

Employed Russian
I tested my PIC/no-PIC objects and this test didn't work. In fact --reloc listed nothing.
teambob
A: 

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.sun.com/rie

indiv
A: 

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.

赵如飞