Annotation of 43BSDReno/sys/hp300/kgdb_stub.c, revision 1.1.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.