动态库全解析

一,Linux平台

每个动态库有三个名字:real name,so name,linker name。

1.1,real name

完整的文件名形式是『lib名字.so.主版本号.次版本号.发行版本号』,例如libexslt.so.0.8.15。这种名字的文件是真正的二进制可执行的库文件。

1.2,so name

完整的文件名形式是『lib名字.so.主版本号』,例如libexslt.so.0。这种名字的文件是符号连接,指向对应的『real name』文件。该名字也会保存于库文件的『SONAME』字段,用命令『readelf -d 库文件名』可以查看:

$ readelf -d libexslt.so.0Dynamic section at offset 0x12af4 contains 28 entries:  Tag        Type                         Name/Value 0x00000001 (NEEDED)                     Shared library: [libgcrypt.so.11] 0x00000001 (NEEDED)                     Shared library: [libdl.so.2] 0x00000001 (NEEDED)                     Shared library: [libgpg-error.so.0] 0x00000001 (NEEDED)                     Shared library: [libxslt.so.1] 0x00000001 (NEEDED)                     Shared library: [libxml2.so.2] 0x00000001 (NEEDED)                     Shared library: [libz.so.1] 0x00000001 (NEEDED)                     Shared library: [libm.so.6] 0x00000001 (NEEDED)                     Shared library: [libc.so.6] 0x0000000e (SONAME)                     Library soname: [libexslt.so.0]...复制代码

该名字可以在生成动态库的时候指定:

gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list复制代码

如果动态库有『SONAME』字段,那么依赖该库的二进制逻辑启动要自动加载该库时,会在依次在各搜索路径下找名字和『SONAME』字段相同的文件,一找到就立即加载。搜索顺序如下:

1,编译器连接阶段通过『-Wl,-rpath,your_path』指定的路径。2,环境变量『LD_LIBRARY_PATH』指定的一组路径从头到尾按序。3,配置文件『/etc/ld.so.conf』中指定的一组路径从头到尾按序。4,系统路径『/lib』。5,系统路径『/usr/lib』。复制代码

系统本身不带可以修改『SONAME』字段的工具。有第三方工具『patchelf』可以修改,从这里下载源码编译可得。修改命令为『patchelf --set-soname your_soname library_name』。

1.3,linker name

完整的文件名形式是『lib名字.so』,例如libexslt.so。这种名字的文件是符号连接,指向对应的『so name』文件或者『real name』文件,用于给编译器进行连接。

gcc -o exe_name obj_list -L路径 -l名字gcc -shared -o lib_name obj_list -L路径 -l名字复制代码

运行时和『linker name』就没关系了,靠的是『so name』。

二,MacOS平台

每个动态库有三个名字:real name、install name、linker name。

2.1,real name

完整的文件名形式是『lib名字.主版本号.次版本号.发行版本号.dylib』,例如libnetsnmp.5.2.1.dylib。这种名字的文件是真正的二进制可执行的库文件。

有时会仿照Linux平台的『so name』,创建一个文件名形式是『lib名字.主版本号.dylib』的符号连接,指向对应的『real name』文件。例如libnetsnmp.5.dylib。

2.2,install name

这是个路径名,保存于库文件的『install_name』字段,用命令『otool -D 库文件名』可以查看:

$ otool -D libncurses.dyliblibncurses.dylib:/usr/lib/libncurses.5.4.dylib复制代码

该名字可以在生成动态库的时候指定:

clang -dynamiclib -install_name your_install_name -o library_name file_list library_list复制代码

如果动态库有『install_name』字段,那么依赖该库的二进制逻辑启动要自动加载该库时,会在『install_name』字段指定的位置加载,因为编译器连接时会把该库的『install_name』字段值写入到生成的二进制逻辑中。

系统本身有工具『install_name_tool』可以修改动态库中的『install_name』字段,或者依赖该库的二进制逻辑中写入的『install_name』字段值:

install_name_tool -id your_install_name lib_nameinstall_name_tool -change old_name new_name exe_name复制代码

『install name』一般是绝对路径(即以『/』开头的),也可以是相对路径,其中可以带环境变量(即『${变量名}』)。若是相对路径,则可以相对于当前位置(即以『./』开头的),也可以相对于当前位置的上一级(即以『../』开头的),也可以相对于预设值(『@executable_path/』开头表示相对于所属可执行文件的所在位置,『@loader_path/』开头表示所属可执行文件的所有可加载位置的列表,『@rpath/』开头表示编译器连接阶段通过『-Wl,-rpath,your_path』指定的路径);除这些以外的相对路径,系统会依次用各搜索路径与之拼接,检查是否存在,一找到就立即加载。关于搜索顺序,目前没有找到能够明确阐述它的资料。

2.3,linker name

完整的文件名形式是『lib名字.dylib』,例如libnetsnmp.dylib。这种名字的文件是符号连接,指向对应的『real name』文件,用于给编译器进行连接。

clang -o exe_name obj_list -L路径 -l名字clang -dynamiclib -o lib_name obj_list -L路径 -l名字复制代码

运行时和『linker name』就没关系了,靠的是『install name』。



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值