在加载第三方库过程中,无法加载到库的问题(使用readelf, patchelf命令)

无法加载到库问题

问题及分析过程

在开发一个程序过程中,需要加载第三方库iTapTradeAPI, 在CMakeList.txt中已经设置了CMAKE_INSTALL_RPATH,但是发布到生产之后由于目录问题无法加载到libiTapTradeAPI库了

下面时分析的过程图

从图中可以看出iTapTradeAPI使用的相对路径,与其他依赖库不同, 然后查看依赖库iTapTradeAPI的信息

可以看到使用的RPATH时 .:/RIGIN路径

刚开始想到的时是否把相对路径去掉, 使用如下命令:

patchelf --remove-rpath <path-to-elf>
eg: patchelf --remove-rpath libiTapTradeAPI.so

去掉之后还是不行,对比项目中的其他动态库,发现这个动态库少了一个选项SONAME, 然后使用命令

patchelf --set-soname libiTapTradeAPI.so ./libiTapTradeAPI.so

进行设置,这样之后就可以了

另外假如在生产上想先快速修复:还可以使用

patchelf --replace-needed LIBRARY NEW_LIBRARY

来做应急修复,替换依赖库的路径

readelf 命令

readelf是一个用于查看可执行文件和共享库的信息的命令行工具。它可以显示二进制文件的各种部分,包括头部信息、节(section)信息、符号表、动态链接信息等

readelf -h
readelf: Warning: Nothing to do.
Usage: readelf <option(s)> elf-file(s)
 Display information about the contents of ELF format files
 Options are:
  -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I	//  显示所有信息,相当于 -h -l -S -s -r -d -V -A -I
  -h --file-header       Display the ELF file header			//  显示ELF文件头信息
  -l --program-headers   Display the program headers	// 显示程序头信息
     --segments          An alias for --program-headers	// --program-headers的别名
  -S --section-headers   Display the sections' header	// 显示节头信息
     --sections          An alias for --section-headers	// --section-headers的别名
  -g --section-groups    Display the section groups	// 显示节组信息
  -t --section-details   Display the section details	// 显示节的详细信息
  -e --headers           Equivalent to: -h -l -S	// 相当于 -h -l -S
  -s --syms              Display the symbol table	//  显示符号表
     --symbols           An alias for --syms	// --syms的别名
  --dyn-syms             Display the dynamic symbol table	// 显示动态符号表
  -n --notes             Display the core notes (if present)	// 显示核心注释(如果存在)
  -r --relocs            Display the relocations (if present)	// 显示重定位信息(如果存在)
  -u --unwind            Display the unwind info (if present)	// 显示展开信息(如果存在)
  -d --dynamic           Display the dynamic section (if present)	//  显示动态节信息(如果存在)
  -V --version-info      Display the version sections (if present)	// 显示版本节信息(如果存在)
  -A --arch-specific     Display architecture specific information (if any)	// 显示特定于体系结构的信息(如果有)
  -c --archive-index     Display the symbol/file index in an archive	// 在存档中显示符号/文件索引
  -D --use-dynamic       Use the dynamic section info when displaying symbols	// 显示符号时使用动态节信息
  -x --hex-dump=<number|name>
                         Dump the contents of section <number|name> as bytes // 以字节形式显示节的内容
  -p --string-dump=<number|name>
                         Dump the contents of section <number|name> as strings //  以字符串形式显示节的内容
  -R --relocated-dump=<number|name>
                         Dump the contents of section <number|name> as relocated bytes // 以重定位后的字节形式显示节的内容
  -z --decompress        Decompress section before dumping it	// 在显示节内容之前解压缩节
  -w[lLiaprmfFsoRt] or
  --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
               =frames-interp,=str,=loc,=Ranges,=pubtypes,
               =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
               =addr,=cu_index]
                         Display the contents of DWARF2 debug sections	// 显示DWARF2调试节的内容
  --dwarf-depth=N        Do not display DIEs at depth N or greater	// 不显示深度大于或等于N的DIEs
  --dwarf-start=N        Display DIEs starting with N, at the same depth
                         or deeper	// 从深度为N的DIE开始显示
  -I --histogram         Display histogram of bucket list lengths	// 显示桶列表长度的直方图
  -W --wide              Allow output width to exceed 80 characters	// 允许输出宽度超过80个字符
  @<file>                Read options from <file>		// 从文件中读取选项
  -H --help              Display this information
  -v --version           Display the version number of readelf
  1. 查看文件头部信息:

    readelf -h executable

  2. 查看节(section)信息:

    readelf -S executable

  3. 查看符号表:

    readelf -s executable

  4. 查看动态链接信息:

    readelf -d executable

  5. 查看库依赖:

    readelf -d executable | grep NEEDED

patchelf命令

patchelf是一个用于修改可执行文件和共享库属性的工具。它可以用来修改运行时搜索路径(rpath)、修改依赖库路径、修改库版本等。

1. 查看文件属性:

patchelf --print-interpreter executable

patchelf --print-rpath executable

patchelf --print-needed executable

2.  将可执行文件的运行时搜索路径(rpath)修改为 "path/to/library-dir"。运行时搜索路径用于指定程序在运行时查找共享库的路径。通过修改运行时搜索路径,您可以控制程序在运行时加载特定的共享库。

patchelf --set-rpath path/to/library-dir executable

3. 将可执行文件的动态链接器(interpreter)路径修改为 "path/to/ld-linux.so.2"。动态链接器负责在程序启动时加载共享库并解析符号。通过修改动态链接器路径,您可以指定程序在运行时使用特定的动态链接器。

patchelf --set-interpreter path/to/ld-linux.so.2 executable

4. 将共享库的 soname 修改为 "new-soname.so.1"。Soname 是共享库的标识符,用于在运行时确定库的版本。通过修改 soname,您可以控制共享库的版本和依赖关系。

patchelf --set-soname new-soname.so.1 library.so

复制代码

patchelf -h

syntax: patchelf

[--set-interpreter FILENAME] // 设置动态库解析器

[--page-size SIZE] // 设置页大小

[--print-interpreter]

[--print-soname] Prints 'DT_SONAME' entry of .dynamic section. Raises an error if DT_SONAME doesn't exist

[--set-soname SONAME] Sets 'DT_SONAME' entry to SONAME. // 设置名字

[--set-rpath RPATH] // 设置 rpath

[--remove-rpath] // 删除 rpath

[--shrink-rpath] // 收缩rpath

[--print-rpath] // 打印 rpath

[--force-rpath] // 强制使用 rpath

[--add-needed LIBRARY] // 添加需要的动态库

[--remove-needed LIBRARY] // 删除需要的动态库

[--replace-needed LIBRARY NEW_LIBRARY] // 替换需要的动态库

[--print-needed] // 打印帮助信息

[--no-default-lib] // 不链接默认的动态库

[--debug]

[--version]

FILENAME

复制代码
相关推荐
内核程序员kevin2 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
‘’林花谢了春红‘’4 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导6 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
朝九晚五ฺ6 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream6 小时前
Linux的桌面
linux
xiaozhiwise7 小时前
Makefile 之 自动化变量
linux
Yang.998 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3
熬夜学编程的小王8 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
zz40_8 小时前
C++自己写类 和 运算符重载函数
c++