CppCon: Linkers, Loaders and Shared Libraries
Tldr; See recommendations at end.
Talk: https://youtu.be/_enXuIxuNV4
Covered topics:
- 101 of linkers+loaders
- Detailed comparison of linking on Linux/Windows (not MacOS)
- Interposition (overriding a symbol in one binary from another)
- Library search order
- Position independent code (GOT)
- Lazy/Delayed Loading
- Symbol visibility
- Recommendations for shared libraries on linux
Interposition
Two binaries (e.g. object files, libraries) define the same symbol, then by default the first one will be taken. Linux specific / Not possible in Windows!
Library search order
Scenario: Executable (exe) loads shared libs lib1, lib2, which load lib3,..,5. The exe tries to load function foo
.
Search order is breadth-first, i.e. first looked in exe, then lib1, lib2, lib3, .., 5. LD_PRELOAD
Can be used to specify libraries to look into after exe, but before lib1.-Bsymbolic
Look at first in current lib (e.g. lib5 calls function foo
, then look at first in lib5).
Position Independent Code
Simple function calls in shared libraries will not be inlined (for default visibility). ...
Implemented via global offset table GOT.
Lazy Loading
Useful for huge number of symbols. On linux enabled by default, windows needs specific flags.
Workings: The function call to a shared library's function has an indirection which gets filled in by the loaded on first call. After that the shared library's function address is plugged in.
Implemented via procedural lookup table PLT.
Symbol Visibility
Question: Which symbols should get exported?
On Windows: Only those which are marked __declspec(dllexport)
.
On Linux: By default all.
Linux visibilities -fvisibility=<default/protected/hidden>
:
default
: all symbols exportedprotected
: symbols visible, but not subjected to interpositionhidden
: not exported- per symbol:
__attribute__ ((visibility ("hidden")))
Recommendation for linux shared libraries:
Opt out of interposition via building with: -fvisibility=hidden, -Bsymbolic
s
Mark symbols to be exported via: __attribute__ ((visibility ("protected")))