一 点睛
可利用readelf工具来查看重定向文件add.o的section表。
[root@localhost 0401]# readelf -S add.o
There are 11 section headers, starting at offset 0x220:
Section Headers:
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040 0000000000000014 0000000000000000 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00000054 0000000000000000 0000000000000000 WA 0 0 1
[ 3] .bss NOBITS 0000000000000000 00000054 0000000000000000 0000000000000000 WA 0 0 1
[ 4] .comment PROGBITS 0000000000000000 00000054 000000000000002e 0000000000000001 MS 0 0 1
[ 5] .note.GNU-stack PROGBITS 0000000000000000 00000082 0000000000000000 0000000000000000 0 0 1
[ 6] .eh_frame PROGBITS 0000000000000000 00000088 0000000000000038 0000000000000000 A 0 0 8
[ 7] .rela.eh_frame RELA 0000000000000000 00000208 0000000000000018 0000000000000018 I 9 6 8
[ 8] .shstrtab STRTAB 0000000000000000 000000c0 0000000000000054 0000000000000000 0 0 1
[ 9] .symtab SYMTAB 0000000000000000 00000118 00000000000000d8 0000000000000018 10 8 8
[10] .strtab STRTAB 0000000000000000 000001f0 0000000000000012 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
二 Elf32_Shdr数据结构分析
// ELF Section Header的结构还是要从/usr/include/elf.h中。
typedef struct
{
/*
1. sh_name(4 bytes): 节区名称,是"节区头部字符串表节区"(Section Header String Table Section)的索引。名字是一个NULL结尾的字符串。
所谓"节区头部字符串表节区",就是一段连续的保存每个节区名字的ascii字符的地址空间
*/
Elf32_Word sh_name;
/*
2. sh_type(4 bytes): 为节区的内容和语义进行分类
1) SHT_NULL: 0: 此值标志节区头部是非活动的,没有对应的节区。此节区头部中的其他成员取值无意义
2) SHT_PROGBITS: 1: 此节区包含程序定义的信息,其格式和含义都由程序来解释
3) SHT_SYMTAB: 2: 此节区包含一个符号表。目前目标文件对每种类型的节区都只能包含一个,不过这个限制将来可能发生变化,通常情况下,SHT_SYMTAB节区提供用于链接编辑(指ld而言)的符号,尽管也可用来实现动态
链接。
4) SHT_STRTAB: 3: 此节区包含字符串表。目标文件可能包含多个字符串表节区。
5) SHT_RELA: 4: 此节区包含重定位表项,其中可能会有补齐内容(addend),例如32位目标文件中的Elf32_Rela类型。目标文件可能拥有多个重定位节区
6) SHT_HASH: 5: 此节区包含符号哈希表。所有参与动态链接的目标都必须包含一个符号哈希表。目前,一个目标文件只能包含一个哈希表,不过此限制将来可能会解除。
7) SHT_DYNAMIC: 6: 此节区包含动态链接的信息。目前一个目标文件中只能包含一个动态节区,将来可能会取消这一限制。
8) SHT_NOTE: 7: 此节区包含以某种方式来标记文件的信息。
9) SHT_NOBITS: 8: 这种类型的节区不占用文件中的空间,其他方面和SHT_PROGBITS相似。尽管此节区不包含任何字节,成员sh_offset中还是会包含概念性的文件偏移
10) SHT_REL: 9: 此节区包含重定位表项,其中没有补齐(addends),例如32位目标文件中的Elf32_rel类型。目标文件中可以拥有多个重定位节区
11) SHT_SHLIB: 10: 此节区被保留,不过其语义是未规定的。包含此类型节区的程序与ABI不兼容。
12) SHT_DYNSYM: 11: 作为一个完整的符号表,它可能包含很多对动态链接而言不必要的符号。因此,目标文件也可以包含一个SHT_DYNSYM节区,其中保存动态链接符号的一个最小集合,以节省空间
13) SHT_LOPROC(0x70000000)~SHT_HIPROC(0x7FFFFFFF): 这一段(包括两个边界),是保留给处理器专用语义的
14) SHT_LOUSER(0X80000000): 此值给出保留给应用程序的索引下界
15) SHT_HIUSER(0X8FFFFFFF): 此值给出保留给应用程序的索引上界
*/
Elf32_Word sh_type;
/*
2. sh_flags(4 bytes): sh_flags字段定义了一个节区中包含的内容是否可以修改、是否可以执行等信息。如果一个标志位被设置,则该位取值为1。未定义的各位都设置为0(这是一种bitmap位图表示法)
1) SHF_WRITE: 0x1: 节区包含进程执行过程中将可写的数据
2) SHF_ALLOC: 0x2: 此节区在进程执行过程中占用内存。某些控制节区并不出现于目标文件的内存映像中,对于那些节区,此位应设置为0
3) SHF_EXECINSTR: 0x4: 节区包含可执行的机器指令
4) SHF_MASKPROC: 0xF0000000: 所有包含于此掩码中的四位都用于处理器专用的语义
*/
Elf32_Word sh_flags;
/*
3. sh_addr(4 bytes): 如果节区将出现在进程的内存映像中,此成员给出节区的第一个字节应处的位置。否则,此字段为0
*/
Elf32_Addr sh_addr;
/*
4. sh_offset(4 bytes): 此成员的取值给出节区的第一个字节与文件头之间的偏移。不过,SHT_NOBITS类型的节区不占用文件的空间,因此其sh_offset成员给出的是其概念性的偏移
*/
Elf32_Off sh_offset;
/*
5. sh_size(4 bytes): 此成员给出节区的长度(字节数)。除非节区的类型是SHT_NOBITS,否则节区占用文件中的sh_size 字节。类型为SHT_NOBITS的节区长度可能非零,不过却不占用文件中的空间
*/
Elf32_Word sh_size;
/*
6. sh_link(4 bytes): 此成员给出节区头部表索引链接。其具体的解释依赖于节区类型
根据节区类型的不同,sh_link和sh_info 的具体含义也有所不同
sh_type sh_link sh_info
SHT_DYNAMIC 此节区中条目所用到的字符串表格的节区头部索引 0
SHT_HASH 此哈希表所适用的符号表的节区头部索引 0
SHT_REL、SHT_RELA 相关符号表的节区头部索引 重定位所适用的节区的节区头部索引
SHT_SYMTAB、SHT_DYNSYM 相关联的字符串表的节区头部索引 最后一个局部符号(绑定 STB_LOCAL)的符号表索引值加一
其它 SHN_UNDEF 0
*/
Elf32_Word sh_link;
/*
7. sh_info(4 bytes): 此成员给出附加信息,其解释依赖于节区类型
*/
Elf32_Word sh_info;
/*
8. sh_addralign(4 bytes): 某些节区带有地址对齐约束。例如,如果一个节区保存一个doubleword,那么系统必须保证整个节区能够按双字对齐。sh_addr对sh_addralign取模,结果必须为0。目前仅允许取值为0和2的幂
次数。数值0和1表示节区没有对齐约束
*/
Elf32_Word sh_addralign;
/*
9. sh_entsize(4 bytes): 某些节区中包含固定大小的项目,如符号表。对于这类节区,此成员给出每个表项的长度字节数。如果节区中并不包含固定长度表项的表格,此成员取值为0
*/
Elf32_Word sh_entsize;
}Elf32_Shdr;
三 参考
https://blog.csdn.net/Linux_ever/article/details/78210089