C实现ELF解析时如何识别GOT条目对应函数及.rela.plt符号名
ELF
.rela.plt 重定位条目与符号名关联实现方法 核心关联字段你之前漏看了:Elf64_Rela(注意.rela.plt是带加数的重定位表,用的是Elf64_Rela不是Elf64_Rel)结构体的r_info字段本身就编码了符号索引,不需要找其他字段关联。
x86_64架构下ELF标准定义了两个宏拆分r_info:
// 从r_info中提取对应符号在关联符号表中的下标 #define ELF64_R_SYM(info) ((info) >> 32) // 从r_info中提取重定位类型 #define ELF64_R_TYPE(info) ((info) & 0xffffffffULL)
拿你贴的readelf输出直接验证:
- 第一条重定位项Info值为
0x0000000100000007,用ELF64_R_SYM计算得到符号索引为1,正好对应.dynsym表中下标为1的条目,就是free@GLIBC_2.2.5 - 第二条重定位项Info值为
0x0000000500000007,计算得到符号索引为5,对应.dynsym下标5的malloc@GLIBC_2.2.5,和readelf输出的符号名完全一致。
.rela.plt段关联的符号表固定是.dynsym,关联的字符串表固定是.dynstr,不需要额外判断关联关系。
为什么st_shndx为SHN_UNDEF是正常现象
你之前猜测的st_shndx字段不参与这个关联逻辑。malloc、free是从glibc动态导入的符号,本身不存在于当前可执行文件的任何段中,所以符号表项的段索引必然是SHN_UNDEF,这个值只用来标记符号是导入还是本地定义,和重定位关联无关。
GOT条目与函数匹配的完整步骤
- 加载解析ELF头,找到
.rela.plt、.dynsym、.dynstr、.got.plt(即存储函数地址的GOT段)的加载基地址和长度 - 遍历
.rela.plt中每一个Elf64_Rela条目 - 对每个条目,用
ELF64_R_SYM(r_info)取出符号索引,用这个索引直接索引.dynsym数组得到对应的Elf64_Sym结构 - 用
Elf64_Sym结构的st_name字段作为偏移,加上.dynstr基地址,就能拿到对应的符号名字符串(这步你已经实现) - 重定位条目的
r_offset字段就是GOT表中对应条目的虚拟地址(文件映射状态下是文件内偏移),把这个地址和拿到的符号名绑定,就完成了GOT条目到对应函数的匹配。
注意:32位ELF的
r_info拆分规则不同,ELF32_R_SYM是取info >> 8,如果需要兼容32位程序要单独做逻辑判断,不要直接套用64位的移位规则。
内容的提问来源于stack exchange,提问作者Daniel Walker
相关产品推荐
相关产品推荐

