当前位置: 首页 > news >正文

readelf 和 ldd 查看文件的依赖

readelf 和 ldd 查看文件的依赖

readelf 和 ldd 都可以用来查看文件的依赖,但它们的工作原理、可靠性和使用场景有本质区别。

简单来说:

  • readelf:是一个静态分析工具,直接读取并解析 ELF 文件本身的头信息和数据结构,告诉你它声称自己需要哪些共享库。

  • ldd:是一个动态模拟/加载工具,它实际上会启动程序的加载器,模拟其运行时的加载过程,然后告诉你在当前环境下实际会找到并加载哪些库。

下面我们进行详细的对比和解释。

1. readelf -d (查看动态节信息)

readelf 是一个用于显示 ELF(Executable and Linkable Format)文件信息的强大工具。-d 选项用于显示文件的动态节(.dynamic section),这个节包含了链接器所需的各种信息,其中就包括依赖的共享库列表。

工作原理:
静态分析。它只是读取 ELF 文件中 DT_NEEDED 类型的条目,这些条目记录的是编译链接时由链接器写入的、程序运行所必需的共享库名字(如 libc.so.6)。

使用方法:

bash

readelf -d /path/to/program | grep NEEDED

输出示例:

text

0x0000000000000001 (NEEDED)             Shared library: [libssl.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so.3]
0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

这个列表是程序内在的、声明的依赖,不依赖于你当前的系统环境。

优点:

  • 绝对可靠:它直接读取文件内容,显示的是程序“设计上”需要什么,永远不会失败或被欺骗。

  • 安全:因为它不执行任何代码,只是读取文件。

缺点:

  • 只显示库的名字(SONAME),不显示库在磁盘上的完整绝对路径

  • 不关心这些库在你的系统上是否真实存在。

2. ldd (列出动态依赖)

ldd 本身并不是一个真正的程序,而是一个shell脚本(在某些发行版上是二进制包装)。它的作用是设置环境变量,然后调用程序的运行时链接器(通常是 /lib/ld-linux.so.2 或 /lib64/ld-linux-x86-64.so.2)来模拟加载过程。

工作原理:
动态模拟。它通过设置 LD_TRACE_LOADED_OBJECTS=1 环境变量,然后启动目标程序。链接器检测到这个变量后,不会真正运行程序的 main 函数,而是打印出它会加载哪些库以及这些库被解析到的具体路径,然后立即退出。

使用方法:

bash

ldd /path/to/program

输出示例:

text

        linux-vdso.so.1 (0x00007ffc12df0000)libssl.so.3 => /usr/lib/x86_64-linux-gnu/libssl.so.3 (0x00007f8a1a2c0000)libcrypto.so.3 => /usr/lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007f8a19c00000)libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8a19bda000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8a199c8000)/lib64/ld-linux-x86-64.so.2 (0x00007f8a1a518000)

这个列表是在当前系统环境和配置下,链接器实际能找到的库。

优点:

  • 信息实用:直接显示了库的完整路径,方便定位问题。

  • 反映了环境的影响:它会遵循 LD_LIBRARY_PATH/etc/ld.so.cacherpath 等运行时配置,展示最终的解析结果。

缺点:

  • 有安全风险:因为它会实际加载程序的依赖库并执行其中的初始化代码(init 代码)。如果程序是恶意的,或者某个依赖库被篡改,使用 ldd 可能会意外执行恶意代码。

  • 可能不可靠:如果程序本身缺少某些关键的依赖,ldd 可能会因为加载失败而报错,无法给出完整的依赖列表。

核心区别总结

特性readelf -dldd
工作原理静态分析ELF文件结构动态模拟加载过程
显示内容声明的依赖项(SONAME)解析后的完整路径
环境依赖。结果与系统环境无关,只与文件本身有关。。结果受 LD_LIBRARY_PATHld.so.cache 等影响。
可靠性。直接读取文件,总能成功。较低。依赖库缺失或损坏会导致命令失败。
安全性安全。不执行任何代码。不安全。会执行库的初始化代码,有风险。
主要用途查看程序的原始依赖声明,用于开发和调试。查看库在当前系统下的实际位置,用于解决运行时依赖问题。

实践与建议

  1. 优先使用 readelf 或 objdump
    出于安全考虑,如果你只是想看程序依赖哪些库,应该优先使用静态分析工具。

    bash

    # 使用 readelf
    readelf -d /bin/ls | grep NEEDED# 或者使用 objdump(效果类似)
    objdump -p /bin/ls | grep NEEDED
  2. 安全地使用 ldd 的替代方案
    如果你需要知道库的路径,但又担心安全问题,可以使用以下方法:

    bash

    # 方法一:使用 ld.so 直接模拟(ldd 的本质)
    LD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /path/to/program# 方法二:使用调试器(最安全,但复杂)
    gdb /path/to/program
    (gdb) start
    (gdb) info sharedlibrary
  3. 何时使用 ldd
    当你需要快速诊断“库未找到”或“库版本冲突”等运行时问题时,ldd 非常有用,因为它能直接告诉你链接器找到了什么。但请仅在对可信的可执行文件使用时才使用它。

readelf 详细用法

readelf 详细用法,涵盖了最常见的选项和场景。

命令格式

bash

readelf <option(s)> <elf-file(s)>

主要选项和用法

1. 查看ELF文件头(File Header)

这是最常用的选项之一,它显示了文件的基本身份信息,包括文件类型、目标架构、入口点地址等。

命令:

bash

readelf -h /path/to/binary
# 或
readelf --file-header /path/to/binary

输出信息解读:

  • Magic: ELF文件的魔数,标识这是一个ELF文件。

  • Class: 文件类别,ELF32(32位)或 ELF64(64位)。

  • Data: 字节序,LSB(小端序,Intel x86/x86_64)或 MSB(大端序,某些ARM、MIPS)。

  • Type: 文件类型,如 EXEC(可执行文件)、DYN(共享库/PIE可执行文件)、REL(可重定位文件,即.o目标文件)。

  • Machine: 目标架构,如 x86-64ARMAArch64

  • Version: ELF版本,通常是 1 (current)

  • Entry point address: 程序入口点的虚拟内存地址。

  • Start of program headers: 程序头表(Program Header Table)在文件中的偏移量。

  • Start of section headers: 节头表(Section Header Table)在文件中的偏移量。

  • Flags: 处理器特定的标志。

  • Size of this header: ELF文件头本身的大小。

  • Size of program headers: 每个程序头(Program Header)的大小。

  • Number of program headers: 程序头的数量。

  • Size of section headers: 每个节头(Section Header)的大小。

  • Number of section headers: 节头的数量。

  • Section header string table index: 节名称字符串表在节头表中的索引。

2. 查看节头表(Section Headers)

节头表描述了ELF文件中的各个“节”(Section),例如代码节(.text)、数据节(.data)等。注意: 节(Section)是链接视图的概念,在程序运行时,这些节会被组织成“段”(Segment)加载到内存。

命令:

bash

readelf -S /path/to/binary
# 或
readelf --section-headers /path/to/binary

输出信息解读:

  • [Nr]: 节的索引号。

  • Name: 节的名称(如 .text.data.bss.rodata.shstrtab)。

  • Type: 节的类型(如 PROGBITS 程序数据, SYMTAB 符号表, STRTAB 字符串表)。

  • Address: 该节加载到内存后的虚拟地址。

  • Off: 该节在文件中的偏移量。

  • Size: 节的大小。

  • ES: 条目大小(如果节是一个表)。

  • Flg: 标志(W 可写, A 可分配, X 可执行)。

  • Lk: 相关链接信息。

  • Inf: 额外信息。

  • Al: 对齐要求。

3. 查看程序头表(Program Headers / Segments)

程序头表描述了运行时的“段”(Segment),这些段告诉系统加载器如何将文件映射到进程的虚拟内存中。这是运行时视图。

命令:

bash

readelf -l /path/to/binary
# 或
readelf --program-headers /path/to/binary
# 或(显示得更详细)
readelf --segments /path/to/binary

输出信息解读:

  • Type: 段的类型,最重要的有:

    • LOAD: 需要被加载到内存的段(通常包含代码和数据)。

    • DYNAMIC: 动态链接信息。

    • INTERP: 指定程序解释器(如 /lib64/ld-linux-x86-64.so.2)的路径。

  • Offset: 段在文件中的偏移。

  • VirtAddr: 段的第一个字节在内存中的虚拟地址。

  • PhysAddr: 物理地址(通常与虚拟地址相同,用于没有MMU的系统)。

  • FileSiz: 段在文件中的大小。

  • MemSiz: 段在内存中的大小(可能比 FileSiz 大,例如对于未初始化的 .bss 节)。

  • Flg: 标志(R 可读, W 可写, X 可执行)。

  • Align: 对齐方式。

输出末尾的 Section to Segment mapping 部分非常有用,它显示了哪些节被合并到了哪个运行时段中。

4. 查看动态节信息(Dynamic Section)

这是查看共享库依赖rpath 等动态链接信息的核心选项。

命令:

bash

readelf -d /path/to/binary
# 或
readelf --dynamic /path/to/binary

常用信息过滤:

bash

# 查看依赖的共享库 (NEEDED)
readelf -d /bin/ls | grep NEEDED# 查看RPATH/RUNPATH(链接器搜索库的额外路径)
readelf -d /bin/ls | grep RPATH
readelf -d /bin/ls | grep RUNPATH# 查看符号表位置
readelf -d /bin/ls | grep SYMTAB# 查看初始化函数(init_array)和终止函数(fini_array)
readelf -d /bin/ls | grep INIT_ARRAY
readelf -d /bin/ls | grep FINI_ARRAY
5. 查看符号表(Symbol Table)

符号表包含了函数、变量等符号的信息。

命令:

bash

