You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何链接器无法将.rodata置于.text之后?RISC-V Rust编译问题

解决.text段定位与重定位错误方案

问题根源分析

  1. 默认链接脚本中.rodata段优先级高于.text,导致它抢占了0x80200000地址
  2. 你提供的链接脚本中data_space起始地址写错(多了一个0,写成0x80200002c,实际应为0x8020002c),导致.rodata被放到距离.text过远的位置,触发RISC-V的R_RISCV_PCREL_HI20重定位范围限制(该重定位仅支持±512KB内的地址跳转)

修正后的链接脚本

MEMORY {
  kernel (rwx) : ORIGIN = 0x80200000, LENGTH = 6K
}

SECTIONS {
  .text : {
    /* 强制_start函数放在段最开头,保证OpenSBI能正确跳转 */
    KEEP(*(.text._start))
    *(.text*)
  } > kernel
  .text ALIGN(4) : {
    /* 确保.text段按4字节对齐,符合RISC-V指令要求 */
  } > kernel

  .rodata : {
    *(.rodata*)
  } > kernel

  /* 保留其他必要段的定义 */
  .comment : { *(.comment) }
  .riscv.attributes : { *(.riscv.attributes) }
}

关键调整说明

  • 合并内存区域:不需要拆分kernel_space和data_space,.text和.rodata属于同类型只读段,放在同一连续内存区域即可,避免跨区域远距离跳转
  • 强制_start位置:用KEEP(*(.text._start))确保入口函数_start位于.text段最开头(即0x80200000地址),匹配OpenSBI的加载预期
  • 对齐修正:给.text段添加4字节对齐,符合RISC-V 32/64位指令的对齐要求,避免地址偏移引发异常
  • 调整段顺序:将.text放在.rodata之前,确保链接器优先为.text分配指定起始地址

编译配置补充

在Rust的.cargo/config.toml中添加以下编译参数,适配内核场景:

[target.riscv-unknown-kadrix]
rustflags = [
  "-C", "link-arg=-Tlinker.ld",
  "-C", "relocation-model=static",
  "-C", "code-model=medium"
]
  • relocation-model=static:禁用动态重定位,适合无OS的内核环境
  • code-model=medium:支持更大范围的地址访问,规避小代码模型的跳转限制

验证方法

编译完成后,执行以下命令查看段信息:

riscv64-unknown-elf-readelf -S target/riscv-unknown-kadrix/release/kadrix

确认:

  • .text的VMA和LMA均为0x80200000
  • .rodata紧跟在.text之后,地址连续

内容的提问来源于stack exchange,提问作者CocytusDEDI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 17:39:56