|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)machine.c 1.9 8/5/83"; ! 4: ! 5: /* ! 6: * Target machine dependent stuff. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "machine.h" ! 11: #include "process.h" ! 12: #include "events.h" ! 13: #include "main.h" ! 14: #include "symbols.h" ! 15: #include "source.h" ! 16: #include "mappings.h" ! 17: #include "object.h" ! 18: #include "ops.h" ! 19: #include <signal.h> ! 20: ! 21: #ifndef public ! 22: typedef unsigned int Address; ! 23: typedef unsigned char Byte; ! 24: typedef unsigned int Word; ! 25: ! 26: #define NREG 16 ! 27: ! 28: #define ARGP 12 ! 29: #define FRP 13 ! 30: #define STKP 14 ! 31: #define PROGCTR 15 ! 32: ! 33: #define BITSPERBYTE 8 ! 34: #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) ! 35: ! 36: #define nargspassed(frame) argn(0, frame) ! 37: ! 38: #include "source.h" ! 39: #include "symbols.h" ! 40: ! 41: Address pc; ! 42: Address prtaddr; ! 43: ! 44: #endif ! 45: ! 46: private Address printop(); ! 47: ! 48: /* ! 49: * Decode and print the instructions within the given address range. ! 50: */ ! 51: ! 52: public printinst(lowaddr, highaddr) ! 53: Address lowaddr; ! 54: Address highaddr; ! 55: { ! 56: register Address addr; ! 57: ! 58: for (addr = lowaddr; addr <= highaddr; ) { ! 59: addr = printop(addr); ! 60: } ! 61: prtaddr = addr; ! 62: } ! 63: ! 64: /* ! 65: * Another approach: print n instructions starting at the given address. ! 66: */ ! 67: ! 68: public printninst(count, addr) ! 69: int count; ! 70: Address addr; ! 71: { ! 72: register Integer i; ! 73: register Address newaddr; ! 74: ! 75: if (count <= 0) { ! 76: error("non-positive repetition count"); ! 77: } else { ! 78: newaddr = addr; ! 79: for (i = 0; i < count; i++) { ! 80: newaddr = printop(newaddr); ! 81: } ! 82: prtaddr = newaddr; ! 83: } ! 84: } ! 85: ! 86: /* ! 87: * Hacked version of adb's VAX instruction decoder. ! 88: */ ! 89: ! 90: private Address printop(addr) ! 91: Address addr; ! 92: { ! 93: Optab op; ! 94: VaxOpcode ins; ! 95: unsigned char mode; ! 96: int argtype, amode, argno, argval; ! 97: String reg; ! 98: Boolean indexf; ! 99: short offset; ! 100: ! 101: argval = 0; ! 102: indexf = false; ! 103: printf("%08x ", addr); ! 104: iread(&ins, addr, sizeof(ins)); ! 105: addr += 1; ! 106: op = optab[ins]; ! 107: printf("%s", op.iname); ! 108: for (argno = 0; argno < op.numargs; argno++) { ! 109: if (indexf == true) { ! 110: indexf = false; ! 111: } else if (argno == 0) { ! 112: printf("\t"); ! 113: } else { ! 114: printf(","); ! 115: } ! 116: argtype = op.argtype[argno]; ! 117: if (is_branch_disp(argtype)) { ! 118: mode = 0xAF + (typelen(argtype) << 5); ! 119: } else { ! 120: iread(&mode, addr, sizeof(mode)); ! 121: addr += 1; ! 122: } ! 123: reg = regname[regnm(mode)]; ! 124: amode = addrmode(mode); ! 125: switch (amode) { ! 126: case LITSHORT: ! 127: case LITUPTO31: ! 128: case LITUPTO47: ! 129: case LITUPTO63: ! 130: if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) ! 131: printf("$%s", fltimm[mode]); ! 132: else ! 133: printf("$%x", mode); ! 134: argval = mode; ! 135: break; ! 136: ! 137: case INDEX: ! 138: printf("[%s]", reg); ! 139: indexf = true; ! 140: argno--; ! 141: break; ! 142: ! 143: case REG: ! 144: printf("%s", reg); ! 145: break; ! 146: ! 147: case REGDEF: ! 148: printf("(%s)", reg); ! 149: break; ! 150: ! 151: case AUTODEC: ! 152: printf("-(%s)", reg); ! 153: break; ! 154: ! 155: case AUTOINC: ! 156: if (reg != regname[PROGCTR]) { ! 157: printf("(%s)+", reg); ! 158: } else { ! 159: printf("$"); ! 160: switch (typelen(argtype)) { ! 161: case TYPB: ! 162: argval = printdisp(addr, 1, reg, amode); ! 163: addr += 1; ! 164: break; ! 165: ! 166: case TYPW: ! 167: argval = printdisp(addr, 2, reg, amode); ! 168: addr += 2; ! 169: break; ! 170: ! 171: case TYPL: ! 172: argval = printdisp(addr, 4, reg, amode); ! 173: addr += 4; ! 174: break; ! 175: ! 176: case TYPF: ! 177: iread(&argval, addr, sizeof(argval)); ! 178: printf("%06x", argval); ! 179: addr += 4; ! 180: break; ! 181: ! 182: case TYPQ: ! 183: case TYPD: ! 184: iread(&argval, addr, sizeof(argval)); ! 185: printf("%06x", argval); ! 186: iread(&argval, addr+4, sizeof(argval)); ! 187: printf("%06x", argval); ! 188: addr += 8; ! 189: break; ! 190: } ! 191: } ! 192: break; ! 193: ! 194: case AUTOINCDEF: ! 195: if (reg == regname[PROGCTR]) { ! 196: printf("*$"); ! 197: argval = printdisp(addr, 4, reg, amode); ! 198: addr += 4; ! 199: } else { ! 200: printf("*(%s)+", reg); ! 201: } ! 202: break; ! 203: ! 204: case BYTEDISP: ! 205: argval = printdisp(addr, 1, reg, amode); ! 206: addr += 1; ! 207: break; ! 208: ! 209: case BYTEDISPDEF: ! 210: printf("*"); ! 211: argval = printdisp(addr, 1, reg, amode); ! 212: addr += 1; ! 213: break; ! 214: ! 215: case WORDDISP: ! 216: argval = printdisp(addr, 2, reg, amode); ! 217: addr += 2; ! 218: break; ! 219: ! 220: case WORDDISPDEF: ! 221: printf("*"); ! 222: argval = printdisp(addr, 2, reg, amode); ! 223: addr += 2; ! 224: break; ! 225: ! 226: case LONGDISP: ! 227: argval = printdisp(addr, 4, reg, amode); ! 228: addr += 4; ! 229: break; ! 230: ! 231: case LONGDISPDEF: ! 232: printf("*"); ! 233: argval = printdisp(addr, 4, reg, amode); ! 234: addr += 4; ! 235: break; ! 236: } ! 237: } ! 238: if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { ! 239: for (argno = 0; argno <= argval; argno++) { ! 240: iread(&offset, addr, sizeof(offset)); ! 241: printf("\n\t\t%d", offset); ! 242: addr += 2; ! 243: } ! 244: } ! 245: printf("\n"); ! 246: return addr; ! 247: } ! 248: ! 249: /* ! 250: * Print the displacement of an instruction that uses displacement ! 251: * addressing. ! 252: */ ! 253: ! 254: private int printdisp(addr, nbytes, reg, mode) ! 255: Address addr; ! 256: int nbytes; ! 257: char *reg; ! 258: int mode; ! 259: { ! 260: char byte; ! 261: short hword; ! 262: int argval; ! 263: Symbol f; ! 264: ! 265: switch (nbytes) { ! 266: case 1: ! 267: iread(&byte, addr, sizeof(byte)); ! 268: argval = byte; ! 269: break; ! 270: ! 271: case 2: ! 272: iread(&hword, addr, sizeof(hword)); ! 273: argval = hword; ! 274: break; ! 275: ! 276: case 4: ! 277: iread(&argval, addr, sizeof(argval)); ! 278: break; ! 279: } ! 280: if (reg == regname[PROGCTR] && mode >= BYTEDISP) { ! 281: argval += addr + nbytes; ! 282: } ! 283: if (reg == regname[PROGCTR]) { ! 284: f = whatblock((Address) argval + 2); ! 285: if (codeloc(f) == argval + 2) { ! 286: printf("%s", symname(f)); ! 287: } else { ! 288: printf("%x", argval); ! 289: } ! 290: } else { ! 291: printf("%d(%s)", argval, reg); ! 292: } ! 293: return argval; ! 294: } ! 295: ! 296: /* ! 297: * Print the contents of the addresses within the given range ! 298: * according to the given format. ! 299: */ ! 300: ! 301: typedef struct { ! 302: String name; ! 303: String printfstring; ! 304: int length; ! 305: } Format; ! 306: ! 307: private Format fmt[] = { ! 308: { "d", " %d", sizeof(short) }, ! 309: { "D", " %ld", sizeof(long) }, ! 310: { "o", " %o", sizeof(short) }, ! 311: { "O", " %lo", sizeof(long) }, ! 312: { "x", " %04x", sizeof(short) }, ! 313: { "X", " %08x", sizeof(long) }, ! 314: { "b", " \\%o", sizeof(char) }, ! 315: { "c", " '%c'", sizeof(char) }, ! 316: { "s", "%c", sizeof(char) }, ! 317: { "f", " %f", sizeof(float) }, ! 318: { "g", " %g", sizeof(double) }, ! 319: { nil, nil, 0 } ! 320: }; ! 321: ! 322: private Format *findformat(s) ! 323: String s; ! 324: { ! 325: register Format *f; ! 326: ! 327: f = &fmt[0]; ! 328: while (f->name != nil and not streq(f->name, s)) { ! 329: ++f; ! 330: } ! 331: if (f->name == nil) { ! 332: error("bad print format \"%s\"", s); ! 333: } ! 334: return f; ! 335: } ! 336: ! 337: public Address printdata(lowaddr, highaddr, format) ! 338: Address lowaddr; ! 339: Address highaddr; ! 340: String format; ! 341: { ! 342: register int n; ! 343: register Address addr; ! 344: register Format *f; ! 345: int value; ! 346: ! 347: if (lowaddr > highaddr) { ! 348: error("first address larger than second"); ! 349: } ! 350: f = findformat(format); ! 351: n = 0; ! 352: value = 0; ! 353: for (addr = lowaddr; addr <= highaddr; addr += f->length) { ! 354: if (n == 0) { ! 355: printf("%08x: ", addr); ! 356: } ! 357: dread(&value, addr, f->length); ! 358: printf(f->printfstring, value); ! 359: ++n; ! 360: if (n >= (16 div f->length)) { ! 361: putchar('\n'); ! 362: n = 0; ! 363: } ! 364: } ! 365: if (n != 0) { ! 366: putchar('\n'); ! 367: } ! 368: prtaddr = addr; ! 369: return addr; ! 370: } ! 371: ! 372: /* ! 373: * The other approach is to print n items starting with a given address. ! 374: */ ! 375: ! 376: public printndata(count, startaddr, format) ! 377: int count; ! 378: Address startaddr; ! 379: String format; ! 380: { ! 381: register int i, n; ! 382: register Address addr; ! 383: register Format *f; ! 384: register Boolean isstring; ! 385: char c; ! 386: union { ! 387: char charv; ! 388: short shortv; ! 389: int intv; ! 390: float floatv; ! 391: double doublev; ! 392: } value; ! 393: ! 394: if (count <= 0) { ! 395: error("non-positive repetition count"); ! 396: } ! 397: f = findformat(format); ! 398: isstring = (Boolean) streq(f->name, "s"); ! 399: n = 0; ! 400: addr = startaddr; ! 401: value.intv = 0; ! 402: for (i = 0; i < count; i++) { ! 403: if (n == 0) { ! 404: printf("%08x: ", addr); ! 405: } ! 406: if (isstring) { ! 407: putchar('"'); ! 408: dread(&c, addr, sizeof(char)); ! 409: while (c != '\0') { ! 410: printchar(c); ! 411: ++addr; ! 412: dread(&c, addr, sizeof(char)); ! 413: } ! 414: putchar('"'); ! 415: putchar('\n'); ! 416: n = 0; ! 417: addr += sizeof(String); ! 418: } else { ! 419: dread(&value, addr, f->length); ! 420: printf(f->printfstring, value); ! 421: ++n; ! 422: if (n >= (16 div f->length)) { ! 423: putchar('\n'); ! 424: n = 0; ! 425: } ! 426: addr += f->length; ! 427: } ! 428: } ! 429: if (n != 0) { ! 430: putchar('\n'); ! 431: } ! 432: prtaddr = addr; ! 433: } ! 434: ! 435: /* ! 436: * Print out a value according to the given format. ! 437: */ ! 438: ! 439: public printvalue(v, format) ! 440: long v; ! 441: String format; ! 442: { ! 443: Format *f; ! 444: char *p, *q; ! 445: ! 446: f = findformat(format); ! 447: if (streq(f->name, "s")) { ! 448: putchar('"'); ! 449: p = (char *) &v; ! 450: q = p + sizeof(v); ! 451: while (p < q) { ! 452: printchar(*p); ! 453: ++p; ! 454: } ! 455: putchar('"'); ! 456: } else { ! 457: printf(f->printfstring, v); ! 458: } ! 459: putchar('\n'); ! 460: } ! 461: ! 462: /* ! 463: * Print out an execution time error. ! 464: * Assumes the source position of the error has been calculated. ! 465: * ! 466: * Have to check if the -r option was specified; if so then ! 467: * the object file information hasn't been read in yet. ! 468: */ ! 469: ! 470: public printerror() ! 471: { ! 472: extern Integer sys_nsig; ! 473: extern String sys_siglist[]; ! 474: Integer err; ! 475: ! 476: if (isfinished(process)) { ! 477: printf("\"%s\" exits with code %d\n", objname, exitcode(process)); ! 478: erecover(); ! 479: } ! 480: if (runfirst) { ! 481: fprintf(stderr, "Entering debugger ..."); ! 482: init(); ! 483: fprintf(stderr, " type 'help' for help\n"); ! 484: } ! 485: err = errnum(process); ! 486: if (err == SIGINT) { ! 487: printf("\n\ninterrupt "); ! 488: printloc(); ! 489: } else if (err == SIGTRAP) { ! 490: printf("\nerror "); ! 491: printloc(); ! 492: } else { ! 493: if (err < 0 or err > sys_nsig) { ! 494: printf("\nsignal %d ", err); ! 495: } else { ! 496: printf("\n%s ", sys_siglist[err]); ! 497: } ! 498: printloc(); ! 499: } ! 500: putchar('\n'); ! 501: if (curline > 0) { ! 502: printlines(curline, curline); ! 503: } else { ! 504: printinst(pc, pc); ! 505: } ! 506: erecover(); ! 507: } ! 508: ! 509: /* ! 510: * Note the termination of the program. We do this so as to avoid ! 511: * having the process exit, which would make the values of variables ! 512: * inaccessible. We do want to flush all output buffers here, ! 513: * otherwise it'll never get done. ! 514: */ ! 515: ! 516: public endprogram() ! 517: { ! 518: Integer exitcode; ! 519: ! 520: stepto(nextaddr(pc, true)); ! 521: printnews(); ! 522: exitcode = argn(1, nil); ! 523: printf("\nexecution completed, exit code is %d\n", exitcode); ! 524: getsrcpos(); ! 525: erecover(); ! 526: } ! 527: ! 528: /* ! 529: * Single step the machine a source line (or instruction if "inst_tracing" ! 530: * is true). If "isnext" is true, skip over procedure calls. ! 531: */ ! 532: ! 533: private Address getcall(); ! 534: ! 535: public dostep(isnext) ! 536: Boolean isnext; ! 537: { ! 538: register Address addr; ! 539: register Lineno line; ! 540: String filename; ! 541: ! 542: addr = nextaddr(pc, isnext); ! 543: if (not inst_tracing and nlhdr.nlines != 0) { ! 544: line = linelookup(addr); ! 545: while (line == 0) { ! 546: addr = nextaddr(addr, isnext); ! 547: line = linelookup(addr); ! 548: } ! 549: curline = line; ! 550: } else { ! 551: curline = 0; ! 552: } ! 553: stepto(addr); ! 554: filename = srcfilename(addr); ! 555: setsource(filename); ! 556: } ! 557: ! 558: /* ! 559: * Compute the next address that will be executed from the given one. ! 560: * If "isnext" is true then consider a procedure call as straight line code. ! 561: * ! 562: * We must unfortunately do much of the same work that is necessary ! 563: * to print instructions. In addition we have to deal with branches. ! 564: * Unconditional branches we just follow, for conditional branches ! 565: * we continue execution to the current location and then single step ! 566: * the machine. We assume that the last argument in an instruction ! 567: * that branches is the branch address (or relative offset). ! 568: */ ! 569: ! 570: public Address nextaddr(startaddr, isnext) ! 571: Address startaddr; ! 572: Boolean isnext; ! 573: { ! 574: register Address addr; ! 575: Optab op; ! 576: VaxOpcode ins; ! 577: unsigned char mode; ! 578: int argtype, amode, argno, argval; ! 579: String r; ! 580: Boolean indexf; ! 581: enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; ! 582: ! 583: argval = 0; ! 584: indexf = false; ! 585: addr = startaddr; ! 586: iread(&ins, addr, sizeof(ins)); ! 587: switch (ins) { ! 588: case O_BRB: ! 589: case O_BRW: ! 590: case O_JMP: ! 591: addrstatus = BRANCH; ! 592: break; ! 593: ! 594: case O_BSBB: ! 595: case O_BSBW: ! 596: case O_JSB: ! 597: case O_CALLG: ! 598: case O_CALLS: ! 599: if (isnext) { ! 600: addrstatus = SEQUENTIAL; ! 601: } else { ! 602: addrstatus = KNOWN; ! 603: stepto(addr); ! 604: pstep(process); ! 605: addr = reg(PROGCTR); ! 606: pc = addr; ! 607: curfunc = whatblock(pc); ! 608: if (not isbperr()) { ! 609: printstatus(); ! 610: /* NOTREACHED */ ! 611: } ! 612: bpact(); ! 613: if (nosource(curfunc) and canskip(curfunc) and ! 614: nlhdr.nlines != 0) { ! 615: addrstatus = KNOWN; ! 616: addr = return_addr(); ! 617: stepto(addr); ! 618: bpact(); ! 619: } else { ! 620: callnews(/* iscall = */ true); ! 621: } ! 622: } ! 623: break; ! 624: ! 625: case O_RSB: ! 626: case O_RET: ! 627: addrstatus = KNOWN; ! 628: callnews(/* iscall = */ false); ! 629: addr = return_addr(); ! 630: stepto(addr); ! 631: bpact(); ! 632: break; ! 633: ! 634: case O_BNEQ: case O_BEQL: case O_BGTR: ! 635: case O_BLEQ: case O_BGEQ: case O_BLSS: ! 636: case O_BGTRU: case O_BLEQU: case O_BVC: ! 637: case O_BVS: case O_BCC: case O_BCS: ! 638: case O_CASEB: case O_CASEW: case O_CASEL: ! 639: case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: ! 640: case O_BBSC: case O_BBCC: case O_BBSSI: ! 641: case O_BBCCI: case O_BLBS: case O_BLBC: ! 642: case O_ACBL: case O_AOBLSS: case O_AOBLEQ: ! 643: case O_SOBGEQ: case O_SOBGTR: ! 644: addrstatus = KNOWN; ! 645: stepto(addr); ! 646: pstep(process); ! 647: addr = reg(PROGCTR); ! 648: pc = addr; ! 649: if (not isbperr()) { ! 650: printstatus(); ! 651: } ! 652: break; ! 653: ! 654: default: ! 655: addrstatus = SEQUENTIAL; ! 656: break; ! 657: } ! 658: if (addrstatus != KNOWN) { ! 659: addr += 1; ! 660: op = optab[ins]; ! 661: for (argno = 0; argno < op.numargs; argno++) { ! 662: if (indexf == true) { ! 663: indexf = false; ! 664: } ! 665: argtype = op.argtype[argno]; ! 666: if (is_branch_disp(argtype)) { ! 667: mode = 0xAF + (typelen(argtype) << 5); ! 668: } else { ! 669: iread(&mode, addr, sizeof(mode)); ! 670: addr += 1; ! 671: } ! 672: r = regname[regnm(mode)]; ! 673: amode = addrmode(mode); ! 674: switch (amode) { ! 675: case LITSHORT: ! 676: case LITUPTO31: ! 677: case LITUPTO47: ! 678: case LITUPTO63: ! 679: argval = mode; ! 680: break; ! 681: ! 682: case INDEX: ! 683: indexf = true; ! 684: --argno; ! 685: break; ! 686: ! 687: case REG: ! 688: case REGDEF: ! 689: case AUTODEC: ! 690: break; ! 691: ! 692: case AUTOINC: ! 693: if (r == regname[PROGCTR]) { ! 694: switch (typelen(argtype)) { ! 695: case TYPB: ! 696: argval = getdisp(addr, 1, r, amode); ! 697: addr += 1; ! 698: break; ! 699: ! 700: case TYPW: ! 701: argval = getdisp(addr, 2, r, amode); ! 702: addr += 2; ! 703: break; ! 704: ! 705: case TYPL: ! 706: argval = getdisp(addr, 4, r, amode); ! 707: addr += 4; ! 708: break; ! 709: ! 710: case TYPF: ! 711: iread(&argval, addr, sizeof(argval)); ! 712: addr += 4; ! 713: break; ! 714: ! 715: case TYPQ: ! 716: case TYPD: ! 717: iread(&argval, addr+4, sizeof(argval)); ! 718: addr += 8; ! 719: break; ! 720: } ! 721: } ! 722: break; ! 723: ! 724: case AUTOINCDEF: ! 725: if (r == regname[PROGCTR]) { ! 726: argval = getdisp(addr, 4, r, amode); ! 727: addr += 4; ! 728: } ! 729: break; ! 730: ! 731: case BYTEDISP: ! 732: case BYTEDISPDEF: ! 733: argval = getdisp(addr, 1, r, amode); ! 734: addr += 1; ! 735: break; ! 736: ! 737: case WORDDISP: ! 738: case WORDDISPDEF: ! 739: argval = getdisp(addr, 2, r, amode); ! 740: addr += 2; ! 741: break; ! 742: ! 743: case LONGDISP: ! 744: case LONGDISPDEF: ! 745: argval = getdisp(addr, 4, r, amode); ! 746: addr += 4; ! 747: break; ! 748: } ! 749: } ! 750: if (ins == O_CALLS or ins == O_CALLG) { ! 751: argval += 2; ! 752: } ! 753: if (addrstatus == BRANCH) { ! 754: addr = argval; ! 755: } ! 756: } ! 757: return addr; ! 758: } ! 759: ! 760: /* ! 761: * Get the displacement of an instruction that uses displacement addressing. ! 762: */ ! 763: ! 764: private int getdisp(addr, nbytes, reg, mode) ! 765: Address addr; ! 766: int nbytes; ! 767: String reg; ! 768: int mode; ! 769: { ! 770: char byte; ! 771: short hword; ! 772: int argval; ! 773: ! 774: switch (nbytes) { ! 775: case 1: ! 776: iread(&byte, addr, sizeof(byte)); ! 777: argval = byte; ! 778: break; ! 779: ! 780: case 2: ! 781: iread(&hword, addr, sizeof(hword)); ! 782: argval = hword; ! 783: break; ! 784: ! 785: case 4: ! 786: iread(&argval, addr, sizeof(argval)); ! 787: break; ! 788: } ! 789: if (reg == regname[PROGCTR] && mode >= BYTEDISP) { ! 790: argval += addr + nbytes; ! 791: } ! 792: return argval; ! 793: } ! 794: ! 795: #define BP_OP O_BPT /* breakpoint trap */ ! 796: #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ ! 797: ! 798: /* ! 799: * Setting a breakpoint at a location consists of saving ! 800: * the word at the location and poking a BP_OP there. ! 801: * ! 802: * We save the locations and words on a list for use in unsetting. ! 803: */ ! 804: ! 805: typedef struct Savelist *Savelist; ! 806: ! 807: struct Savelist { ! 808: Address location; ! 809: Byte save; ! 810: Byte refcount; ! 811: Savelist link; ! 812: }; ! 813: ! 814: private Savelist savelist; ! 815: ! 816: /* ! 817: * Set a breakpoint at the given address. Only save the word there ! 818: * if it's not already a breakpoint. ! 819: */ ! 820: ! 821: public setbp(addr) ! 822: Address addr; ! 823: { ! 824: Byte w; ! 825: Byte save; ! 826: register Savelist newsave, s; ! 827: ! 828: for (s = savelist; s != nil; s = s->link) { ! 829: if (s->location == addr) { ! 830: s->refcount++; ! 831: return; ! 832: } ! 833: } ! 834: iread(&save, addr, sizeof(save)); ! 835: newsave = new(Savelist); ! 836: newsave->location = addr; ! 837: newsave->save = save; ! 838: newsave->refcount = 1; ! 839: newsave->link = savelist; ! 840: savelist = newsave; ! 841: w = BP_OP; ! 842: iwrite(&w, addr, sizeof(w)); ! 843: } ! 844: ! 845: /* ! 846: * Unset a breakpoint; unfortunately we have to search the SAVELIST ! 847: * to find the saved value. The assumption is that the SAVELIST will ! 848: * usually be quite small. ! 849: */ ! 850: ! 851: public unsetbp(addr) ! 852: Address addr; ! 853: { ! 854: register Savelist s, prev; ! 855: ! 856: prev = nil; ! 857: for (s = savelist; s != nil; s = s->link) { ! 858: if (s->location == addr) { ! 859: iwrite(&s->save, addr, sizeof(s->save)); ! 860: s->refcount--; ! 861: if (s->refcount == 0) { ! 862: if (prev == nil) { ! 863: savelist = s->link; ! 864: } else { ! 865: prev->link = s->link; ! 866: } ! 867: dispose(s); ! 868: } ! 869: return; ! 870: } ! 871: prev = s; ! 872: } ! 873: panic("unsetbp: couldn't find address %d", addr); ! 874: } ! 875: ! 876: /* ! 877: * Predicate to test if the reason the process stopped was because ! 878: * of a breakpoint. ! 879: */ ! 880: ! 881: public Boolean isbperr() ! 882: { ! 883: return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP); ! 884: } ! 885: ! 886: /* ! 887: * Enter a procedure by creating and executing a call instruction. ! 888: */ ! 889: ! 890: #define CALLSIZE 7 /* size of call instruction */ ! 891: ! 892: public beginproc(p, argc) ! 893: Symbol p; ! 894: Integer argc; ! 895: { ! 896: char save[CALLSIZE]; ! 897: struct { ! 898: VaxOpcode op; ! 899: unsigned char numargs; ! 900: unsigned char mode; ! 901: char addr[sizeof(long)]; /* unaligned long */ ! 902: } call; ! 903: long dest; ! 904: ! 905: pc = 2; ! 906: iread(save, pc, sizeof(save)); ! 907: call.op = O_CALLS; ! 908: call.numargs = argc; ! 909: call.mode = 0xef; ! 910: dest = codeloc(p) - 2 - (pc + 7); ! 911: mov(&dest, call.addr, sizeof(call.addr)); ! 912: iwrite(&call, pc, sizeof(call)); ! 913: setreg(PROGCTR, pc); ! 914: pstep(process); ! 915: iwrite(save, pc, sizeof(save)); ! 916: pc = reg(PROGCTR); ! 917: if (not isbperr()) { ! 918: printstatus(); ! 919: } ! 920: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.