本文主要讨论 Dynamic Segment 里面的几个子表。
总体结构介绍
我们先总体看下 Dynamic Segment :

这里我们只需要关心图中两个画圆圈的地方。
第一个是虚拟地址
由于 Dynamic Segment 的子表内容都在可加载段的范围里面,所以对这些子表的访问都是在虚拟内存里面进行的。
p_offset_FROM_FILE_BEGIN 这个值我们可以自己静态分析使用,但是解析的时候不要用这个地址。包括 p_filesz_SEGMENT_FILE_LENGTH p_memsz_SEGMENT_RAM_LENGTH,这些值都没用。
有一个需要注意的地方,就是p_offset_FROM_FILE_BEGIN 的值要比 p_vaddr_VIRTUAL_ADDRESS 的值要大一个 PAGE 值。这是为啥呢?
是因为第二个可加载段的映射偏差:

可以看到在第二个可加载段在做内存映射的时候就有一个 PAGE 值的偏差,由于只要是放在第二个段里面的内容,就会有一个 PAGE 的偏差。
第二个是子表
第二个画圈的地方说明了,子表有 39 项。但是实际上最后几项都是 NULL:

所以解析子表的时候,不会去先计算子表的大小,然后用 大小/sizeof(xxx) 这样的方式,而是直接从头开始解析,直到遇到 DT_NULL。
子表的结构体是 struct Elf64_Dyn :
typedef struct
{
Elf64_Sxword d_tag; /* Dynamic entry type */
union
{
Elf64_Xword d_val; /* Integer value */
Elf64_Addr d_ptr; /* Address value */
} d_un;
} Elf64_Dyn;
一共16个字节,前8个字节表示类型,后8个字节表示地址(注意表示的是虚拟地址)或者整数值。
我们先研究字符串表,其 type 为 5:

字符串表
我们找到字符串表的虚拟地址位置 0x2328,它是在第一个段里面。其实这个地址也能在 section header 里面找到:

只不过 section header 里面的这个地址容易被篡改而已。
根据第一个段的mmap映射关系,我们知道,其文件位置也是 0x2328,我们跳过去看看:

明显看出,这里确实是字符串表。
这个表要如

本文详细解读了DynamicSegment中的子表,特别是字符串表、导入库表和符号表的结构,以及重定位表(如plt和rela.plt)的工作原理,着重讲解了不同类型的重定位和链接器如何处理它们。
最低0.47元/天 解锁文章
8250

被折叠的 条评论
为什么被折叠?



