ELF Format 笔记(五)—— 特殊 Section

链接器把一些独立的 object files 和库文件链接起来,形成可执行文件。在这个过程中,链接器需要解决一些符号的引用以及指令的重定位。

除此之外,还有一个动态链接的过程。比如有些符号是定义在某个 so 文件中的,需要由动态链接器在装载的过程中进行一些符号查找和地址重定位的工作。要完成此工作,动态链接器需要一些信息,它们存储在一些特殊的 section 中,比如 .dynamic。

section 和 segment 是分别针对链接视图和执行视图来说的,各种资料对他们的翻译比较混乱,慢慢就会理解了。

还有一些用于支持调试功能的 section,比如 .debug、.line。下面是一张描述特殊 section 的表格:

.bss:保存未初始化的数据,比如那些未初始化的全局变量。因为是“未初始化”,所以也没必要在文件中占用任何空间去记录其初始值(所以类型为 SHT_NOBITS)。在程序开始运行时,系统会将 .bss 映射的内存区域清零。

.comment:保存版本控制信息。

.data / .data1:保存已初始化的数据。它们会在文件中占用存储空间,这与 .bss 不同。

.debug:保存调试相关的信息。

.dynamic:保存动态链接信息。

.dynstr:保存动态链接所需的字符串。比如符号表中的每个符号都有一个 st_name(符号名),他是指向字符串表的索引,这个字符串表可能就保存在 .dynstr。

.dynsym:保存需要动态连接的符号表。

.fini / .init:分别保存进程退出和初始化时要执行的指令。.init 指令会在程序入口点(main)之前被执行。

.got:保存全局偏移量表 (global offset table)。

在 Android 中,GOT 分为两部分:.got 和 .got.plt。其中 .got 表用来保存全局变量引用的地址,而 .got.plt 用来保存函数引用的地址。

.hash:保存符号哈希表,用于快速查找与其对应的符号表中的符号。

.interp:保存 ELF 程序解释器(比如 Android 下的动态链接器)的路径名。

.line:保存用于调试的行号信息。

.note:保存一些注释信息。

.plt:保存过程链接表 (procedure linkage table)。每个外部定义的函数都会在 PLT 中有对应的一项,用于定位外部函数的地址。

.relname / .relaname:保存重定位表。比如:.rel.dyn、.rel.plt。

.rodata / .rodata1:保存程序中的只读数据。

.shstrtab:保存一个字符串表,这些字符串都是 section 的名字。

.strtab:保存字符串表,类似于 .dynstr,但 .dynstr 中保存的都是那些需要动态链接的符号的名字。

.symtab:保存符号表(非动态链接)。

.text:保存可执行的指令代码。

这些以“.”为前缀的 section 名字为系统保留。应用程序可以构造自己的段,但最好不要与系统已定义 section 节重名,也不要以“.”开头,以避免潜在的冲突。

时间: 2024-10-12 14:06:55

ELF Format 笔记(五)—— 特殊 Section的相关文章

ELF Format 笔记(四)—— 节(Section)

ELF 文件可以包含很多 section,所有的 section 都在 section header table 中有对应的一项,每个 section header 都是一个 Elf32_Shdr 结构,用于描述相应 section 的信息. ELF Header 中的 e_shoff 给出了 section header table 在 ELF 文件中的字节偏移量,e_shentsize 指明在 section header table 中的每一项的字节大小,e_shnum 指明共有多少项.

ELF Format 笔记(十五)—— 符号哈希表

ilocker:关注 Android 安全(新手) QQ: 2597294287 符号哈希表用于支援符号表的访问,能够提高符号搜索速度. 下表用于解释该哈希表的组织,但该格式并不属于 ELF 规范. bucket 和 chain 数组中都保存有符号表的索引,数组大小分别为 nbucket 和 nchain. 先来看 android linker 中的 hash 函数: 给定一个符号名字,返回一个哈希值 x,然后由 bucket[x%nbucket] 得到一个符号表索引 y,如果索引 y 对应的符

