ilocker:关注 Android 安全(新手) QQ: 2597294287

程序头表 (program header table) 是一个结构体数组,数组中的每个结构体元素是一个程序头 (program header),每个程序头描述一个段 (segment)。

 ELF Format 笔记(十一)—— 程序头结构

一个 so 通常有两个可加载段 (LOAD) 段,android linker 在加载 so 时会根据 LOAD 段在内存中的最大虚拟地址减去最小虚拟地址,来计算要申请的内存大小。

 ELF Format 笔记(十一)—— 程序头结构

除了两个 LOAD 段,其他段中的数据也是执行程序所需的,如:动态链接需要 DYNAMIC 段,c++ 异常栈展开需要 EXIDX 段。所以其他段也是需要加载到内存的,它们实际就位于两个 LOAD 段内部。

节 (section) 和段 (segment) 分别是从链接视图和执行视图两个不同的角度的来划分的,它们有一个对应关系 (每个段“包含”一个或者多个节):

 ELF Format 笔记(十一)—— 程序头结构

程序头结构:

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 取模后应相等。

相关文章: