什么是ELF
ELF是Linux和安卓下的可执行与可链接格式。是一种用于可执行文件,目标代码,共享库和核心转储的标准文
件格式。
ELF文件类型
- 静态链接库
*.a
- 动态链接库
*.so
- 可执行文件
*.o
文件格式
每个ELF文件都是由一个ELF首部和紧跟其后的文件数据部分组成。数据部分可以包含:
- 程序表头
- 分段表头
- 程序表头与分段表头的引用数据.data和.text
.interp 指定运行时所需的动态链接库,用于动态连接程序
.note.gnu.property 存储gnu属性,例如程序的特定处理需求
.note.gnu.build-id 存储构建的id,标识唯一性
.note.ABI-tag 存储ABI标签,用于二进制文件所遵循的操作系统和ABI标准
.gnu.hash 用于动态链接库的符号查询和解析,提供更快速的符号查找
.dynsym 动态链接器用于查找符号的符号表
.dynstr 存储动态链接器用于查找符号的符号表
.gnu.version 存储符号的版本信息
.gnu.version_r 存储符号的版本信息和引用关系
.rela.dyn 动态重定位表,包含了动态链接器运行时进行重定位的信息
.rela.plt PLT重定位表,用于延迟绑定和函数调用(如printf等动态链接库函数)
.init 存储程序初始化时需要执行的代码
.plt 保存过程连接表,用于对外部函数进行调用
.text 存储程序的代码段
.fini 存储程序终止时需要执行的代码
.rodata 只读数据段,存储常量和只读变量
.eh_frame_hdr 存储异常处理框架的头部信息
.eh_frame 处理异常处理框架的详细信息
.init_array 存储构造函数的地址
.fini_array 存储析构函数的地址
.dynamic 动态链接器使用的动态信息表
.got 全局偏移表,保存全局变量和函数地址
.got.plt 保存plt的全局偏移表
.data 存储已经初始化的全局和静态变量
.bss 存储未初始化的全局和静态变量
.comment 存储注释信息
readelf -h
分析不同类型ELF文件的差异
静态链接库
File: ./libmain(main.o)
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: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 456 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 12
Section header string table index: 11
动态链接库
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: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 64 (bytes into file)
Start of section headers: 98992 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 11
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 29
可执行文件
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: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1040
Start of program headers: 64 (bytes into file)
Start of section headers: 13920 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 29
Section header string table index: 28
从上面打印的三种可执行文件的表头我们可以看到,静态链接文件的Type为REL
动态链接库和可执行文件的Type为DYN
,但可执行文件的Entry point address
数据为 0x1040, 反汇编源代码后我们看到该地址指向的是_start函数起始位置。而其它类型的ELF文件的Entry point address
都指向的是0x00地址,标识首个函数的起始位置。
0000000000001040 :
1040: f3 0f 1e fa endbr64
1044: 31 ed xor %ebp,%ebp
1046: 49 89 d1 mov %rdx,%r9
1049: 5e pop %rsi
104a: 48 89 e2 mov %rsp,%rdx
104d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1051: 50 push %rax
1052: 54 push %rsp
1053: 45 31 c0 xor %r8d,%r8d
1056: 31 c9 xor %ecx,%ecx
1058: 48 8d 3d ca 00 00 00 lea 0xca(%rip),%rdi # 1129
105f: ff 15 73 2f 00 00 call *0x2f73(%rip) # 3fd8
1065: f4 hlt
1066: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
106d: 00 00 00