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--;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to