Removed dbg_set_serial_debug() - there is now only set_dprintf_enabled().
Disabled dbg_get_serial_debug(); it's only used temporarily in the keyboard device (and I removed its usage there, too). Added "continue", "exit", and "es" commands as in the Be kernel debugger (they will all exit the debugger and try to continue normal kernel execution). Reordered the sources so that public kernel API is together. Added a _user_debug_output() syscall (not yet activated) which dumps to the kernel's serial output. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5305 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+210
-189
@@ -26,22 +26,20 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
int dbg_register_file[2][14]; /* XXXmpetit -- must be made generic */
|
struct debugger_command {
|
||||||
|
|
||||||
|
|
||||||
static bool serial_debug_on = false;
|
|
||||||
static spinlock dbg_spinlock = 0;
|
|
||||||
static int debugger_on_cpu = -1;
|
|
||||||
|
|
||||||
struct debugger_command
|
|
||||||
{
|
|
||||||
struct debugger_command *next;
|
struct debugger_command *next;
|
||||||
int (*func)(int, char **);
|
int (*func)(int, char **);
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *description;
|
const char *description;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct debugger_command *commands;
|
int dbg_register_file[2][14]; /* XXXmpetit -- must be made generic */
|
||||||
|
|
||||||
|
static bool sSerialDebugEnabled = false;
|
||||||
|
static spinlock dbg_spinlock = 0;
|
||||||
|
static int debugger_on_cpu = -1;
|
||||||
|
|
||||||
|
static struct debugger_command *sCommands;
|
||||||
|
|
||||||
#define LINE_BUF_SIZE 1024
|
#define LINE_BUF_SIZE 1024
|
||||||
#define MAX_ARGS 16
|
#define MAX_ARGS 16
|
||||||
@@ -199,7 +197,7 @@ debug_parse_line(char *buf, char **argv, int *argc, int max_args)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
kernel_debugger_loop()
|
kernel_debugger_loop(void)
|
||||||
{
|
{
|
||||||
int argc;
|
int argc;
|
||||||
struct debugger_command *cmd;
|
struct debugger_command *cmd;
|
||||||
@@ -212,7 +210,7 @@ kernel_debugger_loop()
|
|||||||
|
|
||||||
cmd = NULL;
|
cmd = NULL;
|
||||||
|
|
||||||
for(;;) {
|
for (;;) {
|
||||||
dprintf("kdebug> ");
|
dprintf("kdebug> ");
|
||||||
debug_read_line(line_buf[cur_line], LINE_BUF_SIZE);
|
debug_read_line(line_buf[cur_line], LINE_BUF_SIZE);
|
||||||
debug_parse_line(line_buf[cur_line], args, &argc, MAX_ARGS);
|
debug_parse_line(line_buf[cur_line], args, &argc, MAX_ARGS);
|
||||||
@@ -226,27 +224,25 @@ kernel_debugger_loop()
|
|||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
// search command by name
|
// search command by name
|
||||||
cmd = commands;
|
cmd = sCommands;
|
||||||
while (cmd != NULL) {
|
while (cmd != NULL) {
|
||||||
if (strcmp(args[0], cmd->name) == 0)
|
if (strcmp(args[0], cmd->name) == 0)
|
||||||
break;
|
break;
|
||||||
cmd = cmd->next;
|
cmd = cmd->next;
|
||||||
};
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
if (cmd == NULL)
|
if (cmd == NULL)
|
||||||
dprintf("unknown command, enter \"help\" to get a list of all supported commands\n");
|
dprintf("unknown command, enter \"help\" to get a list of all supported commands\n");
|
||||||
else {
|
else {
|
||||||
int rc;
|
int rc = cmd->func(argc, args);
|
||||||
|
|
||||||
rc = cmd->func(argc, args);
|
|
||||||
|
|
||||||
if (rc == B_KDEBUG_QUIT)
|
if (rc == B_KDEBUG_QUIT)
|
||||||
break; // okay, exit now.
|
break; // okay, exit now.
|
||||||
|
|
||||||
if (rc != B_KDEBUG_CONT)
|
if (rc != B_KDEBUG_CONT)
|
||||||
cmd = NULL; // forget last command executed...
|
cmd = NULL; // forget last command executed...
|
||||||
};
|
}
|
||||||
|
|
||||||
cur_line++;
|
cur_line++;
|
||||||
if (cur_line >= HISTORY_SIZE)
|
if (cur_line >= HISTORY_SIZE)
|
||||||
@@ -257,18 +253,166 @@ kernel_debugger_loop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
char
|
||||||
kernel_debugger(const char * message)
|
dbg_putch(char c)
|
||||||
{
|
{
|
||||||
arch_dbg_save_registers(&(dbg_register_file[smp_get_current_cpu()][0]));
|
char ret;
|
||||||
|
cpu_status state = disable_interrupts();
|
||||||
|
acquire_spinlock(&dbg_spinlock);
|
||||||
|
|
||||||
if (message) {
|
if (sSerialDebugEnabled)
|
||||||
dprintf(message);
|
ret = arch_dbg_con_putch(c);
|
||||||
dprintf("\n");
|
else
|
||||||
};
|
ret = c;
|
||||||
|
|
||||||
dprintf("Welcome to Kernel Debugging Land...\n");
|
release_spinlock(&dbg_spinlock);
|
||||||
kernel_debugger_loop();
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
dbg_puts(const char *s)
|
||||||
|
{
|
||||||
|
cpu_status state = disable_interrupts();
|
||||||
|
acquire_spinlock(&dbg_spinlock);
|
||||||
|
|
||||||
|
if (sSerialDebugEnabled)
|
||||||
|
arch_dbg_con_puts(s);
|
||||||
|
|
||||||
|
release_spinlock(&dbg_spinlock);
|
||||||
|
restore_interrupts(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_reboot(int argc, char **argv)
|
||||||
|
{
|
||||||
|
reboot();
|
||||||
|
return 0; // I'll be really suprised if this line ever run! ;-)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_help(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct debugger_command *cmd;
|
||||||
|
|
||||||
|
dprintf("debugger commands:\n");
|
||||||
|
cmd = sCommands;
|
||||||
|
while (cmd != NULL) {
|
||||||
|
dprintf(" %-32s\t\t%s\n", cmd->name, cmd->description ? cmd->description : "");
|
||||||
|
cmd = cmd->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmd_continue(int argc, char **argv)
|
||||||
|
{
|
||||||
|
return B_KDEBUG_QUIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dbg_init(kernel_args *ka)
|
||||||
|
{
|
||||||
|
sCommands = NULL;
|
||||||
|
|
||||||
|
return arch_dbg_con_init(ka);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dbg_init2(kernel_args *ka)
|
||||||
|
{
|
||||||
|
add_debugger_command("help", &cmd_help, "List all debugger commands");
|
||||||
|
add_debugger_command("reboot", &cmd_reboot, "Reboot the system");
|
||||||
|
add_debugger_command("gdb", &cmd_gdb, "Connect to remote gdb");
|
||||||
|
add_debugger_command("continue", &cmd_continue, "Leave kernel debugger");
|
||||||
|
add_debugger_command("exit", &cmd_continue, NULL);
|
||||||
|
add_debugger_command("es", &cmd_continue, NULL);
|
||||||
|
|
||||||
|
return arch_dbg_init(ka);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToDo: this one is probably not needed
|
||||||
|
#if 0
|
||||||
|
bool
|
||||||
|
dbg_get_serial_debug()
|
||||||
|
{
|
||||||
|
return sSerialDebugEnabled;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
// public API
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
add_debugger_command(char *name, int (*func)(int, char **), char *desc)
|
||||||
|
{
|
||||||
|
cpu_status state;
|
||||||
|
struct debugger_command *cmd;
|
||||||
|
|
||||||
|
cmd = (struct debugger_command *)malloc(sizeof(struct debugger_command));
|
||||||
|
if (cmd == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
cmd->func = func;
|
||||||
|
cmd->name = name;
|
||||||
|
cmd->description = desc;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
acquire_spinlock(&dbg_spinlock);
|
||||||
|
|
||||||
|
cmd->next = sCommands;
|
||||||
|
sCommands = cmd;
|
||||||
|
|
||||||
|
release_spinlock(&dbg_spinlock);
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
remove_debugger_command(char * name, int (*func)(int, char **))
|
||||||
|
{
|
||||||
|
struct debugger_command *cmd = sCommands;
|
||||||
|
struct debugger_command *prev = NULL;
|
||||||
|
cpu_status state;
|
||||||
|
|
||||||
|
state = disable_interrupts();
|
||||||
|
acquire_spinlock(&dbg_spinlock);
|
||||||
|
|
||||||
|
while (cmd) {
|
||||||
|
if (!strcmp(cmd->name, name) && cmd->func == func)
|
||||||
|
break;
|
||||||
|
|
||||||
|
prev = cmd;
|
||||||
|
cmd = cmd->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd) {
|
||||||
|
if (cmd == sCommands)
|
||||||
|
sCommands = cmd->next;
|
||||||
|
else
|
||||||
|
prev->next = cmd->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
release_spinlock(&dbg_spinlock);
|
||||||
|
restore_interrupts(state);
|
||||||
|
|
||||||
|
if (cmd) {
|
||||||
|
free(cmd);
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_NAME_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -285,7 +429,7 @@ panic(const char *fmt, ...)
|
|||||||
// XXX should be renamed?
|
// XXX should be renamed?
|
||||||
kernel_startup = true;
|
kernel_startup = true;
|
||||||
|
|
||||||
dbg_set_serial_debug(true);
|
set_dprintf_enabled(true);
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
|
|
||||||
@@ -309,13 +453,38 @@ panic(const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
kernel_debugger(const char * message)
|
||||||
|
{
|
||||||
|
arch_dbg_save_registers(&(dbg_register_file[smp_get_current_cpu()][0]));
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
dprintf(message);
|
||||||
|
dprintf("\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
dprintf("Welcome to Kernel Debugging Land...\n");
|
||||||
|
kernel_debugger_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
set_dprintf_enabled(bool newState)
|
||||||
|
{
|
||||||
|
bool oldState = sSerialDebugEnabled;
|
||||||
|
sSerialDebugEnabled = newState;
|
||||||
|
|
||||||
|
return oldState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dprintf(const char *fmt, ...)
|
dprintf(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
char temp[512];
|
char temp[512];
|
||||||
|
|
||||||
if (serial_debug_on) {
|
if (sSerialDebugEnabled) {
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsprintf(temp, fmt, args);
|
vsprintf(temp, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
@@ -325,169 +494,21 @@ dprintf(const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
char
|
// userland syscalls
|
||||||
dbg_putch(char c)
|
|
||||||
{
|
|
||||||
char ret;
|
|
||||||
cpu_status state = disable_interrupts();
|
|
||||||
acquire_spinlock(&dbg_spinlock);
|
|
||||||
|
|
||||||
if (serial_debug_on)
|
|
||||||
ret = arch_dbg_con_putch(c);
|
|
||||||
else
|
|
||||||
ret = c;
|
|
||||||
|
|
||||||
release_spinlock(&dbg_spinlock);
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dbg_puts(const char *s)
|
_user_debug_output(const char *userString)
|
||||||
{
|
{
|
||||||
cpu_status state = disable_interrupts();
|
char string[1024];
|
||||||
acquire_spinlock(&dbg_spinlock);
|
|
||||||
|
|
||||||
if (serial_debug_on)
|
if (!sSerialDebugEnabled)
|
||||||
arch_dbg_con_puts(s);
|
return;
|
||||||
|
|
||||||
release_spinlock(&dbg_spinlock);
|
if (!CHECK_USER_ADDRESS(userString)
|
||||||
restore_interrupts(state);
|
|| user_strlcpy(string, userString, sizeof(string)) < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbg_puts(userString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
add_debugger_command(char *name, int (*func)(int, char **), char *desc)
|
|
||||||
{
|
|
||||||
cpu_status state;
|
|
||||||
struct debugger_command *cmd;
|
|
||||||
|
|
||||||
cmd = (struct debugger_command *)malloc(sizeof(struct debugger_command));
|
|
||||||
if (cmd == NULL)
|
|
||||||
return ENOMEM;
|
|
||||||
|
|
||||||
cmd->func = func;
|
|
||||||
cmd->name = name;
|
|
||||||
cmd->description = desc;
|
|
||||||
|
|
||||||
state = disable_interrupts();
|
|
||||||
acquire_spinlock(&dbg_spinlock);
|
|
||||||
|
|
||||||
cmd->next = commands;
|
|
||||||
commands = cmd;
|
|
||||||
|
|
||||||
release_spinlock(&dbg_spinlock);
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
return B_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
remove_debugger_command(char * name, int (*func)(int, char **))
|
|
||||||
{
|
|
||||||
struct debugger_command *cmd = commands;
|
|
||||||
struct debugger_command *prev = NULL;
|
|
||||||
cpu_status state;
|
|
||||||
|
|
||||||
state = disable_interrupts();
|
|
||||||
acquire_spinlock(&dbg_spinlock);
|
|
||||||
|
|
||||||
while (cmd) {
|
|
||||||
if (!strcmp(cmd->name, name) && cmd->func == func)
|
|
||||||
break;
|
|
||||||
|
|
||||||
prev = cmd;
|
|
||||||
cmd = cmd->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd) {
|
|
||||||
if (cmd == commands)
|
|
||||||
commands = cmd->next;
|
|
||||||
else
|
|
||||||
prev->next = cmd->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
release_spinlock(&dbg_spinlock);
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
if (cmd) {
|
|
||||||
free(cmd);
|
|
||||||
return B_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_NAME_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_reboot(int argc, char **argv)
|
|
||||||
{
|
|
||||||
reboot();
|
|
||||||
return 0; // I'll be really suprised if this line ever run! ;-)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
cmd_help(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct debugger_command *cmd;
|
|
||||||
|
|
||||||
dprintf("debugger commands:\n");
|
|
||||||
cmd = commands;
|
|
||||||
while (cmd != NULL) {
|
|
||||||
dprintf(" %-32s\t\t%s\n", cmd->name, cmd->description);
|
|
||||||
cmd = cmd->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
dbg_init(kernel_args *ka)
|
|
||||||
{
|
|
||||||
commands = NULL;
|
|
||||||
|
|
||||||
return arch_dbg_con_init(ka);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
dbg_init2(kernel_args *ka)
|
|
||||||
{
|
|
||||||
add_debugger_command("help", &cmd_help, "List all debugger commands");
|
|
||||||
add_debugger_command("reboot", &cmd_reboot, "Reboot");
|
|
||||||
add_debugger_command("gdb", &cmd_gdb, "Connect to remote gdb");
|
|
||||||
|
|
||||||
return arch_dbg_init(ka);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
dbg_set_serial_debug(bool new_val)
|
|
||||||
{
|
|
||||||
int temp = serial_debug_on;
|
|
||||||
serial_debug_on = new_val;
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
dbg_get_serial_debug()
|
|
||||||
{
|
|
||||||
return serial_debug_on;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapper(s) for BeOS R5 compatibility:
|
|
||||||
|
|
||||||
bool
|
|
||||||
set_dprintf_enabled(bool new_state)
|
|
||||||
{
|
|
||||||
return dbg_set_serial_debug(new_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ _start(kernel_args *oldka, int cpu_num)
|
|||||||
|
|
||||||
// setup debug output
|
// setup debug output
|
||||||
dbg_init(&ka);
|
dbg_init(&ka);
|
||||||
dbg_set_serial_debug(true);
|
set_dprintf_enabled(true);
|
||||||
dprintf("Welcome to kernel debugger output!\n");
|
dprintf("Welcome to kernel debugger output!\n");
|
||||||
|
|
||||||
// init modules
|
// init modules
|
||||||
|
|||||||
Reference in New Issue
Block a user