set confirm off // 关闭确认,就是操作时Y/N的确认提示
set architecture riscv:rv64 // 设置架构为riscv:rv64
target remote 127.0.0.1:26000 // 2600端口号是make qemu-gdb时随机产生并写入.gdbinit的,可能不同,见makefile
symbol-file kernel/kernel // 指定symbol文件
set disassemble-next-line auto // 自动反汇编后面要执行的代码
set riscv use-compressed-breakpoints yes
// Recursively free page-table pages.
// All leaf mappings must already have been removed.
void
freewalk(pagetable_t pagetable)
{
// there are 2^9 = 512 PTEs in a page table.
for(int i = 0; i < 512; i++){
pte_t pte = pagetable[i];
if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
// this PTE points to a lower-level page table.
uint64 child = PTE2PA(pte);
freewalk((pagetable_t)child);
pagetable[i] = 0;
} else if(pte & PTE_V){
panic("freewalk: leaf");
}
}
kfree((void*)pagetable);
}
注释中已经说了所有的叶子映射必须已经被移除。再搜一下,发现这个函数只在uvmfree()中被调用。由此,我们可以 b uvmfree设置断点,执行到断点后用n 不进入函数的单步执行。发现第一次调用到freewalk()就painc了。 bt 看一下backtrace,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
gdb) bt
|#0 uvmfree (pagetable=pagetable@entry=0x87f75000,
| sz=sz@entry=4096) at kernel/vm.c:290
│#1 0x0000000080001044 in proc_freepagetable (
│ pasz=sz@entry=4096)
│ at kernel/proc.c:227
│#2 0x00000000800042c6 in exec (
│ path=path@einit",
│ argv=argv@entry=0x3fffffce00)
│ at kernel/exec.c:117
│#3 0x0000000080004e7e in sys_exec ()
│ at kernel/sysfile.c:444
│#4 0x000000008000203e in syscall ()
│ at kernel/syscall.c:154
│#5 0x0000000080001d28 in usertrap ()
│ at kernel/trap.c:67
│#6 0x0505050505050505 in ?? ()