1 /* 2 * Copyright (c) 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kgdb_stub.c 7.10 (Berkeley) 06/27/91 8 */ 9 /* 10 * "Stub" to allow remote cpu to debug over a serial line using gdb. 11 */ 12 #ifdef KGDB 13 #ifndef lint 14 static char rcsid[] = "$Header: kgdb_stub.c,v 1.13 91/03/23 13:55:57 mccanne Exp $"; 15 #endif 16 17 #include "param.h" 18 #include "systm.h" 19 #include "../include/trap.h" 20 #include "../include/cpu.h" 21 #include "../include/psl.h" 22 #include "../include/reg.h" 23 #include "../include/frame.h" 24 #include "buf.h" 25 #include "cons.h" 26 27 #include "kgdb_proto.h" 28 #include "machine/remote-sl.h" 29 30 extern int kernacc(); 31 extern void chgkprot(); 32 33 #ifndef KGDBDEV 34 #define KGDBDEV NODEV 35 #endif 36 #ifndef KGDBRATE 37 #define KGDBRATE 9600 38 #endif 39 40 dev_t kgdb_dev = KGDBDEV; /* remote debugging device (NODEV if none) */ 41 int kgdb_rate = KGDBRATE; /* remote debugging baud rate */ 42 int kgdb_active = 0; /* remote debugging active if != 0 */ 43 int kgdb_debug_init = 0; /* != 0 waits for remote at system init */ 44 int kgdb_debug_panic = 1; /* != 0 waits for remote on panic */ 45 int kgdb_debug = 0; 46 47 #define GETC ((*kgdb_getc)(kgdb_dev)) 48 #define PUTC(c) ((*kgdb_putc)(kgdb_dev, c)) 49 #define PUTESC(c) { \ 50 if (c == FRAME_END) { \ 51 PUTC(FRAME_ESCAPE); \ 52 c = TRANS_FRAME_END; \ 53 } else if (c == FRAME_ESCAPE) { \ 54 PUTC(FRAME_ESCAPE); \ 55 c = TRANS_FRAME_ESCAPE; \ 56 } \ 57 PUTC(c); \ 58 } 59 60 static int (*kgdb_getc)(); 61 static int (*kgdb_putc)(); 62 63 /* 64 * Send a message. The host gets one chance to read it. 65 */ 66 static void 67 kgdb_send(type, bp, len) 68 register u_char type; 69 register u_char *bp; 70 register int len; 71 { 72 register u_char csum; 73 register u_char *ep = bp + len; 74 75 csum = type; 76 PUTESC(type) 77 78 while (bp < ep) { 79 type = *bp++; 80 csum += type; 81 PUTESC(type) 82 } 83 csum = -csum; 84 PUTESC(csum) 85 PUTC(FRAME_END); 86 } 87 88 static int 89 kgdb_recv(bp, lenp) 90 u_char *bp; 91 int *lenp; 92 { 93 register u_char c, csum; 94 register int escape, len; 95 register int type; 96 97 csum = len = escape = 0; 98 type = -1; 99 while (1) { 100 c = GETC; 101 switch (c) { 102 103 case FRAME_ESCAPE: 104 escape = 1; 105 continue; 106 107 case TRANS_FRAME_ESCAPE: 108 if (escape) 109 c = FRAME_ESCAPE; 110 break; 111 112 case TRANS_FRAME_END: 113 if (escape) 114 c = FRAME_END; 115 break; 116 117 case FRAME_END: 118 if (type < 0 || --len < 0) { 119 csum = len = escape = 0; 120 type = -1; 121 continue; 122 } 123 if (csum != 0) { 124 return (0); 125 } 126 *lenp = len; 127 return type; 128 } 129 csum += c; 130 if (type < 0) { 131 type = c; 132 escape = 0; 133 continue; 134 } 135 if (++len > SL_BUFSIZE) { 136 while (GETC != FRAME_END) 137 ; 138 return (0); 139 } 140 *bp++ = c; 141 escape = 0; 142 } 143 } 144 145 /* 146 * Translate a trap number into a unix compatible signal value. 147 * (gdb only understands unix signal numbers). 148 */ 149 static int 150 computeSignal(type) 151 int type; 152 { 153 int sigval; 154 155 switch (type) { 156 case T_BUSERR: 157 sigval = SIGBUS; 158 break; 159 case T_ADDRERR: 160 sigval = SIGBUS; 161 break; 162 case T_ILLINST: 163 sigval = SIGILL; 164 break; 165 case T_ZERODIV: 166 sigval = SIGFPE; 167 break; 168 case T_CHKINST: 169 sigval = SIGFPE; 170 break; 171 case T_TRAPVINST: 172 sigval = SIGFPE; 173 break; 174 case T_PRIVINST: 175 sigval = SIGILL; 176 break; 177 case T_TRACE: 178 sigval = SIGTRAP; 179 break; 180 case T_MMUFLT: 181 sigval = SIGSEGV; 182 break; 183 case T_SSIR: 184 sigval = SIGSEGV; 185 break; 186 case T_FMTERR: 187 sigval = SIGILL; 188 break; 189 case T_FPERR: 190 sigval = SIGFPE; 191 break; 192 case T_COPERR: 193 sigval = SIGFPE; 194 break; 195 case T_ASTFLT: 196 sigval = SIGINT; 197 break; 198 case T_TRAP15: 199 sigval = SIGTRAP; 200 break; 201 default: 202 sigval = SIGEMT; 203 break; 204 } 205 return (sigval); 206 } 207 208 /* 209 * Trap into kgdb to wait for debugger to connect, 210 * noting on the console why nothing else is going on. 211 */ 212 kgdb_connect(verbose) 213 int verbose; 214 { 215 216 if (verbose) 217 printf("kgdb waiting..."); 218 /* trap into kgdb */ 219 asm("trap #15;"); 220 if (verbose) 221 printf("connected.\n"); 222 } 223 224 /* 225 * Decide what to do on panic. 226 */ 227 kgdb_panic() 228 { 229 230 if (kgdb_active == 0 && kgdb_debug_panic && kgdb_dev != NODEV) 231 kgdb_connect(1); 232 } 233 234 /* 235 * Definitions exported from gdb. 236 */ 237 #define NUM_REGS 18 238 #define REGISTER_BYTES ((16+2)*4) 239 #define REGISTER_BYTE(N) ((N)*4) 240 241 #define GDB_SR 16 242 #define GDB_PC 17 243 244 static inline void 245 kgdb_copy(register u_char *src, register u_char *dst, register u_int nbytes) 246 { 247 register u_char *ep = src + nbytes; 248 249 while (src < ep) 250 *dst++ = *src++; 251 } 252 253 #define regs_to_gdb(fp, regs) \ 254 (kgdb_copy((u_char *)((fp)->f_regs), (u_char *)(regs), REGISTER_BYTES)) 255 256 #define gdb_to_regs(fp, regs) \ 257 (kgdb_copy((u_char *)(regs), (u_char *)((fp)->f_regs), REGISTER_BYTES)) 258 259 static u_long reg_cache[NUM_REGS]; 260 static u_char inbuffer[SL_BUFSIZE]; 261 static u_char outbuffer[SL_BUFSIZE]; 262 263 /* 264 * This function does all command procesing for interfacing to 265 * a remote gdb. 266 */ 267 int 268 kgdb_trap(int type, struct frame *frame) 269 { 270 register u_long len; 271 u_char *addr; 272 register u_char *cp; 273 register u_char out, in; 274 register int outlen; 275 int inlen; 276 u_long gdb_regs[NUM_REGS]; 277 278 if (kgdb_dev < 0) { 279 /* not debugging */ 280 return (0); 281 } 282 if (kgdb_active == 0) { 283 if (type != T_TRAP15) { 284 /* No debugger active -- let trap handle this. */ 285 return (0); 286 } 287 kgdb_getc = 0; 288 for (inlen = 0; constab[inlen].cn_probe; inlen++) 289 if (major(constab[inlen].cn_dev) == major(kgdb_dev)) { 290 kgdb_getc = constab[inlen].cn_getc; 291 kgdb_putc = constab[inlen].cn_putc; 292 break; 293 } 294 if (kgdb_getc == 0 || kgdb_putc == 0) 295 return (0); 296 /* 297 * If the packet that woke us up isn't an exec packet, 298 * ignore it since there is no active debugger. Also, 299 * we check that it's not an ack to be sure that the 300 * remote side doesn't send back a response after the 301 * local gdb has exited. Otherwise, the local host 302 * could trap into gdb if it's running a gdb kernel too. 303 */ 304 in = GETC; 305 /* 306 * If we came in asynchronously through the serial line, 307 * the framing character is eaten by the receive interrupt, 308 * but if we come in through a synchronous trap (i.e., via 309 * kgdb_connect()), we will see the extra character. 310 */ 311 if (in == FRAME_END) 312 in = GETC; 313 314 if (KGDB_CMD(in) != KGDB_EXEC || (in & KGDB_ACK) != 0) 315 return (0); 316 while (GETC != FRAME_END) 317 ; 318 /* 319 * Do the printf *before* we ack the message. This way 320 * we won't drop any inbound characters while we're 321 * doing the polling printf. 322 */ 323 printf("kgdb started from device %x\n", kgdb_dev); 324 kgdb_send(in | KGDB_ACK, (u_char *)0, 0); 325 kgdb_active = 1; 326 } 327 /* 328 * Stick frame regs into our reg cache then tell remote host 329 * that an exception has occured. 330 */ 331 regs_to_gdb(frame, gdb_regs); 332 if (type != T_TRAP15) { 333 /* 334 * Only send an asynchronous SIGNAL message when we hit 335 * a breakpoint. Otherwise, we will drop the incoming 336 * packet while we output this one (and on entry the other 337 * side isn't interested in the SIGNAL type -- if it is, 338 * it will have used a signal packet.) 339 */ 340 outbuffer[0] = computeSignal(type); 341 kgdb_send(KGDB_SIGNAL, outbuffer, 1); 342 } 343 344 while (1) { 345 in = kgdb_recv(inbuffer, &inlen); 346 if (in == 0 || (in & KGDB_ACK)) 347 /* Ignore inbound acks and error conditions. */ 348 continue; 349 350 out = in | KGDB_ACK; 351 switch (KGDB_CMD(in)) { 352 353 case KGDB_SIGNAL: 354 /* 355 * if this command came from a running gdb, 356 * answer it -- the other guy has no way of 357 * knowing if we're in or out of this loop 358 * when he issues a "remote-signal". (Note 359 * that without the length check, we could 360 * loop here forever if the ourput line is 361 * looped back or the remote host is echoing.) 362 */ 363 if (inlen == 0) { 364 outbuffer[0] = computeSignal(type); 365 kgdb_send(KGDB_SIGNAL, outbuffer, 1); 366 } 367 continue; 368 369 case KGDB_REG_R: 370 case KGDB_REG_R | KGDB_DELTA: 371 cp = outbuffer; 372 outlen = 0; 373 for (len = inbuffer[0]; len < NUM_REGS; ++len) { 374 if (reg_cache[len] != gdb_regs[len] || 375 (in & KGDB_DELTA) == 0) { 376 if (outlen + 5 > SL_MAXMSG) { 377 out |= KGDB_MORE; 378 break; 379 } 380 cp[outlen] = len; 381 kgdb_copy((u_char *)&gdb_regs[len], 382 &cp[outlen + 1], 4); 383 reg_cache[len] = gdb_regs[len]; 384 outlen += 5; 385 } 386 } 387 break; 388 389 case KGDB_REG_W: 390 case KGDB_REG_W | KGDB_DELTA: 391 cp = inbuffer; 392 for (len = 0; len < inlen; len += 5) { 393 register int j = cp[len]; 394 395 kgdb_copy(&cp[len + 1], 396 (u_char *)&gdb_regs[j], 4); 397 reg_cache[j] = gdb_regs[j]; 398 } 399 gdb_to_regs(frame, gdb_regs); 400 outlen = 0; 401 break; 402 403 case KGDB_MEM_R: 404 len = inbuffer[0]; 405 kgdb_copy(&inbuffer[1], (u_char *)&addr, 4); 406 if (len + 1 > SL_MAXMSG) { 407 outlen = 1; 408 outbuffer[0] = E2BIG; 409 } else if (!kgdb_acc(addr, len, B_READ)) { 410 outlen = 1; 411 outbuffer[0] = EFAULT; 412 } else { 413 outlen = len + 1; 414 outbuffer[0] = 0; 415 kgdb_copy(addr, &outbuffer[1], len); 416 } 417 break; 418 419 case KGDB_MEM_W: 420 len = inlen - 4; 421 kgdb_copy(inbuffer, (u_char *)&addr, 4); 422 outlen = 1; 423 if (!kgdb_acc(addr, len, B_READ)) 424 outbuffer[0] = EFAULT; 425 else { 426 outbuffer[0] = 0; 427 if (!kgdb_acc(addr, len, B_WRITE)) 428 chgkprot(addr, len, B_WRITE); 429 kgdb_copy(&inbuffer[4], addr, len); 430 } 431 break; 432 433 case KGDB_KILL: 434 kgdb_active = 0; 435 printf("kgdb detached\n"); 436 /* fall through */ 437 case KGDB_CONT: 438 kgdb_send(out, 0, 0); 439 frame->f_sr &=~ PSL_T; 440 return (1); 441 442 case KGDB_STEP: 443 kgdb_send(out, 0, 0); 444 frame->f_sr |= PSL_T; 445 return (1); 446 447 case KGDB_EXEC: 448 default: 449 /* Unknown command. Ack with a null message. */ 450 outlen = 0; 451 break; 452 } 453 /* Send the reply */ 454 kgdb_send(out, outbuffer, outlen); 455 } 456 } 457 458 /* 459 * XXX do kernacc call if safe, otherwise attempt 460 * to simulate by simple bounds-checking. 461 */ 462 kgdb_acc(addr, len, rw) 463 caddr_t addr; 464 { 465 extern char proc0paddr[], kstack[]; /* XXX */ 466 extern char *kernel_map; /* XXX! */ 467 468 if (kernel_map != NULL) 469 return (kernacc(addr, len, rw)); 470 if (addr < proc0paddr + UPAGES * NBPG || 471 kstack <= addr && addr < kstack + UPAGES * NBPG) 472 return (1); 473 return (0); 474 } 475 #endif 476