V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX  ›  程序员

RISCV 因为两个函数不在 2G 范围内,所以报错 relocation trancated to fit?

  •  
  •   amiwrong123 · 22 天前 · 1014 次点击

    https://blog.csdn.net/qq_24402247/article/details/140617233

    报错原理应该是和 这篇博客一样,因为两个函数最多只能+-2GB 空间。 我这两个函数,都是在 32 位空间内(也就是整个 4G 空间),但这两个函数的距离超过了 2G 的距离(因为我 ld 脚本的写法)。

    一些必要信息:

    • 假设这两个函数是 A 和 B ,注释掉 A 函数里,对 B 函数的调用。则不会报错。A 和 B 函数,分别处于两个 c 文件里。
    • 查阅了 gcc 的 riscv 部分,只支持-mcmodel=medlow 和-mcmodel=medany
    • 如果是-mcmodel=medany ,那么报错 relocation trancated to fit R_RISCV_CALL against symbol xx in .text section
    • 如果是-mcmodel=medlow ,那么报错 relocation trancated to fit R_RISCV_H20 against .LC0 和 relocation trancated to fit R_RISCV_CALL against symbol xx in .text section

    一些猜想:我看了我编译出来的反汇编,大部分函数调用是 jal ,有很少的 jalr 。我理解 jalr ,就可以随便跳转了吧,为啥编译器不帮我 编译成使用 jalr 的汇编呢。

    PS:问了大模型,搜了谷歌,还是没有帮助。

    10 条回复    2025-03-28 20:44:25 +08:00
    julyclyde
        1
    julyclyde  
       22 天前
    你用 64bit 模式试试?
    xixijay1988
        2
    xixijay1988  
       22 天前
    用 JALR 的话也只能在+-2G 的地址空间内;最高比特决定了向前还是向后,剩余的也只有 31bit 的位置信息; JALR 里面的 12 位相对位置 offset 的立即数不是 2 的倍数,否则的话还有戏
    xixijay1988
        3
    xixijay1988  
       22 天前
    RV64 上感觉是编译器故意做的限制,内核设计上应该是参照的规范来的,否则编出来的话在其他内核上跑不了;
    heiher
        4
    heiher  
       21 天前
    不是还有-mcmodel=large 嘛
    amiwrong123
        5
    amiwrong123  
    OP
       21 天前
    @heiher #4
    我是查看的 RISCV 的 Machine-Dependent Options 里面,我看里面只有-mcmodel=medlow 和-mcmodel=medany 啊?
    amiwrong123
        7
    amiwrong123  
    OP
       17 天前
    @xixijay1988 #2
    @xixijay1988 #3
    好吧,那这 JALR 也不行的话。那我应该怎么解决这个问题了啊😂
    amiwrong123
        8
    amiwrong123  
    OP
       4 天前
    @heiher #4
    我尝试了一下,我这个 gcc 居然不支持 large 呢。哈哈,只有自己实现一个 中转函数了
    heiher
        9
    heiher  
       4 天前
    @amiwrong123 那应该是 GCC 版本太老了吧。那也可以用 JALR 间接跳转了,不用再经过一个中间函数中转呀,JALR 是完整地址空间任意位置都能覆盖到。
    amiwrong123
        10
    amiwrong123  
    OP
       4 天前
    @heiher #9 #9
    void jumpAgent(void (*target_func)()) {
    asm volatile(
    "jalr x1, 0(%0)\n\t"
    :
    : "r"((uint64_t)target_func)
    );
    }

    写了一个这个函数,但是我调用的时候,是这样 jumpAgent(myWantFunc);在调用 jumpAgent 的地方又会报错,因为传参是传给 x10 (它是第一个参数),传参的汇编是 auipc+addi 来把 myWantFunc 加载进 x10 ,然后这里就会报错 trancated to fit

    这好像有点无解了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1126 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:34 · PVG 02:34 · LAX 11:34 · JFK 14:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.