enhanced backtrace output
[mit-jos.git] / kern / monitor.c
blob36a5af655a971aabf2f647f8cbe7a8cdf3c36647
1 // Simple command-line kernel monitor useful for
2 // controlling the kernel and exploring the system interactively.
4 #include <inc/stdio.h>
5 #include <inc/string.h>
6 #include <inc/memlayout.h>
7 #include <inc/assert.h>
8 #include <inc/x86.h>
10 #include <kern/console.h>
11 #include <kern/monitor.h>
12 #include <kern/kdebug.h>
14 #define CMDBUF_SIZE 80 // enough for one VGA text line
17 struct Command {
18 const char *name;
19 const char *desc;
20 // return -1 to force monitor to exit
21 int (*func)(int argc, char** argv, struct Trapframe* tf);
24 static struct Command commands[] = {
25 { "help", "Display this list of commands", mon_help },
26 { "kerninfo", "Display information about the kernel", mon_kerninfo },
27 { "backtrace", "Display the backtrace information", mon_backtrace },
29 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
31 unsigned read_eip();
33 /***** Implementations of basic kernel monitor commands *****/
35 int
36 mon_help(int argc, char **argv, struct Trapframe *tf)
38 int i;
40 for (i = 0; i < NCOMMANDS; i++)
41 cprintf("%s - %s\n", commands[i].name, commands[i].desc);
42 return 0;
45 int
46 mon_kerninfo(int argc, char **argv, struct Trapframe *tf)
48 extern char _start[], etext[], edata[], end[];
50 cprintf("Special kernel symbols:\n");
51 cprintf(" _start %08x (virt) %08x (phys)\n", _start, _start - KERNBASE);
52 cprintf(" etext %08x (virt) %08x (phys)\n", etext, etext - KERNBASE);
53 cprintf(" edata %08x (virt) %08x (phys)\n", edata, edata - KERNBASE);
54 cprintf(" end %08x (virt) %08x (phys)\n", end, end - KERNBASE);
55 cprintf("Kernel executable memory footprint: %dKB\n",
56 (end-_start+1023)/1024);
57 return 0;
60 int
61 mon_backtrace(int argc, char **argv, struct Trapframe *tf)
63 // Your code here.
64 struct Eipdebuginfo eip_debug;
65 unsigned int *ebp, *eip;
66 int i;
68 ebp = (unsigned int *)read_ebp();
69 eip = (unsigned int *)read_eip();
70 cprintf("Stack backtrace:\n");
71 while (ebp) {
72 // enhanced backtrace output
73 debuginfo_eip((uintptr_t)eip, &eip_debug);
74 cprintf("%s:%d: ", eip_debug.eip_file, eip_debug.eip_line);
75 for (i = 0; i < eip_debug.eip_fn_namelen; i++)
76 cprintf("%c", eip_debug.eip_fn_name[i]);
77 cprintf("+%x\n",
78 (unsigned int)eip - (unsigned int)eip_debug.eip_fn_addr);
80 eip = (unsigned int *)*(ebp + 1);
82 // basic backtrace output
83 cprintf(" ebp %x eip %x args", ebp, eip);
84 for (i = 0; i < 5; i++)
85 cprintf(" %08x", *(ebp + 2 + i));
86 cprintf("\n");
88 ebp = (unsigned int *)*ebp;
91 return 0;
96 /***** Kernel monitor command interpreter *****/
98 #define WHITESPACE "\t\r\n "
99 #define MAXARGS 16
101 static int
102 runcmd(char *buf, struct Trapframe *tf)
104 int argc;
105 char *argv[MAXARGS];
106 int i;
108 // Parse the command buffer into whitespace-separated arguments
109 argc = 0;
110 argv[argc] = 0;
111 while (1) {
112 // gobble whitespace
113 while (*buf && strchr(WHITESPACE, *buf))
114 *buf++ = 0;
115 if (*buf == 0)
116 break;
118 // save and scan past next arg
119 if (argc == MAXARGS-1) {
120 cprintf("Too many arguments (max %d)\n", MAXARGS);
121 return 0;
123 argv[argc++] = buf;
124 while (*buf && !strchr(WHITESPACE, *buf))
125 buf++;
127 argv[argc] = 0;
129 // Lookup and invoke the command
130 if (argc == 0)
131 return 0;
132 for (i = 0; i < NCOMMANDS; i++) {
133 if (strcmp(argv[0], commands[i].name) == 0)
134 return commands[i].func(argc, argv, tf);
136 cprintf("Unknown command '%s'\n", argv[0]);
137 return 0;
140 void
141 monitor(struct Trapframe *tf)
143 char *buf;
145 cprintf("Welcome to the JOS kernel monitor!\n");
146 cprintf("Type 'help' for a list of commands.\n");
149 while (1) {
150 buf = readline("K> ");
151 if (buf != NULL)
152 if (runcmd(buf, tf) < 0)
153 break;
157 // return EIP of caller.
158 // does not work if inlined.
159 // putting at the end of the file seems to prevent inlining.
160 unsigned
161 read_eip()
163 uint32_t callerpc;
164 __asm __volatile("movl 4(%%ebp), %0" : "=r" (callerpc));
165 return callerpc;