ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

《高级C/C++编译技术》03 - 重复符号处理、版本控制、工具集

2022-09-11 20:00:28  阅读:644  来源: 互联网

标签:03 版本控制 符号 二进制 工具集 静态 文件 动态 链接


重复符号处理

当因符号重复而报错时,提示信息可能是重命名符号名称而非原始符号名称。

在 C 语言中使用 static 声明的函数仅本源代码文件可见,不会被认为是重复符号。

在动态库链接过程中处理重复符号

在动态链接时可以一定程度上接收重复符号,且不会立即报告链接错误。当多个动态库中含有相同符号时,一个解决方案是挑选一个出现的符号并将所有对符号的引用直接指向那一个特定符号。

比如动态库 lib1.so lib2.so lib3.so 都能实现 fun() 方法,而链接器让所有 fun 函数都指向其中一个库,结果三个动态库只初始化了一个。应避免这种情况

处理重复符号问题的一般策略

最好的策略就是强化符号和特定模块的从属关系,比如c++中命名空间。

使用动态加载动态库时通常不会产生这个问题,问题出现在对动态库的静态链接。

链接器解析动态库重复符号的模糊算法准则

搜索重复符号名的最佳候选符号时,链接器根据以下情况做出决定:

  • 重复符号位置:链接器未出现在进程内存映射中不同部分的符号赋予不同重要等级
  • 链接时指定的动态库链接顺序:同等优先级的代码中更早传递给动态库的符号有更高优先级

代码优先级划分规则:位置

优先级从高到低

  1. 客户二进制文件符号
  2. 动态库可见符号
    存储在动态库动态节中的动态库导出符号
  3. 不参与链接
    通常不考虑静态符号,无论属于客户二进制还是静态链接的动态库

案例分析

客户二进制文件符号与动态库ABI函数冲突

即优先级1和优先级2发生冲突,链接器会选择客户二进制文件符号。

静态库和动态库ABI冲突

gcc 使用静态库符号

VS 静态库在前时使用静态库符号,动态库在前时报错。

不同动态库ABI符号冲突

同属优先级2的符号发生冲突,由链接顺序决定。

动态库ABI和另一个动态库局部符号冲突

优先级2与优先级3的符号发生冲突,链接器选择动态库ABI符号。

两个未导出的动态库符号冲突

同属优先级3的符号发生冲突,它们不会出现在链接器符号列表中,也不会引发冲突

注意:静态库中的单例

假设用于日志的单例类在静态库中,多个动态库使用了它。单例类不是ABI接口的一部分,只是动态库内部功能的一部分不会被导出。由于动态库局部符号不会参与最终链接,所以会得到多个共存的单例日志类。

解决方法:

  1. 放松符号导出限制,允许动态库导出单例类符号。这样该符号就会变为ABI符号
  2. 将单例类放入动态库中(推荐)

可靠且有效的方法

每个库,包括静态库和动态库,应该有自己专用的命名空间。

版本控制

Linux

基于 soname 版本控制

库文件名:lib<libname>.so.<M>.<m>.<p>
soname:lib<libname>.so.<M>

常用动态库升级方式

在小版本升级时无需重新编译客户端程序,只使用软链接和soname。将软连接和实际动态库放在同一目录下,将软链接指向动态库文件。软连接文件名与动态库soname相同,客户端二进制文件很少包含完整版本信息的动态库,而是与soname文件链接。

在开发客户端二进制程序时使用“-l:<filename>”向链接器传递动态库文件名。 gcc -shared <inputs> -l:libxyz.so.1 -o <clientBinary>gcc -shared <linker input> -Wl,-soname,<soname> -o <file>

使用 ldconfig -n <file>可显示所有依赖的动态库文件

基于符号的版本控制

链接器将包含符号版本控制信息的节(.gnu.version等)写入 ELF 时,通过一条最简单的命令将基于文件文件的版本控制脚本传递给链接器。它能使动态库文件可以携带多个不同版本的相同符号。不同客户二进制文件可能需要不同版本动态库文件,那么只需要加载同一份二进制文件,并链接特定版本号即可。

省略

Windows

在VS中图形化操作,省略。

 

Linux 工具集

binutils

GNU Binutils是一系列二进制工具的集合。主要包括:

  • ld —— GNU链接器
  • as—— GNU汇编器

但也包括以下二进制工具:

  • addr2line:从目标文件的虚拟地址获取文件的行号或符号。
  • ar:可以对静态库做创建、修改和提取的操作。
  • c++filt:反编译(反混淆,demangle)C++符号的工具。
  • dlltool:创建创建Windows动态库。
  • gold:另一种新的、更快的仅支持ELF的链接器。
  • gprof:性能分析(profiling)工具程序。
  • nlmconv:可以转换成NetWare Loadable Module(NLM)目标文件格式。
  • nm:显示目标文件内的符号信息。
  • objcopy:复制和转译目标文件。
  • objdump:显示目标文件的相关信息,亦可反汇编。
  • ranlib:产生静态库的索引。(和nm -s功能类似)
  • readelf: 显示ELF文件的内容。
  • size:列出目标文件或库文件的section大小。
  • strings:列出文件中可打印的字符串信息。
  • strip:从目标文件中移除符号信息。
  • windmc:Windows消息资源编译器。
  • windres:Windows资源文件编译器。

查看工具

file 查看文件类型详细信息

size 获取ELF节的字节长度信息

详细信息分析工具

ldd 显示静态加载的依赖项
     类似操作:objdump -p /path/program | grep NEEDED   readelf -d /path/program | grep NEEDED

nm 列出二进制文件的符号列表

objdump 二进制分析工具,不止elf

readelf elf格式分析工具,不依赖 Binary_File_Descriptor_library 库,而GNU的所有目标文件解析工具都依赖这个库

部署阶段工具

chrpath 修改rpath

patchelf 修改runpath

strip 清除动态加载过程中不需要的库文件符号

ldconfig 指定装载器运行时的库搜索路径

运行时分析工具

strace 追踪系统调用和接收的信号

addr2line 将运行时地址转换成地址对应的源代码文件信息和行号

gdb

静态库工具

ar

标签:03,版本控制,符号,二进制,工具集,静态,文件,动态,链接
来源: https://www.cnblogs.com/zhh567/p/16684435.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有