跳转至

Guidance

Lab guidance

首先介绍难度分层:

  • Easy: <1h, These exercise are typically often warm-up exercises for subsequent exercises.
  • Moderate: 1-2h
  • Hard: >2h, Often these exercises don't require much code, but the code is tricky to get right.

Debugging Tips

Pointers

确保自己的C语言和pointers学得比较好.

#include <stdio.h>
#include <stdlib.h>

void
f(void)
{
    int a[4];
    int *b = malloc(16);
    int *c;
    int i;

    printf("1: a = %p, b = %p, c = %p\n", a, b, c);

    c = a;
    for (i = 0; i < 4; i++)
    a[i] = 100 + i;
    c[0] = 200;
    printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
       a[0], a[1], a[2], a[3]);

    c[1] = 300;
    *(c + 2) = 301;
    3[c] = 302;
    printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
       a[0], a[1], a[2], a[3]);

    c = c + 1;
    *c = 400;
    printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
       a[0], a[1], a[2], a[3]);

    c = (int *) ((char *) c + 1);
    *c = 500;
    printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
       a[0], a[1], a[2], a[3]);

    b = (int *) a + 1;
    c = (int *) ((char *) a + 1);
    printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}

int
main(int ac, char **av)
{
    f();
    return 0;
}

编译并运行:

guidance$ gcc -o p ptr_exer.c
guidance$ ./p
1: a = 0x7ffefa9e3980, b = 0x5f2e932c42a0, c = (nil)
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0x7ffefa9e3980, b = 0x7ffefa9e3984, c = 0x7ffefa9e3981

Git

一部分完成之后,建议Git存个档,也方便后续回滚.

Make

script内部运行make qemu指令观察输出.

gdb调试

打开一个窗口:

$ make qemu-gdb

打开另一个窗口:

$ gdb
# 或者
$ riscv64-linux-gnu-gdb

信息查看

  • If you want to see what the assembly is that the compiler generates for the kernel or to find out what the instruction is at a particular kernel address, see the file kernel.asm, which the Makefile produces when it compiles the kernel. (The Makefile also produces .asm for all user programs.)
  • If the kernel panics, it will print an error message listing the value of the program counter when it crashed; you can search kernel.asm to find out in which function the program counter was when it crashed, or you can run addr2line -e kernel/kernel pc-value (run man addr2line for details). If you want to get backtrace, restart using gdb: run 'make qemu-gdb' in one window, run gdb (or riscv64-linux-gnu-gdb) in another window, set breakpoint in panic ('b panic'), followed by followed by 'c' (continue). When the kernel hits the break point, type 'bt' to get a backtrace.
  • If your kernel hangs (e.g., due to a deadlock) or cannot execute further (e.g., due to a page fault when executing a kernel instruction), you can use gdb to find out where it is hanging. Run run make qemu-gdb in one window, run gdb (riscv64-linux-gnu-gdb) in another window, followed by followed by c (continue). When the kernel appears to hang hit Ctrl-C in the qemu-gdb window and type bt to get a backtrace.
  • qemu has a "monitor" that lets you query the state of the emulated machine. You can get at it by typing control-a c (the "c" is for console). A particularly useful monitor command is info mem to print the page table. You may need to use the cpu command to select which core info mem looks at, or you could start qemu with make CPUS=1 qemu to cause there to be just one core.

kernel

查看kernel.asm可以得到内核崩溃信息,如在哪个函数崩溃.

$ addr2line -e kernel/kernel pc-value

monitor

获取每个monitor的状态:

$ info mem