diff --git a/answers-traps.txt b/answers-traps.txt new file mode 100644 index 0000000..13c5db4 --- /dev/null +++ b/answers-traps.txt @@ -0,0 +1,33 @@ +Q: Which registers contain arguments to functions? For example, which register holds 13 in main's call to printf? +A: The base integer calling convention provides eight argument registers, a0-a7, the first two of which are also used to return values. Register a2 holds 13. + +Q: Where is the call to function f in the assembly code for main? Where is the call to g? +A: There is no call to function f for main, the value of f(8) (which is 12) is calculated at compile time and hard-coded into the executable. + The call to g is inlined into f, at address 0x14. + +Q: At what address is the function printf located? +A: The function printf is located at address 0x642. + +Q: What value is in the register ra just after the jalr to printf in main? +A: The address of the next instruction after return, aka 0x38. + +Q: +--- +Run the following code. + + unsigned int i = 0x00646c72; + printf("H%x Wo%s", 57616, &i); + +What is the output? Here's an ASCII table that maps bytes to characters. +The output depends on that fact that the RISC-V is little-endian. If the RISC-V were instead big-endian what would you set i to in order to yield the same output? Would you need to change 57616 to a different value? +--- +A: The output is, He110 World(with no whitespace or new line). + If big endian, the new i should be 0x726c6400; and there is no need to change 56716. + +Q: +--- +In the following code, what is going to be printed after 'y='? (note: the answer is not a specific value.) Why does this happen? + printf("x=%d y=%d", 3); +--- +A: The value that register a2 holds when the caller calls printf. By default, the third argument passed to a procedure is stored in a2. + diff --git a/kernel/defs.h b/kernel/defs.h index a3c962b..4b82fc2 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -80,6 +80,7 @@ int pipewrite(struct pipe*, uint64, int); void printf(char*, ...); void panic(char*) __attribute__((noreturn)); void printfinit(void); +void backtrace(void); // proc.c int cpuid(void); diff --git a/kernel/printf.c b/kernel/printf.c index 1a50203..ee17627 100644 --- a/kernel/printf.c +++ b/kernel/printf.c @@ -122,6 +122,7 @@ panic(char *s) printf("panic: "); printf(s); printf("\n"); + backtrace(); panicked = 1; // freeze uart output from other CPUs for(;;) ; @@ -133,3 +134,14 @@ printfinit(void) initlock(&pr.lock, "pr"); pr.locking = 1; } + +void backtrace(void) +{ + printf("backtrace:\n"); + uint64 fp = r_fp(); + uint64 fp_pg = PGROUNDDOWN(fp); + while (PGROUNDDOWN(fp) == fp_pg) { + printf("%p\n", (*(uint64*)(fp-8))); + fp = *(uint64*)(fp-16); + } +} \ No newline at end of file diff --git a/kernel/riscv.h b/kernel/riscv.h index 20a01db..85a08cc 100644 --- a/kernel/riscv.h +++ b/kernel/riscv.h @@ -319,6 +319,14 @@ r_ra() return x; } +static inline uint64 +r_fp() +{ + uint64 x; + asm volatile("mv %0, s0" : "=r" (x) ); + return x; +} + // flush the TLB. static inline void sfence_vma() diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 3b4d5bd..fe64ad3 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -57,6 +57,7 @@ sys_sleep(void) argint(0, &n); if(n < 0) n = 0; + backtrace(); acquire(&tickslock); ticks0 = ticks; while(ticks - ticks0 < n){