6.s081 lab4.2--backtrace

MIT 6.s081 lab4.2–backtrace

No.1 写在前面的话

过了页表,难度降了下来,忽然有些不习惯。通过做lab,我已经养成了在每次实验前都会Google搜索相关补充功能的原型的习惯,进行大致的了解。虽然代码看不懂,但至少知道这东西怎么用,backtrace便是如此。

No.2 实验思路

提示中的添加函数和原型不再赘述,主要看后面需要编写代码的部分,只不过,那些提示实在是不知道如何下手,所以再看看实验指导对于backtrace的说明,咬文嚼字一下:

一个存放于栈上用于指示错误发生位置的函数调用列表

编译器向每一个栈帧中放置一个帧指针(frame pointer)保存调用者帧指针的地址。你的backtrace应当使用这些帧指针来遍历栈,并在每个栈帧中打印保存的返回地址.

仔细阅读,便知道了我们现在的目标,有三点:使用指针,遍历栈,打印地址。那么现在先从第一个目标开始。

说起使用指针,首先想到的就是定义一个变量用来存储帧指针,但是帧指针在哪呢?仔细阅读第二条提示,它将帧指针保存在s0寄存器,并且上面继续写道——在backtrace中调用此函数读取指针,所以可以这样:

  uint64 fp = r_fp();

第一个目标便完成了,接下来则是遍历栈。第一想法是for循环,但是我也不清楚栈的大小,肯定不行,可以用while吗?提示写道——可以通过PGROUNDDOWN(fp)PGROUNDUP(fp)来计算栈页面的顶部和底部地址。我们知道栈是向下增长的,顶是Prev.Frame(fp),底是栈指针(sp),具体如下:

Imgur

那么,要想遍历栈只需让其在底部停止就好:

  while (fp < PGROUNDUP(fp)){}

接下来,只剩打印地址了。话虽如此,通过前面的vmprint已经知道打印地址是%p,但是我们要打印的是哪一部分的地址呢?

仔细阅读任务目标:【你的backtrace应当使用这些帧指针来遍历栈,并在每个栈帧中打印保存的返回地址。】以及提示:【注意返回地址位于栈帧帧指针的固定偏移(-8)位置,并且保存的帧指针位于帧指针的固定偏移(-16)位置】,很清楚,这下就明白怎么写了,完整代码如下:

void
backtrace(void){
  printf("backtrace:\n");
  uint64 fp = r_fp();//存储帧指针

  while (fp < PGROUNDUP(fp))
  {
    uint64 ra = *(uint64*)(fp-8);//转化为uint64的指针,随后指向fp-8的位置
    printf("%p\n", ra);
    fp = *(uint64*)(fp-16);//保存前一个frame指针,为了能跳转回去
      //具体原因在lecture5有说明
  }
}

最后记得panic,以及在defs.h中添加:

  printf("\n");
  backtrace();
  panicked = 1; // freeze uart output from other CPUs

//defs.h
void            backtrace(void);

这就完成了,很是平缓。【用时半天】

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值