探索;实践的BLOG - 2024年4月
type: channel
link: https://blog.eptansuo.life/index.php/2024/04/
description: 一个简单的个人博客, 可以通过邮件eptansuo@126.com与我联系
items: ELF文件格式解析

ELF文件格式解析
type: item
date: 2024-04-14T11:09:25+08:00
description: 说明ELF文件格式可以通过键入命令man 5 elf来查看，本文介绍不如man手册详尽严谨，具体内容还需查看手册！对于使用C语言读取ELF文件，可以参考我写的代码：https://github.com/EPTansuo/elfread与ELF的文件信息相关的结构体在<elf.h>中定义。首先介绍下该头文件中定义的一些数据类型，其中的N=32或64：ElfN_Addr Unsigned program address, uintN_t ElfN_Off Unsigned file offset, uintN_t ElfN_Section Unsigned section index, uint16_t ElfN_Versym Unsigned version symbol information, uint16_t Elf_Byte unsigned char ElfN_Half uint16_t ElfN_Sword int32_t ElfN_Word uint32_t ElfN_Sxword int64_t ElfN_Xword uint64_tELF文件头ELF的文件头由结构体ElfN_Ehdr（ELF32_Ehdr或ELF64_Ehdr）来描述。#define EI_NIDENT 16 typedef struct { unsigned char e_ident[EI_NIDENT]; uint16_t e_type; uint16_t e_machine; uint32_t e_version; ElfN_Addr e_entry; ElfN_Off e_phoff; ElfN_Off e_shoff; uint32_t e_flags; uint16_t e_ehsize; uint16_t e_phentsize; uint16_t e_phnum; uint16_t e_shentsize; uint16_t e_shnum; uint16_t e_shstrndx; } ElfN_Ehdr;关于其成员的解释:e_ident: 16个字节的数组，包含文件的"magic numer"以及表征32位或64位的信息，还有大端小端的信息，以及OS/ABI的信息等。具体可查询man手册。e_type: 代表 了文件的类型，如可执行文件，动态链接库文件、核心转储文件等。e_machine：代表了架构的类型，如Intel 80386， ARM， PowerPC等。e_version: 文件的版本，但是只有EV_NONE(无效版本)和EV_CURRENT（当前版本）两个值。e_entry: 程序的入口地址e_phoff: 代表程序头表(program header table)偏移量。e_shoff: 代表节头表(section header table)偏移量。e_flags: 和处理器的编译选项或特性有关的标志。e_ehsize: 代表文件头的大小。e_phentsize: 代表程序头表的每个条目的大小，所有的条目都是相同的大小。e_phnum: 程序头表条目的数量。如果该值超过了0xffff，则该值设为0xffff，实际的条目数量存储在sh_info（见后文）中。e_shentsize: 代表节头表的每个条目的大小，所有的条目都是相同的大小。e_phnum: 节头表条目的数量。如果该值超过了0xff00，则该值设为0，实际的条目数量存储在sh_size（见后文）中。e_shstrndx: 节名称字符串表的索引。程序头（Program Header）程序头表由结构体Elf32_Phdr或者Elf64_Phdr组成的数组来存放。数组元素的大小由e_phentsize定义，元素的个数由e_phnum定义。typedef struct{ uint32_t p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; uint32_t p_filesz; uint32_t p_memsz; uint32_t p_flags; uint32_t p_align; } Elf32_Phdr; typedef struct{ uint32_t p_type; uint32_t p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; uint64_t p_filesz; uint64_t p_memsz; uint64_t p_align; } Elf64_Phdr; 注意：在32位和64位的系统中，p_flags在结构体中的位置是不同的，这是为了内存对齐，更高效处理数据。对其成员变量的…