summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ddb/db_command.c12
-rw-r--r--sys/gdb/gdb_main.c11
-rw-r--r--sys/gdb/gdb_packet.c12
-rw-r--r--sys/kern/subr_kdb.c52
4 files changed, 55 insertions, 32 deletions
diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c
index 7fab5c2..ba9c094 100644
--- a/sys/ddb/db_command.c
+++ b/sys/ddb/db_command.c
@@ -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
diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c
index 233330e..8f3c271 100644
--- a/sys/gdb/gdb_main.c
+++ b/sys/gdb/gdb_main.c
@@ -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);
}
diff --git a/sys/gdb/gdb_packet.c b/sys/gdb/gdb_packet.c
index d3e5a0a..a62cc8d 100644
--- a/sys/gdb/gdb_packet.c
+++ b/sys/gdb/gdb_packet.c
@@ -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);
}
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index 692ecb4..342c5ca 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.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--;
OpenPOWER on IntegriCloud