|
|
1.1 ! root 1: /* Memory-access and commands for inferior process, for GDB. ! 2: Copyright (C) 1988 Free Software Foundation, Inc. ! 3: ! 4: GDB is distributed in the hope that it will be useful, but WITHOUT ANY ! 5: WARRANTY. No author or distributor accepts responsibility to anyone ! 6: for the consequences of using it or for whether it serves any ! 7: particular purpose or works at all, unless he says so in writing. ! 8: Refer to the GDB General Public License for full details. ! 9: ! 10: Everyone is granted permission to copy, modify and redistribute GDB, ! 11: but only under the conditions described in the GDB General Public ! 12: License. A copy of this license is supposed to have been given to you ! 13: along with GDB so you can know your rights and responsibilities. It ! 14: should be in a file named COPYING. Among other things, the copyright ! 15: notice and this notice must be preserved on all copies. ! 16: ! 17: In other words, go ahead and share GDB, but don't try to stop ! 18: anyone else from sharing it farther. Help stamp out software hoarding! ! 19: */ ! 20: ! 21: /* Remote communication protocol. ! 22: All values are encoded in ascii hex digits. ! 23: ! 24: Request Packet ! 25: ! 26: read registers g ! 27: reply XX....X Each byte of register data ! 28: is described by two hex digits. ! 29: Registers are in the internal order ! 30: for GDB, and the bytes in a register ! 31: are in the same order the machine uses. ! 32: or ENN for an error. ! 33: ! 34: write regs GXX..XX Each byte of register data ! 35: is described by two hex digits. ! 36: reply OK for success ! 37: ENN for an error ! 38: ! 39: read mem mAA..AA,LLLL AA..AA is address, LLLL is length. ! 40: reply XX..XX XX..XX is mem contents ! 41: or ENN NN is errno ! 42: ! 43: write mem MAA..AA,LLLL:XX..XX ! 44: AA..AA is address, ! 45: LLLL is number of bytes, ! 46: XX..XX is data ! 47: reply OK for success ! 48: ENN for an error ! 49: ! 50: cont cAA..AA AA..AA is address to resume ! 51: If AA..AA is omitted, ! 52: resume at same address. ! 53: ! 54: step sAA..AA AA..AA is address to resume ! 55: If AA..AA is omitted, ! 56: resume at same address. ! 57: ! 58: There is no immediate reply to step or cont. ! 59: The reply comes when the machine stops. ! 60: It is SAA AA is the "signal number" ! 61: ! 62: kill req k ! 63: */ ! 64: ! 65: #include <stdio.h> ! 66: #include <signal.h> ! 67: ! 68: #include "defs.h" ! 69: #include "initialize.h" ! 70: #include "param.h" ! 71: #include "frame.h" ! 72: #include "inferior.h" ! 73: ! 74: #include "wait.h" ! 75: #include <sys/ioctl.h> ! 76: #include <a.out.h> ! 77: #include <sys/file.h> ! 78: ! 79: #ifdef HAVE_TERMIO ! 80: #include <termio.h> ! 81: #undef TIOCGETP ! 82: #define TIOCGETP TCGETA ! 83: #undef TIOCSETN ! 84: #define TIOCSETN TCSETA ! 85: #undef TIOCSETP ! 86: #define TIOCSETP TCSETAF ! 87: #define TERMINAL struct termio ! 88: #else ! 89: #include <sgtty.h> ! 90: #define TERMINAL struct sgttyb ! 91: #endif ! 92: ! 93: int kiodebug; ! 94: ! 95: int icache; ! 96: ! 97: /* Descriptor for I/O to remote machine. */ ! 98: int remote_desc; ! 99: ! 100: #define PBUFSIZ 300 ! 101: ! 102: static void remote_send (); ! 103: static void putpkt (); ! 104: static void getpkt (); ! 105: static void dcache_flush (); ! 106: ! 107: START_FILE ! 108: ! 109: /* Open a connection to a remote debugger. ! 110: NAME is the filename used for communication. */ ! 111: ! 112: void ! 113: remote_open (name, from_tty) ! 114: char *name; ! 115: int from_tty; ! 116: { ! 117: TERMINAL sg; ! 118: ! 119: remote_debugging = 0; ! 120: dcache_init (); ! 121: ! 122: remote_desc = open (name, O_RDWR); ! 123: if (remote_desc < 0) ! 124: perror_with_name (name); ! 125: ! 126: ioctl (remote_desc, TIOCGETP, &sg); ! 127: #ifdef HAVE_TERMIO ! 128: sg.c_lflag &= ~ICANON; ! 129: #else ! 130: sg.sg_flags = RAW; ! 131: #endif ! 132: ioctl (remote_desc, TIOCSETP, &sg); ! 133: ! 134: if (from_tty) ! 135: printf ("Remote debugging using %s\n", name); ! 136: remote_debugging = 1; ! 137: } ! 138: ! 139: /* Convert hex digit A to a number. */ ! 140: ! 141: static int ! 142: fromhex (a) ! 143: int a; ! 144: { ! 145: if (a >= '0' && a <= '9') ! 146: return a - '0'; ! 147: else if (a >= 'a' && a <= 'f') ! 148: return a - 'a' + 10; ! 149: else ! 150: error ("Reply contains invalid hex digit"); ! 151: } ! 152: ! 153: /* Convert number NIB to a hex digit. */ ! 154: ! 155: static int ! 156: tohex (nib) ! 157: int nib; ! 158: { ! 159: if (nib < 10) ! 160: return '0'+nib; ! 161: else ! 162: return 'a'+nib-10; ! 163: } ! 164: ! 165: /* Tell the remote machine to resume. */ ! 166: ! 167: int ! 168: remote_resume (step, signal) ! 169: int step, signal; ! 170: { ! 171: char buf[PBUFSIZ]; ! 172: ! 173: dcache_flush (); ! 174: ! 175: strcpy (buf, step ? "s": "c"); ! 176: ! 177: putpkt (buf); ! 178: } ! 179: ! 180: /* Wait until the remote machine stops, then return, ! 181: storing status in STATUS just as `wait' would. */ ! 182: ! 183: int ! 184: remote_wait (status) ! 185: WAITTYPE *status; ! 186: { ! 187: char buf[PBUFSIZ]; ! 188: ! 189: WSETEXIT ((*status), 0); ! 190: getpkt (buf); ! 191: if (buf[0] == 'E') ! 192: error ("Remote failure reply: %s", buf); ! 193: if (buf[0] != 'S') ! 194: error ("Invalid remote reply: %s", buf); ! 195: WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2])))); ! 196: } ! 197: ! 198: /* Read the remote registers into the block REGS. */ ! 199: ! 200: void ! 201: remote_fetch_registers (regs) ! 202: char *regs; ! 203: { ! 204: char buf[PBUFSIZ]; ! 205: int i; ! 206: char *p; ! 207: ! 208: sprintf (buf, "g"); ! 209: remote_send (buf); ! 210: ! 211: /* Reply describes registers byte by byte, ! 212: each byte encoded as two hex characters. */ ! 213: ! 214: p = buf; ! 215: for (i = 0; i < REGISTER_BYTES; i++) ! 216: { ! 217: if (p[0] == 0 || p[1] == 0) ! 218: error ("Remote reply is too short: %s", buf); ! 219: regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]); ! 220: p += 2; ! 221: } ! 222: } ! 223: ! 224: /* Store the remote registers from the contents of the block REGS. */ ! 225: ! 226: void ! 227: remote_store_registers (regs) ! 228: char *regs; ! 229: { ! 230: char buf[PBUFSIZ]; ! 231: int i; ! 232: char *p; ! 233: ! 234: buf[0] = 'G'; ! 235: ! 236: /* Command describes registers byte by byte, ! 237: each byte encoded as two hex characters. */ ! 238: ! 239: p = buf + 1; ! 240: for (i = 0; i < REGISTER_BYTES; i++) ! 241: { ! 242: *p++ = (regs[i] > 4) & 0xf; ! 243: *p++ = regs[i] & 0xf; ! 244: } ! 245: ! 246: remote_send (buf); ! 247: } ! 248: ! 249: /* Read a word from remote address ADDR and return it. ! 250: This goes through the data cache. */ ! 251: ! 252: int ! 253: remote_fetch_word (addr) ! 254: CORE_ADDR addr; ! 255: { ! 256: if (icache) ! 257: { ! 258: extern CORE_ADDR text_start, text_end; ! 259: ! 260: if (addr >= text_start && addr < text_end) ! 261: { ! 262: int buffer; ! 263: xfer_core_file (addr, &buffer, sizeof (int)); ! 264: return buffer; ! 265: } ! 266: } ! 267: return dcache_fetch (addr); ! 268: } ! 269: ! 270: /* Write a word WORD into remote address ADDR. ! 271: This goes through the data cache. */ ! 272: ! 273: void ! 274: remote_store_word (addr, word) ! 275: CORE_ADDR addr; ! 276: int word; ! 277: { ! 278: dcache_poke (addr, word); ! 279: } ! 280: ! 281: /* Write memory data directly to the remote machine. ! 282: This does not inform the data cache; the data cache uses this. ! 283: MEMADDR is the address in the remote memory space. ! 284: MYADDR is the address of the buffer in our space. ! 285: LEN is the number of bytes. */ ! 286: ! 287: void ! 288: remote_write_bytes (memaddr, myaddr, len) ! 289: CORE_ADDR memaddr; ! 290: char *myaddr; ! 291: int len; ! 292: { ! 293: char buf[PBUFSIZ]; ! 294: int i; ! 295: char *p; ! 296: ! 297: if (len > PBUFSIZ / 2 - 20) ! 298: abort (); ! 299: ! 300: sprintf (buf, "M%x,%x:", memaddr, len); ! 301: ! 302: /* Command describes registers byte by byte, ! 303: each byte encoded as two hex characters. */ ! 304: ! 305: p = buf + strlen (buf); ! 306: for (i = 0; i < len; i++) ! 307: { ! 308: *p++ = (myaddr[i] > 4) & 0xf; ! 309: *p++ = myaddr[i] & 0xf; ! 310: } ! 311: ! 312: remote_send (buf); ! 313: } ! 314: ! 315: /* Read memory data directly from the remote machine. ! 316: This does not use the data cache; the data cache uses this. ! 317: MEMADDR is the address in the remote memory space. ! 318: MYADDR is the address of the buffer in our space. ! 319: LEN is the number of bytes. */ ! 320: ! 321: void ! 322: remote_read_bytes (memaddr, myaddr, len) ! 323: CORE_ADDR memaddr; ! 324: char *myaddr; ! 325: int len; ! 326: { ! 327: char buf[PBUFSIZ]; ! 328: int i; ! 329: char *p; ! 330: ! 331: if (len > PBUFSIZ / 2 - 1) ! 332: abort (); ! 333: ! 334: sprintf (buf, "m%x,%x", memaddr, len); ! 335: remote_send (buf); ! 336: ! 337: /* Reply describes registers byte by byte, ! 338: each byte encoded as two hex characters. */ ! 339: ! 340: p = buf; ! 341: for (i = 0; i < REGISTER_BYTES; i++) ! 342: { ! 343: if (p[0] == 0 || p[1] == 0) ! 344: error ("Remote reply is too short: %s", buf); ! 345: myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]); ! 346: p += 2; ! 347: } ! 348: } ! 349: ! 350: /* ! 351: ! 352: A debug packet whose contents are <data> ! 353: is encapsulated for transmission in the form: ! 354: ! 355: $ <data> # CSUM1 CSUM2 ! 356: ! 357: <data> must be ASCII alphanumeric and cannot include characters ! 358: '$' or '#' ! 359: ! 360: CSUM1 and CSUM2 are ascii hex representation of an 8-bit ! 361: checksum of <data>, the most significant nibble is sent first. ! 362: the hex digits 0-9,a-f are used. ! 363: ! 364: Receiver responds with: ! 365: ! 366: + - if CSUM is correct and ready for next packet ! 367: - - if CSUM is incorrect ! 368: ! 369: */ ! 370: ! 371: /* Send the command in BUF to the remote machine, ! 372: and read the reply into BUF. ! 373: Report an error if we get an error reply. */ ! 374: ! 375: static void ! 376: remote_send (buf) ! 377: char *buf; ! 378: { ! 379: int i; ! 380: putpkt (buf); ! 381: getpkt (buf); ! 382: ! 383: if (buf[0] == 'E') ! 384: error ("Remote failure reply: %s", buf); ! 385: } ! 386: ! 387: /* Send a packet to the remote machine, with error checking. ! 388: The data of the packet is in BUF. */ ! 389: ! 390: static void ! 391: putpkt (buf) ! 392: char *buf; ! 393: { ! 394: int i; ! 395: char csum = 0; ! 396: char buf2[500]; ! 397: char buf3[1]; ! 398: int cnt = strlen (buf); ! 399: char *p; ! 400: ! 401: if (kiodebug) ! 402: fprintf (stderr, "Sending packet: %s\n", buf); ! 403: ! 404: /* Copy the packet into buffer BUF2, encapsulating it ! 405: and giving it a checksum. */ ! 406: ! 407: p = buf2; ! 408: *p++ = '$'; ! 409: ! 410: for (i = 0; i < cnt; i++) ! 411: { ! 412: csum += buf[i]; ! 413: *p++ = buf[i]; ! 414: } ! 415: *p++ = '#'; ! 416: *p++ = tohex ((csum >> 4) & 0xf); ! 417: *p++ = tohex (csum & 0xf); ! 418: ! 419: /* Send it over and over until we get a positive ack. */ ! 420: ! 421: do { ! 422: write (remote_desc, buf2, p - buf2); ! 423: read (remote_desc, buf3, 1); ! 424: } while (buf3[0] != '+'); ! 425: } ! 426: ! 427: static int ! 428: readchar () ! 429: { ! 430: char buf[1]; ! 431: while (read (remote_desc, buf, 1) != 1) ; ! 432: return buf[0] & 0x7f; ! 433: } ! 434: ! 435: /* Read a packet from the remote machine, with error checking, ! 436: and store it in BUF. */ ! 437: ! 438: static void ! 439: getpkt (buf) ! 440: char *buf; ! 441: { ! 442: char *bp; ! 443: char csum = 0; ! 444: int c, c1, c2; ! 445: extern kiodebug; ! 446: ! 447: while (1) ! 448: { ! 449: while ((c = readchar()) != '$'); ! 450: ! 451: bp = buf; ! 452: while (1) ! 453: { ! 454: c = readchar (); ! 455: if (c == '#') ! 456: break; ! 457: *bp++ = c; ! 458: csum += c; ! 459: } ! 460: *bp = 0; ! 461: ! 462: c1 = fromhex (readchar ()); ! 463: c2 = fromhex (readchar ()); ! 464: if (csum == (c1 << 4) + c2) ! 465: break; ! 466: printf ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n", ! 467: (c1 << 4) + c2, csum, buf); ! 468: write (remote_desc, "-", 1); ! 469: } ! 470: ! 471: write (remote_desc, "+", 1); ! 472: ! 473: if (kiodebug) ! 474: fprintf (stderr,"Packet received :%s\n", buf); ! 475: } ! 476: ! 477: /* The data cache records all the data read from the remote machine ! 478: since the last time it stopped. ! 479: ! 480: Each cache block holds 16 bytes of data ! 481: starting at a multiple-of-16 address. */ ! 482: ! 483: #define DCACHE_SIZE 64 /* Number of cache blocks */ ! 484: ! 485: struct dcache_block { ! 486: struct dcache_block *next, *last; ! 487: unsigned int addr; /* Address for which data is recorded. */ ! 488: int data[4]; ! 489: }; ! 490: ! 491: struct dcache_block dcache_free, dcache_valid; ! 492: ! 493: /* Free all the data cache blocks, thus discarding all cached data. */ ! 494: ! 495: static void ! 496: dcache_flush () ! 497: { ! 498: register struct dcache_block *db; ! 499: ! 500: while ((db = dcache_valid.next) != &dcache_valid) ! 501: { ! 502: remque (db); ! 503: insque (db, &dcache_free); ! 504: } ! 505: } ! 506: ! 507: /* ! 508: * If addr is present in the dcache, return the address of the block ! 509: * containing it. ! 510: */ ! 511: ! 512: struct dcache_block * ! 513: dcache_hit (addr) ! 514: { ! 515: register struct dcache_block *db; ! 516: ! 517: if (addr & 3) ! 518: abort (); ! 519: ! 520: /* Search all cache blocks for one that is at this address. */ ! 521: db = dcache_valid.next; ! 522: while (db != &dcache_valid) ! 523: { ! 524: if ((addr & 0xfffffff0) == db->addr) ! 525: return db; ! 526: db = db->next; ! 527: } ! 528: return NULL; ! 529: } ! 530: ! 531: /* Return the int data at address ADDR in dcache block DC. */ ! 532: ! 533: int ! 534: dcache_value (db, addr) ! 535: struct dcache_block *db; ! 536: unsigned int addr; ! 537: { ! 538: if (addr & 3) ! 539: abort (); ! 540: return (db->data[(addr>>2)&3]); ! 541: } ! 542: ! 543: /* Get a free cache block, put it on the valid list, ! 544: and return its address. The caller should store into the block ! 545: the address and data that it describes. */ ! 546: ! 547: struct dcache_block * ! 548: dcache_alloc () ! 549: { ! 550: register struct dcache_block *db; ! 551: ! 552: if ((db = dcache_free.next) == &dcache_free) ! 553: /* If we can't get one from the free list, take last valid */ ! 554: db = dcache_valid.last; ! 555: ! 556: remque (db); ! 557: insque (db, &dcache_valid); ! 558: return (db); ! 559: } ! 560: ! 561: /* Return the contents of the word at address ADDR in the remote machine, ! 562: using the data cache. */ ! 563: ! 564: int ! 565: dcache_fetch (addr) ! 566: CORE_ADDR addr; ! 567: { ! 568: register struct dcache_block *db; ! 569: ! 570: db = dcache_hit (addr); ! 571: if (db == 0) ! 572: { ! 573: db = dcache_alloc (); ! 574: remote_read_bytes (addr & ~0xf, db->data, 16); ! 575: db->addr = addr & ~0xf; ! 576: } ! 577: return (dcache_value (db, addr)); ! 578: } ! 579: ! 580: /* Write the word at ADDR both in the data cache and in the remote machine. */ ! 581: ! 582: dcache_poke (addr, data) ! 583: CORE_ADDR addr; ! 584: int data; ! 585: { ! 586: register struct dcache_block *db; ! 587: ! 588: /* First make sure the word is IN the cache. DB is its cache block. */ ! 589: db = dcache_hit (addr); ! 590: if (db == 0) ! 591: { ! 592: db = dcache_alloc (); ! 593: remote_read_bytes (addr & ~0xf, db->data, 16); ! 594: db->addr = addr & ~0xf; ! 595: } ! 596: ! 597: /* Modify the word in the cache. */ ! 598: db->data[(addr>>2)&3] = data; ! 599: ! 600: /* Send the changed word. */ ! 601: remote_write_bytes (addr, &data, 4); ! 602: } ! 603: ! 604: /* Initialize the data cache. */ ! 605: ! 606: dcache_init () ! 607: { ! 608: register i; ! 609: register struct dcache_block *db; ! 610: ! 611: db = (struct dcache_block *) xmalloc (sizeof (struct dcache_block) * ! 612: DCACHE_SIZE); ! 613: dcache_free.next = dcache_free.last = &dcache_free; ! 614: dcache_valid.next = dcache_valid.last = &dcache_valid; ! 615: for (i=0;i<DCACHE_SIZE;i++,db++) ! 616: insque (db, &dcache_free); ! 617: } ! 618: ! 619: static initialize () ! 620: { ! 621: } ! 622: ! 623: END_FILE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.