82

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

1

7 Answers 7

87

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.

Sign up to request clarification or add additional context in comments.

13 Comments

I tested my PIC/no-PIC objects and this test didn't work. In fact --reloc listed nothing.
@teambob Sorry, objdump doesn't understand --relocs flag, readelf does.
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 The test doesn't work for shared libraries, true. But the question was about object files, not shared libraries.
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?
|
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

Comments

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.

Comments

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} 

Comments

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

This should work most of the time.

2 Comments

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.
Unfortunately this doesn't seem to work on aarch64
1

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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.