[BACK]Return to kgdb_stub.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kgdb_stub.c, Revision 1.1

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

CVSweb