Java解析ELF文件:ELF文件格式规范

时间:2024-03-19 12:33:11

1.简介

UNIX类操作系统中普遍采用目标文件格式ELF(Executable and Linkable Format),来实现二进制级软件构件的静态、动态组装技术。
可执行链接格式(Executable and Linking Format)最初是由UNIX系统实验室(UNIX System Laboratories,USL)开发并发布的,作为应用程序二进制接口(Application Binary Interface,ABI)的一部分。工具接口标准(Tool Interface Standards,TIS)委员会将还在发展的ELF标准选作为一种可移植的目标文件格式,可以在32位Intel体系结构上的很多操作系统中使用[1,2]。 
ELF标准的目的是为软件开发人员提供一组二进制接口定义,这些接口可以延伸到多种操作环境,从而减少重新编码、重新编译程序的需要。接口的内容包括目标模块格式、可执行文件格式以及调试记录信息与格式等。 

2.文件格式

2.1简介

目标文件有三种类型: 
可重定位文件(Relocatable File):包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。  
可执行文件(Executable File):包含适合于执行的一个程序,此文件规定了 exec() 如何创建一个程序的进程映像。  
共享目标文件(Shared Object File):包含可在两种上下文中链接的代码和数据。首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。其次,动态链接器(Dynamic Linker)可能将它与某
个可执行文件以及其它共享目标一起组合,创建进程映像。 

以上目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行。

2.2文件格式

目标文件既要参与程序链接又要参与程序执行。出于方便性和效率考虑,目标文件格式提供了两种并行视图,分别反映了这些活动的不同需求。
Java解析ELF文件:ELF文件格式规范
文件开始处是一个 ELF 头部(ELF Header),用来描述整个文件的组织。节区部分包含链接视图的大量信息:指令、数据、符号表、重定位信息等等。 
程序头部表(Program Header Table),如果存在的话,告诉系统如何创建进程映像。用来构造进程映像的目标文件必须具有程序头部表,可重定位文件不需要这个表。 
节区头部表(Section Heade Table)包含了描述文件节区的信息,每个节区在表中都有一项,每一项给出诸如节区名称、节区大小这类信息。用于链接的目标文件必须包含节区头部表,其他目标文件可以有,也可以没有这个表。 

注意:尽管图中显示的各个组成部分是有顺序的,实际上除了 ELF 头部表以外,其他节区和段都没有规定的顺序(但是一般来讲,除开自己新增的节区情况外,程序头部表位于ELF头部后面,节区头部表位于最末端。同时执行视图的段其实就是链接视图不同的节区合起来而已,这一点需要注意下)

2.3读取顺序

Java解析ELF文件:ELF文件格式规范
1.首先读取文件头部,文件头部会提供程序头部表的偏移位置和表内的表项数量、节区头部表的偏移位置和表内的表项数量
链接视图:
2.读取节区头部表,获取每个节区的偏移量
执行视图:
3.读取程序头部表,获取每个段区的偏移量
下图源自非虫大大的图,可以用来加深理解:
Java解析ELF文件:ELF文件格式规范

3.使用010Editor的模块功能查看ELF文件

功能超强大的国外软件十六进制编辑器


安装后,进入模板库安装界面:模板->模板库,选择ELF文件


Java解析ELF文件:ELF文件格式规范
打开一个SO文件,点击运行,模板
Java解析ELF文件:ELF文件格式规范
则会很方便的显示上面说的文件头部、程序头部表、节区头部表的大小和偏移位置,其中最下面的dynamic_symbol_table也是节区的一种类型,只是很重要所以列了出来,包含的是用来定位、重定位程序中符号定义和引用的信息。


本篇只介绍了各个区域的大致描述和文件格式,对于大部分程序员来讲只需要了解格式就行了,至于每个区域的详细内容则内容太多不贴出来了,想了解更多则请移步ELF文件格式分析

4.参考

这篇博客里介绍了使用readelf命令查看ELF文件的用法(NDK里也提供了不同平台下readelf功能的命令,在ndk\toolchains目录下,搜索下readelf就出来了),和作者自己写的java和C++解析类,建议去看看