99

When compiling shared libraries in gcc the -fPIC option compiles the code as position independent. Is there any reason (performance or otherwise) why you would not compile all code position independent?

ojblass
  • 21,146
  • 22
  • 83
  • 132
  • 2
    But wowest is not entirely correct. Many function calls and jumps use relative jumps so they don't even need a jump table after being moved around. – Unknown May 02 '09 at 02:47
  • looking at the generated assembly code it appears that the address of the function is loaded wheras non fpic code it appears it is simply a jump. Am I misunderstanding your statement? – ojblass May 02 '09 at 05:21
  • @ojblass what I mean is that some jumps are like "jump 50 instructions ahead of here" or "jump 5 instructions backwards" instead of "jump to 0x400000". So to say that you have to load an address every time with -fPIC isn't entirely true. – Unknown May 02 '09 at 05:47
  • The Wikipedia [article](http://en.wikipedia.org/wiki/Position-independent_code) provides a good description. Basically, on some architectures there is no direct way to jump to a relative address. Hence, PIC is more expensive to use on those arhcs. See @EvanTeran's answer for more info. – Alexei Sholik Aug 25 '13 at 15:05

7 Answers7

73

It adds an indirection. With position independent code you have to load the address of your function and then jump to it. Normally the address of the function is already present in the instruction stream.

wowest
  • 1,974
  • 14
  • 21
29

Yes there are performance reasons. Some accesses are effectively under another layer of indirection to get the absolute position in memory.

There is also the GOT (Global offset table) which stores offsets of global variables. To me, this just looks like an IAT fixup table, which is classified as position dependent by wikipedia and a few other sources.

http://en.wikipedia.org/wiki/Position_independent_code

Unknown
  • 45,913
  • 27
  • 138
  • 182
29

In addition to the accepted answer. One thing that hurts PIC code performance a lot is the lack of "IP relative addressing" on x86. With "IP relative addressing" you could ask for data that is X bytes from the current instruction pointer. This would make PIC code a lot simpler.

Jumps and calls, are usually EIP relative, so those don't really pose a problem. However, accessing data will require a little extra trickery. Sometimes, a register will be temporarily reserved as a "base pointer" to data that the code requires. For example, a common technique is to abuse the way calls work on x86:

call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp            ; now ebp holds the address of the first dataword
                   ; this works because the call pushes the **next**
                   ; instructions address
                   ; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way

This and other techniques add a layer of indirection to the data accesses. For example, the GOT (Global offset table) used by gcc compilers.

x86-64 added a "RIP relative" mode which makes things a lot simpler.

Evan Teran
  • 87,561
  • 32
  • 179
  • 238
  • 1
    IIRC MIPS doesn't have PC-relative addressing too, except for relative jumps – phuclv Aug 08 '14 at 08:17
  • 1
    This is a common technique used in shellcode to get the address it is executing from. I've used this in a few CTF solutions. – sherrellbc Mar 24 '18 at 00:53
4

Because implementing completely position independent code adds a constraint to the code generator which can prevent the use of faster operations, or add extra steps to preserve that constraint.

This might be an acceptable trade-off to get multiprocessing without a virtual memory system, where you trust processes to not invade each other's memory and might need to load a particular application at any base address.

In many modern systems the performance trade-offs are different, and a relocating loader is often less expensive (it costs any time code is first loaded) than the best an optimizer can do if it has free reign. Also, the availability of virtual address spaces hides most of the motivation for position independence in the first place.

RBerteig
  • 41,948
  • 7
  • 88
  • 128
2

position-independent code has a performance overhead on most architecture, because it requires an extra register.

So, this is for performance purpose.

Eric
  • 22,183
  • 20
  • 145
  • 196
1

Also, virtual memory hardware in most modern processors (used by most modern OSes) means that lots of code (all user space apps, barring quirky use of mmap or the like) doesn't need to be position independent. Every program gets its own address space which it thinks starts at zero.

smcameron
  • 2,547
  • 1
  • 19
  • 12
  • 4
    But even with a VM-MMU PIC code is needed to ensure that the same .so library is loaded only once into memory when it is used by different executables. – mmmmmmmm May 27 '09 at 18:26
0

Nowadays operating system and compiler by default make all the code as position independent code. Try compiling without the -fPIC flag, the code will compile fine but you will just get a warning.OS's like windows use a technique called as memory mapping to achieve this.

Govardhan Murali
  • 91
  • 1
  • 1
  • 8