0

I've read this article about Position Independent Code, and this is what I got (focusing on function calls): When a shared library is built and linked, it is unknown to what memory address it will be loaded, and that's why we use Position Independent Code (PIC).

One of the mechanisms in PIC is the use of PLT (Procedure Linkage Table) for calling functions in a way that our code remains position independent, and it works basically like this: For each function we call (func) in our library, there's a func@plt small procedure, which is the one actually being called. This procedure then jumps to an address stored in a corresponding entry in the GOT. First, this address will point back to the PLT entry which will then call the dynamic linker resolver to resolve the actual function's address. The dynamic linker will now override the entry in the GOT to point to the correct actual function.

Now, all this is possible since when linking the shared library, the distance between the instruction that calls func and the func@plt is known, and also the distance to the entry in the GOT. All relative and great !

My question is: I can understand why wanting to have this mechanism for function calls in the file linking against the shared library: this is in order to only resolve function addresses when they are requested. But I don't understand why is this needed within the shared library itself!

Imagine we have a function func in the shared library, calling func2. The distance between func and func2 is known at the stage of static linking, so we can compute the position of func2 relatively to the instruction pointer, just as we do to find the func2@plt.

YoavKlein
  • 2,005
  • 9
  • 38

1 Answers1

1

PLT is indeed much less efficient than simple PIC call.

In shared library PLT is only needed for external (imported) functions or for internal functions that have default visibility. Such functions can be interposed at runtime by functions with same names from different shlibs and interposition is handled through PLT/GOT.

Unfortunately by default on Linux systems all functions have default visibility but user can change this with -fvisibility=hidden compiler flag or linker version scripts (see e.g. this question for details).

yugr
  • 19,769
  • 3
  • 51
  • 96