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 Number(
7f 45 4c 46标识 ELF 格式) - 文件类型(可执行文件、共享库、目标文件等)
- 机器架构(如
x86-64、ARM) - 入口地址(Entry Point)
- 节头表(Section Headers)和程序头表(Program Headers)的位置。
- Magic Number(
示例:
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. 与其他工具对比
|
工具 |
主要用途 |
特点 |
|
|
直接解析 ELF 结构 |
不依赖 BFD 库,适合低级分析 |
|
|
反汇编、查看节内容 |
依赖 BFD 库,支持更多文件格式 |
|
|
查看符号表(简单场景) |
仅显示符号名和类型 |
|
|
查看动态库依赖 |
仅用于可执行文件/共享库 |
5. 总结
readelf 是分析 ELF 文件的 瑞士军刀,常用功能包括:
- 查看文件头(
-h) - 查看段(
-l)和节(-S) - 查看符号表(
-s) - 分析动态链接(
-d) - 导出节内容(
-x/-p)
适合 逆向工程、链接问题调试、二进制安全分析 等场景。
2679

被折叠的 条评论
为什么被折叠?



