If a gcc-compiled program is calling dlopen, it has to be compiled with the -ldl option enabled. This means that such a program relies at run time on the library libdl.so. In fact by doing ldd on it we see the line:
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
libc.so in turn uses dlopen (e.g., to deal with libnss.so), but doing ldd on libldl.so doesn't appear:
/lib64/ld-linux-x86-64.so.2 (0x00007f5a488e4000)
linux-vdso.so.1 => (0x00007fff7bdfe000)
Why this difference?
libdl
is only exposing the private dl functions that already exist in libc as well as some wrappers to make the use of the libraries a bit easier. You can see some of this behaviour by looking at the symbol table of libdl
.
If you use readelf on libdl
, limiting to PRIVATE symbols:
readelf -s /usr/lib/x86_64-linux-gnu/libdl.so | grep PRIVATE
13: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND _rtld_global_ro@GLIBC_PRIVATE (7)
14: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _dl_vsym@GLIBC_PRIVATE (8)
16: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _dl_addr@GLIBC_PRIVATE (8)
18: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _dl_sym@GLIBC_PRIVATE (8)
20: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _dl_rtld_di_serinfo@GLIBC_PRIVATE (7)
25: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND _rtld_global@GLIBC_PRIVATE (7)
34: 00000000002030c0 8 OBJECT GLOBAL DEFAULT 27 _dlfcn_hook@@GLIBC_PRIVATE
39: 0000000000000000 0 OBJECT GLOBAL DEFAULT ABS GLIBC_PRIVATE
You see all the entries that are UND
, listing from GLIBC_PRIVATE? those are all referencing the implementations within libc.
The defined API of libc itself is not declared as implementing the dl
functions as an exposed API, however in glibc
libdl is tightly bound to libc
, and it exposes the known API. glibc can use the private routines within itself to accomplish the run-time opening and using of the relevant .so
files for nss
routines in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With