thanks to damocles, two places changed. one relates to the performance boost.
[mit-jos.git] / kern / monitor.c
bloba928a95955572faefeb6629342497d35d1282ba2
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/trap.h>
13 #include <kern/kdebug.h>
15 #define CMDBUF_SIZE 80 // enough for one VGA text line
18 struct Command {
19 const char *name;
20 const char *desc;
21 // return -1 to force monitor to exit
22 int (*func)(int argc, char** argv, struct Trapframe* tf);
25 static struct Command commands[] = {
26 { "help", "Display this list of commands", mon_help },
27 { "kerninfo", "Display information about the kernel", mon_kerninfo },
28 { "backtrace", "Display the backtrace information", mon_backtrace },
30 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
32 unsigned read_eip();
34 /***** Implementations of basic kernel monitor commands *****/
36 int
37 mon_help(int argc, char **argv, struct Trapframe *tf)
39 int i;
41 for (i = 0; i < NCOMMANDS; i++)
42 cprintf("%s - %s\n", commands[i].name, commands[i].desc);
43 return 0;
46 int
47 mon_kerninfo(int argc, char **argv, struct Trapframe *tf)
49 extern char _start[], etext[], edata[], end[];
51 cprintf("Special kernel symbols:\n");
52 cprintf(" _start %08x (virt) %08x (phys)\n", _start, _start - KERNBASE);
53 cprintf(" etext %08x (virt) %08x (phys)\n", etext, etext - KERNBASE);
54 cprintf(" edata %08x (virt) %08x (phys)\n", edata, edata - KERNBASE);
55 cprintf(" end %08x (virt) %08x (phys)\n", end, end - KERNBASE);
56 cprintf("Kernel executable memory footprint: %dKB\n",
57 (end-_start+1023)/1024);
58 return 0;
61 int
62 mon_backtrace(int argc, char **argv, struct Trapframe *tf)
64 // Your code here.
65 struct Eipdebuginfo eip_debug;
66 unsigned int *ebp, *eip;
67 int i;
69 ebp = (unsigned int *)read_ebp();
70 eip = (unsigned int *)read_eip();
71 cprintf("Stack backtrace:\n");
72 while (ebp) {
73 // enhanced backtrace output
74 debuginfo_eip((uintptr_t)eip, &eip_debug);
75 cprintf("%s:%d: ", eip_debug.eip_file, eip_debug.eip_line);
76 for (i = 0; i < eip_debug.eip_fn_namelen; i++)
77 cprintf("%c", eip_debug.eip_fn_name[i]);
78 cprintf("+%x\n",
79 (unsigned int)eip - (unsigned int)eip_debug.eip_fn_addr);
81 eip = (unsigned int *)*(ebp + 1);
83 // basic backtrace output
84 cprintf(" ebp %x eip %x args", ebp, eip);
85 for (i = 0; i < 5; i++)
86 cprintf(" %08x", *(ebp + 2 + i));
87 cprintf("\n");
89 ebp = (unsigned int *)*ebp;
92 return 0;
97 /***** Kernel monitor command interpreter *****/
99 #define WHITESPACE "\t\r\n "
100 #define MAXARGS 16
102 static int
103 runcmd(char *buf, struct Trapframe *tf)
105 int argc;
106 char *argv[MAXARGS];
107 int i;
109 // Parse the command buffer into whitespace-separated arguments
110 argc = 0;
111 argv[argc] = 0;
112 while (1) {
113 // gobble whitespace
114 while (*buf && strchr(WHITESPACE, *buf))
115 *buf++ = 0;
116 if (*buf == 0)
117 break;
119 // save and scan past next arg
120 if (argc == MAXARGS-1) {
121 cprintf("Too many arguments (max %d)\n", MAXARGS);
122 return 0;
124 argv[argc++] = buf;
125 while (*buf && !strchr(WHITESPACE, *buf))
126 buf++;
128 argv[argc] = 0;
130 // Lookup and invoke the command
131 if (argc == 0)
132 return 0;
133 for (i = 0; i < NCOMMANDS; i++) {
134 if (strcmp(argv[0], commands[i].name) == 0)
135 return commands[i].func(argc, argv, tf);
137 cprintf("Unknown command '%s'\n", argv[0]);
138 return 0;
141 void
142 monitor(struct Trapframe *tf)
144 char *buf;
146 cprintf("Welcome to the JOS kernel monitor!\n");
147 cprintf("Type 'help' for a list of commands.\n");
149 if (tf != NULL)
150 print_trapframe(tf);
152 while (1) {
153 buf = readline("K> ");
154 if (buf != NULL)
155 if (runcmd(buf, tf) < 0)
156 break;
160 // return EIP of caller.
161 // does not work if inlined.
162 // putting at the end of the file seems to prevent inlining.
163 unsigned
164 read_eip()
166 uint32_t callerpc;
167 __asm __volatile("movl 4(%%ebp), %0" : "=r" (callerpc));
168 return callerpc;