diff options
-rw-r--r-- | sys/ddb/db_command.c | 12 | ||||
-rw-r--r-- | sys/gdb/gdb_main.c | 11 | ||||
-rw-r--r-- | sys/gdb/gdb_packet.c | 12 | ||||
-rw-r--r-- | sys/kern/subr_kdb.c | 52 |
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--; |