2 ELF节头

2 ELF节头
foresta.yangELF节头
ELF二进制文件中的代码和数据在逻辑上被分为连续的非重叠块,称为节(section)。节没有任何预设的结构体,相反,每个节的结构体取决于内容。实际上,节甚至可能没有任何特定的结构体。通常,节只不过是代码或者数据的非结构化blob。每个节由节头描述,节头指定了节的属性,并允许你找到节中字节的位置。二进制文件中所有节的节头都包含在节头表中。
对节进行划分为链接器的使用提供了方便,当然节也可以被其他工具解析(如静态二进制分析工具),这意味着在设置进程和虚拟内存来执行二进制文件的时候,实际上并不需要每个节所包含的数据,有些节所包含的数据在执行的时候是根本不需要的,如符号信息或者重定位信息。
由于节只为链接器提供视图,因此节头表是ELF格式的可选部分,不需要链接的ELF二进制文件不需要有节头表。如果没有节头表,则ELF头部中的e_shoff字段将设置为零。
为了在进程中加载并执行二进制文件,需要对二进制文件中的代码和数据进行不同的组织,为此ELF二进制文件指定了另一种逻辑组织, 称为段(segment),它们在执行的时候使用,与节相对,节在链接的时候使用。
节的内容的逻辑组织只在链接时(被静态分析工具使用时)存在,在运行时不存在。

sh_name字段
节头的第一个字段称为sh_name,如果该字段被设 置,则在字符串表中包含索引,如果索引为零,则表示该节没有名称。
sh_type字段
每个节都有类型,类型由一个称为sh_type的整数字段表示,该类 型告诉链接器关于该节内容结构的信息,图2-1显示了最重要的节类型 信息,这里我们将按顺序讨论各个重要的节类型。
- 类型为SHT_PROGBITS的节包含了程序数据,如机器指令或常量,这些节没有特定的结构供链接器解析。
- 符号表还有特殊的节类型(对静态符号表来说是SHT_SYMTAB,对动态链接器使用的符号表来说是SHT_DYNSYM)和字符串表(SHT_STRTAB)。
- SHT_REL或SHT_RELA类型的节对链接器特别重要,因为它们包含格式明确的重定位项(elf.h中的结构体Elf64_Rel和结构 体Elf64_Rela),链接器可以解析该重定位项以在其他节中进行重定位。每个重定位项都会告诉链接器二进制文件中需要重定位的特定位 置,以及重定位需要解析的符号。实际上重定位的过程相当复杂,这里 不赘述。要注意的是,SHT_REL和SHT_RELA类型的节用于静态链接。
- SHT_DYNAMIC类型的节包含动态链接所需的信息,该信息使用elf.h中的结构体Elf64_Syn。
sh_flags字段
节标志(在sh_flags字段指定)描述了有关节的其他信息,这里最重要的标志是SHF_WRITE、SHF_ALLOC及SHF_EXECINSTR。
- SHF_WRITE指示该节在运行时可写,这样可以轻松地区分包含静态 数据(如常量)的节和包含变量的节。
- SHF_ALLOC指示在执行二进制文件时将节的内容加载到虚拟内存,尽管实际上二进制文件的加载是使用段视图(segment view)而不是节视图(section view)。
- SHF_EXECINSTR指示该节包含可执行指令,这对反汇编二进制文件来说很有用。
sh_addr、sh_offset及sh_size字段
sh_addr、sh_offset及sh_size字段分别描述该节的虚拟地址、文件偏移(文件的起始字节数)及大小(字节)。
乍一看,描述节的虚拟地址的字段(如sh_addr)在这里似乎不合适,毕竟这些节仅用于链接进程,而不用于创建和执行进程。但是尽管如此,链接器有时需要知道特定的代码和数据在运行时最终会在哪个地址进行重定位, 而sh_addr字段会提供此信息。当设置进程的sh_addr值为零时,节不会被加载到虚拟内存中。
sh_link字段
有时链接器需要了解节与节之间的关系,例如与SHT_SYMTAB、SHT_DYNSYM或者SHT_DYNAMIC类型的节有关联的字符串表节,其中包含相关符号的名称。类似地,重定位节(SHT_REL或SHT_RELA类型)与描述重定位所涉及符号的符号表相关联,sh_link字段通过表示相关节的索引(在节头表中)使这些关系变得清晰。
sh_info
sh_info字段存放关于节的额外信息,这些额外信息依赖于节类型 (section type)。例如对于SHT_REL和SHT_RELA类型的重定位节,sh_info存放的是应用重定位节的节头索引。
sh_addralign字段
某些节需要以特定方式在内存中对齐,来提高内存访问的效率。如节可能需要在偏移量为8字节或者16字节倍数的地址处进行加载,这些对齐的要求在sh_addralign字段中指定。如果该字段设置为16,意味 着该节的基址必须为16的倍数(由链接器指定)。保留值0和1均指示无特殊对齐需要。
sh_entsize字段
某些节(如符号表或者重定位表)包含固定大小的条目,如Elf64_Sym或Elf64_Rela。对于这些节,sh_entsize指定了每个条目的长度字节数,如果节中并不包含固定长度条目的表格,那 么sh_entsize取值为0。