How can I tell, with something like objdump, if an object file has been built with -fPIC?
- 31,484
- 13
- 100
- 154
- 11,695
- 12
- 46
- 58
-
related https://unix.stackexchange.com/questions/89211/test-whether-linux-binary-is-compiled-as-position-independent-code – Ciro Santilli Путлер Капут 六四事 Oct 26 '17 at 05:37
6 Answers
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.
- 182,696
- 29
- 267
- 329
-
2I tested my PIC/no-PIC objects and this test didn't work. In fact --reloc listed nothing. – teambob Aug 30 '09 at 02:57
-
1@teambob Sorry, `objdump` doesn't understand `--relocs` flag, `readelf` does. – Employed Russian Apr 05 '12 at 20:58
-
1Now that you have edited it, it works and is a nice easy test. I am voting it up for you. – teambob Apr 09 '12 at 23:13
-
2This is not a very helpful test. This doesn't prove anything if it is not empty. Consider a shared library consisting of 2 object files. One object file is compiled with -fPIC, another is compiled without. The output won't be empty, but the library is not position independent. – Vanuan Jun 11 '12 at 16:42
-
2@Vanuan The test doesn't work for shared libraries, true. But the question was about object files, not shared libraries. – Employed Russian Jun 11 '12 at 20:20
-
@Employed Russian I that case the question is pointless. PIC is very common (if not a must) for shared libraries. Again, if there is no output, this doesn't mean that the file is compiled without -fPIC. You would want to know if something is compiled without -fPIC to fix it. I think, the question meaning is "How to be sure that a shared library is position independent?". – Vanuan Jun 11 '12 at 21:07
-
I can't even get a shared library from object files compiled without -fPIC. ld produces an error : relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC – Vanuan Jun 13 '12 at 15:18
-
2Do you mind explaining why this test makes sense, or what the reasoning behind it is? What is one grepping for? Why won't those things be found in something without -fPIC? – ffledgling Mar 02 '16 at 11:18
-
Doesn't even work for object files. Consider compiling with `-m32` still produces the same output here as compiling with `fPIC`. This isn't sufficient. – Kevin Rak Jun 26 '20 at 21:34
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
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.
readelf -a *.so | grep Flags Flags: 0x50001007, noreorder, pic, cpic, o32, mips32
This should work most of the time.
- 301
- 1
- 6
-
2This looks so simple, but the library in front of me is relocatable, has plenty of R_386_JUMP_SLOT entries in its .rel.plt table, but has 0x0 for Flags. Perhaps it only works on mips32. – James Mar 20 '17 at 23:26
-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}
- 90,984
- 81
- 374
- 818
- 21
- 1
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.
- 1,917
- 18
- 18