美文网首页
为什么 xv6-riscv 编译的时候需要 -mcmodel=m

为什么 xv6-riscv 编译的时候需要 -mcmodel=m

作者: 虾饺的开发手记 | 来源:发表于2023-05-19 23:42 被阅读0次

    xv6-riscv 有这样一行代码:

    // kernel/start.c
    void start() {
      ...
    
      // requires gcc **-mcmodel=medany**
      w_mepc((uint64)main)
    
      ...
    }
    

    对应的,Makefile 里有这个:

    CFLAGS += -mcmodel=medany
    

    然后我就不禁要问了,我拿个 main 函数的地址,关这个 cmodel 啥事?网上翻了一圈后,就有了这篇文章。


    关于 -mcmodel=medany,简单地说,他是指定编译器如何生成访问全局变量指令的命令,cmodel 即是 code model 的意思。相对的,还有另一种模式是 medlow(默认的模式):

    • medany:生成位置无关的代码,全局变量的地址通过 auipc 生成(即他是 PC relative 的)。由于 auipc 的限制,全局变量的地址必须在 PC ± 2G 以内
    • medlow:low 模式,地址通过 lui 生成,这限制了地址范围为 [0, 2G]

    具体可以参考这篇文章

    理解了 code model 以后,我们就可以确信地说,拿个 main 函数的地址,跟 code model 其实没半毛钱关系。或者说,这不是使用 medany 的根本原因。

    那么,要不我们试试把这个 flag 去掉?遗憾的是,如果你真的去掉了这个 flag,链接的时候你会发现有一堆错误:

    kernel/start.o: in function `timerinit':
    xv6-riscv/kernel/start.c:76:(.text+0x34): relocation truncated to fit: R_RISCV_HI20 against `.LANCHOR0'
    kernel/console.o: in function `consoleread':
    xv6-riscv/kernel/console.c:87:(.text+0x84): relocation truncated to fit: R_RISCV_HI20 against `.LANCHOR0'
    ......
    

    意思是,函数 xxx 里面,某个需要重定位的地址超过了 R_RISCV_HI20 能够支持的范围,即超过了 2G(因为默认是 medlow 模式)。原因是,我们在链接的时候,把 text 段放在了 0x80000000(= 2^31 = 2G),我们所有的代码都超过了 2G:

    # kernel/kernel.ld
    SECTIONS
    {
      /*
       * ensure that entry.S / _entry is at 0x80000000,
       * where qemu's -kernel jumps.
       */
      . = 0x80000000;
    
      .text : {
        *(.text .text.*)
        . = ALIGN(0x1000);
        _trampoline = .;
        *(trampsec)
        . = ALIGN(0x1000);
        ASSERT(. - _trampoline == 0x1000, "error: trampoline larger than one page");
        PROVIDE(etext = .);
      }
    
    ...
    
    

    也因此,我们才需要用 medany

    你可以简单验证一下,比方说,把 kernel.ld 里的 0x80000000 改成 0x40000000。这样即使用默认的 medlow,也能够编译成功(但是运行就不行了,qemu 默认会执行 0x80000000 处的代码)。

    相关文章

      网友评论

          本文标题:为什么 xv6-riscv 编译的时候需要 -mcmodel=m

          本文链接:https://www.haomeiwen.com/subject/ltnnsdtx.html