关于 reimu 的一些技术细节 #9
DarkSharpness
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
reimu
是一个高性能的 RISC-V 模拟器。其不同于先前的模拟器 ravel,reimu
是一个更加真实、强大,拥有更好的拓展性、更加人性化的报错信息、更高的模拟速度,甚至内置了类似 gdb 的 debug shell。作为一个用户,你可能并不关心解释器内部的实现细节,但是你依然需要知道一些必要的信息。
首先,
reimu
支持命令行输入参数,具体可以使用reimu --help
来查看帮助信息,这里就不多赘述了。默认情况下,reimu
接受builtin.s
和test.s
作为输入程序,而程序的输入/输出则是由终端进行,当然也可以通过--input
和--output
参数来指定输入输出文件。其次,
reimu
的前端有着远严格于ravel
的检查。首先是section
信息。reimu 只会接受以.
开头的section
名字,格式形如:.section .data
或者.text
。由于reimu
的模拟完全是基于二进制的 (即,后端模拟器拿到的不是形如ret
的字符串形式的指令,而是拿到其二进制值0x00008067
并基于这个值解码再执行,而由输入字符串到二进制的转化会在模拟开始之前完成),所有指令必须是合法的 RISC-V 的指令,例如addi rd, rs, imm
指令,其立即数范围为[-2048, 2047]
。一旦超出范围,则会在链接期间报错。(当然,这也意味着,你可以在代码段直接塞入.word 0x00008067
来代替ret
指令,这样也是合法的)同时,
reimu
链接内存布局完全按照 RISC-V 的规范。代码段.text
的数据从0x10000
开始从低往高排布,然后是静态数据 (.data
,.rodata
,.bss
),在此之后是堆空间 (heap),栈空间 (stack) 则位于最高处。默认内存大小是256 MB
,栈大小是32K
。因此,在默认情况下,栈的地址空间是[0xfff8000, 0x10000000)
。在用户 debug 自己的程序的时候,如果发现内存访问越界的地址在这些位置附近,可以考虑是否是因为栈溢出/栈不平衡 (sp
指针被污染) 等问题导致。在运行期间,
reimu
也会做非常严格的检查,对于越界/不对齐的访问,会直接报错并退出。这样的检查是为了保证模拟器的正确性 (防止模拟器本身崩溃),同时也是为了帮助用户 debug 自己的程序。例如Store Misaligned
, 表示存储访问不对齐,其往往发生在sw
指令上。对于sw
指令,其会向内存写入 4 个字节的数据。一般情况下,CPU 会要求程序保证存储访问的对齐性,对于sw
即为存储的地址必须是 4 的倍数。reimu
会检查这一点,如果发现不对齐的访问,会直接报错。在真实的程序中,这种错误也可能会导致程序崩溃。导致内存访问不对齐地原因有很多,常见问题有全局变量 .word 前没有声明.align 2
,栈上对象偏移量管理不当等。对于前一种情况,一个简单的解决方案如下:最后,
reimu
的 debug shell 也是一个强大的工具。关于 debug shell 的使用请参考docs/manual.md
。例如,当你用reimu
运行程序并且发现程序出错崩溃时,可以尝试加上reimu --debug
,在 debug shell 中输入c
直接运行到程序崩溃处,输入h 10
查看最近的10
条指令,输入bt
调用栈回溯,并且结合其他在 manual 中提到的命令,定位程序错误的原因。需要特别注意的是,reimu
的 debug shell 依赖于 calling convention, 即把jal ra, offset
和jalr ra, offset(rs)
作为函数调用的指令,并且把jalr zero, 0(ra)
作为函数返回的指令,基于此进行栈回溯和检查 (ret
的时候ra
寄存器的值应该是调用者的返回地址,sp
应该恢复到调用者的栈帧)。如果你的程序不符合这个 calling convention,则无法使用 debug shell。目前 debug shell 仍处于开发阶段,可能会有一些 bug,欢迎大家提 issue 以及 request feature。最后的最后,该项目的名字
reimu
来自于东方 project 的博丽灵梦🎀。这是笔者非常喜欢的一个 IP 的角色❤️。以下图片来自萌娘百科。Beta Was this translation helpful? Give feedback.
All reactions