本实验的网站链接:MIT 6.828 Lab 1 Exercise 11

题目

The above exercise should give you the information you need to implement a stack backtrace function, which you should call mon_backtrace(). A prototype for this function is already waiting for you in kern/monitor.c. You can do it entirely in C, but you may find the read_ebp() function in inc/x86.h useful. You'll also have to hook this new function into the kernel monitor's command list so that it can be invoked interactively by the user.

The backtrace function should display a listing of function call frames in the following format:

Stack backtrace:

ebp f0109e58 eip f0100a62 args 00000001 f0109e80 f0109e98 f0100ed2 00000031

ebp f0109ed8 eip f01000d6 args 00000000 00000000 f0100058 f0109f28 00000061

...

By studying kern/entry.S you'll find that there is an easy way to tell when to stop.

Implement the backtrace function as specified above.

解答

题目要求打印调用栈的信息,包括ebp和eip寄存器的值、输入参数的值等。

  1. 按照提示,我们首先可以调用read_ebp函数来获取当前ebp寄存器的值。ebp寄存器的值实际上是一个指针,指向当前函数的栈帧的底部(而esp寄存器指向当前函数的栈顶)。我们可以把整个调用栈看做一个数组,其中每个元素均为4字节的整数,并以ebp指针的值为数组起始地址,那么ebp[1]存储的就是函数返回地址,也就是题目中要求的eip的值,ebp[2]以后存储的是输入参数的值。由于题目要求打印5个输入参数,因此需要获取ebp[2]~ebp[6]的值。这样第一条栈信息便可打印出来。

  2. 那么怎么打印下一条栈信息呢?还得从ebp入手。当前ebp指针存储的恰好是调用者的ebp寄存器的值,因此当前ebp指针又可以看做是一个链表头,我们通过链表头就可以遍历整个链表。举个例子:假设有A、B、C三个函数,A调用B,B调用C,每个函数都对应有一个栈帧,栈帧的底部地址均存储在当时的ebp寄存器中,不妨记为a_ebp, b_ebp和c_ebp,那么将有c_ebp -> b_ebp -> a_ebp,用程序语言表示就是:a_ebp = (uint32_t *)*b_ebpb_ebp = (uint32_t *)*c_ebp

  3. 还有一个问题:怎么知道遍历何时结束呢?题目中提示可以参考kern/entry.S,于是我打开此文件,果然找打答案:内核初始化时会将ebp设置为0,因此当我们检查到ebp为0后就应该结束了。

	# Clear the frame pointer register (EBP)
# so that once we get into debugging C code,
# stack backtraces will be terminated properly.
movl $0x0,%ebp # nuke frame pointer
  1. 代码实现
int mon_backtrace(int argc, char **argv, struct Trapframe *tf)
{
uint32_t *ebp; ebp = (uint32_t *)read_ebp(); cprintf("Stack backtrace:\r\n"); while (ebp)
{
cprintf(" ebp %08x eip %08x args %08x %08x %08x %08x %08x\r\n",
ebp, ebp[1], ebp[2], ebp[3], ebp[4], ebp[5], ebp[6]); ebp = (uint32_t *)*ebp;
} return 0;
}
  1. 输出结果
6828 decimal is 15254 octal!
entering test_backtrace 5
entering test_backtrace 4
entering test_backtrace 3
entering test_backtrace 2
entering test_backtrace 1
entering test_backtrace 0
Stack backtrace:
ebp f010ff18 eip f0100078 args 00000000 00000000 00000000 f010004a f0111308
ebp f010ff38 eip f01000a1 args 00000000 00000001 f010ff78 f010004a f0111308
ebp f010ff58 eip f01000a1 args 00000001 00000002 f010ff98 f010004a f0111308
ebp f010ff78 eip f01000a1 args 00000002 00000003 f010ffb8 f010004a f0111308
ebp f010ff98 eip f01000a1 args 00000003 00000004 00000000 f010004a f0111308
ebp f010ffb8 eip f01000a1 args 00000004 00000005 00000000 f010004a f0111308
ebp f010ffd8 eip f01000dd args 00000005 00001aac f010fff8 f01000bd 00000000
ebp f010fff8 eip f010003e args 00000003 00001003 00002003 00003003 00004003
leaving test_backtrace 0
leaving test_backtrace 1
leaving test_backtrace 2
leaving test_backtrace 3
leaving test_backtrace 4
leaving test_backtrace 5

