动态库全解析

一,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
    评论
使用 dSYM 文件可以帮助我们解析动态库的地址。dSYM 文件是符号调试信息的容器,它包含了编译后的二进制文件与源代码之间的映射关系,以及符号表信息。 对于 iOS 应用程序,可以通过以下步骤来利用 dSYM 文件解析动态库地址: 1. 在 Xcode 中,选择你的项目目录,然后右键点击选择 "Show in Finder"。 2. 在 Finder 中,找到以 ".app" 为后缀的应用程序包,并右键点击选择 "Show Package Contents"。 3. 在应用程序包中,找到对应的 dSYM 文件。通常,dSYM 文件与可执行文件(例如应用程序的主二进制文件)位于同一目录下。 4. 将 dSYM 文件复制到一个方便访问的位置,例如你的项目目录下。 一旦你获得了 dSYM 文件,你可以使用工具来解析动态库地址。以下是一些常用的工具和用法示例: 1. **atos**:使用该命令行工具可以将地址转换为符号名称。在终端中运行以下命令: ```bash # 根据 dSYM 文件和地址解析符号 atos -arch <架构> -o <dSYM 文件路径> -l <加载地址> <要解析的地址> ``` 例如: ```bash # 解析地址 0x0000000100012345 atos -arch arm64 -o /path/to/YourApp.app.dSYM/Contents/Resources/DWARF/YourApp -l 0x100012345 0x0000000100012345 ``` 2. **lldb**:使用 lldb 调试工具可以加载 dSYM 文件并解析地址。在终端中运行以下命令: ```bash # 进入 lldb 调试模式 lldb # 加载可执行文件和 dSYM 文件 target create /path/to/YourApp settings set target.source-map <应用程序路径> <dSYM 文件路径> # 解析地址 image lookup --address <要解析的地址> # 退出 lldb 调试模式 quit ``` 例如: ```bash # 进入 lldb 调试模式 lldb # 加载可执行文件和 dSYM 文件 target create /path/to/YourApp settings set target.source-map /path/to/YourApp.app /path/to/YourApp.app.dSYM # 解析地址 0x0000000100012345 image lookup --address 0x0000000100012345 # 退出 lldb 调试模式 quit ``` 这些工具可以将给定的地址转换为符号名称,帮助你在应用程序中定位和调试问题。请注意,在使用这些工具时,确保提供正确的架构、dSYM 文件路径、加载地址和要解析的地址。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值