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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: kgdb_stub.c,v 1.17 2004/03/23 13:22:03 junyoung 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.17 2004/03/23 13:22:03 junyoung 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 void kgdb_copy(void *, void *, int);
   80 /* static void kgdb_zero(void *, int); */
   81 static void kgdb_send(u_char *);
   82 static int kgdb_recv(u_char *, int);
   83 static int digit2i(u_char);
   84 static u_char i2digit(int);
   85 static void mem2hex(void *, void *, int);
   86 static u_char *hex2mem(void *, u_char *, int);
   87 static vaddr_t hex2i(u_char **);
   88 
   89 static int (*kgdb_getc)(void *);
   90 static void (*kgdb_putc)(void *, int);
   91 static void *kgdb_ioarg;
   92 
   93 /* KGDB_BUFLEN must be at least (2*KGDB_NUMREGS*sizeof(kgdb_reg_t)+1) */
   94 static u_char buffer[KGDB_BUFLEN];
   95 static kgdb_reg_t gdb_regs[KGDB_NUMREGS];
   96 
   97 #define GETC()  ((*kgdb_getc)(kgdb_ioarg))
   98 #define PUTC(c) ((*kgdb_putc)(kgdb_ioarg, c))
   99 
  100 /*
  101  * db_trap_callback can be hooked by MD port code to handle special
  102  * cases such as disabling hardware watchdogs while in kgdb.  Name
  103  * is shared with DDB.
  104  */
  105 void (*db_trap_callback)(int);
  106 
  107 /*
  108  * This little routine exists simply so that bcopy() can be debugged.
  109  */
  110 static void
  111 kgdb_copy(vsrc, vdst, len)
  112         void *vsrc, *vdst;
  113         int len;
  114 {
  115         char *src = vsrc;
  116         char *dst = vdst;
  117 
  118         while (--len >= 0)
  119                 *dst++ = *src++;
  120 }
  121 
  122 #if 0
  123 /* ditto for bzero */
  124 static void
  125 kgdb_zero(vptr, len)
  126         void *vptr;
  127         int len;
  128 {
  129         char *ptr = vptr;
  130 
  131         while (--len >= 0)
  132                 *ptr++ = (char) 0;
  133 }
  134 #endif
  135 
  136 /*
  137  * Convert a hex digit into an integer.
  138  * This returns -1 if the argument passed is no
  139  * valid hex digit.
  140  */
  141 static int
  142 digit2i(c)
  143         u_char c;
  144 {
  145         if (c >= '' && c <= '9')
  146                 return (c - '');
  147         else if (c >= 'a' && c <= 'f')
  148                 return (c - 'a' + 10);  
  149         else if (c >= 'A' && c <= 'F')
  150 
  151                 return (c - 'A' + 10);  
  152         else
  153                 return (-1);
  154 }
  155 
  156 /*
  157  * Convert the low 4 bits of an integer into
  158  * an hex digit.
  159  */
  160 static u_char
  161 i2digit(n)
  162         int n;
  163 {
  164         return ("0123456789abcdef"[n & 0x0f]);
  165 }
  166 
  167 /*
  168  * Convert a byte array into an hex string.
  169  */
  170 static void
  171 mem2hex(vdst, vsrc, len)
  172         void *vdst, *vsrc;
  173         int len;
  174 {
  175         u_char *dst = vdst;
  176         u_char *src = vsrc;
  177 
  178         while (len--) {
  179                 *dst++ = i2digit(*src >> 4);
  180                 *dst++ = i2digit(*src++);
  181         }
  182         *dst = '\0';
  183 }
  184 
  185 /*
  186  * Convert an hex string into a byte array.
  187  * This returns a pointer to the character following
  188  * the last valid hex digit. If the string ends in
  189  * the middle of a byte, NULL is returned.
  190  */
  191 static u_char *
  192 hex2mem(vdst, src, maxlen)
  193         void *vdst;
  194         u_char *src;
  195         int maxlen;
  196 {
  197         u_char *dst = vdst;
  198         int msb, lsb;
  199 
  200         while (*src && maxlen--) {
  201                 msb = digit2i(*src++);
  202                 if (msb < 0)
  203                         return (src - 1);
  204                 lsb = digit2i(*src++);
  205                 if (lsb < 0)
  206                         return (NULL);
  207                 *dst++ = (msb << 4) | lsb;
  208         }
  209         return (src);
  210 }
  211 
  212 /*
  213  * Convert an hex string into an integer.
  214  * This returns a pointer to the character following
  215  * the last valid hex digit.
  216  */ 
  217 static vaddr_t
  218 hex2i(srcp)
  219         u_char **srcp;
  220 {
  221         char *src = *srcp;
  222         vaddr_t r = 0;
  223         int nibble;
  224 
  225         while ((nibble = digit2i(*src)) >= 0) {
  226                 r *= 16;
  227                 r += nibble;
  228                 src++;
  229         }
  230         *srcp = src;
  231         return (r);
  232 }
  233 
  234 /*
  235  * Send a packet.
  236  */
  237 static void
  238 kgdb_send(bp)
  239         u_char *bp;
  240 {
  241         u_char *p;
  242         u_char csum, c;
  243 
  244         DPRINTF(("kgdb_send: %s\n", bp));
  245         do {
  246                 p = bp;
  247                 PUTC(KGDB_START);
  248                 for (csum = 0; (c = *p); p++) {
  249                         PUTC(c);
  250                         csum += c;
  251                 }
  252                 PUTC(KGDB_END);
  253                 PUTC(i2digit(csum >> 4));
  254                 PUTC(i2digit(csum));
  255         } while ((c = GETC() & 0x7f) == KGDB_BADP);
  256 }
  257 
  258 /*
  259  * Receive a packet.
  260  */
  261 static int
  262 kgdb_recv(bp, maxlen)
  263         u_char *bp;
  264         int maxlen;
  265 {
  266         u_char *p;
  267         int c, csum, tmpcsum;
  268         int len;
  269 
  270         DPRINTF(("kgdb_recv:  "));
  271         do {
  272                 p = bp;
  273                 csum = len = 0;
  274                 while ((c = GETC()) != KGDB_START)
  275                         DPRINTF(("%c",c));
  276                 DPRINTF(("%c Start ",c));
  277 
  278                 while ((c = GETC()) != KGDB_END && len < maxlen) {
  279                         DPRINTF(("%c",c));
  280                         c &= 0x7f;
  281                         csum += c;
  282                         *p++ = c;
  283                         len++;
  284                 }
  285                 csum &= 0xff;
  286                 *p = '\0';
  287                 DPRINTF(("%c End ", c));
  288 
  289                 if (len >= maxlen) {
  290                         DPRINTF(("Long- "));
  291                         PUTC(KGDB_BADP);
  292                         continue;
  293                 }
  294                 tmpcsum = csum;
  295 
  296                 c = GETC();
  297                 DPRINTF(("%c",c));
  298                 csum -= digit2i(c) * 16;
  299                 c = GETC();
  300                 DPRINTF(("%c",c));
  301                 csum -= digit2i(c);
  302 
  303                 if (csum == 0) {
  304                         DPRINTF(("Good+ "));
  305                         PUTC(KGDB_GOODP);
  306                         /* Sequence present? */
  307                         if (bp[2] == ':') {
  308                                 DPRINTF(("Seq %c%c ", bp[0], bp[1]));
  309                                 PUTC(bp[0]);
  310                                 PUTC(bp[1]);
  311                                 len -= 3;
  312                                 kgdb_copy(bp + 3, bp, len);
  313                         }
  314                         break;
  315                 }
  316                 DPRINTF((" Bad(wanted %x, off by %d)- ", tmpcsum, csum));
  317                 PUTC(KGDB_BADP);
  318         } while (1);
  319         DPRINTF(("kgdb_recv: %s\n", bp));
  320         return (len);
  321 }
  322 
  323 /*
  324  * This is called by the appropriate tty driver.
  325  */
  326 void
  327 kgdb_attach(getfn, putfn, ioarg)
  328         int (*getfn)(void *);
  329         void (*putfn)(void *, int);
  330         void *ioarg;
  331 {
  332         kgdb_getc = getfn;
  333         kgdb_putc = putfn;
  334         kgdb_ioarg = ioarg;
  335 }
  336 
  337 /*
  338  * This function does all command processing for interfacing to
  339  * a remote gdb.  Note that the error codes are ignored by gdb
  340  * at present, but might eventually become meaningful. (XXX)
  341  * It might makes sense to use POSIX errno values, because
  342  * that is what the gdb/remote.c functions want to return.
  343  */
  344 int
  345 kgdb_trap(type, regs)
  346         int type;
  347         db_regs_t *regs;
  348 {
  349         label_t jmpbuf;
  350         vaddr_t addr;
  351         size_t len;
  352         u_char *p;
  353 
  354         if (kgdb_dev < 0 || kgdb_getc == NULL) {
  355                 /* not debugging */
  356                 return (0);
  357         }
  358 
  359         db_clear_single_step(regs);
  360 
  361         if (db_trap_callback) db_trap_callback(1);
  362 
  363         /* Detect and recover from unexpected traps. */
  364         if (kgdb_recover != 0) {
  365                 printf("kgdb: caught trap 0x%x at %p\n",
  366                            type, (void*)PC_REGS(regs));
  367                 kgdb_send("E0E"); /* 14==EFAULT */
  368                 longjmp(kgdb_recover);
  369         }
  370 
  371         /*
  372          * The first entry to this function is normally through
  373          * a breakpoint trap in kgdb_connect(), in which case we
  374          * must advance past the breakpoint because gdb will not.
  375          *
  376          * Machines vary as to where they leave the PC after a
  377          * breakpoint trap.  Those that leave the PC set to the
  378          * address of the trap instruction (i.e. pc532) will not
  379          * define FIXUP_PC_AFTER_BREAK(), and therefore will just
  380          * advance the PC.  On machines that leave the PC set to
  381          * the instruction after the trap, FIXUP_PC_AFTER_BREAK
  382          * will be defined to back-up the PC, so that after the
  383          * "first-time" part of the if statement below has run,
  384          * the PC will be the same as it was on entry.
  385          *
  386          * On the first entry here, we expect that gdb is not yet
  387          * listening to us, so just enter the interaction loop.
  388          * After the debugger is "active" (connected) it will be
  389          * waiting for a "signaled" message from us.
  390          */
  391         if (kgdb_active == 0) {
  392                 if (!IS_BREAKPOINT_TRAP(type, 0)) {
  393                         /* No debugger active -- let trap handle this. */
  394                         if (db_trap_callback) db_trap_callback(0);
  395                         return (0);
  396                 }
  397                 /* Make the PC point at the breakpoint... */
  398 #ifdef  FIXUP_PC_AFTER_BREAK
  399                 FIXUP_PC_AFTER_BREAK(regs);
  400 #endif
  401                 /* ... and then advance past it. */
  402 #ifdef  PC_ADVANCE
  403                 PC_ADVANCE(regs);
  404 #else
  405                 PC_REGS(regs) += BKPT_SIZE;
  406 #endif
  407                 kgdb_active = 1;
  408         } else {
  409                 /* Tell remote host that an exception has occurred. */
  410                 sprintf(buffer, "S%02x", kgdb_signal(type));
  411                 kgdb_send(buffer);
  412         }
  413 
  414         /* Stick frame regs into our reg cache. */
  415         kgdb_getregs(regs, gdb_regs);
  416 
  417         /*
  418          * Interact with gdb until it lets us go.
  419          * If we cause a trap, resume here.
  420          */
  421         (void)setjmp((kgdb_recover = &jmpbuf));
  422         for (;;) {
  423                 kgdb_recv(buffer, sizeof(buffer));
  424                 switch (buffer[0]) {
  425 
  426                 default:
  427                         /* Unknown command. */
  428                         kgdb_send("");
  429                         continue;
  430 
  431                 case KGDB_SIGNAL:
  432                         /*
  433                          * if this command came from a running gdb,
  434                          * answer it -- the other guy has no way of
  435                          * knowing if we're in or out of this loop
  436                          * when he issues a "remote-signal".
  437                          */
  438                         sprintf(buffer, "S%02x", kgdb_signal(type));
  439                         kgdb_send(buffer);
  440                         continue;
  441 
  442                 case KGDB_REG_R:
  443                         mem2hex(buffer, gdb_regs, sizeof(gdb_regs));
  444                         kgdb_send(buffer);
  445                         continue;
  446 
  447                 case KGDB_REG_W:
  448                         p = hex2mem(gdb_regs, buffer + 1, sizeof(gdb_regs));
  449                         if (p == NULL || *p != '\0')
  450                                 kgdb_send("E01");
  451                         else {
  452                                 kgdb_setregs(regs, gdb_regs);
  453                                 kgdb_send("OK");
  454                         }
  455                         continue;
  456 
  457                 case KGDB_MEM_R:
  458                         p = buffer + 1;
  459                         addr = hex2i(&p);
  460                         if (*p++ != ',') {
  461                                 kgdb_send("E02");
  462                                 continue;
  463                         }
  464                         len = hex2i(&p);
  465                         if (*p != '\0') {
  466                                 kgdb_send("E03");
  467                                 continue;
  468                         }
  469                         if (len > sizeof(buffer) / 2) {
  470                                 kgdb_send("E04");
  471                                 continue;
  472                         }
  473                         if (kgdb_acc(addr, len) == 0) {
  474                                 kgdb_send("E05");
  475                                 continue;
  476                         }
  477                         db_read_bytes(addr, (size_t)len,
  478                                         (char *)buffer + sizeof(buffer) / 2);
  479                         mem2hex(buffer, buffer + sizeof(buffer) / 2, len);
  480                         kgdb_send(buffer);
  481                         continue;
  482 
  483                 case KGDB_MEM_W:
  484                         p = buffer + 1;
  485                         addr = hex2i(&p);
  486                         if (*p++ != ',') {
  487                                 kgdb_send("E06");
  488                                 continue;
  489                         }
  490                         len = hex2i(&p);
  491                         if (*p++ != ':') {
  492                                 kgdb_send("E07");
  493                                 continue;
  494                         }
  495                         if (len > (sizeof(buffer) - (p - buffer))) {
  496                                 kgdb_send("E08");
  497                                 continue;
  498                         }
  499                         p = hex2mem(buffer, p, sizeof(buffer));
  500                         if (p == NULL) {
  501                                 kgdb_send("E09");
  502                                 continue;
  503                         }
  504                         if (kgdb_acc(addr, len) == 0) {
  505                                 kgdb_send("E0A");
  506                                 continue;
  507                         }
  508                         db_write_bytes(addr, (size_t)len, (char *)buffer);
  509                         kgdb_send("OK");
  510                         continue;
  511 
  512                 case KGDB_DETACH:
  513                 case KGDB_KILL:
  514                         kgdb_active = 0;
  515                         printf("kgdb detached\n");
  516                         db_clear_single_step(regs);
  517                         kgdb_send("OK");
  518                         goto out;
  519 
  520                 case KGDB_CONT:
  521                         if (buffer[1]) {
  522                                 p = buffer + 1;
  523                                 addr = hex2i(&p);
  524                                 if (*p) {
  525                                         kgdb_send("E0B");
  526                                         continue;
  527                                 }
  528                                 PC_REGS(regs) = addr;
  529                                 DPRINTF(("kgdb: continuing at %08lx\n", addr));
  530 
  531                         } else {
  532                                 DPRINTF((
  533                                   "kgdb: continuing at old address %08lx\n",
  534                                   (vaddr_t)PC_REGS(regs)));
  535                         }
  536 
  537                         db_clear_single_step(regs);
  538                         goto out;
  539 
  540                 case KGDB_STEP:
  541                         if (buffer[1]) {
  542                                 p = buffer + 1;
  543                                 addr = hex2i(&p);
  544                                 if (*p) {
  545                                         kgdb_send("E0B");
  546                                         continue;
  547                                 }
  548                                 PC_REGS(regs) = addr;
  549                         }
  550                         db_set_single_step(regs);
  551                         goto out;
  552                 }
  553         }
  554  out:
  555         if (db_trap_callback) db_trap_callback(0);
  556         kgdb_recover = 0;
  557         return (1);
  558 }

Cache object: 4064d6a1c8983ee0f81044d62eeba898


[ 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.