libc 和 libdl 中的 dlopen
dlopen in libc and libdl
如果 gcc 编译的程序正在调用 dlopen,则必须在启用 -ldl 选项的情况下进行编译。这意味着这样的程序在 运行 时间依赖库 libdl.so。事实上,通过对它执行 ldd,我们看到了这一行:
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
libc.so 依次使用 dlopen(例如,处理 libnss.so),但在 libldl.so 上执行 ldd 不会出现:
/lib64/ld-linux-x86-64.so.2 (0x00007f5a488e4000)
linux-vdso.so.1 => (0x00007fff7bdfe000)
为什么会有这种差异?
libdl
仅公开 libc 中已经存在的 private dl 函数以及一些包装器,以使库的使用更容易一些。您可以通过查看 libdl
.
的符号 table 来了解其中的一些行为
如果您在 libdl
上使用 readelf,限制为 PRIVATE 符号:
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
您看到 GLIBC_PRIVATE 中 UND
的所有条目了吗?这些都引用了 libc 中的实现。
libc 本身定义的 API 未声明为实现 dl
函数作为公开的 API,但是在 glibc
中,libdl 与 libc
,它公开了已知的 API。在这种情况下,glibc 可以使用自身内部的私有例程来完成 运行 次打开和使用相关 .so
文件用于 nss
例程。
如果 gcc 编译的程序正在调用 dlopen,则必须在启用 -ldl 选项的情况下进行编译。这意味着这样的程序在 运行 时间依赖库 libdl.so。事实上,通过对它执行 ldd,我们看到了这一行:
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
libc.so 依次使用 dlopen(例如,处理 libnss.so),但在 libldl.so 上执行 ldd 不会出现:
/lib64/ld-linux-x86-64.so.2 (0x00007f5a488e4000)
linux-vdso.so.1 => (0x00007fff7bdfe000)
为什么会有这种差异?
libdl
仅公开 libc 中已经存在的 private dl 函数以及一些包装器,以使库的使用更容易一些。您可以通过查看 libdl
.
如果您在 libdl
上使用 readelf,限制为 PRIVATE 符号:
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
您看到 GLIBC_PRIVATE 中 UND
的所有条目了吗?这些都引用了 libc 中的实现。
libc 本身定义的 API 未声明为实现 dl
函数作为公开的 API,但是在 glibc
中,libdl 与 libc
,它公开了已知的 API。在这种情况下,glibc 可以使用自身内部的私有例程来完成 运行 次打开和使用相关 .so
文件用于 nss
例程。