ELF文件格式

道家修今生,佛家修来世.


介绍

目前主流的可执行文件 格式 有 两种, Windows 平 台下 的 PE 文件 格式 和 Linux 平 台下 的 ELF 文件 格式。

Linux 使用 ELF 作为 目标 文件 的 格式。 从前 Linux 中 目标 文件 以 a. out 格式 为主, 不过 由于 a. out 格式 不能 很好 地支 持 动态链接以及 C++, 因此其主流地位 逐渐被 ELF 格式所取代。

 

在 Linux 平台 下, 除了 可执行文件( Executable File), 可重定位目标文件( Relocatable Object File)、 共享目标 文件( Shared Object File)、 核心转储文件( Core Dump File) 也是 ELF 格式 的 文件。

(将上图中的 "段" 改成 "节")

在 ELF 文件 中, 保存的最关键的信息 是 程序中的 代码 和 数据。 一般 的, 程序的代码 以 二进制指令 的 形式保存 在代码段(. text) 中, 程序的数据 以二进制的形式 保存在 数据段(. data)或“. bss” 段中。   

ELF 文件 的 其他结构, 一般用于对 ELF 文件内容进行管理, 为 链接器、 加载器、 调试器、 操作系统等提供必要的信息。

 使用ELF格式的目的只有 一个, 那就是把机器代码 及其对应的 元数据以方便 链接器 和 加载器 处理的形式保存起来。

 

在 Linux 系统 的“/ usr/ include/ elf. h” 头 文件 中, 定义了 ELF 文件涉及的所有数据结构。

(bss段与data段, rodata的区别: https://blog.csdn.net/qq_35865125/article/details/105333719

 


ELF的节和段

为了 兼顾 链接器、 汇编器等 编译工具 以及把程序加载 到内存中的 加载器 两者 的 易用 性 需求, ELF 文件 的 结构 正在 逐步 转变 成 二元 结构。 下面 详细 讲解 二元结构。

下图 粗略 地 表示 了 ELF 文件 的 构造。 如果 以 程序 头( program header) 信息 来 处理, 则 ELF 文件 可以 解释 成段集合;

如果 以 节头( section header) 信息 来 处理, 则可以解 释 成节集合。  ---- 从逻辑上进行区块划分。

节( section) 是 汇编器、 链接器 等 处理 ELF 文件内容 的 单位。 ELF 文件把不同目的的 代码、 数据等分割成节保存。 譬如 机器码 统一 保存到 .text 节 中, 全局变量的初始化 数据则保存 在 .data 节 中。---各个section的位置由 section header table描述。

 

段( segment) 则是把程序加载到内存的加载器 处理 ELF 文件 时 的 单位。 段 由 1 个 以上 的 节 构成。 内存上不同范围 有着“ 只读”“ 可写”“ 可执行” 等 不同属性, 因而需要根据属性 进行分段。 譬如 机器码 如果不 可执行 就 毫无意义, 因此 要 统一 到 具有 可执行属性的段中。 ---各个segment的位置由 program header table 描述。

 

ELF头(ELF header)

ELF 文件头描述了 文件格式、 平台环境 以及文件结构  信息, 其数据结构定义为:

第 1~ 4 行 描述 了 ELF 文件 数据 结构 常用 的 数据 类型, 第 5 行 定义 了 ELF 文件 头 魔 数 字段 的 长度, 结构 体 Elf32_ Ehdr 描述 了 ELF 文件 头数 据 结构。 ELF 文件 头 的 每个 字段 的 含义 如下。

1) e_ ident 称为 ELF 文件 的 魔 数, 是 16 字节 长的 数组, 用于 标识 ELF 文件 格式、 数据 存储 的 字节 序、 ELF 版本 等 信息。 常见 的 初始 值 为:

71 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00

其中 前 4 字节 为 DEL 控制 字符 和 字符“ E”、“ L”、“ F” 对应 的 ASCLL 码, 对于 任意 ELF 文件, 这 4 字节 的 值 是 固定 的。 第 5 字节 表示 文件 类别, 0 表示 无效 文件、 1 表示 32 位 ELF 文件、 2 表示 64 位 ELF 文件, 我们 只 使用 32 位 ELF 文件, 取值 ELFCLASS32。 第 6 字节 表示 字节 序, 0 表示 无效 格式、 1 表示 小 端 字节 序、 2 表示 大端 字节 序, 我们 使用 小 端 字节 序, 取值 ELFDATA2LSB。 第 7 字节 表示 ELF 版本, 默认 为 1, 取值 EV_ CURRENT, 表示 当前 版 本号。 后面 的 9 字节 在 ELF 标准 中 未定义, 一般 用于 平台 相关 的 扩展 标志。 在 Linux 系统 中, 第 8 字节 取值 ELFOSABI_ NONE= 0, 表示 UNIX 系统, 第 9 字节 取值 0, 表示 系统 ABI( Application Binary Interface) 版本 为 0。 其他 字节 默认 为 0。

