sections包含所有的信息,除了ELF头、program header table和section header table。sections满足几个条件:
1. 每个section都有唯一的一个section header,但是section header可能没有section。
2. 每个section占用文件中连续的字节。
3. 文件中的section没有重叠。
4. 目标文件可能有不活动的空间。即文件中的一部分字节,可能既不是头,也不是section、也许是无用的填充。
Section header table包含所有section的基本信息,如类型、地址等。通过section header table可以索引所有的section。通过ELF header中的e_shoff可以确定section header table在文件中的位置、e_shnum可以确定section的个数、e_shentsize可以确定section header table一个section条目的大小。
Section header可以用下述结构体表示:
1 2 3 4 5 6 7 8 9 10 11 12  | typedef struct elf32_shdr {  Elf32_Word  sh_name;  Elf32_Word  sh_type;  Elf32_Word  sh_flags;  Elf32_Addr  sh_addr;  Elf32_Off   sh_offset;  Elf32_Word  sh_size;  Elf32_Word  sh_link;  Elf32_Word  sh_info;  Elf32_Word  sh_addralign;  Elf32_Word  sh_entsize;} Elf32_Shdr; | 
sh_name,确定section的名字,其值是距section header string table开头的偏移。由于string table中的所有字符串是'\0'结尾的,所以只需要知道字符串首即可。
sh_type,是section的类型。
Name  | Value  | 
SHT_NULL  | 0  | 
SHT_PROGBITS  | 1  | 
SHT_SYMTAB  | 2  | 
SHT_STRTAB  | 3  | 
SHT_RELA  | 4  | 
SHT_HASH  | 5  | 
SHT_DYNAMIC  | 6  | 
SHT_NOTE  | 7  | 
SHT_NOBITS  | 8  | 
SHT_REL  | 9  | 
SHT_SHLIB  | 10  | 
SHT_DYNSYM  | 11  | 
SHT_LOPROC  | 0x70000000  | 
SHT_HIPROC  | 0x7fffffff  | 
SHT_LOUSER  | 0x80000000  | 
SHT_HIUSER  | 0xffffffff  | 
sh_flags,section的flags:
Name  | Value  | 
SHF_WRITE  | 0x1  | 
SHF_ALLOC  | 0x2  | 
SHF_EXECINSTR  | 0x4  | 
SHF_MASKPROC  | 0xf0000000  | 
sh_addr,如果section出现在内存镜像中,表示section第一个字节的地址。否则为0。
sh_offset,给出section距文件开始处的偏移。
sh_size,如果type不是SHT_NOBITS,表示section在文件中的大小。如果type是SHT_NOBITS,section不占文件大小,sh_size表示内存中的大小。
sh_link,根据type确定含义。
sh_info,根据type确定含义。
sh_addralign,section的对齐要求。0和1表示无对齐要求。
sh_entsize,一些section包含固定大小的条目,表示一个条目的大小。0表示无固定大小的条目。
ELF中的一些内容如符号表使用section索引。一些特殊的section索引有特殊的含义,这些索引可能并不存在于section header table中。这些特殊的索引如下:
Name  | Value  | 
SHN_UNDEF  | 0  | 
SHN_LORESERVE  | 0xff00  | 
SHN_LOPROC  | 0xff00  | 
SHN_HIPROC  | 0xff1f  | 
SHN_ABS  | oxfff1  | 
SHN_COMMON  | 0xfff2  | 
SHN_HIRESERVE  | 0xffff  | 
SHN_UNDEF,显然这个索引存在于section header table中(如果不存在,那必然与其0号索引冲突)。0号索引的所有成员都是0。
SHN_ABS,表示相关的引用有绝对值。如存储在符号表中的源文件名的section索引为ABS。
SHN_COMMON,相对于这个section索引的符号是公共符号,如c的弱定义符号。
SHT_NULL,section header不活动,没有相关的section。通常,只有0号索引有这个类型。
SHT_PROGBITS,包含程序相关的信息。.text,.data等都是这种类型。
SHT_SYMTAB、SHT_DYNSYM,符号表。
SHT_STRTAB,字符串表。
SHT_REL、SHT_REL,重定向表。
SHT_HASH,字符哈希表。
SHT_DYNAMIC,包含动态链接的信息。
SHT_NOTE,note信息。
SHT_NOBITS,不占用文件空间,其它和PROGBITS类型相似。sh_offset包含概念上的文件偏移。.bss是这种类型。
SHT_SHLIB,保留。
SHF_WRITE,section包含在进程执行期间可写的数据。
SHF_ALLOC,进程执行期间,section占用内存。一些section是控制section,不会加载到内存,此flag被清除。
SHF_EXECINSTR,section包含可执行机器指令。
这两个字段,不同的section type,表示不同的含义,如下:
sh_type  | sh_link  | sh_info  | 
SHT_DYNMIC  | section条目使用的字符串表的section header索引。  | 0  | 
SHT_HASH  | 哈希表对应的符号表的索引  | 0  | 
SHT_REL SHT_RELA  | 相关的符号表的索引。  | 重定向的目标section的索引。  | 
SHT_SYMTAB SHT_DYNSYM  | 操作系统定义  | 操作系统定义  | 
其它  | SHN_UNDEF  | 0  | 
ELF中的许多section是预定义好的,包含程序和控制信息。这些section被操作系统使用。不同的操作系统可能有不同的类型和属性。
Name  | Type  | Atrributes  | 
.bss  | SHT_NOBITS  | SHF_ALLOC_SHF_WRITE  | 
.comment  | SHT_PROGBITS  | none  | 
.data  | SHT_PROGBITS  | SHF_ALLOC_SHF_WRITE  | 
.data1  | SHT_PROGBITS  | SHF_ALLOC_SHF_WRITE  | 
.debug  | SHT_PROGBITS  | none  | 
.dynamic  | SHT_DYNAMIC  | see below  | 
.hash  | SHT_HASH  | SHF_ALLOC  | 
.line  | SHT_PROGBITS  | none  | 
.note  | SHT_NOTE  | none  | 
.rodata  | SHT_PROGBITS  | SHF_ALLOC  | 
.rodata1  | SHT_PROGBITS  | SHF_ALLOC  | 
.shstrtab  | SHT_STRTAB  | none  | 
.strtab  | SHT_STRTAB  | |
.symtab  | SHT_STRTAB  | |
.text  | SHT_PROGBITS  | SHF_ALLOC+SHF_EXECINSTR  | 
这些特殊section的用途如下:
.bss,包含未初始化的数据。程序运行时,系统初始化为0。这个section不占用文件空间。
.comment,包含版本控制信息。
.data与.data1,包含已初始化数据。
.debug,包含符号调试信息。
.dynamic,包含动态链接信息。可以有SHF_ALLOC何SHF_WRITE属性,是否有SHF_WRITE属性是由操作系统和处理器定义的。
.hash,包含符号哈希表。
.line,包含用于符号调试的行号信息。
.note,
.rodata和.rodata1,包含只读数据。
.shstrtab,包含section names。
.strtab,包含字符串,通常表示符号表相关的名字。如果一个文件有一个可加载段包含符号字符串表,这个section的属性将是SHF_ALLOC,否则这个位被关闭。
.symtab,包含符号表。如果有一个可加载段包含符号表,则属性包括SHF_ALLOC。
.text,包含可执行指令。
.开头的section name是保留给系统的。
尽管程序也可使用,但是不建议这样做。