Section Header Table
文章目录
readelf -S
查看。
1. 数据结构
typedef struct
{
Elf32_Word sh_name; /* Section name (string tbl index) */
Elf32_Word sh_type; /* Section type */
Elf32_Word sh_flags; /* Section flags */
Elf32_Addr sh_addr; /* Section virtual addr at execution */
Elf32_Off sh_offset; /* Section file offset */
Elf32_Word sh_size; /* Section size in bytes */
Elf32_Word sh_link; /* Link to another section */
Elf32_Word sh_info; /* Additional section information */
Elf32_Word sh_addralign; /* Section alignment */
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
同样,类型名里的32改为64就是64位系统。
1.1 sh_name
段名字段是4字节相对shstrtab段数据块的偏移。
比如,
textSH.sh_name == 0x9d;
strtab.sh_offset == 0x1844;
".text" == 0x1844 + 0x9d
1.2 sh_type
/* Legal values for sh_type (section type). */
#define SHT_NULL 0 /* Section header table entry unused */
#define SHT_PROGBITS 1 /* Program data */
#define SHT_SYMTAB 2 /* Symbol table */
#define SHT_STRTAB 3 /* String table */
#define SHT_RELA 4 /* Relocation entries with addends */
#define SHT_HASH 5 /* Symbol hash table */
#define SHT_DYNAMIC 6 /* Dynamic linking information */
#define SHT_NOTE 7 /* Notes */
#define SHT_NOBITS 8 /* Program space with no data (bss) */
#define SHT_REL 9 /* Relocation entries, no addends */
#define SHT_SHLIB 10 /* Reserved */
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
#define SHT_INIT_ARRAY 14 /* Array of constructors */
#define SHT_FINI_ARRAY 15 /* Array of destructors */
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
#define SHT_GROUP 17 /* Section group */
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
#define SHT_NUM 19 /* Number of defined types. */
常见的是SHT_PROGBITS, SHT_SYMTAB, SHT_STRTAB, SHT_DYNAMIC, SHT_REL, SHT_INIT_ARRAY, SHT_FINI_ARRAY
.
后两个存放构造/析构函数数组。
1.3 sh_flags
常用的就是前3个:1/2/4. 如text段可分配可执行。
/* Legal values for sh_flags (section flags). */
#define SHF_WRITE (1 << 0) /* Writable */
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
#define SHF_EXECINSTR (1 << 2) /* Executable */
#define SHF_MERGE (1 << 4) /* Might be merged */
#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling required */
#define SHF_GROUP (1 << 9) /* Section is member of a group. */
#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
#define SHF_ORDERED (1 << 30) /* Special ordering requirement (Solaris). */
#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless referenced or allocated (Solaris).*/
1.4 link
sh_link
,sh_info
,
这2个字段表示section的链接信息,一般描述符号表段SHT_SYMTAB
和重定位段SHT_REL
链接信息。
sh_type | sh_link | sh_info |
---|---|---|
SHT_DYNAMIC | 字符串表索引 | |
SHT_HASH | 哈希表使用的符号表索引 | |
SHT_REL/SHT_RELA | 相关符号表索引 | 重定位目标段索引 |
SHT_SYMTAB | 关联字符串表索引 | 最后一个局部符号的索引+1 |
其它 | SHN_UNDEF | 0 |
1.4.1 SHT_SYMTAB举例
符号表加一的sh_info
,一般恰好是第一个全局符号索引,帮助链接器更快定位到第一个全局符号。
readelf -S
:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[26] .symtab SYMTAB 00000000 001034 000430 10 27 43 4
readelf -s
查看符号表:
Num: Value Size Type Bind Vis Ndx Name
42: 00001fd8 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_
43: 000005c0 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini
44: 00000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
1.4.2 SHT_REL举例
再看重定位表段:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 5] .dynsym DYNSYM 000001cc 0001cc
[ 9] .rel.dyn REL 00000328 000328 000040 08 A 5 0 4
[10] .rel.plt REL 00000368 000368 000010 08 AI 5 22 4
[22] .got PROGBITS 00001fd8 000fd8 000028 04 WA 0 0 4
1.5 other fields
-
sh_addr
, section加载后的虚拟地址,重定位文件无法确定,填0; -
sh_offset
, section文件偏移; -
sh_size
, section加载后内存大小,如果type==SHT_NOBITS
,则无数据,如bss; -
sh_addralign
, 对齐规则sh_offset % sh_addralign == 0
。 -
sh_entsize
, 保存符号表、重定位表等表项大小。
2. readelf源码
太多了,看代码文件吧。。。
主要3个函数。
static int
process_section_headers (FILE * file);
static const char *
get_group_flags (unsigned int flags);
static int
process_section_groups (FILE * file);