ELF
更新于2023-11-24
可执行可链接格式(executable and linkable format, ELF)
使用ELF格式的文件
- 可执行文件
- 可重定位文件(Relocatable File),
.o - 共享对象文件(Shared Object File),
.so .a - coredump
组成
- ELF头
- 程序头表,描述若干个内存段
- 节头表,描述若干个节
- data entries
- 符号
- 重定位
- 动态链接
- 编码ELF解释器
- 重定向入口
- 数据动态链接信息
ELF头
ELF头(ELF Header)是每个ELF文件的第一个部分,包含了文件的基本信息和控制信息。它的结构定义了文件的类型、目标架构、入口点地址、程序头表和节头表的位置和大小等。
ELF头结构
ELF头的结构如下:
e_ident:一个16字节的数组,包含魔数、文件类型、目标架构等信息。e_type:文件类型,如可执行文件、重定位文件、共享对象文件等。e_machine:目标架构,如x86、x86-64、ARM等。e_version:ELF版本。e_entry:程序入口点的虚拟地址。e_phoff:程序头表在文件中的偏移。e_shoff:节头表在文件中的偏移。e_flags:与处理器相关的标志。e_ehsize:ELF头的大小。e_phentsize:程序头表中每个条目的大小。e_phnum:程序头表中的条目数。e_shentsize:节头表中每个条目的大小。e_shnum:节头表中的条目数。e_shstrndx:节头字符串表的索引。
示例
以下是一个简单的ELF头表示例:
shell
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: 0x400080
Start of program headers: 64 (bytes into file)
Start of section headers: 0x200 (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: 29
Section header string table index: 28程序头
程序头表(Program Header Table)描述了一个可执行文件或共享对象文件的内存布局。每个程序头条目(Program Header Entry)定义了一个段(Segment),包括段的类型、文件中的位置、内存中的位置、大小、权限等信息。程序头表在程序加载时被操作系统用来将文件中的各个段映射到内存中。
程序头条目类型
常见的程序头条目类型包括:
PT_NULL:无效的条目PT_LOAD:可加载段PT_DYNAMIC:动态链接信息PT_INTERP:解释器路径PT_NOTE:附加信息PT_SHLIB:保留类型PT_PHDR:程序头表自身PT_TLS:线程局部存储段
示例
以下是一个简单的程序头表示例:
shell
readelf -l a.out输出示例:
Elf file type is EXEC (Executable file)
Entry point 0x400080
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x00400040 0x00400040 0x0001c 0x0001c R 0x8
INTERP 0x00005c 0x0040005c 0x0040005c 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x00400000 0x00400000 0x001000 0x001000 R E 0x200000
LOAD 0x001000 0x00601000 0x00601000 0x000004 0x000004 RW 0x200000
DYNAMIC 0x000f98 0x00600f98 0x00600f98 0x0000d0 0x0000d0 RW 0x8
NOTE 0x000070 0x00400070 0x00400070 0x000024 0x000024 R 0x4
GNU_EH_FRAME 0x000f5c 0x00600f5c 0x00600f5c 0x000004 0x000004 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x000f98 0x00600f98 0x00600f98 0x000068 0x000068 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 .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got节头
符号
重定位
动态链接
编码ELF解释器

| 名字 | 类型 | 说明 |
|---|---|---|
| NULL | ||
| .interp | PROGBITS | |
| .note.gnu.pr[...] | NOTE | |
| .note.gnu.bu[...] | NOTE | |
| .note.ABI-tag | NOTE | |
| .gnu.hash | GNU_HASH | |
| .dynsym | DYNSYM | |
| .dynstr | STRTAB | |
| .gnu.version | VERSYM | |
| .gnu.version_r | VERNEED | |
| .rela.dyn | RELA | |
| .rela.plt | RELA | |
| .init | PROGBITS | |
| .plt | PROGBITS | 过程链接表 |
| .plt.got | PROGBITS | |
| .plt.sec | PROGBITS | |
| .text | PROGBITS | 程序代码指令 |
| .fini | PROGBITS | |
| .rodata | PROGBITS | 只读数据 |
| .eh_frame_hdr | PROGBITS | |
| .eh_frame | PROGBITS | |
| .init_array | INIT_ARRAY | |
| .fini_array | FINI_ARRAY | |
| .dynamic | DYNAMIC | |
| .got | PROGBITS | |
| .data | PROGBITS | 已经初始化的全局变量和静态变量 |
| .bss | NOBITS | 未初始化或初始化为0的全局变量和静态变量 |
| .comment | PROGBITS | |
| .symtab | SYMTAB | |
| .strtab | STRTAB | 一个符号表存放程序中定义和引用的函数和全局变量信息;不包含局部变量信息 |
| .shstrtab | STRTAB | |
| .debug | 调试符号表;通过-g添加 | |
| .rel.text | .text节中位置的列表;链接时,需要将修改这些位置 | |
| .rel.data | 被模块引用和定义的所有全局变量的重定位信息 | |
| .line | 源程序的行号和.text节中机器指令之间的映射,通过-g添加 | |
| strtab | 字符串表;包含.symtab和.debug节中的符号表 | |
| .ctors | 指向构造函数的指针 | |
| .dtors | 指向析构函数的指针 |
text段
.txt .rodata .hash .dynsym .dynstr .plt .rel.got
data段
.data .dybanic .got.plt .bss
shell
#查询ELF文件的信息
readelf -a a.out
#查询节头表
readelf -S a.out
#查询程序头表
readelf -s a.out
#查询文件头数据
readelf -e a.out
#查询重定向入口
readelf -r a.out
#查询动态段
readelf -d a.out符号
- 模块定义被其他模块引用的全局符号。非静态函数和全局变量。
- 模块引用其他模块定义的全局符号,这些符号也叫
外部符号。其他模块的非静态函数和全局变量。 - 模块内定义和引用的局部符号。static属性的函数和全局变量。
符号表
.systab节中包含ELF符号表