Linkers, Loaders and Shared Libraries in Windows, Linux, and C++ - Ofek Shilon - CppCon 2023

Explore the intricacies of linkers, loaders, and shared libraries in Windows, Linux, and C++ with this talk, delving into symbol resolution, interposition, and more.

Key takeaways
  • The Linux binary loader uses separate techniques for resolving symbol addresses compared to Windows.
  • Lazy binding, which postpones symbol resolution until first use, is not the default behavior in Windows, but can be enabled with the delay load switch.
  • In Linux, a symbol can be overridden from another binary using interposition, but this is not supported by default.
  • The ELF (Executable and Linkable Format) linker assists shared libraries by resolving symbols and adjusting permissions.
  • Linkers, particularly in Linux, have specific design goals that affect performance and symbol resolution.
  • By default, most binaries are linked with f_visibility=hidden, making it easy to override symbols.
  • To use interposition, mark symbols as dll_export or dll_import to modify visibility.
  • On Windows, f_visibility=hidden is not the default, but can be achieved with specific linker switches.
  • shared libraries are outside the scope of C++, but impact its implementation.
  • In Linux, the linker resolves symbols at runtime and uses the global offset table to facilitate interposition.
  • The performance cost of interposition can be substantial.
  • Interposition can be used to override symbols in shared libraries.
  • Linux uses multiple sections to encode information about shared libraries, while Windows uses a single edata section.
  • Linkers and shared libraries have a direct impact on C++ development.
  • The procedure lookup table (PLT) enables lazy binding and is specific to each binary.
  • The C++ standard does not provide a direct mechanism for interposition, but dll_export and dll_import attributes can achieve similar results.
  • The bsymbolic linker switch can be used to resolve symbol clashes and optimize code.
  • The ELF linker defaults to lazy binding, but can be configured to use direct binding instead.
  • Developing code that works across different platforms and linkers is crucial for software development.