1

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?

peppone
  • 85
  • 6
  • 1
    So that they can be mapped into different base addresses in different processes, so that the calling programs can be different. NB Dynamic libraries have data as well as functions, and that data has to go somewhere that doesn't conflict with the calling program's address space. – user207421 Jun 14 '21 at 00:59
  • I still don't get it. Why is it not possible, to save the global address of the dynamic library and use it in different processes? If it is an address used by different processes, instead of updating all addressing offsets, wouldn't it be easier to refer to the dynamic library with one and unique global address? – peppone Jun 14 '21 at 09:13
  • Perhaps this is not possible due to the virtual addresses are (often) the same between processes? – peppone Jun 14 '21 at 14:22
  • Because it doesn't have a global address. It gets a new address every time it is loaded into a process. Otherwise you would have to allocate each dynamic library its own permanent address and you would run out of address space in about two minutes. – user207421 Jun 17 '21 at 05:17

1 Answers1

3

-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.

yugr
  • 19,769
  • 3
  • 51
  • 96