《MIT 6.828 Lab 1 Exercise 11》实验报告的更多相关文章

  1. [操作系统实验lab3]实验报告

    [感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...

  2. Ucore lab1实验报告

    练习一 Makefile 1.1 OS镜像文件ucore.img 是如何一步步生成的? + cc kern/init/init.c + cc kern/libs/readline.c + cc ker ...

  3. ucore操作系统学习(三) ucore lab3虚拟内存管理分析

    1. ucore lab3介绍 虚拟内存介绍 在目前的硬件体系结构中,程序要想在计算机中运行,必须先加载至物理主存中.在支持多道程序运行的系统上,我们想要让包括操作系统内核在内的各种程序能并发的执行, ...

  4. 《ucore lab3》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:给未被映射的地址映射上物理页 题目 完成do_pgfault(mm/vmm.c)函数,给未被映射的地址映射上物理页.设置访问权限的时候需 ...

  5. 《ucore lab1 exercise5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 题目:实现函数调用堆栈跟踪函数 我们需要在lab1中完成kdebug.c中函数print_stackframe的实现,可以通过函数print_s ...

  6. 《ucore lab8》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 完成读文件操作的实现(需要编码) 题目 首先了解打开文件的处理流程,然后参考本实验后续的文件读写操作的过程分析,编写在sfs_inod ...

  7. 《ucore lab7》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码) 题目 完成练习0后,建议大家比较一下(可用meld等文件dif ...

  8. 《ucore lab6》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 使用 Round Robin 调度算法(不需要编码) 题目 完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件) 个人完成 ...

  9. 《ucore lab5》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1: 加载应用程序并执行(需要编码) 题目 do_execv函数调用load_icode(位于kern/process/proc.c中) 来 ...

  10. 《ucore lab4》实验报告

    资源 ucore在线实验指导书 我的ucore实验代码 练习1:分配并初始化一个进程控制块 题目 alloc_proc函数(位于kern/process/proc.c中) 负责分配并返回一个新的str ...

随机推荐

  1. 1、python--第一天练习题

    #1.使用while循环输入 1 2 3 4 5 6 8 9 10 k = 0 while k < 10: k += 1 if k == 7: continue print(k) #2.求1-1 ...

  2. fputcsv

    1.a是從結尾添加,w是從頭添加,不知爲什麽 這樣寫最後一行會是錯的,似乎不會自動添加換行符,只有在最後以行寫上"\r\n",才會正確. $fp = sugar_fopen('fi ...

  3. ueditor百度编辑器destoon的word图片转存功能

    图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码目前限chrome浏览器使用首先以um-editor的二进制流保存为例:打开umeditor.js,找到UM ...

  4. win下安装jupyter遇到的问题

    一:安装jupyter 1.首先要用管理员方式打开cmd,没用管理员打开后面安装不上. 2.安装jupyter.我用的是python3,所以用pip3 install jupyter进行安装. 3.安 ...

  5. c++容器 算法 迭代

    #include <iostream> #include <vector> using namespace std; int main() { // 创建一个向量存储 int ...

  6. 微信小程序之简单记账本开发记录(四)

    昨天搭建了大致界面 今天需要将用到的一系列样式表配置出来并检查错误

  7. jenkins之docker安装

    此方法安装还存在两个问题1.构建node程序:2.时区问题(在docker run 设置环境变量是否能解决没有试过) 不建议用此方法安装,查看我的其他安装方式 搬运官网步骤,稍微改动. 1.安装doc ...

  8. CF1217B

    CF1217B 题意: 有一个有 $ x $ 个头的龙,你有 $ n $ 种方案,每种方案中包含你可以砍掉的头 $ d_i $ 和龙会生长的头 $ h_i $ 找到一种方案,使得操作数最少. 解法: ...

  9. JAVA - IO - IO的类型(AIO, BIO, NIO)

    IO的方式通常分为几种,同步阻塞的BIO.同步非阻塞的NIO.异步非阻塞的AIO. 一.BIO 在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSock ...

  10. SpringBoot2.0 Actuator 监控参数说明

    主要内容更 监控参数说明 Maven坐标 <dependency> <groupId>org.springframework.boot</groupId> < ...