2) e_ type 表示 ELF 文件 类型, 0 表示 无效 文件 类型、 1 表示 可 重定 位 目标 文件、 2 表示 可执行 文件、 3 表示 共享 目标 文件、 4 表示 核心 转储 文件。 我们 设计 的 汇编 器 输出 可 重定 位 目标 文件, 该 字段 取值 为 ET_ REL。 静态 链接 器 输出 可执行 文件, 该 字段 取值 为 ET_ EXEC。

3) e_ machine 表示 ELF 所在 的 机器 类型, 例如 3 表示 Intel 80386 体系 结构、 40 表示 Arm 体系 结构。 我们 生成 x86 平台 的 ELF 文件, 该 字段 取值 为 EM_ 386。

4) e_ version 表示 ELF 文件 的 版本, 一般 取值 1, 即 EV_ CURRENT。

5) e_ entry 表示 ELF 文件程序的入口线性 地址, 一般 用于 ELF 可执行 文件。 对于 可 重定 位 目标 文件, 该 字段 设置 为 0。

6) e_ phoff 表示 程序头表 在 ELF 文件 内 的 偏移 地址, 标识 了 程序 头 表 在 文件 内 的 位置。

7) e_ shoff 表示 段表 在 ELF 文件 内 的 偏移 地址, 标识 了 段 表 在 文件 内 的 位置。

8) e_ flags 表示 ELF 文件平台相关的属性, 一般默认为 0。

9) e_ ehsize 表示 ELF 文件 头 的 大小, 即 sizeof( Elf32_ Ehdr)= 52 字节。

10) e_ phentsize 表示 程序头表项 的 大小, 即 sizeof( Elf32_ Phdr)= 32 字节。

11) e_ phnum 表示 程序头表项的 个数, 因此 可以 确定 程序头表 在 ELF 文件偏移 e_ phoff 到 e_ phoff+ e_ phentsize* e_ phnum 的 数据 块 中。

    --- 也就是说程序头表是一块连续区域,包括多个程序头表项目,每个项的大小是相同的。

12) e_ shentsize 表示 section表项的大小, 即 sizeof( Elf32_ Shdr)= 40 字节。

13) e_ shnum 表示 sectioin表项 的 个数, 因此 可以 确定段表在ELF文件偏移 e_ shoff 到 e_ shoff+ e_ shentsize* e_ shnum 的 数据 块 中。

     --- 也就是说section表是一块连续区域,包括多个section表项目,每个section表项的大小是相同的。

14) e_ shstrndx 表示 段表 字符串表 所在段在段表中的索引。

使用命令“ readelf -h file. o” 可以 查看 ELF 文件 头 的 完整 信息:

从 输出 信息 中 可以 看出, 该 文件 为 可 重定 位 目标 文件, 程序 入口 点 为 0。 程序 头 表 文件 偏移 为 0, 程序 头 表项 大小 为 0, 程序 头 表项 的 个数 为 0, 因此 不存在 程序头表。 --- 程序头表格是给加载器用的,目标文件不可以被加载器处理哦。

section表 文件 偏移为 224 字节, sectioin表项大小为40 字节, section表项 个数 为 11 个, 因此 文件 224 字节 到 224+ 11* 40= 664 处保存 了 section表的内容。

通过 ELF 文件 头, 可以 访问 到 ELF 内 两个 最 关键 的 数据 结构: section头表( Section Header Table) 和 程序头 表( Program Header Table)。

 

section header table

section header table 包含了多个项, 每个项记录了一个section 的相关信息, 比如 section的 名称、位置、大小、属性等信息。 项的数据结构定义 为:

