The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kgdb_stub.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kgdb_stub.c,v 1.22 2005/12/07 05:53:24 thorpej Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1990, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This software was developed by the Computer Systems Engineering group
    8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
    9  * contributed to Berkeley.
   10  *
   11  * All advertising materials mentioning features or use of this software
   12  * must display the following acknowledgement:
   13  *      This product includes software developed by the University of
   14  *      California, Lawrence Berkeley Laboratories.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  *      @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
   41  */
   42 
   43 /*
   44  * "Stub" to allow remote CPU to debug over a serial line using gdb.
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: kgdb_stub.c,v 1.22 2005/12/07 05:53:24 thorpej Exp $");
   49 
   50 #include "opt_kgdb.h"
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/kgdb.h>
   55 
   56 #undef  DEBUG_KGDB
   57 
   58 #ifdef DEBUG_KGDB
   59 #define DPRINTF(x)      printf x
   60 #else
   61 #define DPRINTF(x)
   62 #endif
   63 
   64 /* XXX: Maybe these should be in the MD files? */
   65 #ifndef KGDB_DEV
   66 #define KGDB_DEV NODEV
   67 #endif
   68 #ifndef KGDB_DEVRATE
   69 #define KGDB_DEVRATE 19200
   70 #endif
   71 
   72 int kgdb_dev = KGDB_DEV;        /* remote debugging device (NODEV if none) */
   73 int kgdb_rate = KGDB_DEVRATE;   /* remote debugging baud rate */
   74 int kgdb_active = 0;            /* remote debugging active if != 0 */
   75 int kgdb_debug_init = 0;        /* != 0 waits for remote at system init */
   76 int kgdb_debug_panic = 0;       /* != 0 waits for remote on panic */
   77 label_t *kgdb_recover = 0;
   78 
   79 static int (*kgdb_getc)(void *);
   80 static void (*kgdb_putc)(void *, int);
   81 static void *kgdb_ioarg;
   82 
   83 /* KGDB_BUFLEN must be at least (2*KGDB_NUMREGS*sizeof(kgdb_reg_t)+1) */
   84 static u_char buffer[KGDB_BUFLEN];
   85 static kgdb_reg_t gdb_regs[KGDB_NUMREGS];
   86 
   87 #define GETC()  ((*kgdb_getc)(kgdb_ioarg))
   88 #define PUTC(c) ((*kgdb_putc)(kgdb_ioarg, c))
   89 
   90 /*
   91  * db_trap_callback can be hooked by MD port code to handle special
   92  * cases such as disabling hardware watchdogs while in kgdb.  Name
   93  * is shared with DDB.
   94  */
   95 void (*db_trap_callback)(int);
   96 
   97 /*
   98  * This little routine exists simply so that bcopy() can be debugged.
   99  */
  100 static void
  101 kgdb_copy(void *vsrc, void *vdst, int len)
  102 {
  103         char *src = vsrc;
  104         char *dst = vdst;
  105 
  106         while (--len >= 0)
  107                 *dst++ = *src++;
  108 }
  109 
  110 #if 0
  111 /* ditto for bzero */
  112 static void
  113 kgdb_zero(void *vptr, int len)
  114 {
  115         char *ptr = vptr;
  116 
  117         while (--len >= 0)
  118                 *ptr++ = (char) 0;
  119 }
  120 #endif
  121 
  122 /*
  123  * Convert a hex digit into an integer.
  124  * This returns -1 if the argument passed is no
  125  * valid hex digit.
  126  */
  127 static int
  128 digit2i(u_char c)
  129 {
  130         if (c >= '' && c <= '9')
  131                 return (c - '');
  132         else if (c >= 'a' && c <= 'f')
  133                 return (c - 'a' + 10);
  134         else if (c >= 'A' && c <= 'F')
  135 
  136                 return (c - 'A' + 10);
  137         else
  138                 return (-1);
  139 }
  140 
  141 /*
  142  * Convert the low 4 bits of an integer into
  143  * an hex digit.
  144  */
  145 static u_char
  146 i2digit(int n)
  147 {
  148         return (hexdigits[n & 0x0f]);
  149 }
  150 
  151 /*
  152  * Convert a byte array into an hex string.
  153  */
  154 static void
  155 mem2hex(void *vdst, void *vsrc, int len)
  156 {
  157         u_char *dst = vdst;
  158         u_char *src = vsrc;
  159 
  160         while (len--) {
  161                 *dst++ = i2digit(*src >> 4);
  162                 *dst++ = i2digit(*src++);
  163         }
  164         *dst = '\0';
  165 }
  166 
  167 /*
  168  * Convert an hex string into a byte array.
  169  * This returns a pointer to the character following
  170  * the last valid hex digit. If the string ends in
  171  * the middle of a byte, NULL is returned.
  172  */
  173 static u_char *
  174 hex2mem(void *vdst, u_char *src, int maxlen)
  175 {
  176         u_char *dst = vdst;
  177         int msb, lsb;
  178 
  179         while (*src && maxlen--) {
  180                 msb = digit2i(*src++);
  181                 if (msb < 0)
  182                         return (src - 1);
  183                 lsb = digit2i(*src++);
  184                 if (lsb < 0)
  185                         return (NULL);
  186                 *dst++ = (msb << 4) | lsb;
  187         }
  188         return (src);
  189 }
  190 
  191 /*
  192  * Convert an hex string into an integer.
  193  * This returns a pointer to the character following
  194  * the last valid hex digit.
  195  */
  196 static vaddr_t
  197 hex2i(u_char **srcp)
  198 {
  199         char *src = *srcp;
  200         vaddr_t r = 0;
  201         int nibble;
  202 
  203         while ((nibble = digit2i(*src)) >= 0) {
  204                 r *= 16;
  205                 r += nibble;
  206                 src++;
  207         }
  208         *srcp = src;
  209         return (r);
  210 }
  211 
  212 /*
  213  * Send a packet.
  214  */
  215 static void
  216 kgdb_send(const u_char *bp)
  217 {
  218         const u_char *p;
  219         u_char csum, c;
  220 
  221         DPRINTF(("kgdb_send: %s\n", bp));
  222         do {
  223                 p = bp;
  224                 PUTC(KGDB_START);
  225                 for (csum = 0; (c = *p); p++) {
  226                         PUTC(c);
  227                         csum += c;
  228                 }
  229                 PUTC(KGDB_END);
  230                 PUTC(i2digit(csum >> 4));
  231                 PUTC(i2digit(csum));
  232         } while ((c = GETC() & 0x7f) == KGDB_BADP);
  233 }
  234 
  235 /*
  236  * Receive a packet.
  237  */
  238 static int
  239 kgdb_recv(u_char *bp, int maxlen)
  240 {
  241         u_char *p;
  242         int c, csum, tmpcsum;
  243         int len;
  244 
  245         DPRINTF(("kgdb_recv:  "));
  246         do {
  247                 p = bp;
  248                 csum = len = 0;
  249                 while ((c = GETC()) != KGDB_START)
  250                         DPRINTF(("%c",c));
  251                 DPRINTF(("%c Start ",c));
  252 
  253                 while ((c = GETC()) != KGDB_END && len < maxlen) {
  254                         DPRINTF(("%c",c));
  255                         c &= 0x7f;
  256                         csum += c;
  257                         *p++ = c;
  258                         len++;
  259                 }
  260                 csum &= 0xff;
  261                 *p = '\0';
  262                 DPRINTF(("%c End ", c));
  263 
  264                 if (len >= maxlen) {
  265                         DPRINTF(("Long- "));
  266                         PUTC(KGDB_BADP);
  267                         continue;
  268                 }
  269                 tmpcsum = csum;
  270 
  271                 c = GETC();
  272                 DPRINTF(("%c",c));
  273                 csum -= digit2i(c) * 16;
  274                 c = GETC();
  275                 DPRINTF(("%c",c));
  276                 csum -= digit2i(c);
  277 
  278                 if (csum == 0) {
  279                         DPRINTF(("Good+ "));
  280                         PUTC(KGDB_GOODP);
  281                         /* Sequence present? */
  282                         if (bp[2] == ':') {
  283                                 DPRINTF(("Seq %c%c ", bp[0], bp[1]));
  284                                 PUTC(bp[0]);
  285                                 PUTC(bp[1]);
  286                                 len -= 3;
  287                                 kgdb_copy(bp + 3, bp, len);
  288                         }
  289                         break;
  290                 }
  291                 DPRINTF((" Bad(wanted %x, off by %d)- ", tmpcsum, csum));
  292                 PUTC(KGDB_BADP);
  293         } while (1);
  294         DPRINTF(("kgdb_recv: %s\n", bp));
  295         return (len);
  296 }
  297 
  298 /*
  299  * This is called by the appropriate tty driver.
  300  */
  301 void
  302 kgdb_attach(int (*getfn)(void *), void (*putfn)(void *, int), void *ioarg)
  303 {
  304         kgdb_getc = getfn;
  305         kgdb_putc = putfn;
  306         kgdb_ioarg = ioarg;
  307 }
  308 
  309 /*
  310  * This function does all command processing for interfacing to
  311  * a remote gdb.  Note that the error codes are ignored by gdb
  312  * at present, but might eventually become meaningful. (XXX)
  313  * It might makes sense to use POSIX errno values, because
  314  * that is what the gdb/remote.c functions want to return.
  315  */
  316 int
  317 kgdb_trap(int type, db_regs_t *regs)
  318 {
  319         label_t jmpbuf;
  320         vaddr_t addr;
  321         size_t len;
  322         u_char *p;
  323 
  324         if (kgdb_dev < 0 || kgdb_getc == NULL) {
  325                 /* not debugging */
  326                 return (0);
  327         }
  328 
  329         db_clear_single_step(regs);
  330 
  331         if (db_trap_callback) db_trap_callback(1);
  332 
  333         /* Detect and recover from unexpected traps. */
  334         if (kgdb_recover != 0) {
  335                 printf("kgdb: caught trap 0x%x at %p\n",
  336                            type, (void*)PC_REGS(regs));
  337                 kgdb_send("E0E"); /* 14==EFAULT */
  338                 longjmp(kgdb_recover);
  339         }
  340 
  341         /*
  342          * The first entry to this function is normally through
  343          * a breakpoint trap in kgdb_connect(), in which case we
  344          * must advance past the breakpoint because gdb will not.
  345          *
  346          * Machines vary as to where they leave the PC after a
  347          * breakpoint trap.  Those that leave the PC set to the
  348          * address of the trap instruction (i.e. pc532) will not
  349          * define FIXUP_PC_AFTER_BREAK(), and therefore will just
  350          * advance the PC.  On machines that leave the PC set to
  351          * the instruction after the trap, FIXUP_PC_AFTER_BREAK
  352          * will be defined to back-up the PC, so that after the
  353          * "first-time" part of the if statement below has run,
  354          * the PC will be the same as it was on entry.
  355          *
  356          * On the first entry here, we expect that gdb is not yet
  357          * listening to us, so just enter the interaction loop.
  358          * After the debugger is "active" (connected) it will be
  359          * waiting for a "signaled" message from us.
  360          */
  361         if (kgdb_active == 0) {
  362                 if (!IS_BREAKPOINT_TRAP(type, 0)) {
  363                         /* No debugger active -- let trap handle this. */
  364                         if (db_trap_callback) db_trap_callback(0);
  365                         return (0);
  366                 }
  367                 /* Make the PC point at the breakpoint... */
  368 #ifdef  FIXUP_PC_AFTER_BREAK
  369                 FIXUP_PC_AFTER_BREAK(regs);
  370 #endif
  371                 /* ... and then advance past it. */
  372 #ifdef  PC_ADVANCE
  373                 PC_ADVANCE(regs);
  374 #else
  375                 PC_REGS(regs) += BKPT_SIZE;
  376 #endif
  377                 kgdb_active = 1;
  378         } else {
  379                 /* Tell remote host that an exception has occurred. */
  380                 snprintf(buffer, sizeof(buffer), "S%02x", kgdb_signal(type));
  381                 kgdb_send(buffer);
  382         }
  383 
  384         /* Stick frame regs into our reg cache. */
  385         kgdb_getregs(regs, gdb_regs);
  386 
  387         /*
  388          * Interact with gdb until it lets us go.
  389          * If we cause a trap, resume here.
  390          */
  391         (void)setjmp((kgdb_recover = &jmpbuf));
  392         for (;;) {
  393                 kgdb_recv(buffer, sizeof(buffer));
  394                 switch (buffer[0]) {
  395 
  396                 default:
  397                         /* Unknown command. */
  398                         kgdb_send("");
  399                         continue;
  400 
  401                 case KGDB_SIGNAL:
  402                         /*
  403                          * if this command came from a running gdb,
  404                          * answer it -- the other guy has no way of
  405                          * knowing if we're in or out of this loop
  406                          * when he issues a "remote-signal".
  407                          */
  408                         snprintf(buffer, sizeof(buffer), "S%02x",
  409                             kgdb_signal(type));
  410                         kgdb_send(buffer);
  411                         continue;
  412 
  413                 case KGDB_REG_R:
  414                         mem2hex(buffer, gdb_regs, sizeof(gdb_regs));
  415                         kgdb_send(buffer);
  416                         continue;
  417 
  418                 case KGDB_REG_W:
  419                         p = hex2mem(gdb_regs, buffer + 1, sizeof(gdb_regs));
  420                         if (p == NULL || *p != '\0')
  421                                 kgdb_send("E01");
  422                         else {
  423                                 kgdb_setregs(regs, gdb_regs);
  424                                 kgdb_send("OK");
  425                         }
  426                         continue;
  427 
  428                 case KGDB_MEM_R:
  429                         p = buffer + 1;
  430                         addr = hex2i(&p);
  431                         if (*p++ != ',') {
  432                                 kgdb_send("E02");
  433                                 continue;
  434                         }
  435                         len = hex2i(&p);
  436                         if (*p != '\0') {
  437                                 kgdb_send("E03");
  438                                 continue;
  439                         }
  440                         if (len > sizeof(buffer) / 2) {
  441                                 kgdb_send("E04");
  442                                 continue;
  443                         }
  444                         if (kgdb_acc(addr, len) == 0) {
  445                                 kgdb_send("E05");
  446                                 continue;
  447                         }
  448                         db_read_bytes(addr, (size_t)len,
  449                                         (char *)buffer + sizeof(buffer) / 2);
  450                         mem2hex(buffer, buffer + sizeof(buffer) / 2, len);
  451                         kgdb_send(buffer);
  452                         continue;
  453 
  454                 case KGDB_MEM_W:
  455                         p = buffer + 1;
  456                         addr = hex2i(&p);
  457                         if (*p++ != ',') {
  458                                 kgdb_send("E06");
  459                                 continue;
  460                         }
  461                         len = hex2i(&p);
  462                         if (*p++ != ':') {
  463                                 kgdb_send("E07");
  464                                 continue;
  465                         }
  466                         if (len > (sizeof(buffer) - (p - buffer))) {
  467                                 kgdb_send("E08");
  468                                 continue;
  469                         }
  470                         p = hex2mem(buffer, p, sizeof(buffer));
  471                         if (p == NULL) {
  472                                 kgdb_send("E09");
  473                                 continue;
  474                         }
  475                         if (kgdb_acc(addr, len) == 0) {
  476                                 kgdb_send("E0A");
  477                                 continue;
  478                         }
  479                         db_write_bytes(addr, (size_t)len, (char *)buffer);
  480                         kgdb_send("OK");
  481                         continue;
  482 
  483                 case KGDB_DETACH:
  484                 case KGDB_KILL:
  485                         kgdb_active = 0;
  486                         printf("kgdb detached\n");
  487                         db_clear_single_step(regs);
  488                         kgdb_send("OK");
  489                         goto out;
  490 
  491                 case KGDB_CONT:
  492                         if (buffer[1]) {
  493                                 p = buffer + 1;
  494                                 addr = hex2i(&p);
  495                                 if (*p) {
  496                                         kgdb_send("E0B");
  497                                         continue;
  498                                 }
  499                                 PC_REGS(regs) = addr;
  500                                 DPRINTF(("kgdb: continuing at %08lx\n", addr));
  501 
  502                         } else {
  503                                 DPRINTF((
  504                                   "kgdb: continuing at old address %08lx\n",
  505                                   (vaddr_t)PC_REGS(regs)));
  506                         }
  507 
  508                         db_clear_single_step(regs);
  509                         goto out;
  510 
  511                 case KGDB_STEP:
  512                         if (buffer[1]) {
  513                                 p = buffer + 1;
  514                                 addr = hex2i(&p);
  515                                 if (*p) {
  516                                         kgdb_send("E0B");
  517                                         continue;
  518                                 }
  519                                 PC_REGS(regs) = addr;
  520                         }
  521                         db_set_single_step(regs);
  522                         goto out;
  523                 }
  524         }
  525  out:
  526         if (db_trap_callback) db_trap_callback(0);
  527         kgdb_recover = 0;
  528         return (1);
  529 }

Cache object: bca36e2fa99389fba21780c76cbb5e43


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.