ELF重定位偏移r_offset什么时候需要加上装载基地址?
ElfN_Rela 结构体 r_offset 字段叠加装载基址的规则
你产生误解的核心原因是man elf文档中提到的「虚拟地址」是ELF对象自身地址空间的定义,而非进程全局的绝对虚拟地址,具体适用规则如下:
- 当ELF头
e_type为ET_REL(可重定位目标文件,通常为.o后缀):r_offset是受重定位的存储单元距离所属节首地址的字节偏移,需要先确定该节加载到进程地址空间后的首地址,再叠加r_offset得到最终的绝对虚拟地址。 - 当ELF头
e_type为ET_EXEC(非PIE固定地址可执行文件):
该类ELF的装载基址在编译时就已固定,自身地址空间和进程绝对地址空间完全对齐,r_offset直接对应进程空间的绝对虚拟地址,无需额外叠加装载基址。 - 当ELF头
e_type为ET_DYN(包含共享库、PIE可执行文件两类):
该类ELF的装载基址运行时才会确定,自身地址空间的0地址对应实际的装载基址,因此r_offset是相对于装载基址的偏移,最终绝对虚拟地址 = 装载基址 +r_offset。
man 文档的歧义说明
文档中「对于可执行文件或共享对象,该值是受重定位影响的存储单元的虚拟地址」的描述,对两类可装载ELF的语义是统一的:这个值都是要修改的存储单元在ELF自身地址空间中的地址。只是ET_EXEC的自身地址空间和进程绝对地址空间没有偏移,所以不需要额外计算,ET_DYN的自身地址空间有整体偏移,因此需要叠加装载基址。
内容的提问来源于stack exchange,提问作者Daniel Walker
相关产品推荐
相关产品推荐