typedef struct{ 
Elf32_ Word sh_ name; //section名 
Elf32_ Word sh_ type; //section 类型 
Elf32_ Word sh_ flags; //section 标志 
Elf32_ Addr sh_ addr; //section 虚拟基址 
Elf32_ Off sh_ offset; //section 文件偏移 
Elf32_ Word sh_ size; //section 大小 
Elf32_ Word sh_ link; //section 链接 信息 1 
Elf32_ Word sh_ info; //section段 链接 信息 2 
Elf32_ Word sh_ addralign; //section 对齐 方式 
Elf32_ Word sh_ entsize; //项 大小 
} Elf32_ Shdr;

1) sh_ name 是 一个 4 字节偏移量, 记录 了section名 字符串在  “section表字符串表”  内的偏移。

---即存了一个地址,该地址对应一个字符串,且该字符串也存在一个section中,该section也对应着一个section header table中的项。

section表字符串表 并非表的形式, 而是 一个文件 块, 保存了 所有的 sectioin表 字符串 内容, 存储 在 名为“. shstrtab” 的 section 中。 根据“. shstrtab”  的 偏移, 加上 sh_ name 便可 以 访问 到 每个 section对应 的 section名字符串, 因此 欲解析section名 必须 访问“. shstrtab” section。

然而,“. shstrtab” section 的 信息 也 是以 section表项 存储 在section header table内的, 欲 访问“. shstrtab” 段 必须 先 访问 section header table。 这样, 问题 好像 陷入 了 一个 section表、“. shstrtab” section、 section表 的“ 死 循环” 中, 而 ELF 文件 头 的 e- shstrndx 字段 的 意义 在此 便 体现 出来。 e- shstrndx 字段记录 sectioin表字符串表 所在 的“. shstrtab” section 对应 的 section表项 在 section header table内 的 索引, 根据 该 索引, 可以 定位 到“. shstrtab” section表项 的 位置.

2) sh_ type 表示section 的 类型

其中 1 表示 程序section, 取值 SHT_ PROGBITS, 比如 代码 段“. text”、 数据 段“. data” 等。

2 表示 符号表section, 取值 SHT_ SYMTAB, 如 符号表section “. symtab”。

3 表示 串表section, 取值 SHT_ STRTAB, 如 section表的字符串表section“. shstrtab” 和 串表section“. strtab”。

8 表示 无 内容section, 取值 SHT_ NOBITS, 比如“. bss” section。

9 表示重定位表section, 取值 SHT_ REL, 比如 重定位表section“. rel. text” 和“. rel. data” 等。

3) sh_ flags 为 段 标志, 记录 段 的 属性。

其中 0 表示 默认属性。 1表示段可写, 取值 SHF_ WRITE。

2 表示段加载后 需要为之分配 内存空间, 取值 SHF_ ALLOC。

4 表示 段可以 执行, 取值 SHF_ EXECINSTR。

段 标志 属性 可以 进行 复合, 比如 代码section “. text” 属性 为 可分配、 可执行、 不可写, 因此 其 段 属性 为 SHF_ ALLOC| SHF_ EXECINSTR。 而 数据section “. data” 或“. bss” section 属性 为可分配、 可写、 不可执行, 因此 其section属性 为 SHF_ ALLOC| SHF_ WRITE。 对于 一般 的section, 如果 需要 分配 内存 则 取值 SHF_ ALLOC, 如果不 需要 配 内存 则 取 默认值 0 即可。

4)sh_ addr 表示 section加载 后的 线性地址。 在 可 重定 位 目标 文件 内, 无法 确定section的 虚拟 地址, 故 设为 默认值 0。 在 可执行 文件 内, 链接器会计算出需 加载的段 的 线性 地址。

5) sh_ offset 表示 section 在 文件 内 的 偏移, 根据 此 偏移 可以 确定 段 的 位置, 读取 段 的 内容。

6) sh_ size 表示 section 的 大小, 单位 为 字节。 需要 注意 的 是, 如果 section类型 为 SHT_ NOBITS, section内 是 没有 数据 的, 那么 section大小 并非 指 文件 块 的 大小, 而 是指 sectioin加载 后 占用 内存 的 大小。

