Using gdb
gdb使用:
xv6 gdb调试方法
问题1:
- Looking at the backtrace output, which function called syscall?
按照提示开启gdb后键入:
b syscall
c
layout src
backtrace
输出结果:
(gdb) backtrace
#0 syscall () at kernel/syscall.
#1 0x0000000080001d70 in usertra
#2 0x0505050505050505 in ?? ()
(gdb)
usertra调用了syscall
问题2:
- What is the value of p->trapframe->a7 and what does that value represent?
- (线索: look user/initcode.S, the first user program xv6 starts.)
- proc结构体源码:
// Per-process state
struct proc {struct spinlock lock;// p->lock must be held when using these:enum procstate state; // Process statevoid *chan; // If non-zero, sleeping on chanint killed; // If non-zero, have been killedint xstate; // Exit status to be returned to parent's waitint pid; // Process ID// wait_lock must be held when using this:struct proc *parent; // Parent process// these are private to the process, so p->lock need not be held.uint64 kstack; // Virtual address of kernel stackuint64 sz; // Size of process memory (bytes)pagetable_t pagetable; // User page tablestruct trapframe *trapframe; // data page for trampoline.Sstruct context context; // swtch() here to run processstruct file *ofile[NOFILE]; // Open filesstruct inode *cwd; // Current directorychar name[16]; // Process name (debugging)
};
- trapframe结构体:
// the entire kernel call stack.
struct trapframe {/* 0 */ uint64 kernel_satp; // kernel page table/* 8 */ uint64 kernel_sp; // top of process's kernel stack/* 16 */ uint64 kernel_trap; // usertrap()/* 24 */ uint64 epc; // saved user program counter/* 32 */ uint64 kernel_hartid; // saved kernel tp/* 40 */ uint64 ra;/* 48 */ uint64 sp;/* 56 */ uint64 gp;/* 64 */ uint64 tp;/* 72 */ uint64 t0;/* 80 */ uint64 t1;/* 88 */ uint64 t2;/* 96 */ uint64 s0;/* 104 */ uint64 s1;/* 112 */ uint64 a0;/* 120 */ uint64 a1;/* 128 */ uint64 a2;/* 136 */ uint64 a3;/* 144 */ uint64 a4;/* 152 */ uint64 a5;/* 160 */ uint64 a6;/* 168 */ uint64 a7;/* 176 */ uint64 s2;/* 184 */ uint64 s3;/* 192 */ uint64 s4;/* 200 */ uint64 s5;/* 208 */ uint64 s6;/* 216 */ uint64 s7;/* 224 */ uint64 s8;/* 232 */ uint64 s9;/* 240 */ uint64 s10;/* 248 */ uint64 s11;/* 256 */ uint64 t3;/* 264 */ uint64 t4;/* 272 */ uint64 t5;/* 280 */ uint64 t6;
};
- initcode.S源码:
# Initial process that execs /init.
# This code runs in user space.#include "syscall.h"# exec(init, argv)
.globl start
start:la a0, initla a1, argvli a7, SYS_exececall# for(;;) exit();
exit:li a7, SYS_exitecalljal exit# char init[] = "/init\0";
init:.string "/init\0"# char *argv[] = { init, 0 };
.p2align 2
argv:.long init.long 0
键入n
数次使gdb越过struct proc *p = myproc();
,此后键入p /x *p
,此命令打印了进程的proc struct
打印输出:
$1 = {lock = {locked = 0x0, name = 0x800081b8, cpu = 0x0},state = 0x4, chan = 0x0, killed = 0x0, xstate = 0x0, pid = 0x1,parent = 0x0, kstack = 0x3fffffd000, sz = 0x1000,pagetable = 0x87f73000, trapframe = 0x87f74000, context = {ra = 0x800014c2, sp = 0x3fffffde80, s0 = 0x3fffffdeb0,s1 = 0x80008d50, s2 = 0x80008920, s3 = 0x1, s4 = 0x0,s5 = 0x3, s6 = 0x800199f0, s7 = 0x8, s8 = 0x80019b18,s9 = 0x4, s10 = 0x1, s11 = 0x0}, ofile = {0x0 <repeats 16 times>}, cwd = 0x80016e60, name = {0x69, 0x6e,0x69, 0x74, 0x63, 0x6f, 0x64, 0x65, 0x0, 0x0, 0x0, 0x0, 0x0,0x0, 0x0, 0x0}}
(gdb)
p->trapframe->a7
为proc结构体中trapframe指针指向的结构体中a7的值
(gdb) p /x p->trapframe->a7
$8 = 0x7
(gdb)
所以a7中存放值为0x07,此值代表exec系统调用的编号,后续用于调用 ecall 重新进入内核。
问题3:
- What was the previous mode that the CPU was in?
(gdb) p /x $sstatus
$9 = 0x22
(gdb)
十进制为100010
,查询RISC-V privileged instructions可知:
此时第八位为0,代表CPU之前处于用户态
问题4:(错误测试)
- Write down the assembly instruction the kernel is panicing at. Which register corresponds to the variable num?