# 查看 .dynsym (动态符号表,用于动态链接)
readelf --dyn-syms /path/to/binary# 查看 .symtab (完整符号表,通常存在于非strip的可执行文件中)
readelf --syms /path/to/binary

常用过滤:

bash

# 查看动态符号表中定义的函数(过滤掉UND未定义的)
readelf --dyn-syms /bin/ls | grep -v UND# 查找某个特定的符号(如malloc)
readelf --dyn-syms /bin/ls | grep malloc
6. 查看重定位信息(Relocations)

显示需要在链接时或加载时进行修正的位置。

命令:

bash

readelf -r /path/to/binary
# 或
readelf --relocs /path/to/binary
7. 查看节内容(Section Contents)

以十六进制和ASCII形式显示指定节的内容。

命令:

bash

readelf -x <section-name> /path/to/binary
# 或
readelf --hex-dump=<section-name> /path/to/binary# 例如,查看 .comment 节的内容
readelf -x .comment /bin/ls
8. 显示所有信息(All)

使用 -a 选项可以显示 readelf 能提供的所有信息。输出会非常长,通常用于全面分析或重定向到文件仔细查看。

命令:

bash

readelf -a /path/to/binary

总结

你的需求应使用的 readelf 选项
快速查看文件基本信息(架构、类型)-h (--file-header)
查看代码、数据等节的布局-S (--section-headers)
查看运行时内存如何映射-l (--program-headers--segments)
查看依赖的共享库和rpath-d (--dynamic)
查看导出的函数/符号--dyn-syms
全面分析,获取所有信息-a (--all)

文章转载自:

http://NX2kUa27.dwrjj.cn
http://xj3FXVZQ.dwrjj.cn
http://ZbCrEOim.dwrjj.cn
http://5OEw9hD1.dwrjj.cn
http://0URvH1tj.dwrjj.cn
http://Hu9l6a12.dwrjj.cn
http://kizonZ1D.dwrjj.cn
http://Tj478gEa.dwrjj.cn
http://W4EN4n4s.dwrjj.cn
http://GfHhl8mE.dwrjj.cn
http://BPWGU1Tq.dwrjj.cn
http://iY0lJ53X.dwrjj.cn
http://93bawvoO.dwrjj.cn
http://p1pnEUCF.dwrjj.cn
http://gGEgKThx.dwrjj.cn
http://V0zlBD3o.dwrjj.cn
http://N53yeIsV.dwrjj.cn
http://eF9S8m5d.dwrjj.cn
http://gAeFlpNN.dwrjj.cn
http://RNT0Uwak.dwrjj.cn
http://Bb5508Qz.dwrjj.cn
http://pIgBZ9Gt.dwrjj.cn
http://YrItfyqT.dwrjj.cn
http://H0ZUXEKB.dwrjj.cn
http://C6EnnjP1.dwrjj.cn
http://o1DMsZ0U.dwrjj.cn
http://rPgp1mki.dwrjj.cn
http://DqSBBjAm.dwrjj.cn
http://wLOvCbwB.dwrjj.cn
http://GnQxbZ1I.dwrjj.cn
http://www.dtcms.com/a/379076.html

相关文章:

  • 基于社交媒体数据的公众情绪指数构建与重大事件影响分析
  • Cosign 实战:构建可信容器镜像的签名与验证体系
  • 定时器实战:LED闪烁与呼吸灯调试
  • docker部署Gitlab社区版,步骤以及外网访问出现502的解决方式
  • FairGuard aab包签名工具
  • 企业文件图纸全自动加密怎么设置?三步实现自动防护!
  • Redis C++ 实现笔记(I篇)
  • [css] 实现禁止文本被选中
  • MATLAB中进行视觉检测入门教程
  • 人工智能深度学习——多层感知器(人工神经网络)
  • 2025最新超详细FreeRTOS入门教程:第十二章 FreeRTOS调度器与时间片管理
  • 软考系统架构设计师之项目管理篇
  • OpenSTL PredRNNv2 模型复现与自定义数据集训练
  • 基于STM32的单片机开发复盘
  • Git 目录详解和基本操作(1)
  • 机器学习之K折交叉验证
  • Android Gradle Project (AGP) gradle-xxxx-src.zip无法正常下载问题解决方法
  • 图观 应用编辑器 产品介绍
  • 探讨Hyperband 等主要机器学习调优方法的机制和权衡
  • Apple产品发布会拆解:体验下放、设计极限、AI 入耳
  • 如何解决 Spring Bean 循环依赖
  • sdio NOT_AUTOGATING
  • 华为X考拉悠然 联合发布悠然智擎城市交通拥堵治理空间智能体方案
  • 《微服务事务管理》
  • CentOS 7 安装 MySQL 详细教程
  • 分布式锁解决集群下一人一单超卖问题
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘sweetviz’问题
  • @DateTimeFormat.fallbackPatterns 详解
  • 使用wavesurfer.js自定义波形绘制,集成频谱、时间轴、缩放、区域选择等插件
  • 数据库主从同步