ELF Format 笔记(八)—— 符号的类型和属性(st_info)

我是天空里的一片云,偶尔投影在你的波心,你不必讶异,更无须欢喜,在转瞬间消灭了踪影.你我相逢在黑夜的海上,你有你的,我有我的,方向:你记得也好,最好你忘掉,在这交会时互放的光亮! —— 徐志摩·偶然 ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 上篇笔记中说过,Elf32_Sym 结构的 st_info 成员包含了符号的类型和绑定属性等信息. 在 android linker 做重定位时,如果遇到未定义的符号,会判断该符号是否是一个弱引用符号,如果不

ELF Format 笔记(九)—— Elf32_Sym 结构的 st_value 和 st_shndx 成员

ilocker:关注 Android 安全(新手) QQ: 2597294287 前面的笔记中提到过 Elf32_Sym 结构,本篇笔记再写一下其中的 st_value 和 st_shndx 成员. 对于不同类型的 object file,st_value 的含义略有不同: · 对于 relocatable (.o) 文件,如果相应的 st_shndx 的值为 SHN_COMMON,则 st_value 保存的是对齐字节数. · 对于 relocatable (.o) 文件,如果该符号已定义,则

ELF Format 笔记(六)—— 字符串表

字符串表中包含若干以 null 结尾的字符串,这些字符串通常是 symbol 或 section 的名字.当 ELF 文件的其它部分需要引用字符串时,只需提供该字符串在字符串表中的位置索引即可. 字符串表中首先是一个空串,用于表示一个空名字,所以字符串表的第一个字节是“\0”. 下图展示了一个长度为 25 字节的字符串表: 字符串引用示例: 既可以引用一个完整的字符串,也可以引用一个字符串的子串. 一个目标文件中会有多个字符串表,比如 android libstdc++.so 中有 .dynst

ELF Format 笔记(二)—— ELF Header

以 32 位的 ELF header 数据结构为例: 1 #define EI_NIDENT 16 2 typedef struct { 3 unsigned char e_ident[EI_NIDENT]; 4 Elf32_Half e_type; 5 Elf32_Half e_machine; 6 Elf32_Word e_version; 7 Elf32_Addr e_entry; 8 Elf32_Off e_phoff; 9 Elf32_Off e_shoff; 10 Elf32_Wor

ELF Format 笔记(七)—— 符号表

最是那一低头的温柔,像一朵水莲花不胜凉风的娇羞,道一声珍重,道一声珍重,那一声珍重里有蜜甜的忧愁 —— 徐志摩 符号表 (symbol table) 中保存着符号的定义或者引用信息.对于 android so 文件来说,.dynsym 符号表保存着库文件的导入和导出符号. 用 readelf 看一下 android liblog.so 的 .dynsym 动态符号表: 符号 __cxa_finalize 的 Ndx(st_shndx) 为 UND,表明该符号在本 so 中未定义,需要去 libl

ELF Format 笔记(一)—— 概述

ELF Object files 参与程序的链接和执行,从这两个角度分别有两种视图: ELF header 位于文件的最开始处,描述整个文件的组织结构. Program Header Table 告诉系统如何创建进程镜像,在执行程序时必须存在,在 relocatable files 中则不需要.每个 program header 分别描述一个 segment,包括 segment 在文件和内存中的大小及地址等等. 执行视图中的 segment 其实是由很多个 section 组成.在一个进程镜像

ELF Format 笔记(十)—— 重定位(relocation)

ilocker:关注 Android 安全(新手) QQ: 2597294287 重定位就是把符号引用与符号定义链接起来的过程,这也是 android linker 的主要工作之一. 当程序中调用一个函数时,相关的 call 指令必须在执行期将控制流转到正确的目标地址.所以,so 文件中必须包含一些重定位相关的信息,linker 据此完成重定位的工作. 这些重定位信息保存在一系列的重定位项中,重定位项的结构如下: 这些重定位项位于 .rel.plt section 中. r_offset:对于可