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.
$ 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)
-
3488646
works; [original example using the--default-symver
flag]
RE dynamically link against both libd1.so libd2.sop -> libd1 -> libbase.so.1 -> libd2 -> libbase.so.2
-
e58d5c6
works; [compatible definitions]
RE dynamically link against libd1.so; dynamically load (dlopen
) libd2.sop -> libd1 -> libbase.so.1 libd2.so -> libbase.so.2
-
a774a61
works; [compatible definitions]
RE dynamic linker (ld.so) won't reload libbase.so[.2] as it has already been loadedp -> 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)
-
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 loadedp -> libd1 -> libbase.so # ld linked against libbase.so.1 libd2.so -> libbase.so # ld linked against libbase.so.2
-
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
-
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 scopep libd1.so -> libbase.so.1 libd2.so -> libbase.so.2
-
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 loadedp libd1.so -> libbase.so # ld linked against libbase.so.1 libd2.so -> libbase.so # ld linked against libbase.so.2
-
fa1bab5
won't work; similar to5f7a95e
RE RTLD_GLOBAL adds loaded symbols (including those from dependencies) into the global scopep libd1.so (RTLD_GLOBAL) -> libbase.so.1 libd2.so -> libbase.so.2
-
482352f
works - dynamically load incompatible librariesp libbase.so.1 libbase.so.2
-
89c6b64
won't workp libd1.so -> libbase.so # ld linked against libbase.so.1 libd2.so -> libbase.so [not loaded] # ld linked against libbase.so.2
TODO
- What if the duplicate symbol is defined in the parent (p), will it be loaded when the dependency is
dlopen
'd - What happens when the libraries are statically linked
- see https://github.com/andyneff/diamond tests 5-8
[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