NJU PA1 “优美地退出” 问题解决

问题描述

本文通过gdb调试的方法来弄懂nemu大概执行流程,由此找到报错的源头并加以解决,其实很多内容是不必要的,但为了能够更清晰地理解nemu框架代码,导致本文看起来比较繁琐

调试全过程

进入tmux,方便后续调试

首先,我们可以通过find找到nemu的main函数在哪里(在nemu目录下)

find ./ -name '*' | xargs grep 'main' 2>/dev/null

会发现输出了很多行的结果,往下找,找到可能性最大的那个:


但这是源代码,用gdb调试的话,需要找到编译后的文件,这些文件全放在/nemu/build目录下,其中obj-riscv32-nemu-interpreter /src下面放每个源代码编译后的结果,而riscv32-nemu-interpreter才是我们需要关注的文件,输入gdb进入调试,file到riscv32-nemu-interpreter里面

用list查看源码,在main函数处设置断点、随后运行

然后输入n,跳过init_monitor函数,进入engine_start,再进入sdb_mainloop

经过rl_gets的时候,输入q,通过后面的调试看看为什么会报错

当走到下面这个位置的时候就会进入cmd_q

 由于直接返回-1,导致return,跳出sdb_mainloop

回到main函数,继续执行,进入is_exit_status_bad函数,打印nemu_state.state值,发现是1

但暂时还不知道NEMU_END这些常量,以及nemu_state.state的初值在哪里定义,在右边开一个窗口,搜这些量,可以发现在src/utils/state.c中初始化了.state为NEMU_STOP,同时在下面的util.h中,看到了NEMU_STOP这个值为1也正是左边的gbd输出值

good的值是:

由于nemu_state.state是NEMU_STOP,导致good==0,return为1所以报错

于是有一个猜想:

先输入c再输入q不报错是因为改变了nemu_state.state的值使得good == 1 

为了证实这个猜想,gdb重新运行代码,这次,在该输入指令的地方首先输入c指令、再输入q

这次nemu_state.state的值变成了2,也就是对应的NEMU_END,到底在哪里发生改变了呢?

回到sdb_mainloop,当指令为c时,执行cmd_c,进入cpu_exec

继续往下进行会发现cpu_exec会执行execute,然后又执行exec_once然后又执行其它,由于代码比较多而且很多细节也看不懂,可以先用find去寻找一下"NEMU_END"的字样,发现有一个:set_nemu_state(NEMU_END, thispc, code),很可能就是让状态值改变的原因,于是继续搜索这个函数所在的文件、查看函数定义:

终于找到了让state改变的原因!

最终结论

所以现在的猜想就是:

输入c——》调用cpu_exec——》调用execute——》调用exec_once——》。。。。。。——》调用set_nemu_state——》修改nemu_state.state——》good=1——》再输入q——》不报错

直接输入q——》good=0——》报错

至于。。。。。。哪一部分调用了那个函数可以通过gdb一直往后next找到,此处就不作演示了

好了,回到主题上,现在想让最后return 0,只需让good=1

所以:只需在调用cmd_q的时候,把state改为:NEMU_QUIT即可

 

如下,不再报错

  • 18
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值