readelf工具有哪些主要功能

readelf 是 Linux/Unix 下用于分析 ELF(Executable and Linkable Format) 文件的强大工具,可以查看 ELF 文件的头部信息、节(Sections)、段(Segments)、符号表(Symbol Table)、动态链接信息等。以下是 readelf 的主要功能及常用选项详解:

1. 基本语法

readelf [选项] <ELF文件>

[host]$ readelf
Usage: readelf <option(s)> elf-file(s)
Display information about the contents of ELF format files

2. 主要功能及常用选项

(1)查看 ELF 文件头信息(ELF Header)

  • -h / --file-header
    显示 ELF 文件头信息,包括:
    • Magic Number7f 45 4c 46 标识 ELF 格式)
    • 文件类型(可执行文件、共享库、目标文件等)
    • 机器架构(如 x86-64ARM
    • 入口地址(Entry Point)
    • 节头表(Section Headers)和程序头表(Program Headers)的位置。

示例

base_demo]$ readelf -h a.out
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4005a0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          16416 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

(2)查看程序头表(Program Headers)

  • -l / --program-headers / --segments
    显示 段(Segments) 信息,用于指导操作系统如何加载程序(仅对可执行文件或共享库有效)。
    关键段:
    • PT_LOAD(需加载到内存的段,如代码段 .text 和数据段 .data
    • PT_INTERP(动态链接器路径,如 /lib64/ld-linux-x86-64.so.2
    • PT_DYNAMIC(动态链接信息)。

示例

[base_demo]$ readelf -l a.out

Elf file type is EXEC (Executable file)
Entry point 0x4005a0
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R      0x8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000000bb8 0x0000000000000bb8  R E    0x200000
  LOAD           0x0000000000000e00 0x0000000000600e00 0x0000000000600e00
                 0x000000000000023c 0x0000000000000240  RW     0x200000
  DYNAMIC        0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
                 0x00000000000001d0 0x00000000000001d0  RW     0x8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x0000000000000a38 0x0000000000400a38 0x0000000000400a38
                 0x000000000000004c 0x000000000000004c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000000e00 0x0000000000600e00 0x0000000000600e00
                 0x0000000000000200 0x0000000000000200  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .init_array .fini_array .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .init_array .fini_array .dynamic .got

(3)查看节头表(Section Headers)

  • -S / --section-headers / --sections
    显示 节(Sections) 信息,用于链接和调试。
    常见节:
    • .text(代码)
    • .data(已初始化数据)
    • .bss(未初始化数据)
    • .rodata(只读数据)
    • .symtab(符号表)
    • .strtab(字符串表)
    • .dynamic(动态链接信息)。

示例:(S 为 大写)

[base_demo]$ readelf -S a.out
There are 30 section headers, starting at offset 0x4020:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000400254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000400274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400298  00000298
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           00000000004002b8  000002b8
       00000000000000d8  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000400390  00000390
       0000000000000093  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           0000000000400424  00000424
       0000000000000012  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000400438  00000438
       0000000000000030  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400468  00000468
       0000000000000060  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             00000000004004c8  000004c8
       0000000000000060  0000000000000018  AI       5    22     8
  [11] .init             PROGBITS         0000000000400528  00000528
       000000000000001b  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000400550  00000550
       0000000000000050  0000000000000010  AX       0     0     16
  [13] .text             PROGBITS         00000000004005a0  000005a0
       0000000000000405  0000000000000000  AX       0     0     16
  [14] .fini             PROGBITS         00000000004009a8  000009a8
       000000000000000d  0000000000000000  AX       0     0     4
  [15] .rodata           PROGBITS         00000000004009b8  000009b8
       0000000000000080  0000000000000000   A       0     0     8
  [16] .eh_frame_hdr     PROGBITS         0000000000400a38  00000a38
       000000000000004c  0000000000000000   A       0     0     4
  [17] .eh_frame         PROGBITS         0000000000400a88  00000a88
       0000000000000130  0000000000000000   A       0     0     8
  [18] .init_array       INIT_ARRAY       0000000000600e00  00000e00
       0000000000000008  0000000000000008  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       0000000000600e08  00000e08
       0000000000000008  0000000000000008  WA       0     0     8
  [20] .dynamic          DYNAMIC          0000000000600e10  00000e10
       00000000000001d0  0000000000000010  WA       6     0     8
  [21] .got              PROGBITS         0000000000600fe0  00000fe0
       0000000000000020  0000000000000008  WA       0     0     8
  [22] .got.plt          PROGBITS         0000000000601000  00001000
       0000000000000038  0000000000000008  WA       0     0     8
  [23] .data             PROGBITS         0000000000601038  00001038
       0000000000000004  0000000000000000  WA       0     0     1
  [24] .bss              NOBITS           000000000060103c  0000103c
       0000000000000004  0000000000000000  WA       0     0     1
  [25] .comment          PROGBITS         0000000000000000  0000103c
       000000000000002d  0000000000000001  MS       0     0     1
  [26] .gnu.build.attrib NOTE             0000000000a01040  0000106c
       0000000000001df4  0000000000000000           0     0     4
  [27] .symtab           SYMTAB           0000000000000000  00002e60
       0000000000000a08  0000000000000018          28    82     8
  [28] .strtab           STRTAB           0000000000000000  00003868
       0000000000000698  0000000000000000           0     0     1
  [29] .shstrtab         STRTAB           0000000000000000  00003f00
       0000000000000119  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

(4)查看符号表(Symbol Table)

  • -s / --syms / --symbols
    显示符号表,包括函数、变量名及其地址。
    • 用于分析可执行文件或库的导出/导入符号。
    • 结合 grep 可快速查找特定符号。

示例(查找 main 函数):

[base_demo]$ readelf -s a.out |grep main
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
    90: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
   103: 000000000040075b   459 FUNC    GLOBAL DEFAULT   13 main

(5)查看动态链接信息

  • -d / --dynamic
    显示动态节(.dynamic)内容,包括:
    • 依赖的共享库(NEEDED
    • 符号表(SYMTAB
    • 重定位信息(REL/RELA
    • 动态链接器路径(INTERP)。

示例(查看依赖的库):

[base_demo]$ readelf -d a.out |grep NEEDED
 0x0000000000000001 (NEEDED) 

(6)查看重定位信息

  • -r / --relocs
    显示重定位条目,用于分析地址修正(如动态链接时的符号解析)。

示例

[base_demo]$ readelf -r a.out

Relocation section '.rela.dyn' at offset 0x468 contains 4 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000600fe0  000100000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_deregisterTMClone + 0
000000600fe8  000500000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.2.5 + 0
000000600ff0  000600000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000600ff8  000800000006 R_X86_64_GLOB_DAT 0000000000000000 _ITM_registerTMCloneTa + 0

Relocation section '.rela.plt' at offset 0x4c8 contains 4 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000601018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000601020  000300000007 R_X86_64_JUMP_SLO 0000000000000000 strlen@GLIBC_2.2.5 + 0
000000601028  000400000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
000000601030  000700000007 R_X86_64_JUMP_SLO 0000000000000000 memcpy@GLIBC_2.14 + 0

(7)查看节内容(Hex 或字符串)

  • -x <节名> / --hex-dump=<节名>
    以十六进制格式显示指定节的内容。
  • -p <节名> / --string-dump=<节名>
    以字符串格式显示指定节的内容(如 .rodata 中的常量字符串)。

示例(查看 .rodata 节):

readelf -x .rodata a.out

[base_demo]$ readelf -x .rodata a.out

Hex dump of section '.rodata':
  0x004009b8 01000200 00000000 00000000 00000000 ................
  0x004009c8 66697273 74206c65 6e3a2564 2c207365 first len:%d, se
  0x004009d8 636f6e64 206c656e 3a25640a 00706572 cond len:%d..per
  0x004009e8 736f6e20 696e666f 3a000000 00000000 son info:.......
  0x004009f8 09666972 73745f6e 616d653a 25732c20 .first_name:%s,
  0x00400a08 7365636f 6e645f6e 616d653a 25732c20 second_name:%s,
  0x00400a18 6167653a 25640a00 6d610078 69616f00 age:%d..ma.xiao.
  0x00400a28 7869616e 7368656e 67007a68 6f6e6700 xiansheng.zhong.

(8)查看版本信息

  • -V / --version-info
    显示版本控制信息(如符号版本)。
[base_demo]$ readelf -V a.out

Version symbols section '.gnu.version' contains 9 entries:
 Addr: 0000000000400424  Offset: 0x000424  Link: 5 (.dynsym)
  000:   0 (*local*)       1 (*global*)      2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)
  004:   2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)   1 (*global*)      3 (GLIBC_2.14)
  008:   1 (*global*)

Version needs section '.gnu.version_r' contains 1 entry:
 Addr: 0x0000000000400438  Offset: 0x000438  Link: 6 (.dynstr)
  000000: Version: 1  File: libc.so.6  Cnt: 2
  0x0010:   Name: GLIBC_2.14  Flags: none  Version: 3
  0x0020:   Name: GLIBC_2.2.5  Flags: none  Version: 2

(9)查看所有信息(调试用)

  • -a / --all
    显示 ELF 文件的 全部信息(等效于组合使用 -h-l-S-s 等)。

示例

readelf -a a.out

3. 常见用途示例

(1)判断文件是否为 ELF 格式

readelf -h file.bin | grep "Magic"

如果输出包含 7f 45 4c 46,则是 ELF 文件。

[base_demo]$ readelf -a a.out |grep "Magic"
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00

(2)分析可执行文件的依赖库

readelf -d /usr/bin/ls | grep NEEDED

 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

(3)查找未定义的符号(用于链接错误排查)

readelf -s libfoo.so | grep UND

UND 表示未定义的符号(需在运行时动态解析)。

(4)对比两个 ELF 文件的差异

diff <(readelf -a file1) <(readelf -a file2)

4. 与其他工具对比

工具

主要用途

特点

readelf

直接解析 ELF 结构

不依赖 BFD 库,适合低级分析

objdump

反汇编、查看节内容

依赖 BFD 库,支持更多文件格式

nm

查看符号表(简单场景)

仅显示符号名和类型

ldd

查看动态库依赖

仅用于可执行文件/共享库

5. 总结

readelf 是分析 ELF 文件的 瑞士军刀,常用功能包括:

  • 查看文件头(-h
  • 查看段(-l)和节(-S
  • 查看符号表(-s
  • 分析动态链接(-d
  • 导出节内容(-x/-p

适合 逆向工程、链接问题调试、二进制安全分析 等场景。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值