printf()
可以用来定位错误,不用多说
ASSERT
pintos项目中,在<debug.h>头文件中定义了用于debug的Macro
Macro: ASSERT (expression) 当expression的值为零(假)时,kernel 会 panics, panic message 会包括发生错误的表达式,文件、它的line number和backtrace。
Function and Parameter Attributes
在<debug.h>中定义了一些Macro, 用于告诉编译器某个函数或函数参数的特殊性质。
Macro: UNUSED 附加到函数参数后以告诉编译器该参数可能不在函数中使用。它将抑制否则会出现的警告
Macro: NO_RETURN 附加到函数原型后以告诉编译器函数永远不会返回。它允许编译器微调其警告和代码生成。
Macro: NO_INLINE 附加到函数原型中,以告诉编译器永远不要以内联形式调用函数。偶尔有助于提高backtraces的质量。
Macro: PRINTF_FORMAT (format, first) 附加到函数原型中,告诉编译器该函数采用类似printf()的格式字符串作为参数编号格式(从1开始),相应的值参数从第一个编号的参数开始。这让编译器告诉您是否传递了错误的参数类型。
backtrace
在debug的时候,我们很可能遇到这样一个错误信息:Call stack: 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8.
我们就可以用backtrace工具来解释这一段错误:backtrace kernel.o 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8
注:kernel.o 必须是之前发生运行错误的内核文件
会得到
0xc0106eff: debug_panic (lib/debug.c:86)
0xc01102fb: file_seek (filesys/file.c:405)
0xc010dc22: seek (userprog/syscall.c:744)
0xc010cf67: syscall_handler (userprog/syscall.c:444)
0xc0102319: intr_handler (threads/interrupt.c:334)
0xc010325a: intr_entry (threads/intr-stubs.S:38)
0x0804812c: (unknown)
0x08048a96: (unknown)
0x08048ac8: (unknown)
后面三行(unknown)可以运行我们测试的程序文件来得到解释,如:
backtrace tests/filesys/extended/grow-too-big 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8
会得到
0xc0106eff: (unknown)
0xc01102fb: (unknown)
0xc010dc22: (unknown)
0xc010cf67: (unknown)
0xc0102319: (unknown)
0xc010325a: (unknown)
0x0804812c: test_main (...xtended/grow-too-big.c:20)
0x08048a96: main (tests/main.c:10)
0x08048ac8: _start (lib/user/entry.c:9)
也可以直接运行backtrace kernel.o tests/filesys/extended/grow-too-big 0xc0106eff 0xc01102fb 0xc010dc22 0xc010cf67 0xc0102319 0xc010325a 0x804812c 0x8048a96 0x8048ac8
得到完整解释:
In kernel.o:
0xc0106eff: debug_panic (lib/debug.c:86)
0xc01102fb: file_seek (filesys/file.c:405)
0xc010dc22: seek (userprog/syscall.c:744)
0xc010cf67: syscall_handler (userprog/syscall.c:444)
0xc0102319: intr_handler (threads/interrupt.c:334)
0xc010325a: intr_entry (threads/intr-stubs.S:38)
In tests/filesys/extended/grow-too-big:
0x0804812c: test_main (...xtended/grow-too-big.c:20)
0x08048a96: main (tests/main.c:10)
0x08048ac8: _start (lib/user/entry.c:9)
GDB
要在GDB模式下运行pintos,可以这样做:
首先,用-gdb选项来跑一个测试, e.g: pintos -gdb -- run mytest, 然后打开第二个窗口,输入pintos-gdb kernel.o后再输入target remote localhost:1234。
现在GDB通过本地网络连接到模拟器。您现在可以发出任何正常的GDB命令。如果您发出“c”命令,模拟BIOS将控制、加载Pintos,然后Pintos将以通常的方式运行。您可以使用Ctrl+C在任意点暂停进程
详细的GDB命令请参照(web.stanford.edu/~ouster/cgi…)