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:
parent
79c77d726e
commit
3a5d36716f
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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--;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user