ilocker:关注 Android 安全(新手) QQ: 2597294287
程序头表 (program header table) 是一个结构体数组,数组中的每个结构体元素是一个程序头 (program header),每个程序头描述一个段 (segment)。
一个 so 通常有两个可加载段 (LOAD) 段,android linker 在加载 so 时会根据 LOAD 段在内存中的最大虚拟地址减去最小虚拟地址,来计算要申请的内存大小。
除了两个 LOAD 段,其他段中的数据也是执行程序所需的,如:动态链接需要 DYNAMIC 段,c++ 异常栈展开需要 EXIDX 段。所以其他段也是需要加载到内存的,它们实际就位于两个 LOAD 段内部。
节 (section) 和段 (segment) 分别是从链接视图和执行视图两个不同的角度的来划分的,它们有一个对应关系 (每个段“包含”一个或者多个节):
程序头结构:
typedef struct { Elf32_Word p_type; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Addr p_paddr; Elf32_Word p_filesz; Elf32_Word p_memsz; Elf32_Word p_flags; Elf32_Word p_align;} Elf32_Phdr;
p_type:段类型,如:PT_LOAD (可加载段)、PT_DYNAMIC (动态段)。
p_offset:段数据的第一个字节相对于文件开头的偏移量。
p_vaddr:段数据的第一个字节在内存中的虚拟地址 (只是一个偏移)。
p_paddr:暂时不用关心。
p_filesz:段数据在文件中的的字节大小,可以是 0。
p_memsz:段数据在内存映像中的字节大小,可以是 0。
p_flags:段内存映像的访问权限:PF_X (可执行)、PF_W (可写)、PF_R (可读)。
p_align:如果为 0 或 1,表示不需要对齐。否则,p_align 应该是 2 的正整数幂,p_vaddr 和 p_offset 在对 p_align 取模后应相等。