ELF文件有32位版本和64位版本,故其头文件结构也有32位结构和64位结构,分别定义为Elf32_Ehdr和Elf64_Ehdr。两种版本文件内容一样,只是有些成员的大小不一样。由于SPARC-V8是32位架构,所以以下只分析32位ELF文件头。以下是32位版本的文件头结构Elf32_Ehdr:
1、头部定义的数据结构
- typedef struct{
- unsigned char e_ident[EI_NIDENT]; //最开头是16个字节的e_ident, 其中包含用以表示ELF文件的字符,以及其他一些与机器无关的信息。开头的4个字节值固定不变,为0x7f和ELF三个字符。
- Elf32_Half e_type; //该文件的类型 2
- Elf32_Half e_machine; //该程序需要的体系结构 2
- Elf32_Word e_version; //文件的版本 4
- Elf32_Addr e_entry; //程序的入口地址 4
- Elf32_Off e_phoff; //Program header table 在文件中的偏移量 4
- Elf32_Off e_shoff; //Section header table 在文件中的偏移量 4
- Elf32_Word e_flags; //对IA32而言,此项为0。 4
- Elf32_Half e_ehsize; //表示ELF header大小 2
- Elf32_Half e_phentsize; //表示Program header table中每一个条目的大小 2
- Elf32_Half e_phnum; //表示Program header table中有多少个条目 2
- Elf32_Half e_shentsize; //表示Section header table中的每一个条目的大小 2
- Elf32_Half e_shnum; //表示Section header table中有多少个条目 2
- Elf32_Half e_shstrndx; //包含节名称的字符串是第几个节 2
- }Elf32_Ehdr;
复制代码 2、数据类型说明
名称
| 大小
| 对齐
| 用途
| Elf32_Addr
| 4
| 4
| 无符号程序地址
| Elf32_Half
| 2
| 2
| 无符号中等大小整数
| Elf32_Off
| 4
| 4
| 无符号文件偏移
| Elf32_Sword
| 4
| 4
| 有符号大整数
| Elf32_Word
| 4
| 4
| 无符号大整数
| unsigned char
| 1
| 1
| 无符号小整数
|
3、ELF头存储结构
4、ELF头解析
由readelf -h nuttx.elf 可得如下输出:
- zouboan@T450:~/NuttX/nuttx$ readelf -h nuttx.elf
- ELF Header:
- Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
- Class: ELF32
- Data: 2's complement, big endian
- Version: 1 (current)
- OS/ABI: UNIX - System V
- ABI Version: 0
- Type: EXEC (Executable file)
- Machine: Sparc
- Version: 0x1
- Entry point address: 0x20001000
- Start of program headers: 52 (bytes into file)
- Start of section headers: 835764 (bytes into file)
- Flags: 0x0
- Size of this header: 52 (bytes)
- Size of program headers: 32 (bytes)
- Number of program headers: 1
- Size of section headers: 40 (bytes)
- Number of section headers: 17
- Section header string table index: 16
复制代码 下面对读取的ELF头进行注释
- zouboan@T450:~/NuttX/nuttx$ readelf -h nuttx.elf
- ELF Header:
- Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00 //Magic 魔数,用来指名该文件是一个 ELF 目标文件。第一个字节 7F 是个固定的数;后面的 3 个字节正是 E, L, F 三个字母的 ASCII 形式。
- Class: ELF32 //CLASS 表示文件类型,这里是 32位的 ELF 格式。
- Data: 2's complement,big endian //Data 表示文件中的数据是按照什么格式组织(大端或小端)的,不同处理器平台数据组织格式可能就不同,如SPARC平台为大端存储格式。
- Version: 1 (current) //当前 ELF 文件头版本号,这里版本号为 1 。
- OS/ABI: UNIX - System V //OS/ABI ,指出操作系统类型,ABI 是 Application Binary Interface 的缩写。
- ABI Version: 0 //ABI 版本号,当前为 0 。
- Type: EXEC (Executable file) //Type 表示文件类型。ELF 文件有 3 种类型,一种是如上所示的 Relocatable file 可重定位目标文件,一种是可执行文件(Executable),另外一种是共享库(Shared Library) 。
- Machine: Sparc //机器平台类型。
- Version: 0x1 //当前目标文件的版本号。
- Entry point address: 0x20001000 //程序进入点指当程序真正执行起来的时候,其第1条要运行的指令地址。因为可重入文件只是供再链接而已,所以它不存在进入点,而可执行文件和动态库文件都存在所谓进入点。
- Start of program headers: 52 (bytes into file) //因为这nuttx.elf是可运行的程序,故而这里为52。
- Start of section headers: 835764 (bytes into file) //sections 头开始处,这里 835764 是十进制,表示从地址偏移 835764处开始。
- Flags: 0x0 //是一个与处理器相关联的标志,sparc平台上该处为 0 。
- Size of this header: 52 (bytes) //ELF 文件头的字节数
- Size of program headers: 32 (bytes) //因为这个是可执行程序,故此处大小为 32。
- Number of program headers: 1 //因为这个是可执行程序,故此处大小为1。
- Size of section headers: 40 (bytes) //sections header 的大小,这里每个 section 头大小为 40个字节。
- Number of section headers: 17 //一共有多少个 section 头,这里是 17 个。
- Section header string table index: 16
复制代码- 我们将Elf32_Ehdr结构与readelf命令输出的信息对比可得如下对应关系:
成员 | readelf输出结果 | e_ident | Magic,类别,数据,版本,OS/ABI,ABI | e_type | 类型 | e_machine | 系统架构 | e_version | 版本 | e_entry | 入口点地址 | e_phoff | start of program headers | e_shoff | start of section headers | e_flags | 标志 | e_ehsize | 文件头的大小 | e_phentsize | 程序头大小 | e_phnum | number of program headers | e_shentsize | 节头大小 | e_shnum | number of program headers | e_shstrndx | 字符串表段索引 |
下面我们依次分析各个部分。 魔数:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
7f 、45、4c、46分别对应ascii码的Del(删除)、字母E、字母L、字母F。这四个字节被称为ELF文件的魔数,操作系统在加载可执行文件时会确认魔数是否正确,如果不正确则拒绝加载。
第五个字节标识ELF文件是32位(01)还是64位(02)的。
第六个字节标识该ELF文件字节序是小端(01)还是大端(02)的。
第七个字节指示ELF文件的版本号,一般是01。
后九个字节ELF标准未做定义。一般为00. 文件类型:
类型: REL (可重定位文件)
e_type成员标识文件类型,ELF文件有三种类型,如下表所示。 常量标识 | 值 | 类型 | ET_REL | 1 | 可重定位文件,一般位.o文件 | ET_EXEC | 2 | 可执行文件 | ET_DYN | 3 | 共享目标文件,一般位.so文件 |
|