手写操作系统 - 8.ELF文件格式

231 阅读3分钟

ELF文件格式

B站视频链接 - 【209.ELF文件格式】

ELF(Executable and Linkable Format)是一种常用的可执行文件和可链接库格式。它是一种通用的二进制文件格式,用于在 Unix 和类 Unix 系统上进行可执行文件和库的存储和传输。

ELF文件的四种类型

  • 可执行文件(Executable File):包含可执行的机器代码,可以直接在操作系统中运行。
  • 可重定位文件(Relocatable File):机器代码和数据,但其地址空间是相对的,需要进行重定位才能正确运行。可重定位文件通常用于静态库和动态库的编译过程。
  • 共享对象文件(Shared Object File):这种类型的 ELF 文件是一种动态链接库(DLL),它包含了可共享的代码和数据,可以在运行时被多个进程共享。
  • 核心转储文件(Core Dump File):这种类型的 ELF 文件是操作系统在程序崩溃或异常终止时生成的,它包含了程序在崩溃时的内存状态和寄存器信息,用于调试和故障排除。
#define  ET_REL   1
#define  ET_EXEC  2
#define  ET_DYN   3
#define  ET_CORE  4

结构体定义

typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;

#define EI_NIDENT 16
typedef struct{
    /*ELF的一些标识信息,固定值*/
    unsigned char e_ident[EI_NIDENT];
    Elf32_Half e_type;
    /* 目标文件类型:1-可重定位文件,2-可执行文件,3-共享目标文件等 */
    Elf32_Half e_machine;
    /* 文件的目标体系结构类型:3-intel 80386 */    
    Elf32_Word e_version;
    /* 目标文件版本:1-当前版本 */    
    Elf32_Addr e_entry;
    /* 程序入口的虚拟地址,如果没有入口,可为0 */    
    Elf32_Off e_phoff;
    /* 程序头表(segment header table)的偏移量,如果没有,可为0 */    
    Elf32_Off e_shoff;
    /* 节区头表(section header table)的偏移量,没有可为0 */    
    Elf32_Word e_flags;
    /* 与文件相关的,特定于处理器的标志 */    
    Elf32_Half e_ehsize;
    /* ELF头部的大小,单位字节 */    
    Elf32_Half e_phentsize;
    /* 程序头表每个表项的大小,单位字节 */
    Elf32_Half e_phnum;
    /* 程序头表表项的个数 */
    Elf32_Half e_shentsize;
    /* 节区头表每个表项的大小,单位字节 */
    Elf32_Half e_shnum;
    /* 节区头表表项的数目 */
    Elf32_Half e_shstrndx;
    /* 某些节区中包含固定大小的项目,如符号表。对于这类节区,此成员给出每个表项的长度字节数 */
}Elf32_Ehdr;
typedef struct
{   
    Elf32_Word p_type;
    /* segment的类型:PT_LOAD= 1 可加载的段 */    
    Elf32_Off p_offset;
    /* 从文件头到该段第一个字节的偏移 */
    Elf32_Addr p_vaddr;
    /* 该段第一个字节被放到内存中的虚拟地址 */  
    Elf32_Addr p_paddr;
    /* 在linux中这个成员没有任何意义,值与p_vaddr相同 */
    Elf32_Word p_filesz;
    /* 该段在文件映像中所占的字节数 */
    Elf32_Word p_memsz;
    /* 该段在内存映像中占用的字节数 */
    Elf32_Word p_flags;
    /* 段标志 */
    Elf32_Word p_align;
    /* p_vaddr是否对齐 */
} Elf32_phdr;

文件头格式

  • e_ident[EI_NIDENT]
名称取值目的
EI_MAG00文件标识(0x7f)
EI_MAG11文件标识(E)
EI_MAG22文件标识(L)
EI_MAG33文件标识(F)
EI_CLASS4文件类
EI_DATA 5数据编码
EI_VERSION6文件版本
EI_PAD7补齐字节开始处
EI_NIDENT16e_ident[]大小