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

RISC-V 64gc LD出现R_RISCV_PCREL_HI20截断重定位错误如何解决

错误原因

这个错误的核心原因是RISC-V默认的medlow代码模型不支持你当前使用的地址范围:

  • RISC-V 64位的默认medlow代码模型要求所有符号地址必须是可符号扩展到64位的32位有符号数,即地址的第31位到第63位必须完全相同,仅支持0x0000000000000000 ~ 0x000000007FFFFFFF(低2GiB)或者0xFFFFFFFF80000000 ~ 0xFFFFFFFFFFFFFFFF(高2GiB)两个地址区间。
  • 你在链接脚本中指定的加载基址是0x0000000080000000,刚好落在上述两个区间的间隙中,第31位为1、第32~63位全为0,不符合medlow模型的地址要求,导致重定位时无法用32位偏移表示地址,触发截断错误。

额外存在一个容易引发后续运行时错误的问题:你在C代码中将链接脚本定义的globalPointer声明为指针类型是错误的。链接脚本中PROVIDE(globalPointer = .)定义的符号本身的值就是目标地址,不是存储地址的指针变量,声明为指针会导致编译器去读取该地址存储的内容作为指针,而非直接使用该地址值。

解决方案

你可以根据自己的需求选择以下任意一种方案解决链接错误,建议同时修正C代码的符号声明避免后续运行时问题:

  1. 修改代码模型为medany(最通用的解决方案)
    medany代码模型支持任意地址的PC相对寻址,只要符号和当前指令的偏移在±2GiB范围内即可,完全覆盖你的使用场景。你需要在编译汇编和C代码时都加上-mcmodel=medany参数:
# 汇编编译命令添加参数
riscv64-elf-as -march=rv64gc -mcmodel=medany source/entry.s -o build/entry.o
# C代码编译命令也需要添加同样参数
riscv64-elf-gcc -march=rv64gc -mcmodel=medany -c source/kernel.c -o build/kernel.o
  1. 调整链接基址符合medlow模型要求
    如果你不想修改代码模型,可以将链接脚本中的基址修改为高2GiB的对应地址,即可匹配medlow的地址要求:
. = 0xFFFFFFFF80000000;
  1. 修正C代码中的符号声明
    将C代码中的globalPointer声明修改为数组类型,即可直接获取符号对应的地址值:
#include <stdint.h>

extern volatile char globalPointer[];

int kernalMain(void){
    *(volatile uint64_t*)globalPointer = 0;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:36:06