理论——ELF可执行文件格式分析

在分析Binonic的Linker之前,我们先介绍Android的可执行文件格式,linker本事并不是很复杂,但是,如果对可执行文件格式不了解,就不太容易理解程序的逻辑。了解可执行文件的另一个好处是能开发出一些特殊功能的软件。Hook系统API软件

Android的可执行文件和动态库就是Linux的ELF文件格式,但是,由于使用了Android自己的linker,因此,和普通的Linux系统不完全兼容。

ELF是executable and Linking Format (可执行连接格式)的缩写,最初由UNIX系统实验室发布,它是应用程序二进制接口(Application Binary Interface,ABI)的一部分。ELF 标准的目的是为软件开发人员提供一组二进制接口定义,这些接口可以在多种操作系统下生效,从而减少开发的工作量。

ELF文件以节(Section)的方式组织在一起,“节”描述了文件的各项信息,例如代码,数据,符号表,重定位表,全局偏移表等。

可执行文件装载进内存时,并不是被“完整”的映射进内存,而是根据ELF文件中格式的定义,一段一段地装载进去。因此,可执行文件的格式和内存的映象并不完全相同,文件装载进内存后是以‘段’的方式来组织的,如代码段,数据段,动态段等。

ELF格式的文件有3种:可执行文件,动态库(.so文件)和重定位(.o文件)。

这3中文件都有一个ELF头,描述了整个可执行文件的基本信息,如目标代码的格式,体系结构,各种段或节的偏移和大小等。可执行文件和动态库中会有“程序头部表(porgram Header Table)、但是,重定位文件中没有程序头部表。此外。ELF文件中还会有一个“节区头部表”(Section Header Table)  ,描述文件中各个 节区的内容。这个表的内容和程序头部表的内容有点重复,这是因为两张表的用途不一样。在编译和链接阶段(符号地址,不执行库文件)。也就在可执行文件的生成阶段,需要使用“节区头部表”,而可执行文件装载的时候使用的是程序头部表。

分析ELF格式文件的目的,是为了了解可执行文件的装载过程,因此,下面重点介绍,“程序头部表”及其相关的数据结构,对“节区头部表”有兴趣的读取可以了解本节的内容后自行分析。


3.5 图

XXX.C---->GCC----xxx.ELF(此时使用节区头部表)-----./(装载时使用程序头部表)------执行

本节的内容主要介绍32为可执行文件额格式,64位的格式除了一些字段的长度不同外,文件的组织方式是一样的。

ELF文件格式的数据结构和常量的文件是exec_elf.h,位于目录bionic/libc/include/sys下。其中ELF头定义如下:

typeof struct {

unsigned char e_ident[ELF_NIDENT] //目标文件标示

Elf32_Half e_type ; //目标文件类型

Elf32_Half e_machine; //目标运行平台的体系结构

Elf32_Word e_version; //目标文件版本

Elf32_Addr e_entry; //程序的入口地址

Elf32_Off e_phoff; //程序头部表的偏移量

Elf32_Off e_shoff; //节区头部表的偏移量

Elf32_world e_flags; //文件相关的,特定于处理器的标志。

Elf32_Half  e_ehsize; //ELF头部的字节大小

Elf32_Half e_phentsize; //程序头部表的表项的字节大小

Elf32_Half e_shentsize; //程序头部表的表项数目

Elf32_Half e_shnum; //节区头部表的表项的字节大小

Elf32_Half e_shstrndxl //节区头部表的表项数目

} Elf32_Ehdr;

在程序头部表里,最重要的是记录“程序头部表”和“节区头部表”的位置,表示表项数目和表项大小的字段。余下的字段中。

e_ident的16个字节标明了ELF文件的标志(7F+'E'+'L'+'F');

e_type表示文件类型,2表示可执行文件。

e_machine 表示机器类别,3表示386机器、8表示mips机器

e_entry表示程序的入口地址。

查看头程序的文件readelf和objdump这两个工具在prebuild目录下有多份,分别对应不同的平台。在Android5.0的源码里,可以使用的是目录prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin下的工具

arm-eabi-readelf 有很多参数,其中-h参数能查看ELF文件的头部信息,

程序头部表

程序头部表的作用是记录文件中各种段的地址,大小等信息。在程序装在和连接时都需要它。

程序头部表示一个结构Elf32_Phdr的数组,每个结构中记录了装入内存中的各个段的信息,包括类型,地址,大小等。结构Elf32_Phdr的定义如下:

typedef  struct{

Elf32_Word p_tpye; //段的类型

Elf32_Off p_offset; //段的文件中的偏移

Elf32_Addr p_vaddr; //段装入内存后的虚拟地址

Elf32_Addr p_paddr; //端装入内存后的物理地址

Elf32_Word p_filesz; //段在文件中的大小

Elf32_Word p_memsz; //段装入内存后的大小

Elf32_Word p_flags; //段的标志

Elf32_Word p_align; //内存的对齐方式

} Elf32_Phdr;


同样,可以使用工具arm-eabi-readelf 来查看程序头部表的信息,这次需要使用的参数是"-l"

虽然“程序头部表”可能包含多个段,但是,只有类型为"PT_LOAD"的“段”才会从文件映射到内存中。其余类型的"段"如果有实际的节区,这些“节区”也会出现在"PT_LOAD"类型的“段”中。

图3.5中上半部分是程序头部表,可以看到它有8个“段”,图3.5的下半部分是这些“段”包含的“节区”。这些段中只有两个段的类型是“PT_LOAD”,因此,装载这个文件时,实际mmap进内存的也只有这两个“段”。它们就是所谓的代码段和数据段,从它们的属性也可以看出一个是“只读”,另一个是“读写”。

这两个“PT_LOAD段"在图3.5下半部分的对应关系位于第02项和第03项,从图3.5中可以看到他们包含了可执行文件的所有"节区"。而DYNAMIC段(第04项)只"包含"了一个".dynamic节区",这个"节区"和第03项中的".dynamic"是同一个。只不过".dynamic节区"的起始地址和大小等数据保存在“Dynamic段”中,只能通过“DYNAMIC”段来找到“.dynamic”节区,从而再找到“.plt”、“.dynsym”、“.got”等“节区”。相反,虽然“PT_LOAD”类型的“段”的地址空间范围覆盖了".dynmic节区"

但是无法通过它来找到“.dynamic节区”。这样设计的目的是,当系统装在可执行文件时只需要将"PT_LOAD"类型的"段"完整的映射进内存就完成了,而访问各个“节区”还是通过相应的段所记录的地址来完成。


与重定位相关的"节区"的信息------DYNAMIC段

"DYNAMIC段"描述的是与重定位相关的"节区"的信息。"DYNAMIC段"也是个数组,每项描述了"节区"的一些信息,一些复杂的"节区"需要好几项来共同说明,如".plt节区"就用了3项分别来描述"节区"的地址、大小、和"节区条目"的大小

“DYNAMIC段”的项数不是在文件的某个地方指定的,而是通过数组将最后一项的数据置为NULL来表示数组的结尾。

typedef struct{

Elf32_Word d_tag;

union {

Elf32_Addr d_ptr;

Elf32_Word d_val;

}d_un;

} Elf32_Dyn;

其中,d_tag 表示每项的类型。d_un是个联合,根据类型使用,器字段的作用是。

d_val 表示一个整数值,根据d_tag的类型不同有多种解释,如偏移、尺寸等。

d_ptr 表示"节对象"的虚拟地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容