1 /**************************************************************************** 2 3 THIS SOFTWARE IS NOT COPYRIGHTED 4 5 HP offers the following for use in the public domain. HP makes no 6 warranty with regard to the software or its performance and the 7 user accepts the software "AS IS" with all faults. 8 9 HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD 10 TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES 11 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12 13 ****************************************************************************/ 14 15 /**************************************************************************** 16 * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ 17 * 18 * Module name: remcom.c $ 19 * Revision: 1.34 $ 20 * Date: 91/03/09 12:29:49 $ 21 * Contributor: Lake Stevens Instrument Division$ 22 * 23 * Description: low level support for gdb debugger. $ 24 * 25 * Considerations: only works on target hardware $ 26 * 27 * Written by: Glenn Engel $ 28 * ModuleState: Experimental $ 29 * 30 * NOTES: See Below $ 31 * 32 * Modified for FreeBSD by Stu Grossman. 33 * 34 * To enable debugger support, two things need to happen. One, a 35 * call to set_debug_traps() is necessary in order to allow any breakpoints 36 * or error conditions to be properly intercepted and reported to gdb. 37 * Two, a breakpoint needs to be generated to begin communication. This 38 * is most easily accomplished by a call to breakpoint(). Breakpoint() 39 * simulates a breakpoint by executing a trap #1. 40 * 41 * The external function exceptionHandler() is 42 * used to attach a specific handler to a specific 386 vector number. 43 * It should use the same privilege level it runs at. It should 44 * install it as an interrupt gate so that interrupts are masked 45 * while the handler runs. 46 * Also, need to assign exceptionHook and oldExceptionHook. 47 * 48 * Because gdb will sometimes write to the stack area to execute function 49 * calls, this program cannot rely on using the supervisor stack so it 50 * uses its own stack area reserved in the int array remcomStack. 51 * 52 ************* 53 * 54 * The following gdb commands are supported: 55 * 56 * command function Return value 57 * 58 * g return the value of the CPU registers hex data or ENN 59 * G set the value of the CPU registers OK or ENN 60 * 61 * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN 62 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN 63 * 64 * c Resume at current address SNN ( signal NN) 65 * cAA..AA Continue at address AA..AA SNN 66 * 67 * s Step one instruction SNN 68 * sAA..AA Step one instruction from AA..AA SNN 69 * 70 * k kill 71 * 72 * ? What was the last sigval ? SNN (signal NN) 73 * 74 * D detach OK 75 * 76 * All commands and responses are sent with a packet which includes a 77 * checksum. A packet consists of 78 * 79 * $<packet info>#<checksum>. 80 * 81 * where 82 * <packet info> :: <characters representing the command or response> 83 * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> 84 * 85 * When a packet is received, it is first acknowledged with either '+' or '-'. 86 * '+' indicates a successful transfer. '-' indicates a failed transfer. 87 * 88 * Example: 89 * 90 * Host: Reply: 91 * $m0,10#2a +$00010203040506070809101112131415#42 92 * 93 ****************************************************************************/ 94 /* 95 * $FreeBSD: src/sys/i386/i386/i386-gdbstub.c,v 1.13.2.1 2000/08/03 00:54:41 peter Exp $ 96 */ 97 98 #include "opt_ddb.h" 99 100 #include <sys/param.h> 101 #include <sys/reboot.h> 102 #include <sys/systm.h> 103 #include <sys/cons.h> 104 105 #include <ddb/ddb.h> 106 107 #include <setjmp.h> 108 109 void gdb_handle_exception (db_regs_t *, int, int); 110 111 /************************************************************************/ 112 113 extern jmp_buf db_jmpbuf; 114 115 /************************************************************************/ 116 /* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ 117 /* at least NUMREGBYTES*2 are needed for register packets */ 118 #define BUFMAX 400 119 120 /* Create private copies of common functions used by the stub. This prevents 121 nasty interactions between app code and the stub (for instance if user steps 122 into strlen, etc..) */ 123 124 #define strlen gdb_strlen 125 #define strcpy gdb_strcpy 126 127 static int 128 strlen (const char *s) 129 { 130 const char *s1 = s; 131 132 while (*s1++ != '\000'); 133 134 return s1 - s; 135 } 136 137 static char * 138 strcpy (char *dst, const char *src) 139 { 140 char *retval = dst; 141 142 while ((*dst++ = *src++) != '\000'); 143 144 return retval; 145 } 146 147 static int 148 putDebugChar (int c) /* write a single character */ 149 { 150 if (gdb_tab == NULL) 151 return 0; 152 gdb_tab->cn_putc(gdb_tab->cn_gdbprivate, c); 153 return 1; 154 } 155 156 static int 157 getDebugChar (void) /* read and return a single char */ 158 { 159 if (gdb_tab == NULL) 160 return -1; 161 return gdb_tab->cn_getc(gdb_tab->cn_gdbprivate); 162 } 163 164 static const char hexchars[]="0123456789abcdef"; 165 166 static int 167 hex(char ch) 168 { 169 if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10); 170 if ((ch >= '0') && (ch <= '9')) return (ch-'0'); 171 if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10); 172 return (-1); 173 } 174 175 /* scan for the sequence $<data>#<checksum> */ 176 static void 177 getpacket (char *buffer) 178 { 179 unsigned char checksum; 180 unsigned char xmitcsum; 181 int i; 182 int count; 183 unsigned char ch; 184 185 do 186 { 187 /* wait around for the start character, ignore all other characters */ 188 189 while ((ch = (getDebugChar () & 0x7f)) != '$'); 190 191 checksum = 0; 192 xmitcsum = -1; 193 194 count = 0; 195 196 /* now, read until a # or end of buffer is found */ 197 198 while (count < BUFMAX) 199 { 200 ch = getDebugChar () & 0x7f; 201 if (ch == '#') 202 break; 203 checksum = checksum + ch; 204 buffer[count] = ch; 205 count = count + 1; 206 } 207 buffer[count] = 0; 208 209 if (ch == '#') 210 { 211 xmitcsum = hex (getDebugChar () & 0x7f) << 4; 212 xmitcsum += hex (getDebugChar () & 0x7f); 213 214 if (checksum != xmitcsum) 215 putDebugChar ('-'); /* failed checksum */ 216 else 217 { 218 putDebugChar ('+'); /* successful transfer */ 219 /* if a sequence char is present, reply the sequence ID */ 220 if (buffer[2] == ':') 221 { 222 putDebugChar (buffer[0]); 223 putDebugChar (buffer[1]); 224 225 /* remove sequence chars from buffer */ 226 227 count = strlen (buffer); 228 for (i=3; i <= count; i++) 229 buffer[i-3] = buffer[i]; 230 } 231 } 232 } 233 } 234 while (checksum != xmitcsum); 235 } 236 237 /* send the packet in buffer. */ 238 239 static void 240 putpacket (char *buffer) 241 { 242 unsigned char checksum; 243 int count; 244 unsigned char ch; 245 246 /* $<packet info>#<checksum>. */ 247 do 248 { 249 /* 250 * This is a non-standard hack to allow use of the serial console for 251 * operation as well as debugging. Simply turn on 'remotechat' in gdb. 252 * 253 * This extension is not part of the Cygnus protocol, is kinda gross, 254 * but gets the job done. 255 */ 256 #ifdef GDB_REMOTE_CHAT 257 putDebugChar ('|'); 258 putDebugChar ('|'); 259 putDebugChar ('|'); 260 putDebugChar ('|'); 261 #endif 262 putDebugChar ('$'); 263 checksum = 0; 264 count = 0; 265 266 while ((ch=buffer[count]) != 0) 267 { 268 putDebugChar (ch); 269 checksum += ch; 270 count += 1; 271 } 272 273 putDebugChar ('#'); 274 putDebugChar (hexchars[checksum >> 4]); 275 putDebugChar (hexchars[checksum & 0xf]); 276 } 277 while ((getDebugChar () & 0x7f) != '+'); 278 } 279 280 static char remcomInBuffer[BUFMAX]; 281 static char remcomOutBuffer[BUFMAX]; 282 283 static int 284 get_char (vm_offset_t addr) 285 { 286 char data; 287 288 if (setjmp (db_jmpbuf)) 289 return -1; 290 291 db_read_bytes (addr, 1, &data); 292 293 return data & 0xff; 294 } 295 296 static int 297 set_char (vm_offset_t addr, int val) 298 { 299 char data; 300 301 if (setjmp (db_jmpbuf)) 302 return -1; 303 304 data = val; 305 306 db_write_bytes (addr, 1, &data); 307 return 0; 308 } 309 310 /* convert the memory pointed to by mem into hex, placing result in buf */ 311 /* return a pointer to the last char put in buf (null) */ 312 313 static char * 314 mem2hex (vm_offset_t mem, char *buf, int count) 315 { 316 int i; 317 int ch; 318 319 for (i=0;i<count;i++) { 320 ch = get_char (mem++); 321 if (ch == -1) 322 return NULL; 323 *buf++ = hexchars[ch >> 4]; 324 *buf++ = hexchars[ch % 16]; 325 } 326 *buf = 0; 327 return(buf); 328 } 329 330 /* convert the hex array pointed to by buf into binary to be placed in mem */ 331 /* return a pointer to the character AFTER the last byte written */ 332 static char * 333 hex2mem (char *buf, vm_offset_t mem, int count) 334 { 335 int i; 336 int ch; 337 int rv; 338 339 for (i=0;i<count;i++) { 340 ch = hex(*buf++) << 4; 341 ch = ch + hex(*buf++); 342 rv = set_char (mem++, ch); 343 if (rv == -1) 344 return NULL; 345 } 346 return(buf); 347 } 348 349 /* this function takes the 386 exception vector and attempts to 350 translate this number into a unix compatible signal value */ 351 static int 352 computeSignal (int exceptionVector) 353 { 354 int sigval; 355 switch (exceptionVector & ~T_USER) 356 { 357 case 0: sigval = 8; break; /* divide by zero */ 358 case 1: sigval = 5; break; /* debug exception */ 359 case 3: sigval = 5; break; /* breakpoint */ 360 case 4: sigval = 16; break; /* into instruction (overflow) */ 361 case 5: sigval = 16; break; /* bound instruction */ 362 case 6: sigval = 4; break; /* Invalid opcode */ 363 case 7: sigval = 8; break; /* coprocessor not available */ 364 case 8: sigval = 7; break; /* double fault */ 365 case 9: sigval = 11; break; /* coprocessor segment overrun */ 366 case 10: sigval = 5; break; /* Invalid TSS (also single-step) */ 367 case 11: sigval = 11; break; /* Segment not present */ 368 case 12: sigval = 11; break; /* stack exception */ 369 case 13: sigval = 11; break; /* general protection */ 370 case 14: sigval = 11; break; /* page fault */ 371 case 16: sigval = 7; break; /* coprocessor error */ 372 default: 373 sigval = 7; /* "software generated"*/ 374 } 375 return (sigval); 376 } 377 378 /* 379 * While we find nice hex chars, build an int. 380 * Return number of chars processed. 381 */ 382 383 static int 384 hexToInt(char **ptr, int *intValue) 385 { 386 int numChars = 0; 387 int hexValue; 388 389 *intValue = 0; 390 391 while (**ptr) 392 { 393 hexValue = hex(**ptr); 394 if (hexValue >=0) 395 { 396 *intValue = (*intValue <<4) | hexValue; 397 numChars ++; 398 } 399 else 400 break; 401 402 (*ptr)++; 403 } 404 405 return (numChars); 406 } 407 408 /* 409 * While we find nice hex chars, build a long. 410 * Return number of chars processed. 411 */ 412 413 static long 414 hexToLong(char **ptr, long *longValue) 415 { 416 int numChars = 0; 417 int hexValue; 418 419 *longValue = 0; 420 421 while (**ptr) 422 { 423 hexValue = hex(**ptr); 424 if (hexValue >=0) 425 { 426 *longValue = (*longValue <<4) | hexValue; 427 numChars ++; 428 } 429 else 430 break; 431 432 (*ptr)++; 433 } 434 435 return (numChars); 436 } 437 438 #define NUMREGBYTES (sizeof registers) 439 #define PC 16 440 #define SP 7 441 #define FP 6 442 #define NUM_REGS 22 443 444 /* 445 * This function does all command procesing for interfacing to gdb. 446 */ 447 void 448 gdb_handle_exception (db_regs_t *raw_regs, int type, int code) 449 { 450 int sigval; 451 long addr; 452 int length; 453 char * ptr; 454 struct x86_64regs { 455 unsigned long rax; 456 unsigned long rbx; 457 unsigned long rcx; 458 unsigned long rdx; 459 unsigned long rsi; 460 unsigned long rdi; 461 unsigned long rbp; 462 unsigned long rsp; 463 unsigned long r8; 464 unsigned long r9; 465 unsigned long r10; 466 unsigned long r11; 467 unsigned long r12; 468 unsigned long r13; 469 unsigned long r14; 470 unsigned long r15; 471 unsigned long rip; 472 unsigned long rflags; 473 unsigned int cs; 474 unsigned int ss; 475 }; 476 struct x86_64regs registers; 477 478 registers.rax = raw_regs->tf_rax; 479 registers.rbx = raw_regs->tf_rbx; 480 registers.rcx = raw_regs->tf_rcx; 481 registers.rdx = raw_regs->tf_rdx; 482 483 registers.rsp = raw_regs->tf_rsp; 484 registers.rbp = raw_regs->tf_rbp; 485 registers.rsi = raw_regs->tf_rsi; 486 registers.rdi = raw_regs->tf_rdi; 487 488 registers.r8 = raw_regs->tf_r8; 489 registers.r9 = raw_regs->tf_r9; 490 registers.r10 = raw_regs->tf_r10; 491 registers.r11 = raw_regs->tf_r11; 492 registers.r12 = raw_regs->tf_r12; 493 registers.r13 = raw_regs->tf_r13; 494 registers.r14 = raw_regs->tf_r14; 495 registers.r15 = raw_regs->tf_r15; 496 497 registers.rip = raw_regs->tf_rip; 498 registers.rflags = raw_regs->tf_rflags; 499 500 registers.cs = raw_regs->tf_cs; 501 registers.ss = raw_regs->tf_ss; 502 503 /* reply to host that an exception has occurred */ 504 sigval = computeSignal (type); 505 ptr = remcomOutBuffer; 506 507 *ptr++ = 'T'; 508 *ptr++ = hexchars[sigval >> 4]; 509 *ptr++ = hexchars[sigval & 0xf]; 510 511 *ptr++ = hexchars[PC >> 4]; 512 *ptr++ = hexchars[PC & 0xf]; 513 *ptr++ = ':'; 514 ptr = mem2hex ((vm_offset_t)®isters.rip, ptr, 8); 515 *ptr++ = ';'; 516 517 *ptr++ = hexchars[FP >> 4]; 518 *ptr++ = hexchars[FP & 0xf]; 519 *ptr++ = ':'; 520 ptr = mem2hex ((vm_offset_t)®isters.rbp, ptr, 8); 521 *ptr++ = ';'; 522 523 *ptr++ = hexchars[SP >> 4]; 524 *ptr++ = hexchars[SP & 0xf]; 525 *ptr++ = ':'; 526 ptr = mem2hex ((vm_offset_t)®isters.rsp, ptr, 8); 527 *ptr++ = ';'; 528 529 *ptr++ = 0; 530 531 putpacket (remcomOutBuffer); 532 533 while (1) 534 { 535 remcomOutBuffer[0] = 0; 536 537 getpacket (remcomInBuffer); 538 switch (remcomInBuffer[0]) 539 { 540 case '?': 541 remcomOutBuffer[0] = 'S'; 542 remcomOutBuffer[1] = hexchars[sigval >> 4]; 543 remcomOutBuffer[2] = hexchars[sigval % 16]; 544 remcomOutBuffer[3] = 0; 545 break; 546 547 case 'D': /* detach; say OK and turn off gdb */ 548 putpacket(remcomOutBuffer); 549 boothowto &= ~RB_GDB; 550 return; 551 552 case 'g': /* return the value of the CPU registers */ 553 mem2hex ((vm_offset_t)®isters, remcomOutBuffer, NUMREGBYTES); 554 break; 555 556 case 'G': /* set the value of the CPU registers - return OK */ 557 hex2mem (&remcomInBuffer[1], (vm_offset_t)®isters, NUMREGBYTES); 558 strcpy (remcomOutBuffer, "OK"); 559 break; 560 561 case 'P': /* Set the value of one register */ 562 { 563 int regno; 564 565 ptr = &remcomInBuffer[1]; 566 567 if (hexToInt (&ptr, ®no) 568 && *ptr++ == '=' 569 && regno < NUM_REGS) 570 { 571 /* JG */ 572 hex2mem (ptr, (vm_offset_t)®isters + regno * 8, 8); 573 strcpy(remcomOutBuffer,"OK"); 574 } 575 else 576 strcpy (remcomOutBuffer, "P01"); 577 break; 578 } 579 case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 580 /* Try to read %x,%x. */ 581 582 ptr = &remcomInBuffer[1]; 583 584 if (hexToLong (&ptr, &addr) 585 && *(ptr++) == ',' 586 && hexToInt (&ptr, &length)) 587 { 588 if (mem2hex((vm_offset_t) addr, remcomOutBuffer, length) == NULL) 589 strcpy (remcomOutBuffer, "E03"); 590 break; 591 } 592 else 593 strcpy (remcomOutBuffer, "E01"); 594 break; 595 596 case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 597 598 /* Try to read '%x,%x:'. */ 599 600 ptr = &remcomInBuffer[1]; 601 602 if (hexToLong(&ptr,&addr) 603 && *(ptr++) == ',' 604 && hexToInt(&ptr, &length) 605 && *(ptr++) == ':') 606 { 607 if (hex2mem(ptr, (vm_offset_t) addr, length) == NULL) 608 strcpy (remcomOutBuffer, "E03"); 609 else 610 strcpy (remcomOutBuffer, "OK"); 611 } 612 else 613 strcpy (remcomOutBuffer, "E02"); 614 break; 615 616 /* cAA..AA Continue at address AA..AA(optional) */ 617 /* sAA..AA Step one instruction from AA..AA(optional) */ 618 case 'c' : 619 case 's' : 620 /* try to read optional parameter, pc unchanged if no parm */ 621 622 ptr = &remcomInBuffer[1]; 623 if (hexToLong(&ptr,&addr)) 624 registers.rip = addr; 625 626 627 /* set the trace bit if we're stepping */ 628 if (remcomInBuffer[0] == 's') 629 registers.rflags |= PSL_T; 630 else 631 registers.rflags &= ~PSL_T; 632 633 raw_regs->tf_rax = registers.rax; 634 raw_regs->tf_rbx = registers.rbx; 635 raw_regs->tf_rcx = registers.rcx; 636 raw_regs->tf_rdx = registers.rdx; 637 638 raw_regs->tf_rsp = registers.rsp; 639 raw_regs->tf_rbp = registers.rbp; 640 raw_regs->tf_rsi = registers.rsi; 641 raw_regs->tf_rdi = registers.rdi; 642 643 raw_regs->tf_r8 = registers.r8; 644 raw_regs->tf_r9 = registers.r9; 645 raw_regs->tf_r10 = registers.r10; 646 raw_regs->tf_r11 = registers.r11; 647 raw_regs->tf_r12 = registers.r12; 648 raw_regs->tf_r13 = registers.r13; 649 raw_regs->tf_r14 = registers.r14; 650 raw_regs->tf_r15 = registers.r15; 651 652 raw_regs->tf_rip = registers.rip; 653 raw_regs->tf_rflags = registers.rflags; 654 655 raw_regs->tf_cs = registers.cs; 656 raw_regs->tf_ss = registers.ss; 657 return; 658 659 } /* switch */ 660 661 /* reply to the request */ 662 putpacket (remcomOutBuffer); 663 } 664 } 665 666