|
|
1.1 ! root 1: /* ! 2: * db/db3.c ! 3: * A debugger. ! 4: * Command execution and display routines. ! 5: */ ! 6: ! 7: #include "db.h" ! 8: #include <signal.h> ! 9: ! 10: /* ! 11: * Execute a command. ! 12: * Return 1 if more commands may be read, ! 13: * 0 to stop reading commands (for :e, :c, :s). ! 14: */ ! 15: int ! 16: command(vp) register VAL *vp; ! 17: { ! 18: register int c, sig; ! 19: ! 20: switch (c = getn()) { ! 21: ! 22: /* [addr]:a Print address (default: .) */ ! 23: case 'a': ! 24: if (getn() != '\n') ! 25: break; ! 26: putaddr(val_segn(vp), lvalue(vp, dot)); ! 27: putx('\n'); ! 28: return 1; ! 29: ! 30: /* [addr]:b[r][cmd] Set [return] breakpoint */ ! 31: case 'b': ! 32: if (!IS_OBJ) ! 33: break; ! 34: if ((c = getn()) != 'r') { ! 35: ungetn(c); ! 36: c = 'b'; ! 37: } ! 38: getline("i+.:a\ni+.?i\n:x"); ! 39: /* FIX_ME :br only works at current pc, not at specified addr. */ ! 40: if ((c == 'r' && bpt_setr(miscbuf) == 0) ! 41: || (c != 'r' && bpt_set(BBPT, lvalue(vp, dot), 0L, miscbuf) == 0)) ! 42: printe("Cannot set breakpoint"); ! 43: return 1; ! 44: ! 45: /* [addr]:c Continue */ ! 46: case 'c': ! 47: if (getn() != '\n') ! 48: break; ! 49: else ! 50: c = '\n'; ! 51: if (execflag == 0) ! 52: break; ! 53: if (nvalue(vp) == 0) ! 54: set_pc(lvalue(vp, (ADDR_T)0)); ! 55: step_mode = SNULL; ! 56: return 0; ! 57: ! 58: /* [addr]:d[r][s] Delete breakpoint */ ! 59: case 'd': ! 60: if (!IS_OBJ) ! 61: break; ! 62: if ((c = getn()) != 'r' && c != 's') { ! 63: ungetn(c); ! 64: c = 'b'; ! 65: } ! 66: if (getn() != '\n') ! 67: break; ! 68: if (bpt_del(c, lvalue(vp, dot)) == 0) ! 69: printe("Cannot delete breakpoint"); ! 70: return 1; ! 71: ! 72: /* [addr]:eargs Execute */ ! 73: case 'e': ! 74: if (nvalue(vp) == 0) ! 75: set_pc(lvalue(vp, (ADDR_T)0)); ! 76: getline(""); ! 77: return runfile(); ! 78: ! 79: /* :f Print fault type */ ! 80: case 'f': ! 81: if (getn() != '\n') ! 82: break; ! 83: sig = get_sig(); ! 84: printx("%s\n", (sig == 0) ? "no fault" ! 85: : (sig > NSIG) ? "bad signal number" ! 86: : signame[sig]); ! 87: return 1; ! 88: ! 89: /* :h[f] Print help info */ ! 90: case 'h': ! 91: if ((c = getn()) != 'f') ! 92: ungetn(c); ! 93: if (getn() != '\n') ! 94: break; ! 95: helpinfo(c == 'f'); ! 96: return 1; ! 97: ! 98: /* [n]:k ??? send a signal ??? */ ! 99: case 'k': ! 100: if (execflag == 0) ! 101: break; ! 102: if (getn() != '\n') ! 103: break; ! 104: if (nvalue(vp) != 0) { ! 105: printe("No signal specified"); ! 106: return 1; ! 107: } ! 108: printr("Cannot send %d", (int)rvalue(vp, 0L)); ! 109: return 1; ! 110: ! 111: /* :m Print segmentation map */ ! 112: case 'm': ! 113: if (getn() != '\n') ! 114: break; ! 115: map_print(); ! 116: return 1; ! 117: ! 118: /* case 'n': Documented but not implemented? */ ! 119: ! 120: #ifndef NOCANON ! 121: /* [expr]:o Change canon type, UNDOCUMENTED... */ ! 122: case 'o': ! 123: if (getn() != '\n') ! 124: break; ! 125: cantype = rvalue(vp, 0L); ! 126: return 1; ! 127: #endif ! 128: ! 129: /* :p Print breakpoints */ ! 130: case 'p': ! 131: if (getn() != '\n') ! 132: break; ! 133: bpt_display(); ! 134: return 1; ! 135: ! 136: /* [expr]:q Quit */ ! 137: case 'q': ! 138: if (getn() != '\n') ! 139: break; ! 140: if (rvalue(vp, 1L)) ! 141: leave(); ! 142: return 1; ! 143: ! 144: /* :r[N] Print registers [including NDP] */ ! 145: case 'r': ! 146: if ((c = getn()) == 'N') ! 147: c = R_ALL; ! 148: else { ! 149: ungetn(c); ! 150: c = R_GEN; ! 151: } ! 152: if (getn() != '\n') ! 153: break; ! 154: if (reg_flag == R_INVALID) ! 155: break; ! 156: display_reg(c); ! 157: return 1; ! 158: ! 159: /* [addr][,n]:s[c] Single step [n times] [over calls] */ ! 160: case 's': ! 161: if (execflag == 0) ! 162: break; ! 163: if (nvalue(vp) == 0) ! 164: set_pc(lvalue(vp, (ADDR_T)0)); ! 165: step_count = rvalue(&vp[1], 1L); ! 166: if ((c = getn()) != 'c') { ! 167: step_mode = SSTEP; ! 168: ungetn(c); ! 169: } else ! 170: step_mode = SCONT; ! 171: getline("i+.?i"); ! 172: step_cmd = save_cmd(step_cmd, miscbuf); ! 173: return 0; ! 174: ! 175: /* [expr]:t Call traceback [expr levels] */ ! 176: case 't': ! 177: if (getn() != '\n') ! 178: break; ! 179: else ! 180: c = '\n'; ! 181: if (reg_flag == R_INVALID) ! 182: break; ! 183: traceback((int)rvalue(vp, 0L)); ! 184: return 1; ! 185: ! 186: /* [expr]:x Read and execute stdin */ ! 187: case 'x': ! 188: if (getn() != '\n') ! 189: break; ! 190: if (rvalue(vp, 1L)) { ! 191: step_prev = step_mode; ! 192: step_mode = SNULL; ! 193: add_input(IFILE, (char *)stdin); ! 194: } ! 195: return 1; ! 196: } ! 197: printe("Illegal command"); ! 198: while (c != '\n') ! 199: c = getn(); ! 200: return 1; ! 201: } ! 202: ! 203: /* ! 204: * Print out data from segment 's' according to the given format "t1 t2". ! 205: */ ! 206: char * ! 207: conform(sp, s, t1, t2) register char *sp; int s, t1, t2; ! 208: { ! 209: register char *lp; ! 210: char c; ! 211: unsigned char uc; ! 212: short sh; ! 213: unsigned short us; ! 214: int i; ! 215: unsigned int ui; ! 216: long l; ! 217: unsigned char v[3]; ! 218: ADDR_T p; ! 219: #ifndef NOFP ! 220: float f; ! 221: double d; ! 222: struct _fpreg fpreg; ! 223: #endif ! 224: ! 225: dbprintf(("conform(... s=%d t1=%c t2=%c)\n", s, t1, t2)); ! 226: switch (t1) { ! 227: ! 228: case 'b': /* byte */ ! 229: if (getb(s, &uc, sizeof(uc)) == 0) ! 230: return NULL; ! 231: modsize = sizeof(uc); ! 232: ! 233: /* Sign-extend or 0-extend depending on display format. */ ! 234: if (t2 != 'd') ! 235: i = ui = (unsigned int)uc; ! 236: else ! 237: i = c = uc; ! 238: sprintf(sp, get_format(t1, t2), i); ! 239: break; ! 240: case 'c': /* char with escapes */ ! 241: if (getb(s, &uc, sizeof(uc)) == 0) ! 242: return NULL; ! 243: modsize = sizeof(uc); ! 244: return printable(sp, uc); ! 245: case 'C': /* char */ ! 246: if (getb(s, &uc, sizeof(uc)) == 0) ! 247: return NULL; ! 248: modsize = sizeof(uc); ! 249: *sp++ = (uc >= 0x20 && uc < 0x7F) ? uc : '.'; ! 250: return sp; ! 251: #ifndef NOFP ! 252: case 'f': /* float */ ! 253: if (getb(s, (char *)&f, sizeof(f)) == 0) ! 254: return NULL; ! 255: modsize = sizeof(f); ! 256: sprintf(sp, get_format(t1, t2), f); ! 257: break; ! 258: case 'F': /* double */ ! 259: if (getb(s, (char *)&d, sizeof(d)) == 0) ! 260: return NULL; ! 261: modsize = sizeof(d); ! 262: sprintf(sp, get_format(t1, t2), d); ! 263: break; ! 264: case 'N': /* NDP fp register */ ! 265: if (getb(s, (char *)&fpreg, sizeof(fpreg)) == 0) ! 266: return NULL; ! 267: if (get_fp_reg(&fpreg, &d) == 0) ! 268: return NULL; ! 269: modsize = sizeof(fpreg); ! 270: sprintf(sp, get_format('F', t2), d); ! 271: break; ! 272: #endif ! 273: case 'h': ! 274: if (getb(s, (char *)&us, sizeof(us)) == 0) ! 275: return NULL; ! 276: modsize = sizeof(us); ! 277: ! 278: /* Sign-extend or 0-extend depending on display format. */ ! 279: if (t2 != 'd') ! 280: i = ui = us; ! 281: else ! 282: i = sh = us; ! 283: sprintf(sp, get_format(t1, t2), i); ! 284: break; ! 285: case 'i': /* machine instruction */ ! 286: modsize = INLEN; ! 287: return disassemble(sp, s); ! 288: case 'l': /* long */ ! 289: if (getb(s, (char *)&l, sizeof(l)) == 0) ! 290: return NULL; ! 291: modsize = sizeof(l); ! 292: sprintf(sp, get_format(t1, t2), l); ! 293: break; ! 294: case 'p': /* pointer */ ! 295: if (getb(s, (char *)&p, sizeof(p)) == 0) ! 296: return NULL; ! 297: modsize = sizeof(p); ! 298: return cvt_addr(sp, find_seg(p), p); ! 299: case 's': /* string with escapes */ ! 300: case 'S': /* string */ ! 301: lp = &sp[DISSIZE]; ! 302: for (;;) { ! 303: if (getb(s, &uc, sizeof(uc)) == 0) ! 304: return NULL; ! 305: if (uc == '\0') ! 306: break; ! 307: if (t1 == 's') ! 308: sp = printable(sp, uc); ! 309: else ! 310: *sp++ = uc; ! 311: if (sp > lp) ! 312: return NULL; ! 313: } ! 314: modsize = sizeof(i); ! 315: return sp; ! 316: case 'v': /* l3 */ ! 317: if (getb(s, (char *)v, sizeof(v)) == 0) ! 318: return NULL; ! 319: modsize = sizeof(v); ! 320: l3tol(&l, v, 1); ! 321: sprintf(sp, get_format(t1, t2), l); ! 322: break; ! 323: case 'w': /* word */ ! 324: if (getb(s, (char *)&us, sizeof(us)) == 0) ! 325: return NULL; ! 326: modsize = sizeof(us); ! 327: sprintf(sp, get_format(t1, t2), (int)us); ! 328: break; ! 329: case 'Y': /* time */ ! 330: modsize = sizeof(i); ! 331: return gettime(sp, s); ! 332: default: ! 333: return NULL; ! 334: } ! 335: return strchr(sp, '\0'); ! 336: } ! 337: ! 338: /* ! 339: * Print out 'n' data items from segment 's'. ! 340: */ ! 341: int ! 342: display(s, n) int s, n; ! 343: { ! 344: register char *sp1, *sp2, *fs; ! 345: register int c, r, t1, t2; ! 346: register char *sp3, *fp; ! 347: register ADDR_T nad, pad, uad; ! 348: ! 349: dbprintf(("display(%d, %d) dot=%x\n", s, n, dot)); ! 350: r = 1; ! 351: t2 = '\0'; ! 352: add = nad = pad = uad = dot; ! 353: sp1 = miscbuf; ! 354: sp3 = &sp1[DISSIZE]; ! 355: fs = seg_format[s]; ! 356: while (n--) { ! 357: fp = fs; ! 358: for (;;) { ! 359: c = *fp++; ! 360: if (isascii(c) && isdigit(c)) { ! 361: r = 0; ! 362: do { ! 363: r = r*10 + c-'0'; ! 364: c = *fp++; ! 365: } while (isascii(c) && isdigit(c)); ! 366: --fp; ! 367: continue; ! 368: } ! 369: switch (c) { ! 370: case '^': ! 371: add = uad; ! 372: continue; ! 373: case '+': ! 374: add += r; ! 375: r = 1; ! 376: continue; ! 377: case '-': ! 378: add -= r; ! 379: r = 1; ! 380: continue; ! 381: case 'n': ! 382: *sp1 = '\0'; ! 383: flushb(nad); ! 384: sp1 = miscbuf; ! 385: nad = add; ! 386: continue; ! 387: case 'd': ! 388: case 'o': ! 389: case 'u': ! 390: case 'x': ! 391: t2 = c; ! 392: continue; ! 393: default: ! 394: t1 = c; ! 395: if (t1=='\0' && t2=='\0') ! 396: break; ! 397: if (t1 == '\0') ! 398: t1 = 'w'; ! 399: if (t2 == '\0') ! 400: t2 = DDCHR; ! 401: uad = add; ! 402: while (r--) { ! 403: if (testint()) ! 404: return 1; ! 405: *sp1++ = ' '; ! 406: pad = add; ! 407: sp2 = conform(sp1, s, t1, t2); ! 408: if (sp2 == NULL) { ! 409: *--sp1 = '\0'; ! 410: if (sp1 != miscbuf) ! 411: flushb(nad); ! 412: dbprintf(("add=0x%lX cseg=%d\n", add, cseg)); ! 413: return printe("Addressing error"); ! 414: } ! 415: if (sp2 <= sp3) ! 416: sp1 = sp2; ! 417: else { ! 418: *--sp1 = '\0'; ! 419: flushb(nad); ! 420: *sp2 = '\0'; ! 421: *sp1 = ' '; ! 422: sp2 = sp1; ! 423: sp1 = miscbuf; ! 424: while (*sp2) ! 425: *sp1++ = *sp2++; ! 426: nad = pad; ! 427: } ! 428: if (c == 'i') { ! 429: *sp1++ = '\0'; ! 430: flushb(nad); ! 431: sp1 = miscbuf; ! 432: nad = add; ! 433: } ! 434: } ! 435: r = 1; ! 436: t2 = '\0'; ! 437: if (c != '\0') ! 438: continue; ! 439: } ! 440: break; ! 441: } ! 442: old_add = add; ! 443: } ! 444: if (sp1 != miscbuf) { ! 445: *sp1 = '\0'; ! 446: flushb(nad); ! 447: } ! 448: return 1; ! 449: } ! 450: ! 451: /* ! 452: * Execute a command string. ! 453: */ ! 454: void ! 455: execute(cmd) char *cmd; ! 456: { ! 457: register INP *ip; ! 458: ! 459: dbprintf(("execute(%s)\n", cmd)); ! 460: ! 461: /* Delete input list starting at "inpp". */ ! 462: while ((ip = inpp) != (INP *)NULL) { ! 463: inpp = ip->i_next; ! 464: nfree(ip); ! 465: } ! 466: ungotc = '\0'; /* clear ungot character */ ! 467: ! 468: /* Muck with some globals. */ ! 469: modsize = sizeof(int); ! 470: step_prev = SNULL; ! 471: dot = get_pc(); ! 472: ! 473: /* Add string "cmd" to the input list and process it. */ ! 474: if (cmd != NULL) { ! 475: add_input(ICORE, cmd); ! 476: request(); ! 477: } ! 478: ! 479: /* Check for interrupt. */ ! 480: testint(); ! 481: } ! 482: ! 483: /* ! 484: * Flush the output buffer. ! 485: * Print the given address 'addr' before the contents of the buffer ! 486: * and set dot to it. ! 487: */ ! 488: void ! 489: flushb(addr) ADDR_T addr; ! 490: { ! 491: dot = addr; ! 492: printx(addr_fmt, dot); ! 493: printx("\t%s\n", miscbuf); ! 494: } ! 495: ! 496: /* ! 497: * Display help info. ! 498: * The flag is false for :h, true for :hf. ! 499: */ ! 500: void ! 501: helpinfo(flag) int flag; ! 502: { ! 503: printf(flag ! 504: ? "[addr][,n]?[ft]\tDisplay formatted information.\n" ! 505: "Display formats:\n" ! 506: "\tb\tbyte\n" ! 507: "\tc\tchar, control and non-chars escaped\n" ! 508: "\tC\tchar, control and non-chars print as '.'\n" ! 509: "\td\tdecimal\n" ! 510: "\tf\tfloat\n" ! 511: "\tF\tdouble\n" ! 512: "\ti\tdisassembled machine instruction\n" ! 513: "\tl\tlong\n" ! 514: "\tn\toutput '\\n'\n" ! 515: "\tN\tNDP (80387) floating point register (10 bytes)\n" ! 516: "\to\toctal\n" ! 517: "\tp\tsymbolic address\n" ! 518: "\ts\tstring (NUL-terminated) with escapes\n" ! 519: "\tS\tstring (NUL-terminated)\n" ! 520: "\tu\tunsigned\n" ! 521: "\tv\tfilesystem l3 block address (3 bytes)\n" ! 522: "\tw\tword\n" ! 523: "\tx\thexadecimal\n" ! 524: "\tY\ttime\n" ! 525: "[doux] specify numeric bases (decimal, octal, unsigned decimal, hexadecimal).\n" ! 526: "Each may be followed by [bwl] to indicate a datum size [byte, word, long].\n" ! 527: : "Requests:\n" ! 528: "\t[addr][,n]?[ft]\tDisplay formatted information.\n" ! 529: "\t\t\tFormats: bcCdfFilnNopsSuvwxY [see :hf for details]\n" ! 530: "\taddr?\t\tPrint address\n" ! 531: "\t[addr]=\t\tPrint address\n" ! 532: "\t[addr]=val...\tPatch address with val...\n" ! 533: "\t?\t\tPrint last error message\n" ! 534: "\t!cmd\t\tSend cmd to system\n" ! 535: "\t[addr]:a\tPrint address\n" ! 536: "\t[addr]:b[cmd]\tSet breakpoint [to execute cmd]\n" ! 537: "\t:br[cmd]\tSet return breakpoint [to execute cmd]\n" ! 538: "\t[addr]:c\tContinue [from addr]\n" ! 539: "\t[addr]:d[r][s]\tDelete breakpoint\n" ! 540: "\t[addr]:e args\tExecute\n" ! 541: "\t:f\t\tPrint fault type\n" ! 542: "\t:h[f]\t\tPrint help information [about display formats]\n" ! 543: /* "\t:k\t\t???\n" */ ! 544: "\t:m\t\tPrint segmentation map\n" ! 545: #ifndef NOCANON ! 546: "\t[expr]:o\t\tSet canonization type\n" ! 547: #endif ! 548: "\t:p\t\tPrint breakpoints\n" ! 549: "\t[expr]:q\tQuit\n" ! 550: "\t:r[N]\t\tPrint registers [including NDP]\n" ! 551: "\t[addr][,n]:s[c]\tSingle step [over calls]\n" ! 552: "\t[expr]:t\tPrint traceback [to expr levels]\n" ! 553: "\t[expr]:x\tRead commands from stdin\n" ! 554: ); ! 555: } ! 556: ! 557: /* ! 558: * Get a long representing the current time and convert it. ! 559: */ ! 560: char * ! 561: gettime(sp, s) register char *sp; int s; ! 562: { ! 563: long l; ! 564: ! 565: if (getb(s, (char *)&l, sizeof(l)) == 0) ! 566: return NULL; ! 567: memcpy(sp, ctime(&l), 24); ! 568: return sp + 24; ! 569: } ! 570: ! 571: /* ! 572: * If the given character is unprintable, ! 573: * convert it into an escape sequence. ! 574: */ ! 575: char * ! 576: printable(sp, c) register char *sp; register int c; ! 577: { ! 578: *sp++ = '\\'; ! 579: switch (c) { ! 580: case '\0': *sp++ = '0'; break; ! 581: case '\b': *sp++ = 'b'; break; ! 582: case '\n': *sp++ = 'n'; break; ! 583: case '\f': *sp++ = 'f'; break; ! 584: case '\r': *sp++ = 'r'; break; ! 585: case '\\': *sp++ = '\\'; break; ! 586: default: ! 587: if (c<040 || c>=0177) { ! 588: sprintf(sp, "%03o", c); ! 589: while (*sp) ! 590: sp++; ! 591: break; ! 592: } ! 593: sp[-1] = c; ! 594: break; ! 595: } ! 596: return sp; ! 597: } ! 598: ! 599: /* ! 600: * Talk to the user and try to solve his problems. ! 601: */ ! 602: void ! 603: process() ! 604: { ! 605: static char *xcmd = ":x\n"; ! 606: static char *fxcmd = ":f\n:x\n"; ! 607: register BPT *bp; ! 608: register ADDR_T pc, fp; ! 609: register int n; ! 610: register int bpt_next, bpt_skipped; ! 611: int step_flag; /* 0==not step, 1==step, 2==syscall */ ! 612: ! 613: /* ! 614: * Reverse-engineered pseudocode, minus global variable garbage. ! 615: * ! 616: * forever: ! 617: * execute(":x\n") <= Preload interpreter stack. ! 618: * (Will come back after traced process traps, e.g. after ":e".) ! 619: * forever: ! 620: * See if at call instruction. ! 621: * Install breakpoints, except at current instruction. ! 622: * See if current instruction is a breakpoint opcode. ! 623: * Start up traced process, full speed or single step. ! 624: * Report any error from ptrace call. ! 625: * Wait for traced process. ! 626: * Fetch registers and signal received from traced process. ! 627: * Replace breakpoints with instructions. ! 628: * If signal to child was not SIGTRAP ! 629: * display message ! 630: * execute(":f\n:x\n"); ! 631: * continue inner loop ! 632: * Back up instruction pointer to start of the breakpoint. ! 633: * If single stepping ! 634: * Execute single step command string (step_cmd). ! 635: * If last single step in count ! 636: * execute(":x\n") ! 637: * end forever ! 638: * end forever ! 639: * ! 640: */ ! 641: top: ! 642: execute(xcmd); ! 643: for (;;) { ! 644: ! 645: /* ! 646: * If in single step mode, set up for single step. ! 647: * If in SCONT mode (for :sc), ! 648: * change to SCALL mode at call instruction. ! 649: */ ! 650: if (step_mode != SNULL && step_mode != SWAIT) { ! 651: /* Single stepping. */ ! 652: step_flag = 1; ! 653: if (step_mode == SCONT && is_call()) ! 654: step_mode = SCALL; ! 655: } else ! 656: step_flag = 0; ! 657: ! 658: /* Place all breakpoints. */ ! 659: if (reg_flag != R_INVALID) ! 660: pc = get_pc(); ! 661: for (bpt_skipped = 0, bp = &bpt[0]; bp < &bpt[NBPT]; bp++) { ! 662: ! 663: /* Skip unused table entries. */ ! 664: if (bp->b_flag == 0) ! 665: continue; ! 666: ! 667: /* ! 668: * If there is a breakpoint at the current PC, ! 669: * we do not want to install it, or we'll get nowhere. ! 670: * But if we are not single-stepping, we really want ! 671: * the breakpoint reinstalled after doing a single step. ! 672: * Kludge the mode to SSTEP and set 'bpt_skipped' in ! 673: * this case so SNULL mode gets restored after a step. ! 674: */ ! 675: if (reg_flag!=R_INVALID && bp->b_badd == pc) { ! 676: if (step_mode == SNULL) { ! 677: step_mode = SSTEP; ! 678: bpt_skipped = step_flag = 1; ! 679: } ! 680: continue; ! 681: } ! 682: ! 683: /* Install a breakpoint. */ ! 684: add = bp->b_badd; ! 685: dbprintf(("setting breakpoint @ %lX\n", add)); ! 686: if (putb(ISEG, bin, sizeof(BIN)) == 0) { ! 687: printb(bp->b_badd); ! 688: goto err; ! 689: } ! 690: } ! 691: ! 692: /* Set 'bpt_next' if next instruction is a breakpoint. */ ! 693: bpt_next = (reg_flag!=R_INVALID && bpt_test(pc)); ! 694: ! 695: /* Watch out for system calls if single stepping. */ ! 696: if (is_syscall(&step_flag) == 0) ! 697: goto err; ! 698: ! 699: /* Run the child. */ ! 700: if (runc() == 0) ! 701: goto err; ! 702: ! 703: /* Restore if we have stepped past system call. */ ! 704: if (step_flag == 2 && rest_syscall(&step_flag) == 0) ! 705: goto err; ! 706: ! 707: /* Replace breakpoints with instructions. */ ! 708: dbprintf(("Replace breakpoints with instructions\n")); ! 709: for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) { ! 710: if (bp->b_flag == 0) ! 711: continue; /* unused */ ! 712: dbprintf(("Restore instruction %X in bpt[%d]\n", bp->b_bins[0] & 0xFF, bp - bpt)); ! 713: add = bp->b_badd; ! 714: if (putb(ISEG, bp->b_bins, sizeof(BIN)) == 0) { ! 715: printb(bp->b_badd); ! 716: goto err; ! 717: } ! 718: } ! 719: ! 720: /* ! 721: * If latest signal to traced process was not SIGTRAP, ! 722: * tell the user, then accept input. ! 723: */ ! 724: if (get_sig() != SIGTRAP) { ! 725: if (get_sig() != SIGINT) ! 726: printr("Traced process did not stop at a breakpoint"); ! 727: printf("Traced process: "); ! 728: execute(fxcmd); ! 729: continue; ! 730: } ! 731: ! 732: /* Resume running following skipped breakpoint. */ ! 733: if (bpt_skipped) { ! 734: step_mode = SNULL; ! 735: continue; ! 736: } ! 737: ! 738: /* ! 739: * Find the breakpoint we are at. ! 740: * Back up pc to start of the breakpoint. ! 741: */ ! 742: bp = (BPT *)NULL; ! 743: pc = get_pc() - sizeof(BIN); ! 744: dbprintf(("find bpt: --pc=%x step_flag=%d bpt_next=%d\n", pc, step_flag, bpt_next)); ! 745: if (step_flag == 0 || bpt_next) { ! 746: for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) { ! 747: if (bp->b_flag == 0) ! 748: continue; ! 749: if (bp->b_badd != pc) ! 750: continue; ! 751: dbprintf(("found bpt[%d] at %x\n", bp-bpt, pc)); ! 752: set_pc(pc); ! 753: break; ! 754: } ! 755: if (bp == &bpt[NBPT]) ! 756: bp = (BPT *)NULL; /* unknown */ ! 757: } ! 758: ! 759: /* If in single step mode, execute command. */ ! 760: dbprintf(("step_mode=%d\n", step_mode)); ! 761: switch (step_mode) { ! 762: case SSTEP: ! 763: case SCONT: ! 764: execute(step_cmd); ! 765: if (--step_count == 0) ! 766: execute(xcmd); ! 767: continue; ! 768: case SCALL: ! 769: /* ! 770: * :sc has stepped into call with step_mode SCALL. ! 771: * Clear other BSIN breakpoints, place a BSIN breakpoint ! 772: * at the return address, and set step_mode SWAIT ! 773: * to run until the return is executed. ! 774: */ ! 775: for (n = 0; n < NBPT; n++) ! 776: bpt[n].b_flag &= ~BSIN; ! 777: step_mode = SWAIT; ! 778: set_ra_bpt(); /* set BSIN bpt at return address */ ! 779: break; ! 780: } ! 781: ! 782: /* ! 783: * Handle an unexpected trace trap or unknown breakpoint. ! 784: * One way this can happen: if the child does not handle ! 785: * SIGINT, type "100:s" followed by "<Ctrl-C>" and ":c". ! 786: * The child is interrupted, the parent prints "Interrupted" ! 787: * and prompts, ":c" resumes the child with SNULL (step_flag 0), ! 788: * and the child then hits the actual breakpoint. ! 789: * t ! 790: */ ! 791: if (bp == (BPT *)NULL) { ! 792: dbprintf(("step_mode=%d step_flag=%d bpt_next=%d\n", step_mode, step_flag, bpt_next)); ! 793: if (step_flag == 0 || bpt_next) { ! 794: printf("Unexpected "); ! 795: execute(fxcmd); ! 796: } ! 797: continue; ! 798: } ! 799: ! 800: /* Single step breakpoints have highest priority. */ ! 801: fp = get_fp(); ! 802: if (bp->b_flag & BSIN) { ! 803: if (bp->b_sfpt==0 || bp->b_sfpt == fp) { ! 804: bp->b_flag &= ~BSIN; ! 805: if (step_mode == SWAIT) { ! 806: /* ! 807: * We hit the return from a called ! 808: * function with :sc, restore SCONT mode. ! 809: */ ! 810: step_mode = SCONT; ! 811: execute(step_cmd); ! 812: if (--step_count == 0) ! 813: execute(xcmd); ! 814: continue; ! 815: } ! 816: } ! 817: } ! 818: ! 819: /* Return breakpoints are next. */ ! 820: if (bp->b_flag & BRET) { ! 821: if (bp->b_rfpt == fp) { ! 822: bp->b_flag &= ~BRET; ! 823: execute(bp->b_rcom); ! 824: continue; ! 825: } ! 826: } ! 827: ! 828: /* Your conventional everyday ordinary breakpoint. */ ! 829: if (bp->b_flag & BBPT) { ! 830: execute(bp->b_bcom); ! 831: continue; ! 832: } ! 833: } ! 834: ! 835: /* ! 836: * Something is terribly wrong. ! 837: * Kill off our child and generally reset everything to the start. ! 838: */ ! 839: err: ! 840: killc(); ! 841: initialize(); ! 842: map_init(); ! 843: if (IS_LOUT) ! 844: setloutseg(); ! 845: else if (IS_COFF) ! 846: setcoffseg(); ! 847: goto top; ! 848: } ! 849: ! 850: /* ! 851: * Parse requests and execute them. ! 852: * This is a loop which eats input and process it, ! 853: * using command() to execute commands. ! 854: * It returns when command() returns 0 or on '\n' for single step. ! 855: */ ! 856: void ! 857: request() ! 858: { ! 859: static int ttyflag = -1; ! 860: register int c; ! 861: register char *cp; ! 862: register unsigned segn; ! 863: register ADDR_T l, d; ! 864: VAL val[VALSIZE]; ! 865: ! 866: for(;;) { ! 867: /* Prompt if appropriate. */ ! 868: if (ttyflag == -1) ! 869: ttyflag = isatty(fileno(stdin)); ! 870: if (ttyflag && inpp->i_type==IFILE && inpp->i_u.i_filp==stdin) { ! 871: printf(prompt); ! 872: fflush(stdout); ! 873: } ! 874: if ((c = getn()) == EOF) ! 875: break; ! 876: ! 877: /* !cmd Execute cmd */ ! 878: if (c == '!') { ! 879: syscall(); ! 880: continue; ! 881: } ! 882: ! 883: /* ? Print fault type */ ! 884: if (c == '?') { ! 885: if ((c = getn()) != '\n') { ! 886: printe("Syntax error"); ! 887: goto next; ! 888: } ! 889: printr("%s", (lasterr == NULL) ? "No error" : lasterr); ! 890: continue; ! 891: } ! 892: ungetn(c); ! 893: if (expr_list(val) == 0) /* get expression list */ ! 894: goto next; ! 895: ! 896: switch (c = getn()) { ! 897: ! 898: /* : indicates commands, handled by command(). */ ! 899: case ':': ! 900: step_prev = SNULL; ! 901: if (command(val) == 0) ! 902: return; ! 903: continue; ! 904: ! 905: /* \n indicates more of the same, single step or display */ ! 906: case '\n': ! 907: if (nvalue(&val[0]) && step_prev != SNULL) { ! 908: if (execflag == 0) { ! 909: step_prev = SNULL; ! 910: printe("Cannot single step"); ! 911: continue; ! 912: } ! 913: step_mode = step_prev; ! 914: step_count = rvalue(&val[1], 1L); ! 915: return; ! 916: } ! 917: /* else fall through to print value */ ! 918: ! 919: /* addr\n Print value */ ! 920: /* [addr]=val Assign value */ ! 921: /* [addr]? Print value */ ! 922: case '=': ! 923: ungetn(c); ! 924: /* fall through... */ ! 925: case '?': ! 926: step_prev = SNULL; ! 927: segn = val_segn(&val[0]); ! 928: if ((c = getn()) == '=') { ! 929: l = lvalue(&val[0], dot); ! 930: if ((c = getn()) == '\n') { ! 931: dbprintf(("print seg=%d loc=%lx fmt=%s\n", segn, l, addr_fmt)); ! 932: printx(addr_fmt, l); ! 933: printx("\n"); ! 934: continue; ! 935: } ! 936: ungetn(c); ! 937: dbprintf(("assign to seg=%d loc=%lx\n", segn, l)); ! 938: if (setdata(segn, l) == 0) ! 939: break; ! 940: continue; ! 941: } ! 942: if (c != '\n') { ! 943: cp = &seg_format[segn][0]; ! 944: while (c != '\n') { ! 945: *cp++ = c; ! 946: c = getn(); ! 947: } ! 948: *cp++ = '\0'; ! 949: dbprintf(("new seg_format[%d]=%s\n", segn, seg_format[segn])); ! 950: } ! 951: d = dot; ! 952: l = old_add; ! 953: dot = lvalue(&val[0], old_add); ! 954: display(segn, (int)rvalue(&val[1], 1L)); ! 955: if (segn != USEG) ! 956: cseg = segn; /* set cseg unless USEG */ ! 957: else { ! 958: dot = d; /* restore dot, old_add if USEG */ ! 959: old_add = l; ! 960: } ! 961: continue; ! 962: ! 963: default: ! 964: step_prev = SNULL; ! 965: printe("Syntax error"); ! 966: break; ! 967: } ! 968: next: ! 969: while ((c = getn()) != '\n') ! 970: ; ! 971: } ! 972: } ! 973: ! 974: /* ! 975: * Parse the command line in 'miscbuf', ! 976: * kill the current child and start up a new one. ! 977: * Return 0 on success, 1 on failure. ! 978: */ ! 979: int ! 980: runfile() ! 981: { ! 982: register char *bp, *cp; ! 983: register int c; ! 984: char *ifn, *ofn, *argl[ARGSIZE]; ! 985: int qflag, aflag, n; ! 986: ! 987: killc(); ! 988: if (!IS_OBJ) { ! 989: printe("No executable"); ! 990: return 1; ! 991: } ! 992: ifn = ofn = NULL; ! 993: aflag = qflag = n = 0; ! 994: for (bp = cp = miscbuf, c = *bp++; c != '\n'; ) { ! 995: switch (c) { ! 996: case '<': ! 997: ifn = cp; ! 998: c = *bp++; ! 999: break; ! 1000: case '>': ! 1001: ofn = cp; ! 1002: if ((c = *bp++) == '>') { ! 1003: aflag = 1; ! 1004: c = *bp++; ! 1005: } ! 1006: break; ! 1007: default: ! 1008: if (n >= ARGSIZE-1) { ! 1009: printe("Too many arguments"); ! 1010: return 1; ! 1011: } ! 1012: argl[n++] = cp; ! 1013: } ! 1014: while (qflag || !isascii(c) || !isspace(c)) { ! 1015: if (c == '\n') ! 1016: break; ! 1017: if (c == '"') { ! 1018: qflag ^= 1; ! 1019: c = *bp++; ! 1020: continue; ! 1021: } ! 1022: if (c == '\\') { ! 1023: if ((c=*bp++) == '\n') { ! 1024: printe("Syntax error"); ! 1025: return 1; ! 1026: } ! 1027: } ! 1028: *cp++ = c; ! 1029: c = *bp++; ! 1030: } ! 1031: if (qflag) { ! 1032: printe("Missing '\"'"); ! 1033: return 1; ! 1034: } ! 1035: *cp++ = '\0'; ! 1036: if (c == '\n') ! 1037: break; ! 1038: while (isascii(c) && isspace(c)) ! 1039: c = *bp++; ! 1040: } ! 1041: if (n == 0) ! 1042: argl[n++] = lfn; ! 1043: argl[n] = NULL; ! 1044: return startc(argl, ifn, ofn, aflag) == 0; ! 1045: } ! 1046: ! 1047: /* ! 1048: * Given a pointer to an allocated buffer and a pointer to a command string, ! 1049: * copy the command string to the allocated buffer. ! 1050: * If the buffer hasn't been allocated, allocate it. ! 1051: */ ! 1052: char * ! 1053: save_cmd(buf, s) register char *buf, *s; ! 1054: { ! 1055: if (buf == NULL) ! 1056: buf = nalloc(COMSIZE, "command buffer"); ! 1057: buf[COMSIZE-1] = '\0'; ! 1058: return strncpy(buf, s, COMSIZE-1); ! 1059: } ! 1060: ! 1061: /* ! 1062: * Change the value of a location. ! 1063: */ ! 1064: int ! 1065: setdata(segn, a) int segn; ADDR_T a; ! 1066: { ! 1067: register char *cp; ! 1068: register int n; ! 1069: register int c; ! 1070: char b[1]; ! 1071: char l3[3]; ! 1072: int i[1]; ! 1073: long l[1]; ! 1074: VAL val[VALSIZE]; ! 1075: ! 1076: if (expr_list(val) == 0) ! 1077: return 0; ! 1078: if ((c = getn()) != '\n') ! 1079: return 0; ! 1080: for (n = 0; n < VALSIZE; n++, a += modsize) { ! 1081: if (nvalue(&val[n])) ! 1082: continue; ! 1083: l[0] = rvalue(&val[n], 0L); ! 1084: switch (modsize) { ! 1085: case (sizeof(char)): ! 1086: b[0] = l[0]; ! 1087: cp = b; ! 1088: break; ! 1089: case (sizeof(short)): ! 1090: i[0] = l[0]; ! 1091: cp = (char *)i; ! 1092: break; ! 1093: case (sizeof(l3)): ! 1094: ltol3(l3, l, 1); ! 1095: cp = l3; ! 1096: break; ! 1097: case (sizeof(long)): ! 1098: cp = (char *)l; ! 1099: break; ! 1100: default: ! 1101: printe("Bad change type"); ! 1102: return 1; ! 1103: } ! 1104: add = a; ! 1105: if (putb(segn, cp, modsize) == 0) { ! 1106: printe("Cannot change value"); ! 1107: return 1; ! 1108: } ! 1109: } ! 1110: if (segn == USEG) { ! 1111: /* Reread required registers after writing register data. */ ! 1112: reg_flag = R_INVALID; ! 1113: get_regs(R_SOME); ! 1114: } ! 1115: return 1; ! 1116: } ! 1117: ! 1118: /* ! 1119: * Send a command to the shell. ! 1120: * Return its exit status. ! 1121: */ ! 1122: int ! 1123: syscall() ! 1124: { ! 1125: register int c, status; ! 1126: register char *cp; ! 1127: ! 1128: for (cp = miscbuf; (c = getn()) != '\n'; ) ! 1129: *cp++ = c; ! 1130: *cp = '\0'; ! 1131: status = system(miscbuf); ! 1132: testint(); ! 1133: printf("!\n"); ! 1134: return status; ! 1135: } ! 1136: ! 1137: /* end of db/db3.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.