2012-08-22 12:32:13 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <mmu.h>
|
|
|
|
#include <trap.h>
|
2012-08-26 18:04:26 +08:00
|
|
|
#include <kmonitor.h>
|
2012-08-22 12:32:13 +08:00
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
/* *
|
|
|
|
* Simple command-line kernel monitor useful for controlling the
|
|
|
|
* kernel and exploring the system interactively.
|
|
|
|
* */
|
|
|
|
|
|
|
|
struct command {
|
|
|
|
const char *name;
|
|
|
|
const char *desc;
|
|
|
|
// return -1 to force monitor to exit
|
|
|
|
int(*func)(int argc, char **argv, struct trapframe *tf);
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct command commands[] = {
|
|
|
|
{"help", "Display this list of commands.", mon_help},
|
|
|
|
{"kerninfo", "Display information about the kernel.", mon_kerninfo},
|
|
|
|
{"backtrace", "Print backtrace of stack frame.", mon_backtrace},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* return if kernel is panic, in kern/debug/panic.c */
|
|
|
|
bool is_kernel_panic(void);
|
|
|
|
|
|
|
|
#define NCOMMANDS (sizeof(commands)/sizeof(struct command))
|
|
|
|
|
|
|
|
/***** Kernel monitor command interpreter *****/
|
|
|
|
|
|
|
|
#define MAXARGS 16
|
|
|
|
#define WHITESPACE " \t\n\r"
|
|
|
|
|
|
|
|
/* parse - parse the command buffer into whitespace-separated arguments */
|
|
|
|
static int
|
|
|
|
parse(char *buf, char **argv) {
|
|
|
|
int argc = 0;
|
|
|
|
while (1) {
|
|
|
|
// find global whitespace
|
|
|
|
while (*buf != '\0' && strchr(WHITESPACE, *buf) != NULL) {
|
|
|
|
*buf ++ = '\0';
|
|
|
|
}
|
|
|
|
if (*buf == '\0') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// save and scan past next arg
|
|
|
|
if (argc == MAXARGS - 1) {
|
|
|
|
cprintf("Too many arguments (max %d).\n", MAXARGS);
|
|
|
|
}
|
|
|
|
argv[argc ++] = buf;
|
|
|
|
while (*buf != '\0' && strchr(WHITESPACE, *buf) == NULL) {
|
|
|
|
buf ++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return argc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *
|
|
|
|
* runcmd - parse the input string, split it into separated arguments
|
|
|
|
* and then lookup and invoke some related commands/
|
|
|
|
* */
|
|
|
|
static int
|
|
|
|
runcmd(char *buf, struct trapframe *tf) {
|
|
|
|
char *argv[MAXARGS];
|
|
|
|
int argc = parse(buf, argv);
|
|
|
|
if (argc == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < NCOMMANDS; i ++) {
|
|
|
|
if (strcmp(commands[i].name, argv[0]) == 0) {
|
|
|
|
return commands[i].func(argc - 1, argv + 1, tf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cprintf("Unknown command '%s'\n", argv[0]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***** Implementations of basic kernel monitor commands *****/
|
|
|
|
|
|
|
|
void
|
2012-08-26 18:04:26 +08:00
|
|
|
kmonitor(struct trapframe *tf) {
|
2012-08-22 12:32:13 +08:00
|
|
|
cprintf("Welcome to the kernel debug monitor!!\n");
|
|
|
|
cprintf("Type 'help' for a list of commands.\n");
|
|
|
|
|
|
|
|
if (tf != NULL) {
|
|
|
|
print_trapframe(tf);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *buf;
|
|
|
|
while (1) {
|
|
|
|
if ((buf = readline("K> ")) != NULL) {
|
|
|
|
if (runcmd(buf, tf) < 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mon_help - print the information about mon_* functions */
|
|
|
|
int
|
|
|
|
mon_help(int argc, char **argv, struct trapframe *tf) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < NCOMMANDS; i ++) {
|
|
|
|
cprintf("%s - %s\n", commands[i].name, commands[i].desc);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *
|
|
|
|
* mon_kerninfo - call print_kerninfo in kern/debug/kdebug.c to
|
|
|
|
* print the memory occupancy in kernel.
|
|
|
|
* */
|
|
|
|
int
|
|
|
|
mon_kerninfo(int argc, char **argv, struct trapframe *tf) {
|
|
|
|
print_kerninfo();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* *
|
|
|
|
* mon_backtrace - call print_stackframe in kern/debug/kdebug.c to
|
|
|
|
* print a backtrace of the stack.
|
|
|
|
* */
|
|
|
|
int
|
|
|
|
mon_backtrace(int argc, char **argv, struct trapframe *tf) {
|
|
|
|
print_stackframe();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|