gccdynamic-linkingdynamic-libraryfpicposition-independent-code

Why dynamic libraries source code should be compiled with position-independent code?


I'm very confused about position-independent code and its usage for dynamic libraries.

I found this good example about -fPIC option of GCC: GCC -fPIC option and I figure out how it works.

However, I'm struggling to understand why dynamic libraries need code independent of specific address. When a dynamic library is loaded, why we cannot just save its absolute addresses (ex. the address of a function in the library) and use them? Why the usage of relative address becomes mandatory in this case?

A simple program int main() { return 0; } compiled with "gcc main.c" will be always position dependent?


Solution

  • -fPIC is by no means the only solution to shared library problem. Prior to ELF Linux used an a.out executable format. In a.out all shared libraries have used unique addresses in global address space so they were always loaded to same fixed address by all processes. This proved extremely hard to manage: all distro packages had to agree between each other which address range is reserved for which library and to constantly revise this agreement as libraries evolved over time.

    -fPIC got us out of this mess.

    With your suggestion, global dynamic reservation of address ranges across all processes, once some process mapped a library in some memory area, no other process would be able to reuse this area even if it never actually loads the library. For 32-bit systems with 4G of address space (or even 2G is upper 2G are reserved for the kernel) that might quickly exhaust the VM. Another problem comes from the fact that size of main executable file is different across processes so there is no global start address from which libraries can be safely loaded.