1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| typedef struct elf64_hdr { unsigned char e_ident[EI_NIDENT]; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;
|
![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/15256694/1698403732697-e68320a2-8fbd-4575-98ee-efe0e7285f56.png#clientId=ufad65cf1-b4a9-4&from=paste&height=303&id=udf417040&originHeight=606&originWidth=1618&originalType=binary&ratio=2&rotation=0&showTitle=false&size=1018950&status=done&style=none&taskId=ud15691e7-0246-46c4-8475-9fab2a1e69b&title=&width=809)
e_machine 取值
https://codebrowser.dev/glibc/glibc/elf/elf.h.html
1 2 3 4 5 6 7 8 9 10
| typedef struct elf64_phdr { Elf64_Word p_type; Elf64_Word p_flags; Elf64_Off p_offset; Elf64_Addr p_vaddr; Elf64_Addr p_paddr; Elf64_Xword p_filesz; Elf64_Xword p_memsz; Elf64_Xword p_align; } Elf64_Phdr;
|
- 该段开始位置为基地址 + p_offset,长度为 p_memsz
![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/15256694/1698404678248-ae719690-5fd3-45ca-bb24-12cdb2cab36b.png#clientId=ufad65cf1-b4a9-4&from=paste&height=601&id=ue543dfbd&originHeight=1202&originWidth=1588&originalType=binary&ratio=2&rotation=0&showTitle=false&size=2033165&status=done&style=none&taskId=u9a40ca70-aadf-4d07-95c3-d5b3db65c2a&title=&width=794)
p_flags
![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/15256694/1698405916504-bc3aedb9-3dfe-41a3-8ca6-3e56efdfa396.png#clientId=ufad65cf1-b4a9-4&from=paste&height=150&id=uf5e3829c&originHeight=300&originWidth=346&originalType=binary&ratio=2&rotation=0&showTitle=false&size=123581&status=done&style=stroke&taskId=u0f787f0b-17ec-4282-b71d-b2a9109536b&title=&width=173)
p_type
取值 |
代表 |
含义 |
00 |
PT_NULL |
此数组元素未用。结构中其他成员都是未定义的。 |
01 |
PT_LOAD |
此数组元素给出一个可加载的段,段的大小由 p_filesz 和 p_memsz 描述。文件中的字节被映射到内存段开始处。如果 p_memsz 大于 p_filesz,“剩余”的字节要清零。p_filesz 不能大于 p_memsz。可加载的段在程序头部表格中根据 p_vaddr 成员按升序排列。 |
02 |
PT_DYNAMIC |
数组元素给出动态链接信息。 |
03 |
PT_INTERP |
数组元素给出一个 NULL 结尾的字符串的位置和长度,该字符串将被当作解释器调用。这种段类型仅对与可执行文件有意义(尽管也可能在共享目标文件上发生)。在一个文件中不能出现一次以上。如果存在这种类型的段,它必须在所有可加载段项目的前面。 |
04 |
PT_NOTE |
此数组元素给出附加信息的位置和大小。 |
05 |
PT_SHLIB |
此段类型被保留,不过语义未指定。包含这种类型的段的程序与 ABI不符。 |
06 |
PT_PHDR |
此类型的数组元素如果存在,则给出了程序头部表自身的大小和位置,既包括在文件中也包括在内存中的信息。此类型的段在文件中不能出现一次以上。并且只有程序头部表是程序的内存映像的一部分时才起作用。如果存在此类型段,则必须在所有可加载段项目的前面。 |
0x70000000 |
PT_LOPROC |
此范围的类型保留给处理器专用语义。 |
0x7fffffff |
PT_HIPROC |
此范围的类型保留给处理器专用语义。 |
1 2 3 4 5 6 7 8 9 10 11 12
| typedef struct elf64_shdr { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; } Elf64_Shdr;
|
成员 |
说明 |
sh_name |
节名称,是节区头字符串表节区中(Section Header String Table Section)的索引,因此该字段实际是一个数值。在字符串表中的具体内容是以 NULL 结尾的字符串。 |
sh_type |
根据节的内容和语义进行分类,具体的类型下面会介绍 |
sh_flags |
每一比特代表不同的标志,描述节是否可写,可执行,需要分配内存等属性。 |
sh_addr |
如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应该在进程镜像中的位置。否则,此字段为 0 |
sh_offset |
给出节区的第一个字节与文件开始处之间的偏移。SHT_NOBITS 类型的节区不占用文件的空间,因此其 sh_offset 成员给出的是概念性的偏移。 |
sh_size |
此成员给出节区的字节大小。除非节区的类型是 SHT_NOBITS ,否则该节占用文件中的 sh_size 字节。类型为 SHT_NOBITS 的节区长度可能非零,不过却不占用文件中的空间。 |
sh_link |
此成员给出节区头部表索引链接,其具体的解释依赖于节区类型 |
sh_info |
此成员给出附加信息,其解释依赖于节区类型。 |
sh_addralign |
某些节区的地址需要对齐。例如,如果一个节区有一个 doubleword 类型的变量,那么系统必须保证整个节区按双字对齐。也就是说sh_addr%sh_addralign = 0。 目前它仅允许为 0,以及 2 的正整数幂数。 0 和 1 表示没有对齐约束 |
sh_entsize |
某些节区中存在具有固定大小的表项的表,如符号表。对于这类节区,该成员给出每个表项的字节大小。反之,此成员取值为 0 |
- header中e_shstrndx记录了.shstrtab的索引位置,sh_name的字符串名为 :基地址 + shstrtab.sh_offset + section_h.sh_name
- section_h.sh_offset + section_h.sh_size = 下一个section的起始位置
- section_h.sh_size / section_h.sh_entsize = entry count (symtab count 和dynsym count)