7) sh_ link 和 sh_ info 表示section的链接信息, 一般 用 描述 符号表section 和 重定位表section的 链接 信息。 对于 符号表 section( 段类型

为 SHT_ SYMTAB), sh_ link 记录 符号表 使用的 串表 所在段( 一般 是“. strtab”) 对应段表项在段表内的 索引。 就 像 section表项 的 sh_ name 记录 段 名字 符 串在 section表 字符串 表 所在 section“. shstrtab” 的 偏移 一样, 符号表项 的 st_ name 记录 符号 名字 符 串在 字符串 表 所在 section“. strtab” 的 偏移, 而 sh_ info 记录 符号 表内 最后 一个 局部 符号 的 符号 表项 在 符号 表内 的 索引+ 1, 一般 恰好 是 第一个 全局 符号 的 符号 表项 的 索引, 这可 以 帮助 链接 器 更快 地 定位 到 第一个 全局 符号。 对于 重 定位 表 段( 段 类型 为 SHT_ REL), sh_ link 记录 重 定位 表 使用 的 符号 表 段( 一般 是“. symtab”) 对应 段 表项 在 段 表内 的 索引, 而 sh_ info 记录 重定 位 所作 用的 段 对应 的 段 表项 在 段 表内 的 索引。

一般 的, 重 定位 表 段“. rel. text” 作用于 代码 段“. text”,“. rel. data” 作用于 数据 段“. data”。 对于 其他 类型 的 段, 如无 特殊要求, sh_ link 和 sh_ info 默认 为 0。

8) sh_ addralign 表示 段 的 对齐 方式, 对齐 规则 为 sh_ offset% sh_ addralign= 0, 即 段 的 文件 偏移 必须 是 sh_ addralign 的 整 数倍。 sh_ addralign 取值 必须 是 2 的 整数 幂, 如 1、 2、 4、 8 等, 特别 地, 如果 sh_ addralign 取值 0 或 1 表示 无对 齐 要求。 比如“. text” 段 的 文件 偏移 为 118 字节, 对齐 大小 为 4 字节, 那么 对齐 后 新的 文件 偏移 为 120 字节, 第 118~ 119 字节 的 两字 节 数据 被“ 空出”, 需要 使用 数据 填充。 数据 填充 一般 使用 0x00, 但是 对于 代码 段 数据, 使用 字节 0x90 填充 会 更好, 它们 对应 汇编 指令“ nop”, 不会 影响 代码 的 执行。

 

Program header table(程序头表)

ELF 文件 的 程序 头 表 与 段 表 是 相互 独立 的, 它们由 ELF 文件头统一管理。 程序头表管理 ELF 文件加载 后, ELF文件内可加载段 到 内存镜像 的 映射关系, 一般 只有 可执行文件 包含 程序头表。 程序 头 表 包含 多个 程序头表项, 程序头表项 描述的对象称为“ Segment”。

程序头表项记录了每个段的相关信息, 比如段的类型、 对应文件的位置、 大小、 属性等信息, 这些信息与section表描述的节信息是相互独立 的。 程序头表项的数据 结构 定义 为:

结构体 Elf32_ Phdr 描述 了 ELF 文件 程序 头 表项 的 数据 结构, 其 每个 字段 的 含义 如下。

1) p_ type 表示 段 的 类型, 这里 我们 只 关心 可 加载 的 段, 取值 为 PT_ LOAD。

2) p_ offset 表示段 对应的内容在 文件内的偏移。

3) p_ vaddr 表示段在内存的线性地址。

4) p_ paddr 表示 段 在 内存 的 物理 地址, 由于 现代 操作系统 中 使用 了 分页 机制, 因此 不需要 关心 段 的 物理 地址, 一般 该 字段 值 与 p_ vaddr 相同。 但是 对于 未使用 分页 机制 的 系统, 该 字段 可以 另行 设置。

5) p_ filesz 表示 段 在 文件内 的 大小。

6) p_ memsz 表示 段 在内存 的 大小。

我们 可以 总结 出 字段 2、 3、 5、 6 表达 的 含义 为: ELF 文件 内 从 p_ offset 开始 的 p_ filesz 大小 的 数据块 被 加载到 内存 以

p_ vaddr 开始 的 p_ memsz 大小 的 内存块 中。 由于 段 的 内容 需要 完整 加载 到 内存, 因此 p_ memsz 字段 的 值 一般 等于 p_ filesz。 但是 对于 类型 为 SHT_ NOBITS 的 节, 在 ELF 文件 内 不存在 数据。 例如“. bss” 节, 它在 ELF 文件 内 的 大小 为 0, 如果 加载 到 内存 后 大小 大于 0, 那么 其 对应 的 程序 头 表项 的 p_ filesz 等于 0, 而 p_ memsz 为 一个 正 整数。

7) p_ flags 表示 段标志, 与段表项 的 sh_ flags 类似, 描述 了 段 的 属性( 权限)。

1 表示 可执行, 取值 为 PF_ X。

2 表示 可 写, 取值 为 PF_ W。

4 表示 可读, 取值 为 PF_ R。 段 标志 可以 进行 复合。

8) p_ align 表示 段 对齐 方式, 对齐 规则 为 p_ vaddr% p_ align= 0, 即 段 的 线性 地址 必须 是 p_ align 的 整 数倍。 一般 情况下, p_ align 取值 为 0x1000= 4096, 即 Linux 操作系统 默认的页大小。

段到内存空间的映射,具体看《自己动手构造编译系统:编译、汇编与链接》的5.2.3.

通过 ELF 文件 的 程序 头 表, 可以 为 加载 器 提供 可执行 文件 的 详细 加载 信息, 包括 哪些 文件 内容 需要 加载、 加载 到 进程 地址 空间 的 哪个 位置、 页面 的 权限 等 信息。

 

符号表

       符号是表示每个ELF文件的一个重要部分,因为它保存了程序实现或使用的所有(全局)变量和函数。

符号表 一般 保存 在 名为“. symtab” 的 section内, 该section对应 section header table中的 类型为 SHT_ SYMTAB的项。

符号表包含 多个符号表项(就像section header table包含多个项), 每个符号表项 记录 了 符号的 名称、 位置、 类型 等 信息, (self: 一个符号表项对应一个符号吧)。

符号表项的数据结构定义为:

1) st_ name 是 一个 4 字节 字段, 记录 了 符号 名字 符 串在 字符串 表 的 偏移。

2) st_ value 记录 了 符 号的 值, 一般 在 可 重定 位 目标 文件 内, 该 值 记录 了 符号 相对于 所在 段 基址 的 偏移量, 而在 可执行 文件 内, 该 值 记录 了 符号 的 线性 地址.

3) st_ size 表示 符号 的 大小, 单位 为 字节。

4) st_ info 大小 为 一个 字节, 表示 符号类型 相关 的 信息,

其 低 4 位 表示 符号 的 类型 使用 宏 ELF32_ ST_ TYPE 获取, 高 4 位 表示 符 号的 绑 定 信息, 使用 宏 ELF32_ ST_ BIND 获取。    

符号 类型 为 0 时 表示 未知 类型, 取值 STT_ NOTYPE。 1 表示 数据 对象, 比如 变量、 数组 等, 取值 STT_ OBJECT。 2 表示 函数, 取值 STT_ FUNC。 3 表示 段, 取值 STT_ SECTION。 4 表示 文件名, 取值 STT_ FILE。

符号 绑 定 信息 为 0 时 表示 局部 符号, 取值 STB_ LOCAL。 1 表示 全局 符号, 取值 STB_ GLOBAL。 2 表示 弱 符号, 取值 STB_ WEAK。

5) st_ other 没有 实际 含义, 默认 为 0。

6) st_ shndx 表示 符号 所在section对应 的 sectioin表项 在 section header table内 的 索引, 一般 取值 为 正 整数。

 

 

重定位表

重定位表 常见于 可重定位目标 文件 内, 对于 静态 链接 生成 的 可执行 文件, 一般 不 包含 重 定位 表。 重 定位 表 一般 保 存在 以 名为“. rel” 开头 的 section内, 该 section对应 section header table表项 的 类型 为 SHT_ REL。

ELF 文件 需要 重定位 的 section, 一般 都对 应 一个 重定位 表。 比如 代码section 即“. text”  sectioin的 重 定位 表 保存 在“. rel. text” section内, “. data” 的 重 定位 表 保存 在“. rel. data” 内。

重 定位 表 包含 多个 重定位表项, 每个 重定 位 表项 记录 一条 重定 位 信息, 包括 重 定位 的 符号、 位置、 类型 等 信息。 重定 位 表项 的 数据 结构 定义 为:

1) r_ offset 表示 重定位地址, 对于可重定位目标 文件 来说, 表示 重定 位 位置 相对于 被重定位section的 基址 的 偏移(例如,prinft符号再在.text section内的偏移, 这个应该是给链接器看的吧,链接器计算出prinf函数的地址后,去修改这个位置吧).

而 对于 可执行文件 或 共享目标 文件 来说, 表示 重定 位 位置 对应 的 线性 地址, 这与 动态 链接 相关, 我们 不作 深入 讨论。

