Modify kdb_trap() so that it re-calls the dbbe_trap function as long as

the debugger back-end has changed.  This means that switching from ddb
to gdb no longer requires a "step" which can be dangerous on an
already-crashed kernel.

Also add a capability to get from the gdb back-end back to ddb, by
typing ^C in the console window.

While here, simplify kdb_sysctl_available() by using
sbuf_new_for_sysctl(), and use strlcpy() instead of strncpy() since the
strlcpy semantic is desired.

MFC after:	1 month
This commit is contained in:
Matthew D Fleming 2011-02-18 22:25:11 +00:00
parent 79c77d726e
commit 3a5d36716f
4 changed files with 55 additions and 32 deletions

View File

@ -723,10 +723,16 @@ static void
db_gdb(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
{
if (kdb_dbbe_select("gdb") != 0)
if (kdb_dbbe_select("gdb") != 0) {
db_printf("The remote GDB backend could not be selected.\n");
else
db_printf("Step to enter the remote GDB backend.\n");
return;
}
/*
* Mark that we are done in the debugger. kdb_trap()
* should re-enter with the new backend.
*/
db_cmd_loop_done = 1;
db_printf("(ctrl-c will return control to ddb)\n");
}
static void

View File

@ -95,7 +95,17 @@ gdb_init(void)
static int
gdb_trap(int type, int code)
{
jmp_buf jb;
struct thread *thr_iter;
void *prev_jb;
prev_jb = kdb_jmpbuf(jb);
if (setjmp(jb) != 0) {
printf("%s bailing, hopefully back to ddb!\n", __func__);
gdb_listening = 0;
(void)kdb_jmpbuf(prev_jb);
return (1);
}
gdb_listening = 0;
/*
@ -291,5 +301,6 @@ gdb_trap(int type, int code)
break;
}
}
(void)kdb_jmpbuf(prev_jb);
return (0);
}

View File

@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/ctype.h>
#include <sys/kdb.h>
#include <sys/ttydefaults.h>
#include <machine/gdb_machdep.h>
#include <machine/kdb.h>
@ -60,6 +61,17 @@ gdb_getc(void)
do
c = gdb_cur->gdb_getc();
while (c == -1);
if (c == CTRL('C')) {
printf("Received ^C; trying to switch back to ddb.\n");
if (kdb_dbbe_select("ddb") != 0)
printf("The ddb backend could not be selected.\n");
else {
printf("using longjmp, hope it works!\n");
kdb_reenter();
}
}
return (c);
}

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/stack.h>
#include <sys/sysctl.h>
@ -108,33 +109,17 @@ const char * volatile kdb_why = KDB_WHY_UNSET;
static int
kdb_sysctl_available(SYSCTL_HANDLER_ARGS)
{
struct kdb_dbbe *be, **iter;
char *avail, *p;
ssize_t len, sz;
struct kdb_dbbe **iter;
struct sbuf sbuf;
int error;
sz = 0;
sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
SET_FOREACH(iter, kdb_dbbe_set) {
be = *iter;
if (be->dbbe_active == 0)
sz += strlen(be->dbbe_name) + 1;
if ((*iter)->dbbe_active == 0)
sbuf_printf(&sbuf, "%s ", (*iter)->dbbe_name);
}
sz++;
avail = malloc(sz, M_TEMP, M_WAITOK);
p = avail;
*p = '\0';
SET_FOREACH(iter, kdb_dbbe_set) {
be = *iter;
if (be->dbbe_active == 0) {
len = snprintf(p, sz, "%s ", be->dbbe_name);
p += len;
sz -= len;
}
}
KASSERT(sz >= 0, ("%s", __func__));
error = sysctl_handle_string(oidp, avail, 0, req);
free(avail, M_TEMP);
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
return (error);
}
@ -144,10 +129,9 @@ kdb_sysctl_current(SYSCTL_HANDLER_ARGS)
char buf[16];
int error;
if (kdb_dbbe != NULL) {
strncpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
} else
if (kdb_dbbe != NULL)
strlcpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
else
*buf = '\0';
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
if (error != 0 || req->newptr == NULL)
@ -513,13 +497,15 @@ kdb_thr_select(struct thread *thr)
int
kdb_trap(int type, int code, struct trapframe *tf)
{
struct kdb_dbbe *be;
register_t intr;
#ifdef SMP
int did_stop_cpus;
#endif
int handled;
if (kdb_dbbe == NULL || kdb_dbbe->dbbe_trap == NULL)
be = kdb_dbbe;
if (be == NULL || be->dbbe_trap == NULL)
return (0);
/* We reenter the debugger through kdb_reenter(). */
@ -543,7 +529,15 @@ kdb_trap(int type, int code, struct trapframe *tf)
makectx(tf, &kdb_pcb);
kdb_thr_select(curthread);
handled = kdb_dbbe->dbbe_trap(type, code);
for (;;) {
handled = be->dbbe_trap(type, code);
if (be == kdb_dbbe)
break;
be = kdb_dbbe;
if (be == NULL || be->dbbe_trap == NULL)
break;
printf("Switching to %s back-end\n", be->dbbe_name);
}
kdb_active--;