Elf32转Uniflex:.rela.rodata是否包含.rodata.str的重定位记录?
Elf32转Uniflex .r格式转换器的重定位问题解答
背景
我正在编写一个从Elf32格式转换为Uniflex .r格式的转换器。由于Uniflex .r格式没有只读数据段,我将.data、.rodata和.rodata.str这几个段合并到一起。目前使用的重映射规则如下:
.rela.text对应.text.rela.data对应.data.rela.rodata对应.rodata
问题
.rodata.str 的重定位记录是否包含在 .rela.rodata 中?我尝试对 .rodata.str 应用重定位时,得到了「无效加数」的错误。
解答
关于.rodata.str的重定位归属
在ELF规范里,.rodata.str是.rodata的细分子段,专门存储只读字符串数据。链接器不会为这类子段单独生成独立的.rela重定位段,所有和只读数据相关的重定位记录(包括.rodata.str的)都会统一归类到.rela.rodata中。所以答案是是。
「无效加数」错误的原因及解决思路
你遇到的错误核心是合并段后重定位偏移的计算基准发生了变化:
- 原始
.rela.rodata中的重定位项,其偏移量是基于原始.rodata(或.rodata.str)段的起始地址计算的; - 当你把
.data、.rodata、.rodata.str合并成一个段后,原有的偏移基准不再适用,直接套用旧规则计算会导致目标地址超出合并段的有效范围,触发「无效加数」。
解决步骤:
- 先解析ELF文件中
.rodata.str的段信息,记录它的原始起始地址和长度; - 遍历
.rela.rodata中的每一条重定位项,通过重定位项的r_offset字段判断该目标地址是否落在.rodata.str的地址范围内; - 对于属于
.rodata.str的重定位项,重新计算其在合并段中的偏移:新偏移 = (原始r_offset - .rodata.str原始起始地址) + 合并段中.rodata.str部分的起始偏移 - 确保所有重定位项的目标段基址更新为合并后新段的基址,而不是原始单个段的基址。
内容的提问来源于stack exchange,提问作者Elektraglide
相关产品推荐
相关产品推荐

