Android平台ELF文件格式简单介绍

ELF英文全程为:Executable Linkable Format,ELF属于Linux平台下可执行文件。ELF文件格式与Windows下的PE(Portable Executable)文件格式相似,都是属于COFF(Common File Format)文件格式变种。谷歌的Android操作系统内核采用Linux内核框架实现,所以Android平台原生文件格式与Linux可执行文件格式完全相似,同属于ELF类型文件。

Android平台下游戏逻辑通常使用C、C++语言实现,编译之后的可执行文件属于ELF文件格式,ELF文件格式整体布局如下图所示:
在这里插入图片描述
谷歌的Android NDK提供工具方便开发者查看ELF文件格式,对应工具名为:arm-linux-androideabi-readelf,工具所在NDK根目录的相对路径为:android-ndk-r9c\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin\,arm-linux-androideabi-readelf工具部分使用说明如下图所示:
在这里插入图片描述
本章使用“libTest.so”文件作为实例介绍ELF格式信息。下面将详细讲解ELF文件格式,以便让读者对Android平台原生程序的文件格式有较好理解。

1.1.1文件头信息

ELF文件头描述文件基本属性信息,包括ELF文件版本号、目标机器型号、程序入口、段表描述信息等信息。ELF文件头数据大小为0x34字节,实例文件的ELF文件头信息二进制数据如下所示:
在这里插入图片描述
上图中标为蓝色的数据为ELF文件头二进制内存数据,最右边可明显看出有“ELF”字符串,读者也许已猜到数据对应ELF文件标志,即判断是否为ELF文件表示。arm-linux-androideabi-readelf工具可方便查看ELF文件头信息。

利用arm-linux-androideabi-readelf工具查看ELF文件头信息命令如下:

arm-linux-androideabi-readelf.exe -h libTest.so

对应获取的文件头信息如下:
在这里插入图片描述
上图重要信息解释如下:

Magic:表示魔数标志信息,用来指明该文件是一个ELF目标文件,第一个字节固定为“7F”,后面三个字节为E、L、F字母的ASCII数值。同时魔数信息中还包含:版本信息、机器类型、文件类型等。

Type:表明文件类型,“DYN”表示实例所使用的文件属于动态链接库文件。

Machine:标识文件所采用指令类型,“ARM“表示当前ELF采用Arm指令集。

Start of program headers:表示程序头信息的起始偏移。        

Start of section headers: 表示节表头信息的起始。                                 

Size of program headers:表示程序头信息总共大小。      

Number of program headers:表示程序头信息总共包含的项数。         

Size of section headers: 表示节表头信息总共大小。      

Number of section headers: 表示节表头信息总共包含的项数。    

下面附上ELF文件头每项数据定义:

typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; // Entry point
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;

ELF文件头属于最开始的信息,从整理描述ELF文件下面各子项信息。

1.1.2 程序头信息

ELF文件程序头信息(program headers)是一个数据结构,每个数据结构描述一个段或者系统准备程序执行所需的其他信息,ELF文件的段(Segment)包含一个或者多个节区(Section)。ELF文件的段是为方便操作系统根据相同权限区段合并到一个段进行映射。ELF文件的程序头信息定义如下:

typedef struct elf32_phdr{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr; /* virtual address /
Elf32_Addr p_paddr; /
ignore /
Elf32_Word p_filesz; /
segment size in file /
Elf32_Word p_memsz; /
size in memory */
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;

利用arm-linux-androideabi-readelf工具查看ELF文件程序头信息,对应的命令如下:

arm-linux-androideabi-readelf.exe -l libTest.so

获取到的ELF文件程序头信息如下图所示:
在这里插入图片描述
上图总共有7个段信息,通过每个段的FLg表示可获取到段对应的内存属性。实际上真正需要装载到内存中的只有类型为“LOAD”的段,即:只有第2个和第3个需要装载到内存中,并且还可以看到每一个段的起始文件偏移地址、起始内存偏移地址、段大小、段权限、段对齐方式等信息。

命令输出的信息中包含“Section to Segment mapping”项数据,该项信息代表了section到segment的映射关键,例如:标号为2的Load段包含了: “.fini_array”、“.init_array”、“.dynamic”、 “.got”、“.data”、“.bss”六个节信息。

1.1.3 节表头信息

ELF文件中包含各种节段信息,它是一个Elf32_Shdr结构的数组,数据内容的定义如下所示:

typedef struct {

Elf32_Word sh_name; /* name of section, index */

Elf32_Word sh_type;

Elf32_Word sh_flags;

Elf32_Addr sh_addr; /* memory address, if any */

Elf32_Off sh_offset;

Elf32_Word sh_size; /* section size in file */

Elf32_Word sh_link;

Elf32_Word sh_info;

Elf32_Word sh_addralign;

Elf32_Word sh_entsize; /* fixed entry size, if have */

} Elf32_Shdr;

利用arm-linux-androideabi-readelf工具查看ELF文件节表头信息,对应的命令如下:

arm-linux-androideabi-readelf.exe -S libTest.so

获取到的ELF文件节表头信息如下图所示:
在这里插入图片描述
从节表头信息可获取到每个节段名字、长度、内存和文件的相对偏移、链接器、编译器、装载器等信息。实例样本总共有21个阶段,其中“.text”属于出现频率非常高的节段,绝大部分代码编译之后存放于“.text”段中。

ELF文件格式主要由以上介绍的三部分信息组成,分别为:ELF文件头、ELF程序头、ELF节表头。通过以上学习,读者可掌握Android平台原生ELF文件格式的结构信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

douluo998

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

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

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

打赏作者

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

抵扣说明:

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

余额充值