2) r_ info 描述 了 重定 位 类型 和 符号, 其 低 8 位 表示 重定 位 类型, 使用 宏 ELF32_ R_ TYPE 获取, 高 24 位 表示 重定 位 符号 对应 的 符号 表项 在 符号 表内 的 索引, 使用 宏 ELF32_ R_ SYM 获取。 不同 的 处理器 体系 结构 都有属于自己的 一套 重定 位 类型, 对于 x86 体系 结构 而言, 静态 链接 中 常见 的 重定 位 类型 有 两种: 绝对 地址 重定 位( 取值 R_ 386_ 32) 和 相对 地址 重定 位 R_ 386_ PC32。

 

串表 / 字符串表

ELF 文件 内 的 section表 和 符号表 需要 记录 段section 和 符号 名, 这些 名称 都是 字符串。

然而, section表项 和 符号表项 都是 固定 长度 的 数据 结构, 无法 存储 不定 长的 字符串。 因此 ELF 文件 将 名称字符串内容集中存放 在 一个 section内, 称为 串表。 这样 段 表项 或 符号 表项 只需 要 记录 section名字符串 或 符号名字符串在 对应串表内 的 位置 即可。 虽然 存储 的 字符串 内容 称为 串 表, 但 并非“ 表” 的 形式, 而是 一块 文件 区域。

 


总结常见ELF文件结构之间 的关系:

通过 ELF 文件 头 的 e_ ph* 字段 可以 定位 到 程序 头 表。 同样 地, 通过 e_ sh* 可以 定位 到 段 表。

 

段 表内 记录 了 串表(.strtab)、 符号表(.symtab)、 重定位表(.rel.***) , 段表字符串表段(“. shstrtab")对应 的 section, 以及代码 段 和 数据 段 的 信息,       欲取 得 这些 section 的 section名, 必须 通过 ELF 文件头结构提供的 e_ shstrndx 字段 找到“. shstrtab” 的 段表项, 继而 定位 到 该 sectioin的 数据, 取得 其 保存 的 所有section的 名字 sh_ name。

通过 “. symtab”  section的表项内 的 sh_ link 字段记录 的“. strtab” 段 在 section header table 的 索引 找到 字符串表(.strtab), 继而 取得 该 表内 保存 的 所有 符号 的 名字 st_ name。

重定位 表 section(“. rel. data” 和“. rel. text”) 通过其section表项内 的 sh_ info 字段 找到 重定位 的 段, 并 通过 重定位 项内 的 r_ offset 找到需要 重定位 的位置。 另外, 重 定位 表 还 通过 其 section 表内 的 sh_ link 字段 找到 被 重定 位 符号 所在 的 符号 表 段, 并 结合 重 定位 项 的 r_ info 字段 保存 的 被 重定 位 符号 在 符号表内 的 位置 找到 被重定位的符号信息。

 


Ref:

青木峰郎. 《自制编译器》 人民邮电出版社.

范志东; 张琼声. 《自己动手构造编译系统:编译、汇编与链接》机械工业出版社.

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ELF (Executable and Linkable Format)是一种用于存储可执行文件、目标文件和共享库的文件格式。它是Linux系统上常用的二进制文件格式之一,也是其他类UNIX系统所采用的标准格式。 ELF文件格式由三个主要部分组成:头部、段表和节表。 头部包含了一些重要的信息,如文件类型、系统架构、入口地址等。它还包含了段表和节表的偏移地址和大小等信息,以便系统可以正确解析文件。 段表记录了程序的运行时需要的各种段的信息。一个段可以是代码段、数据段、动态链接信息段等。每个段都有自己的虚拟地址和大小等属性。段表中的每个条目描述了一个段的属性和位置,用于程序的加载和运行。 节表类似于段表,不过节表记录了程序的编译时需要的各种节的信息。一个节可以是代码节、数据节、符号表等。每个节都有自己的虚拟地址和大小等属性。与段表类似,节表中的每个条目描述了一个节的属性和位置,用于编译、链接和调试。 ELF文件格式的优点是它的灵活性和可扩展性。由于ELF文件规范定义了头部、段表和节表等结构,因此可以通过添加新的段或节来实现文件的自定义属性和功能。这使得ELF文件格式非常适合于Linux系统的动态链接和加载机制。 总的来说,ELF文件格式是一种Linux系统中常用的二进制文件格式,它定义了文件的结构和属性,包括头部、段表和节表等部分。通过这个格式,可以实现文件的加载、链接和调试等功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值