相比PE文件格式,ELF的格式要容易记很多,简单来说就是3个“头”结构+众多节区
1、文件头
每种文件格式都会在文件的起始位置有固定的格式表明自己是何种文件,ELF格式在文件起始位置使用3行零4个字节放置自己的文件头,如下图,可以通过readelf -h [文件名]读取
从中可以读到3大部分如下信息:
32位可执行ELF文件;小端存储,运行在Intelx86CPU上面;程序入口点0x8048310;文件头大小是52字节(3行零4字节);
节区头在文件中的位置偏移0x17D8( 6104 )处,节区数量为31个,一个节区大小40字节(2行半,和PE节区头数据结构大小一致),.shstrtab节区在节区头中的下标索引是28
段表在文件中的位置偏移52处(就是紧挨着文件头),有9个段,每个段结构长度是32字节(2行)
2、节区头、节区(和PE中的节区定义相似;节区头的位置一般在文件结尾处,也可能下面还有节区)
通过readelf -S [文件名]读取;
有2个特殊节区,其中下表为0的节区定义为空节区(全零),存放各个节区名的(以字符串形式存放)节区(.shstrtab)下表在文件头中直接标出位置;
每个节区都有大小、文件中偏移、加载进内存的虚拟地址、节区属性;
如下图:
3、段表(位置紧接着文件头)
节区加载进内存时是以内存页的整数倍为基本单位,PE中的节区一般是3、5个,最多浪费3、5个;ELF文件一下就31个(排除掉一些不加载内存的节区,剩下的也不少)这浪费的内存可不是少数。
ELF格式为了减少加载过程中的内存浪费,就把属性相同的节区归到一个段中,例子中ELF文件是由9个段(只有个别段要加载进内存,其他段起辅助作用)。
比如说其中一个段包含a、b、c、d四个节区,且这个段要加载进内存:先加载a节区,如果最后一个内存页没有占满,那最后这个内存页就接着存放b,按这样的顺序加载c、d节区。(这样一个段浪费的内存页最多是一个),可以通过readelf -l [文件名]命令读取,如下图:
4、ELF文件布局:
文件头
段表
节区a
节区b
……
……
节区表(节区表可能是最后一项)
……
节区m
节区n
5、ELF文件常见节区作用: