riscv-xv6单步调试1

  过了两个月,现在准备重新看xv6的源代码,调试的时候却死活记不起来自己当初是怎么调试的,遂明白写博客记录的重要性,打算这次看源代码的时候,把容易遗忘的东西都记录下来,留待后观吧。

xv6调试方法

  在xv6源代码有Makefile的路径上,一个终端输入

make CPUS=1 qemu-gdb

  然后在另一个终端输入

gdb-multiarch

  特别注意这里用的是gdb-multiarch(花了好多时间就是找不到合适的gdb,MIT的教学视频里面的riscv64-linux-gnu-gdb在我的linux上找不到这玩意)。该路径下有一个.gdbinit的初始化文件,gdb-multiarch会读取这个文件然后自动连接之前的gdb,然后就可以正常调试了。
  记得之前还遇到了因为权限问题,gdb没办法读取这个.gdbinit文件而报错,可能因为之前配置好了,这次就没遇到这个问题了。

xv6的单步调试

  从入口点entry.S的汇编代码开始。

_entry:
	# set up a stack for C.
        # stack0 is declared in start.c,
        # with a 4096-byte stack per CPU.
        # sp = stack0 + (hartid * 4096)
        la sp, stack0
        li a0, 1024*4
	csrr a1, mhartid
        addi a1, a1, 1
        mul a0, a0, a1
        add sp, sp, a0
	# jump to start() in start.c
        call start

  初始情况entry.S被加载到地址0x80000000。这里的la是一条伪指令,由aupic和addi组合而成,实际效果相当于,sp = stack + pc。gdb显示如下:
在这里插入图片描述
  在执行auipc指令之后,sp的值变为0x80009000,因此auipc指令的作用是 rd = sp + (立即数 << 12)。接着的li也是一条伪指令,在gdb中对应指令lui。lui指令的作用是rd = 立即数 << 12
  csrr伪指令用于读取CSR到目的寄存器rd。mhartid感觉可以简单地理解为cpu编号的标识?下面是文档中的描述。
在这里插入图片描述
实际上通过print可以知道此时mhartid=0。我想这个作用在于多个cpu启动时为每个cpu建立一个不同的栈吧。
  总的来说,entry.S的汇编代码在进入start函数之前,设置了栈指针esp = 0x80000000 + stack0 + 4096 * (mhartid + 1)。因此在进入start函数前,esp = 0x8000a180。
  再查看一下stack0的值:
在这里插入图片描述
反汇编内核代码可以看到,stack0是位于.bss段的一个全局数据结构,声明为一个数组,为每个cpu提供一页的栈空间

小结关键词:

gdb调试内核方法,la指令,mhartid含义,aupic,lui指令。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值