|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.