/linking_examples

Example of a diamond linking thingy with version problems. See http://blog.habets.pp.se/2012/05/Shared-libraries-diamond-problem

Primary LanguageC

Experiment with dynamic symbol resolution across dynamically linked and loaded ELF libraries

TLDR;

  • Dynamically linked dependencies are scanned in a breadth-first search according to their order on the link line.
  • Dynamically loaded dependencies (dlopen) are, by default, added to a private link chain.

Compiling and running

$ make && ./p # see p.c for expected output

In the following examples, a symbol collision exists between base1.c and base1.c (specifically, base_print)

  1. 3488646 works; [original example using the --default-symver flag]
    RE dynamically link against both libd1.so libd2.so

    p -> libd1 -> libbase.so.1
      -> libd2 -> libbase.so.2
    
  2. e58d5c6 works; [compatible definitions]
    RE dynamically link against libd1.so; dynamically load (dlopen) libd2.so

    p -> libd1 -> libbase.so.1
      libd2.so -> libbase.so.2
    
  3. a774a61 works; [compatible definitions]
    RE dynamic linker (ld.so) won't reload libbase.so[.2] as it has already been loaded

    p -> libd1 -> libbase.so # ld actually linked against libbase.so.1 (but the SONAME is libbase.so)
      libd2.so -> libbase.so # ld actually linked against libbase.so.2 (but the SONAME is libbase.so)
    
  4. 8e1cfed won't work; [diamond linking problem with incompatible definitions]
    RE dynamic linker (ld.so) won't reload libbase.so[.2] since it has already been loaded

    p -> libd1 -> libbase.so # ld linked against libbase.so.1
      libd2.so -> libbase.so # ld linked against libbase.so.2
    
  5. 5f7a95e won't work; [multiple incompatible definitions in different SONAMEs; global link chain (aka scope) is searched first]
    RE both libbase.so.1 and libbase.so.2 are ultimately loaded
    RE the fact that the second .so has a different name doesn't actually matter (symbols are not namespaced by library)

    p -> libd1 -> libbase.so.1
      libd2.so -> libbase.so.2
    
  6. 966d1f6 works - [a la manylinux python import]
    RE dynamic libraries are each loaded into a private scope appended to the global scope; the 'duplicate' symbol is also not defined in the global scope

    p
      libd1.so -> libbase.so.1
      libd2.so -> libbase.so.2
    
  7. 70f3c8c won't work - [a la python import]
    RE similar to the diamond linking problem; the dynamic linker (ld.so) won't reload libbase.so[.2] as it has already been loaded

    p
      libd1.so -> libbase.so # ld linked against libbase.so.1
      libd2.so -> libbase.so # ld linked against libbase.so.2
    
  8. fa1bab5 won't work; similar to 5f7a95e
    RE RTLD_GLOBAL adds loaded symbols (including those from dependencies) into the global scope

    p
      libd1.so (RTLD_GLOBAL) -> libbase.so.1
      libd2.so -> libbase.so.2
    
  9. 482352f works - dynamically load incompatible libraries

    p
      libbase.so.1
      libbase.so.2
    
  10. 89c6b64 won't work

    p
      libd1.so -> libbase.so              # ld linked against libbase.so.1
      libd2.so -> libbase.so [not loaded] # ld linked against libbase.so.2
    

TODO

  1. What if the duplicate symbol is defined in the parent (p), will it be loaded when the dependency is dlopen'd
  2. What happens when the libraries are statically linked

[verilook case] shouldn't work; [diamond linking problem again]
RE similar to 70f3c8c

p
  libd1.so -> libbase.so
  libd2.so
    lib3.so -> libbase.so

shouldn't work; [diamond linking problem again]
RE similar to 70f3c8c

p
  libd1.so
    libdynamicK.so -> libbase.so
  libd2.so
    lib3.so -> libbase.so