Annotation of 43BSDReno/sys/hp300/kgdb_stub.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             9:  *
        !            10:  * Redistribution is only permitted until one year after the first shipment
        !            11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            12:  * binary forms are permitted provided that: (1) source distributions retain
        !            13:  * this entire copyright notice and comment, and (2) distributions including
        !            14:  * binaries display the following acknowledgement:  This product includes
        !            15:  * software developed by the University of California, Berkeley and its
        !            16:  * contributors'' in the documentation or other materials provided with the
        !            17:  * distribution and in all advertising materials mentioning features or use
        !            18:  * of this software.  Neither the name of the University nor the names of
        !            19:  * its contributors may be used to endorse or promote products derived from
        !            20:  * this software without specific prior written permission.
        !            21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            24:  *
        !            25:  *     @(#)kgdb_stub.c 7.3 (Berkeley) 6/22/90
        !            26:  */
        !            27: 
        !            28: /*
        !            29:  *
        !            30:  *    The following gdb commands are supported:
        !            31:  *
        !            32:  * command          function                               Return value
        !            33:  *
        !            34:  *    g             return the value of the CPU registers  hex data or ENN
        !            35:  *    G             set the value of the CPU registers     OK or ENN
        !            36:  *
        !            37:  *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
        !            38:  *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
        !            39:  *
        !            40:  *    c             Resume at current address              SNN   ( signal NN)
        !            41:  *    cAA..AA       Continue at address AA..AA             SNN
        !            42:  *
        !            43:  *    s             Step one instruction                   SNN
        !            44:  *    sAA..AA       Step one instruction from AA..AA       SNN
        !            45:  *
        !            46:  *    k             kill
        !            47:  *
        !            48:  *    ?             What was the last sigval ?             SNN   (signal NN)
        !            49:  *
        !            50:  * All commands and responses are sent with a packet which includes a
        !            51:  * checksum.  A packet consists of
        !            52:  *
        !            53:  * $<packet info>#<checksum>.
        !            54:  *
        !            55:  * where
        !            56:  * <packet info> :: <characters representing the command or response>
        !            57:  * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
        !            58:  *
        !            59:  * When a packet is received, it is first acknowledged with either '+' or '-'.
        !            60:  * '+' indicates a successful transfer.  '-' indicates a failed transfer.
        !            61:  *
        !            62:  * Example:
        !            63:  *
        !            64:  * Host:                  Reply:
        !            65:  * $m0,10#2a               +$00010203040506070809101112131415#42
        !            66:  *
        !            67:  ****************************************************************************/
        !            68: 
        !            69: #ifdef KGDB
        !            70: #include "param.h"
        !            71: #include "systm.h"
        !            72: #include "trap.h"
        !            73: #include "cpu.h"
        !            74: #include "psl.h"
        !            75: #include "reg.h"
        !            76: #include "frame.h"
        !            77: #include "buf.h"
        !            78: 
        !            79: extern void printf();
        !            80: extern void bcopy();
        !            81: extern int kernacc();
        !            82: extern void chgkprot();
        !            83: 
        !            84: /* # of additional (beyond 4) bytes in 680x0 exception frame format n */
        !            85: static int frame_bytes[16] = {
        !            86:        4,      4,      8,      4,
        !            87:        4,      4,      4,      4,
        !            88:        54,     16,     28,     88,
        !            89:        4,      4,      4,      4
        !            90: };
        !            91: 
        !            92: #define USER    040             /* (XXX from trap.c) user-mode flag in type */
        !            93: 
        !            94: /*
        !            95:  * BUFMAX defines the maximum number of characters in inbound/outbound
        !            96:  * buffers.  At least NUMREGBYTES*2 are needed for register packets.
        !            97:  */
        !            98: #define BUFMAX 512
        !            99: 
        !           100: #ifndef KGDBDEV
        !           101: #define KGDBDEV -1
        !           102: #endif
        !           103: #ifndef KGDBRATE
        !           104: #define KGDBRATE 9600
        !           105: #endif
        !           106: 
        !           107: int kgdb_dev = KGDBDEV;                /* remote debugging device (-1 if none) */
        !           108: int kgdb_rate = KGDBRATE;      /* remote debugging baud rate */
        !           109: int kgdb_debug_init = 0;       /* != 0 waits for remote at system init */
        !           110: int kgdb_debug = 0;            /* > 0 prints command & checksum errors */
        !           111: 
        !           112: #include "../hp300/cons.h"
        !           113: 
        !           114: #define GETC   \
        !           115:        (constab[major(kgdb_dev)].cn_getc ? \
        !           116:                (*constab[major(kgdb_dev)].cn_getc)(kgdb_dev) : 0)
        !           117: #define PUTC(c)        { \
        !           118:        if (constab[major(kgdb_dev)].cn_putc) \
        !           119:                (*constab[major(kgdb_dev)].cn_putc)(kgdb_dev, c); \
        !           120: }
        !           121: 
        !           122: static char hexchars[] = "0123456789abcdef";
        !           123: 
        !           124: /*
        !           125:  * There are 180 bytes of registers on a 68020 w/68881.  Many of the fpa
        !           126:  * registers are 12 byte (96 bit) registers.
        !           127:  */
        !           128: #define NUMREGBYTES 180
        !           129: 
        !           130: static char inbuffer[BUFMAX];
        !           131: static char outbuffer[BUFMAX];
        !           132: 
        !           133: static inline int 
        !           134: hex(ch)
        !           135:        char ch;
        !           136: {
        !           137:        if ((ch >= '0') && (ch <= '9'))
        !           138:                return (ch - '0');
        !           139:        if ((ch >= 'a') && (ch <= 'f'))
        !           140:                return (ch - ('a' - 10));
        !           141:        return (0);
        !           142: }
        !           143: 
        !           144: /* scan for the sequence $<data>#<checksum>     */
        !           145: static void 
        !           146: getpacket(char *buffer)
        !           147: {
        !           148:        unsigned char checksum;
        !           149:        unsigned char xmitcsum;
        !           150:        int i;
        !           151:        int count;
        !           152:        char ch;
        !           153: 
        !           154:        do {
        !           155:                /*
        !           156:                 * wait around for the start character, ignore all other
        !           157:                 * characters
        !           158:                 */
        !           159:                while ((ch = GETC) != '$')
        !           160:                        ;
        !           161:                checksum = 0;
        !           162:                count = 0;
        !           163:                xmitcsum = 1;
        !           164: 
        !           165:                /* now, read until a # or end of buffer is found */
        !           166:                while (count < BUFMAX) {
        !           167:                        ch = GETC;
        !           168:                        if (ch == '#')
        !           169:                                break;
        !           170:                        checksum = checksum + ch;
        !           171:                        buffer[count] = ch;
        !           172:                        count = count + 1;
        !           173:                }
        !           174:                buffer[count] = 0;
        !           175: 
        !           176:                if (ch == '#') {
        !           177:                        xmitcsum = hex(GETC) << 4;
        !           178:                        xmitcsum += hex(GETC);
        !           179:                        if (kgdb_debug && (checksum != xmitcsum)) {
        !           180:                                printf(
        !           181:                        "bad checksum.  My count = 0x%x, sent=0x%x. buf=%s\n",
        !           182:                                        checksum, xmitcsum, buffer);
        !           183:                        }
        !           184:                        if (checksum != xmitcsum) {
        !           185:                                PUTC('-');      /* failed checksum */
        !           186:                        } else {
        !           187:                                PUTC('+');      /* successful transfer */
        !           188:                                /*
        !           189:                                 * if a sequence char is present, reply the
        !           190:                                 * sequence ID
        !           191:                                 */
        !           192:                                if (buffer[2] == ':') {
        !           193:                                        PUTC(buffer[0]);
        !           194:                                        PUTC(buffer[1]);
        !           195:                                        /* remove sequence chars from buffer */
        !           196:                                        for (i = 3; i <= count; ++i)
        !           197:                                                buffer[i - 3] = buffer[i];
        !           198:                                }
        !           199:                        }
        !           200:                }
        !           201:        } while (checksum != xmitcsum);
        !           202: }
        !           203: 
        !           204: /*
        !           205:  * send the packet in buffer.  The host gets one chance to read it.  This
        !           206:  * routine does not wait for a positive acknowledge.
        !           207:  */
        !           208: static void 
        !           209: putpacket(char *buffer)
        !           210: {
        !           211:        unsigned char checksum;
        !           212:        int count;
        !           213:        char ch;
        !           214: 
        !           215:        /* $<packet info>#<checksum>. */
        !           216:        do {
        !           217:                PUTC('$');
        !           218:                checksum = 0;
        !           219:                count = 0;
        !           220: 
        !           221:                while (ch = buffer[count]) {
        !           222:                        PUTC(ch);
        !           223:                        checksum += ch;
        !           224:                        count += 1;
        !           225:                }
        !           226:                PUTC('#');
        !           227:                PUTC(hexchars[checksum >> 4]);
        !           228:                PUTC(hexchars[checksum & 15]);
        !           229: 
        !           230:        } while (0);    /* (GETC != '+'); */
        !           231: 
        !           232: }
        !           233: 
        !           234: static inline void 
        !           235: debug_error(char *format, char *parm)
        !           236: {
        !           237:        if (kgdb_debug)
        !           238:                printf(format, parm);
        !           239: }
        !           240: 
        !           241: /*
        !           242:  * Convert at most 'dig' digits of hex data in buf into a value.
        !           243:  * Stop on non-hex char.  Return a pointer to next char in buf.
        !           244:  */
        !           245: static char *
        !           246: hex2val(char *buf, int *val, int dig)
        !           247: {
        !           248:        int i, v;
        !           249:        char ch;
        !           250: 
        !           251:        v = 0;
        !           252:        for (i = dig; --i >= 0; ) {
        !           253:                ch = *buf++;
        !           254:                if ((ch >= '0') && (ch <= '9'))
        !           255:                        v = (v << 4) | (ch - '0');
        !           256:                else if ((ch >= 'a') && (ch <= 'f'))
        !           257:                        v = (v << 4) | (ch - ('a' - 10));
        !           258:                else {
        !           259:                        --buf;
        !           260:                        break;
        !           261:                }
        !           262:        }
        !           263:        *val = v;
        !           264:        return (buf);
        !           265: }
        !           266: 
        !           267: /*
        !           268:  * convert the integer value 'val' into 'dig' hex digits, placing
        !           269:  * result in buf.  Return a pointer to the last char put in buf (null).
        !           270:  */
        !           271: static char *
        !           272: val2hex(char *buf, int val, int dig)
        !           273: {
        !           274:        for (dig <<= 2; (dig -= 4) >= 0; )
        !           275:                *buf++ = hexchars[(val >> dig) & 0xf];
        !           276:        *buf = 0;
        !           277:        return (buf);
        !           278: }
        !           279: 
        !           280: /*
        !           281:  * convert the memory pointed to by mem into hex, placing result in buf.
        !           282:  * return a pointer to the last char put in buf (null).
        !           283:  */
        !           284: static char *
        !           285: mem2hex(char *buf, char *mem, int count)
        !           286: {
        !           287:        if ((count & 1) || ((int)mem & 1)) {
        !           288:                char ch;
        !           289: 
        !           290:                while(--count >= 0) {
        !           291:                        ch = *mem++;
        !           292:                        *buf++ = hexchars[ch >> 4];
        !           293:                        *buf++ = hexchars[ch & 15];
        !           294:                }
        !           295:        } else {
        !           296:                u_short s;
        !           297:                u_short *mp = (u_short *)mem;
        !           298: 
        !           299:                for (count >>= 1; --count >= 0; ) {
        !           300:                        s = *mp++;
        !           301:                        *buf++ = hexchars[(s >> 12) & 15];
        !           302:                        *buf++ = hexchars[(s >> 8) & 15];
        !           303:                        *buf++ = hexchars[(s >> 4) & 15];
        !           304:                        *buf++ = hexchars[s & 15];
        !           305:                }
        !           306:        }
        !           307:        *buf = 0;
        !           308:        return (buf);
        !           309: }
        !           310: 
        !           311: /*
        !           312:  * Convert the hex array pointed to by buf into binary to be placed in mem.
        !           313:  * Return a pointer to next char in buf.
        !           314:  */
        !           315: static char *
        !           316: hex2mem(char *buf, char *mem, int count)
        !           317: {
        !           318:        int i;
        !           319:        unsigned char ch;
        !           320: 
        !           321:        for (i = 0; i < count; ++i) {
        !           322:                ch = hex(*buf++) << 4;
        !           323:                ch = ch + hex(*buf++);
        !           324:                *mem++ = ch;
        !           325:        }
        !           326:        return (buf);
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Translate a trap number into a unix compatible signal value.
        !           331:  * (gdb only understands unix signal numbers).
        !           332:  */
        !           333: static int 
        !           334: computeSignal(int type)
        !           335: {
        !           336:        int sigval;
        !           337: 
        !           338:        switch (type &~ USER) {
        !           339:        case T_BUSERR:
        !           340:                sigval = SIGBUS;
        !           341:                break;          /* bus error           */
        !           342:        case T_ADDRERR:
        !           343:                sigval = SIGBUS;
        !           344:                break;          /* address error       */
        !           345:        case T_ILLINST:
        !           346:                sigval = SIGILL;
        !           347:                break;          /* illegal instruction */
        !           348:        case T_ZERODIV:
        !           349:                sigval = SIGFPE;
        !           350:                break;          /* zero divide         */
        !           351:        case T_CHKINST:
        !           352:                sigval = SIGFPE;
        !           353:                break;          /* chk instruction     */
        !           354:        case T_TRAPVINST:
        !           355:                sigval = SIGFPE;
        !           356:                break;          /* trapv instruction   */
        !           357:        case T_PRIVINST:
        !           358:                sigval = SIGILL;
        !           359:                break;          /* privilege violation */
        !           360:        case T_TRACE:
        !           361:                sigval = SIGTRAP;
        !           362:                break;          /* trace trap          */
        !           363:        case T_MMUFLT:
        !           364:                sigval = SIGSEGV;
        !           365:                break;
        !           366:        case T_SSIR:
        !           367:                sigval = SIGSEGV;
        !           368:                break;
        !           369:        case T_FMTERR:
        !           370:                sigval = SIGILL;
        !           371:                break;
        !           372:        case T_FPERR:
        !           373:                sigval = SIGFPE;
        !           374:                break;
        !           375:        case T_COPERR:
        !           376:                sigval = SIGFPE;
        !           377:                break;
        !           378:        case T_ASTFLT:
        !           379:                sigval = SIGINT;
        !           380:                break;
        !           381:        case T_TRAP15:
        !           382:                sigval = SIGIOT;
        !           383:                break;
        !           384:        default:
        !           385:                sigval = SIGEMT;
        !           386:                break;
        !           387:        }
        !           388:        return (sigval);
        !           389: }
        !           390: 
        !           391: #define RESPOND(str) (bcopy(str, outbuffer, sizeof(str)))
        !           392: 
        !           393: /*
        !           394:  * This function does all command procesing for interfacing to 
        !           395:  * a remote gdb.
        !           396:  */
        !           397: int 
        !           398: kgdb_trap(int type, unsigned code, unsigned v, struct frame *frame)
        !           399: {
        !           400:        int sigval;
        !           401:        int addr, length;
        !           402:        char *ptr;
        !           403: 
        !           404:        if (kgdb_dev < 0)
        !           405:                /* not debugging */
        !           406:                return (0);
        !           407: 
        !           408:        if (kgdb_debug)
        !           409:                printf("type=%d, code=%d, vector=0x%x, pc=0x%x, sr=0x%x\n",
        !           410:                        type, code, frame->f_vector, frame->f_pc, frame->f_sr);
        !           411: 
        !           412:        /* reply to host that an exception has occurred */
        !           413:        sigval = computeSignal(type);
        !           414:        outbuffer[0] = 'S';
        !           415:        (void)val2hex(&outbuffer[1], sigval, 2);
        !           416:        putpacket(outbuffer);
        !           417: 
        !           418:        while (1) {
        !           419:                outbuffer[0] = 0;
        !           420:                getpacket(inbuffer);
        !           421:                ptr = inbuffer;
        !           422:                switch (*ptr++) {
        !           423:                case '?':
        !           424:                        outbuffer[0] = 'S';
        !           425:                        (void)val2hex(&outbuffer[1], sigval, 2);
        !           426:                        break;
        !           427:                case 'g':       /* return the value of the CPU registers */
        !           428:                        ptr = outbuffer;
        !           429:                        if (type & USER)
        !           430:                                ptr = mem2hex(ptr, (char *)frame->f_regs,
        !           431:                                              sizeof(frame->f_regs));
        !           432:                        else {
        !           433:                                ptr = mem2hex(ptr, (char *)frame->f_regs,
        !           434:                                              sizeof(frame->f_regs) - 4);
        !           435:                                addr = (int)&frame->f_pc -
        !           436:                                        frame_bytes[frame->f_format];
        !           437:                                ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
        !           438:                        }
        !           439:                        addr = frame->f_sr;
        !           440:                        ptr = mem2hex(ptr, (char *)&addr, sizeof(addr));
        !           441:                        ptr = mem2hex(ptr, (char *)&frame->f_pc,
        !           442:                                      sizeof(frame->f_pc));
        !           443:                        break;
        !           444:                case 'G':       /* set the value of the CPU registers */
        !           445:                        ptr = hex2mem(ptr, (char *)frame->f_regs,
        !           446:                                      sizeof(frame->f_regs) - 4);
        !           447:                        ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
        !           448:                        ptr = hex2mem(ptr, (char *)&addr, sizeof(addr));
        !           449:                        frame->f_sr = addr;
        !           450:                        ptr = hex2mem(ptr, (char *)&frame->f_pc,
        !           451:                                      sizeof(frame->f_pc));
        !           452:                        RESPOND("OK");
        !           453:                        break;
        !           454: 
        !           455:                        /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
        !           456:                case 'm':
        !           457:                        ptr = hex2val(ptr, &addr, 8);
        !           458:                        if (*ptr++ != ',') {
        !           459:                                RESPOND("E01");
        !           460:                                debug_error("malformed read memory cmd: %s\n",
        !           461:                                            inbuffer);
        !           462:                                break;
        !           463:                        }
        !           464:                        ptr = hex2val(ptr, &length, 8);
        !           465:                        if (length <= 0 || length >= BUFMAX*2) {
        !           466:                                RESPOND("E02");
        !           467:                                if (kgdb_debug)
        !           468:                                        printf("bad read memory length: %d\n",
        !           469:                                               length);
        !           470:                                break;
        !           471:                        }
        !           472:                        if (! kernacc(addr, length, B_READ)) {
        !           473:                                RESPOND("E03");
        !           474:                                if (kgdb_debug)
        !           475:                                        printf("read access violation addr 0x%x len %d\n", addr, length);
        !           476:                                break;
        !           477:                        }
        !           478:                        (void)mem2hex(outbuffer, (char *)addr, length);
        !           479:                        break;
        !           480: 
        !           481:                        /*
        !           482:                         * MAA..AA,LLLL: Write LLLL bytes at address AA.AA
        !           483:                         * return OK
        !           484:                         */
        !           485:                case 'M':
        !           486:                        ptr = hex2val(ptr, &addr, 8);
        !           487:                        if (*ptr++ != ',') {
        !           488:                                RESPOND("E01");
        !           489:                                debug_error("malformed write memory cmd: %s\n",
        !           490:                                            inbuffer);
        !           491:                                break;
        !           492:                        }
        !           493:                        ptr = hex2val(ptr, &length, 8);
        !           494:                        if (*ptr++ != ':') {
        !           495:                                RESPOND("E01");
        !           496:                                debug_error("malformed write memory cmd: %s\n",
        !           497:                                            inbuffer);
        !           498:                                break;
        !           499:                        }
        !           500:                        if (length <= 0 || length >= BUFMAX*2 - 32) {
        !           501:                                RESPOND("E02");
        !           502:                                if (kgdb_debug)
        !           503:                                        printf("bad write memory length: %d\n",
        !           504:                                               length);
        !           505:                                break;
        !           506:                        }
        !           507:                        if (! kernacc(addr, length, B_READ)) {
        !           508:                                RESPOND("E03");
        !           509:                                if (kgdb_debug)
        !           510:                                        printf("write access violation addr 0x%x len %d\n", addr, length);
        !           511:                                break;
        !           512:                        }
        !           513:                        if (! kernacc(addr, length, B_WRITE))
        !           514:                                chgkprot(addr, length, B_WRITE);
        !           515:                        (void)hex2mem(ptr, (char *)addr, length);
        !           516:                        RESPOND("OK");
        !           517:                        break;
        !           518: 
        !           519:                        /*
        !           520:                         * cAA..AA  Continue at address AA..AA
        !           521:                         * sAA..AA  Step one instruction from AA..AA
        !           522:                         * (addresses optional)
        !           523:                         */
        !           524:                case 'c':
        !           525:                case 's':
        !           526:                        /*
        !           527:                         * try to read optional start address.
        !           528:                         */
        !           529:                        if (ptr != hex2val(ptr, &addr, 8)) {
        !           530:                                frame->f_pc = addr;
        !           531:                                if (kgdb_debug)
        !           532:                                        printf("new pc = 0x%x\n", addr);
        !           533:                        }
        !           534:                        /* deal with the trace bit */
        !           535:                        if (inbuffer[0] == 's')
        !           536:                                frame->f_sr |= PSL_T;
        !           537:                        else
        !           538:                                frame->f_sr &=~ PSL_T;
        !           539: 
        !           540:                        if (kgdb_debug)
        !           541:                                printf("restarting at 0x%x\n", frame->f_pc);
        !           542: 
        !           543:                        return (1);
        !           544: 
        !           545:                        /* kill the program (same as continue for now) */
        !           546:                case 'k':
        !           547:                        return (1);
        !           548:                }
        !           549:                /* reply to the request */
        !           550:                putpacket(outbuffer);
        !           551:        }
        !           552: }
        !           553: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.