svn commit: r218825 - in head/sys: ddb gdb kern

Matthew D Fleming mdf at FreeBSD.org
Fri Feb 18 22:25:12 UTC 2011


Author: mdf
Date: Fri Feb 18 22:25:11 2011
New Revision: 218825
URL: http://svn.freebsd.org/changeset/base/218825

Log:
  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

Modified:
  head/sys/ddb/db_command.c
  head/sys/gdb/gdb_main.c
  head/sys/gdb/gdb_packet.c
  head/sys/kern/subr_kdb.c

Modified: head/sys/ddb/db_command.c
==============================================================================
--- head/sys/ddb/db_command.c	Fri Feb 18 21:44:53 2011	(r218824)
+++ head/sys/ddb/db_command.c	Fri Feb 18 22:25:11 2011	(r218825)
@@ -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

Modified: head/sys/gdb/gdb_main.c
==============================================================================
--- head/sys/gdb/gdb_main.c	Fri Feb 18 21:44:53 2011	(r218824)
+++ head/sys/gdb/gdb_main.c	Fri Feb 18 22:25:11 2011	(r218825)
@@ -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);
 }

Modified: head/sys/gdb/gdb_packet.c
==============================================================================
--- head/sys/gdb/gdb_packet.c	Fri Feb 18 21:44:53 2011	(r218824)
+++ head/sys/gdb/gdb_packet.c	Fri Feb 18 22:25:11 2011	(r218825)
@@ -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);
 }
 

Modified: head/sys/kern/subr_kdb.c
==============================================================================
--- head/sys/kern/subr_kdb.c	Fri Feb 18 21:44:53 2011	(r218824)
+++ head/sys/kern/subr_kdb.c	Fri Feb 18 22:25:11 2011	(r218825)
@@ -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_
 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 trap
 	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--;
 


More information about the svn-src-head mailing list