ELF文件
ELF(Executable and Linkable Format)是一种在类Unix系统(如Linux、FreeBSD)中广泛使用的标准文件格式,主要用于可执行文件、目标文件、共享库和核心转储(core dumps)。以下是ELF文件的详细解析:
1. ELF文件类型
| 类型 | 扩展名 | 用途 |
|---|---|---|
| 可执行文件 | 无或自定义 | 可直接运行的程序(如编译后的a.out或自定义名称) |
| 目标文件 | .o |
编译器生成的中间文件,包含代码、数据及链接信息 |
| 共享库 | .so |
动态链接库,运行时被加载到内存供多个程序共享(如libc.so) |
| 核心转储文件 | 无 | 程序崩溃时生成的内存快照,用于调试(如core) |
2. ELF文件结构
ELF文件由以下核心部分组成,使用工具如readelf或objdump可查看具体内容:
(1) ELF头部(ELF Header)
- 位置:文件起始位置。
- 作用:描述文件的基本属性。
readelf -h program- 关键字段:
- Magic Number:
7f 45 4c 46(标识ELF文件)。 - 文件类型:可执行(
EXEC)、共享库(DYN)或目标文件(REL)。 - 目标架构:如x86-64、ARM。
- 入口地址:程序执行的起始地址(
Entry point address)。
- Magic Number:
- 关键字段:
(2) 程序头表(Program Header Table)
- 作用:指导操作系统如何将文件加载到内存(仅可执行文件和共享库包含)。
readelf -l program- 关键段类型:
LOAD:需加载到内存的段(代码段、数据段)。DYNAMIC:动态链接信息(如依赖的共享库)。INTERP:指定动态链接器路径(如/lib64/ld-linux-x86-64.so.2)。
- 关键段类型:
(3) 节头表(Section Header Table)
- 作用:描述文件中的节(section),用于链接和调试。
readelf -S program- 关键节:
.text:可执行代码。.data:已初始化的全局/静态变量。.bss:未初始化的全局/静态变量(不占文件空间,加载时分配内存)。.rodata:只读数据(如字符串常量)。.symtab:符号表(函数和变量名与地址的映射)。.strtab:字符串表(符号名称等字符串存储)。
- 关键节:
(4) 数据部分
- 代码节与数据节:实际存储程序代码和数据的区域。
- 重定位信息(目标文件):记录链接时需要调整的地址偏移。
3. ELF文件生命周期
(1) 编译阶段
- 编译器(如
gcc)生成目标文件(.o),包含代码、数据及符号表。 - 示例:
gcc -c main.c -o main.o
(2) 链接阶段
- 静态链接器(
ld)合并多个目标文件及静态库(.a),生成可执行文件或共享库。 - 示例:
gcc main.o -o program
(3) 执行阶段
- 操作系统加载ELF文件,解析程序头表,将代码和数据段映射到内存。
- 动态链接器加载依赖的共享库(如
libc.so),处理符号重定位。
4. 工具与调试
(1) 查看文件类型
file program # 输出:"ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked..."
(2) 分析符号
nm program # 显示符号表(函数、全局变量地址)
objdump -t program # 更详细的符号信息
(3) 动态链接依赖
ldd program # 列出运行时依赖的共享库
(4) 反汇编代码
objdump -d program # 反汇编.text节中的机器码
5. 示例:简单ELF可执行文件生成
# 编写C程序
echo -e '#include <stdio.h>\nint main() { printf("Hello ELF\\n"); return 0; }' > hello.c
# 编译
gcc hello.c -o hello
# 查看ELF信息
readelf -h hello
总结
ELF文件通过模块化的结构(头部、程序头、节头及数据块)实现了灵活的程序表示,支持静态/动态链接、跨平台兼容及高效加载。理解其结构对于程序优化、调试及安全分析(如逆向工程)至关重要。

浙公网安备 33010602011771号