ELF 64 格式详解

2022-11-05  本文已影响0人  android小奉先

本篇介绍

本篇详细介绍下ELF 64的文件格式。

ELF文件分类

ELF文件内容

一个ELF文件需要包含以下部分:

节头表和段头表其实分别是链接和加载的视图,结构大致如下:


image.png

ELF 64的数据类型定义如下:


image.png

ELF文件头格式

文件头格式如下:


image.png

可以找一个so,用 readelf -h 看看输出,结果可以完全对上:


image.png

对于MacBook M1 的设备可能没有readelf,objdump等命令,一个简单的方法是可以直接使用ndk中的命令,llvm-readelf, llvm-objdump等

接下来分别看下各个字段的含义:

e_ident

elf文件的标识,一共16个字节,各个字段的含义如下:


image.png

ELF节

节包含了ELF文件中除了文件头,程序段头表,节头表之外的所有内容。
节的索引中有几项是特殊的,比如如下几个:


image.png

可以实际看一下节的内容,通过readelf -S 命令就可以看到:


image.png

再看下节头表中项结构的定义,可以和输出的格式对上:


image.png

字符串表的索引是24,那偏移就是0xD4F1C0,内容如下:


image.png

按照上述的结构定义,可以看到sh_offset 的偏移是0xD4EADC, 再加上字符串偏移 0x0B,位置就是0xD4EAE7


image.png

这样就字符串位置计算出来了。

用于程序代码和数据的节如下:


image.png

用于文件信息的节如下:


image.png

字符串表

字符串节表包含用于节名字和符号名字的字符串,内部的字符串表是包含C格式的字符串,对外的索引就是对应字符串的起始位置偏移,单位是字节。

符号表

符号表结构如下:


image.png

符号类型定义如下:


image.png image.png

可重定位表

ELF 文件有2种重定位格式,"Rel"和"Rela", 前者较短,记录相对于符号原始值的偏移,后者是记录相对于特定字段的偏移。结构定义如下:


image.png
#define ELF64_R_SYM(i)((i) >> 32)
#define ELF64_R_TYPE(i)((i) & 0xf f f f f f f f L)
#define ELF64_R_INFO(s, t)(((s) << 32) + ((t) & 0xf f f f f f f f L))

程序段头表

对于可执行和共享库,为了加载方便,用的视图是段,也就是内容一样,只是分类方式变化了。
可以先实际看下共享库的段表信息,readelf -l libtxffmpeg.so

image.png
可以看到,段是由节组成的,这是对于加载器,权限一样的,就可以合并到一块,方便内存的管理。
再看下段结构,可以和上图对得上:
image.png image.png

Note 节

SHT_NOTE的节或PT_NOTE的段,被编译器或其他用于用于存放一些特殊的信息,而这些信息可以被特定的工具所用,格式如下:


image.png

动态段表

动态段表的实际内容如下:


image.png

结构定义如下:


image.png image.png image.png

哈希表

使用哈希表可以加快动态符号表的查找速度。哈希表就是DT_HASH的节,看下实际例子的输出,命令是readelf --gnu-hash-table

image.png

内容比较多,忽略了一部分,接下来看下结构:


image.png

对应的哈希函数如下:


image.png

一个哈希表需要解决如何快速查找,如何解决冲突的问题。
看看hash 表如何快速查找,这儿用到了一个Bloom Filter, 本质上就是在查找前先用Bloom Filter判断下,如果结果是不在,那么就没必要查找了,如果是在,实际上也不一定在,就需要实际去查一下。
解决冲突时利用了chain数组,在查找符号时,如果Bloom Filter判断出在,然后就在bueket中对应索引位置看看,如果等于期望的字符串,那么直接返回,然后在chain数组同样索引位置拿到下一个需要查找的位置,然后递归查找下去,直到 chain中的值是STN_UNDEF。

上一篇 下一篇

猜你喜欢

热点阅读