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