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/kdebug.h>
14 #define CMDBUF_SIZE 80 // enough for one VGA text line
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]))
33 /***** Implementations of basic kernel monitor commands *****/
36 mon_help(int argc
, char **argv
, struct Trapframe
*tf
)
40 for (i
= 0; i
< NCOMMANDS
; i
++)
41 cprintf("%s - %s\n", commands
[i
].name
, commands
[i
].desc
);
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);
61 mon_backtrace(int argc
, char **argv
, struct Trapframe
*tf
)
64 struct Eipdebuginfo eip_debug
;
65 unsigned int *ebp
, *eip
;
68 ebp
= (unsigned int *)read_ebp();
69 eip
= (unsigned int *)read_eip();
70 cprintf("Stack backtrace:\n");
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
]);
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
));
88 ebp
= (unsigned int *)*ebp
;
96 /***** Kernel monitor command interpreter *****/
98 #define WHITESPACE "\t\r\n "
102 runcmd(char *buf
, struct Trapframe
*tf
)
108 // Parse the command buffer into whitespace-separated arguments
113 while (*buf
&& strchr(WHITESPACE
, *buf
))
118 // save and scan past next arg
119 if (argc
== MAXARGS
-1) {
120 cprintf("Too many arguments (max %d)\n", MAXARGS
);
124 while (*buf
&& !strchr(WHITESPACE
, *buf
))
129 // Lookup and invoke the command
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]);
141 monitor(struct Trapframe
*tf
)
145 cprintf("Welcome to the JOS kernel monitor!\n");
146 cprintf("Type 'help' for a list of commands.\n");
150 buf
= readline("K> ");
152 if (runcmd(buf
, tf
) < 0)
157 // return EIP of caller.
158 // does not work if inlined.
159 // putting at the end of the file seems to prevent inlining.
164 __asm
__volatile("movl 4(%%ebp), %0" : "=r" (callerpc
));