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

7

77

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

Collin answered 27/8, 2009 at 11:15 Comment(1)
related unix.stackexchange.com/questions/89211/…Quick
G
84

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.

Gewirtz answered 29/8, 2009 at 16:2 Comment(10)
I tested my PIC/no-PIC objects and this test didn't work. In fact --reloc listed nothing.Peppers
@Peppers Sorry, objdump doesn't understand --relocs flag, readelf does.Gewirtz
Now that you have edited it, it works and is a nice easy test. I am voting it up for you.Peppers
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.Counsel
@Counsel The test doesn't work for shared libraries, true. But the question was about object files, not shared libraries.Gewirtz
@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?".Counsel
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 -fPICCounsel
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?Ionogen
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.Childress
Is there a way to figure out if an object was not compiled with -fPIC or it doesn't contain any code where -fPIC matters?Choosey
T
18

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

Tailgate answered 25/11, 2009 at 1:42 Comment(0)
C
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.

Counsel answered 13/6, 2012 at 15:31 Comment(0)
S
2
readelf -a *.so | grep Flags
  Flags:                             0x50001007, noreorder, pic, cpic, o32, mips32

This should work most of the time.

Shive answered 11/12, 2014 at 10:51 Comment(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.Tolerance
Unfortunately this doesn't seem to work on aarch64Samala
S
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}
Superscribe answered 19/6, 2015 at 15:43 Comment(0)
D
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.

Daradarach answered 26/6, 2010 at 8:32 Comment(0)
M
0

From The Linux Programming Interface:

On Linux/x86-32, it is possible to create a shared library using modules compiled without the –fPIC option. However, doing so loses some of the benefits of shared libraries, since pages of program text containing position-dependent memory references are not shared across processes. On some architectures, it is impossible to build shared libraries without the –fPIC option.

In order to determine whether an existing object file has been compiled with the –fPIC option, we can check for the presence of the name _GLOBAL_OFFSET_TABLE_ in the object file’s symbol table, using either of the following commands:

$ nm mod1.o | grep _GLOBAL_OFFSET_TABLE_
$ readelf -s mod1.o | grep _GLOBAL_OFFSET_TABLE_

Conversely, if either of the following equivalent commands yields any output, then the specified shared library includes at least one object module that was not compiled with –fPIC:

$ objdump --all-headers libfoo.so | grep TEXTREL
$ readelf -d libfoo.so | grep TEXTREL

However, neither above quoting nor any answer of this question works for x86_64.

What I've observed on my x86_64 Ubuntu machine is that, whether specifying -fPIC or not, it would generate fPIC .o. That is

gcc -g -Wall -c -o my_so.o my_so.c // has _GLOBAL_OFFSET_TABLE_
gcc -g -Wall -fPIC -c -o my_so_fpic.o my_so.c // has _GLOBAL_OFFSET_TABLE_

readelf -s my_so.o > 1.txt && readelf -s my_so_fpic > 2.txt && diff 1.txt 2.txt

has no difference and both my_so.o and my_so_fpic.o can be used to create a shared library.

In order to generate non fpic object file, I found a gcc flag called -fno-pic in the first comment of How to test whether a Linux binary was compiled as position independent code? .

This works,

gcc -g —Wall -fno-pic -c -o my_so_fnopic.o my_so.c // no _GLOBAL_OFFSET_TABLE_ 

and

gcc -g -Wall -shared -o libdemo.so my_so_fnopic.o 

gives error:

/usr/bin/ld: my_so_fnopic.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
collect2: error: ld returned 1 exit status

can not create a shared library with non pic .o.

Magritte answered 16/6, 2022 at 15:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.