1 // Simple command-line kernel monitor useful for
2 // controlling the kernel and exploring the system interactively.
5 #include <inc/string.h>
6 #include <inc/memlayout.h>
7 #include <inc/assert.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
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]))
34 /***** Implementations of basic kernel monitor commands *****/
37 mon_help(int argc
, char **argv
, struct Trapframe
*tf
)
41 for (i
= 0; i
< NCOMMANDS
; i
++)
42 cprintf("%s - %s\n", commands
[i
].name
, commands
[i
].desc
);
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);
62 mon_backtrace(int argc
, char **argv
, struct Trapframe
*tf
)
65 struct Eipdebuginfo eip_debug
;
66 unsigned int *ebp
, *eip
;
69 ebp
= (unsigned int *)read_ebp();
70 eip
= (unsigned int *)read_eip();
71 cprintf("Stack backtrace:\n");
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
]);
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
));
89 ebp
= (unsigned int *)*ebp
;
97 /***** Kernel monitor command interpreter *****/
99 #define WHITESPACE "\t\r\n "
103 runcmd(char *buf
, struct Trapframe
*tf
)
109 // Parse the command buffer into whitespace-separated arguments
114 while (*buf
&& strchr(WHITESPACE
, *buf
))
119 // save and scan past next arg
120 if (argc
== MAXARGS
-1) {
121 cprintf("Too many arguments (max %d)\n", MAXARGS
);
125 while (*buf
&& !strchr(WHITESPACE
, *buf
))
130 // Lookup and invoke the command
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]);
142 monitor(struct Trapframe
*tf
)
146 cprintf("Welcome to the JOS kernel monitor!\n");
147 cprintf("Type 'help' for a list of commands.\n");
153 buf
= readline("K> ");
155 if (runcmd(buf
, tf
) < 0)
160 // return EIP of caller.
161 // does not work if inlined.
162 // putting at the end of the file seems to prevent inlining.
167 __asm
__volatile("movl 4(%%ebp), %0" : "=r" (callerpc
));