代码可从 /usr/include/elf.h 中找到

Executable Header

以下是 ELF header 的结构体

1

接下来,我们详细解析下每个字段

e_ident

这是一个 16字节 的数组,主要包含的是 ELF header标识信息,(ident = identity)

以下解释每一个索引处的内容

  • 0-3:魔数,用于标识这是一个 ELF 文件,内容为 0x7f E L F

  • 4: EI_CLASS = 4,二进制文件是 32 还是 64 位架构

    • ELFCLASS32 = 1

    • ELFCLASS64 = 2

  • 5:EI_DATA = 5,架构是 大端序 还是 小端序

    • ELFDATA2LSB = 1,小端序

    • ELFDATA2MSB = 2,大端序

  • 6: EI_VERSION = 6ELF 文件格式的版本

    • EV_CURRENT = 1
  • 7:EI_OSABI = 7,确定 ABI 类型,默认值是0,即UNIX System V ABI

  • 8: EI_ABIVERSION = 8,确定 ABI 版本,默认值是0

  • 9-15:EI_PAD = 9,这段用作填充,设置为0,用于以后的扩展

e_type

确定该 ELF 文件的类型

  • ET_NONE = 0:无类型

  • ET_REL = 1:可重定位文件

  • ET_EXEC = 2:可执行文件

  • ET_DYN = 3:动态库,或者叫共享目标文件

  • ET_CORE = 4: 核心转储文件

e_machine

确定该文件可运行的目标架构

  • EM_X86_64 = 62:x86_64 平台

  • EM_386 = 3: x86 平台

  • EM_ARM = 40:arm 平台

...

e_version

确定 ELF 文件格式的版本

  • EV_CURRENT = 1

e_entry

确定该文件的 入口点,当 动态链接器 结束加载 动态库 之后,需要将控制权移交到此处

这个字段的值是 虚拟地址

e_phoff

program header table文件偏移量,不是 虚拟地址

值为0,表示没有 segemnt

e_shoff

section header table文件偏移量,不是 虚拟地址

值为0,表示没有 section

e_flag

ELF 文件中用于存储与架构相关的标志,一般设置为0

e_ehsize

Executable header 的大小

e_phentsize

program header table 中每个条目的大小,即一个 program header 的大小

e_phnum

program header table 中的条目数量

e_shentsize

section header table 中每个条目的大小,即一个 section header 的大小

e_shnum

section header table 中的条目数量

e_shstrndx

一个 sectionsection header table 中的索引,这个 section 是一个特殊的 string table,里面包含的字符串是 ELF 文件中的各个 section 的名字

Section Headers

1

sh_name

确定当前 section header 的名字

值表示在 .shstrtab 中的下标,如果为0,表示没有名字

sh_type

确定 section 的类型

  • SHT_PROGBITS = 1,包含程序数据(指令和常量)

  • SHT_SYMTAB = 2,符号表(静态,用于链接器)

  • SHT_STRTAB = 3, 字符串表

  • SHT_DYNSYM = 11,符号表(动态,用于动态链接器)

  • SHT_REL = 9 静态链接的重定位信息

  • SHT_RELA = 4 静态链接的重定位信息(包含额外添加值 addend

  • SHT_DYNAMIC = 6 动态链接所需信息

...

sh_flags

描述了 section 的附加信息

  • SHF_WRITE = 1,运行时可写

  • SHF_ALLOC = 2,执行时被加载到虚拟内存中

  • SHF_EXECINSTR = 4,包含可执行的指令

...

sh_addr

section虚拟地址,用于链接的重定位,如果为0,表示不需要加载到虚拟内存中

sh_offset

section文件偏移量

sh_size

section大小

用于表示与当前 section 有关联的其他 section索引,帮助链接器识别并处理 sectionsection 之间的 关联

sh_info

包含了当前 section额外信息(具体内容取决于 section类型

sh_addralign

当前 section内存对齐要求,0和1表示没有对齐要求

sh_entsize

有一些 section,比如符号表,会有对应的 结构体,这个字段就包含了每个条目(即使用的结构体)的大小,如果不使用,就设置为0

Sections

.init 和 .fini

section .init 包含 执行初始化任务 的代码,SHF_EXECINSTR,操作系统在将控制转移至 entry point 前,会先执行这里的代码,相当于 构造函数.fini.init 的作用相反,相当于 析构函数

.text

代码段

.bss, .data, .rodata

  • .rodata 只读数据,存放常量

  • .data 存放初始化的全局/静态变量

  • .bss 存放未初始化的全局/静态变量,又被称为 零初始化段,不占用磁盘空间,当程序运行时才分配实际空间

延迟绑定和 .plt, .got, .got.plt

Program Headers

1

p_type

确定了 segment 的类型

  • PT_LOAD = 1, 存储程序的可执行部分和数据部分,程序在加载时会将这些内容加载到内存中

  • PT_DYNAMIC = 2,指定了用于加载该程序的解释器(通常是动态链接器)

  • PT_INTERP = 3,包含动态链接相关信息,帮助解释器加载并解析程序

  • PT_PHDR = 6,包含 program header table

p_flags

确定了运行时对 segment 的访问权限

  • PF_X = 1,可执行

  • PF_W = 2,可写

  • PF_R = 4,可读

p_offset

当前 segment文件偏移量

p_vaddr

当前 segment虚拟地址 (被加载到这个地址处)

p_paddr

当前 segment物理地址,一般被设置为0,表示不使用

p_filesz

当前 segment在磁盘文件中所占的大小(不包括 .bss 这种零初始化段,因为全都是0,所以不需要存储在磁盘中,节省空间**

p_memsz

当前 segment 在运行时,分配到的虚拟空间的大小(包括 .bss 这种零初始化段,所以有时候可能会比 p_filesz 大)

p_align

确定当前 segment内存对齐数

0和1表示不需要进行对齐

Summary

1

 posted on 2025-05-25 23:14  Dylaris  阅读(47)  评论(0)    收藏  举报