68

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

ks1322
  • 31,484
  • 13
  • 100
  • 154
Crazy Chenz
  • 11,695
  • 12
  • 46
  • 58

6 Answers6

77

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.

Employed Russian
  • 182,696
  • 29
  • 267
  • 329
  • 2
    I 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
  • 1
    Now 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
  • 2
    This 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
  • 2
    Do 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
16

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

alanc
  • 3,999
  • 20
  • 24
indiv
  • 16,628
  • 6
  • 58
  • 82
3

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.

James
  • 889
  • 2
  • 12
  • 19
Vanuan
  • 29,202
  • 9
  • 94
  • 99
2
readelf -a *.so | grep Flags
  Flags:                             0x50001007, noreorder, pic, cpic, o32, mips32

This should work most of the time.

Ternvein
  • 301
  • 1
  • 6
  • 2
    This 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
2

-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}
jww
  • 90,984
  • 81
  • 374
  • 818
CodeWizard
  • 21
  • 1
0

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.

zhaorufei
  • 1,917
  • 18
  • 18