|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)tahoe.c 5.8 (Berkeley) 6/1/90"; ! 22: #endif /* not lint */ ! 23: ! 24: /* ! 25: * Target machine dependent stuff. ! 26: */ ! 27: ! 28: #include "defs.h" ! 29: #include "machine.h" ! 30: #include "process.h" ! 31: #include "runtime.h" ! 32: #include "events.h" ! 33: #include "main.h" ! 34: #include "symbols.h" ! 35: #include "source.h" ! 36: #include "mappings.h" ! 37: #include "object.h" ! 38: #include "keywords.h" ! 39: #include "ops.h" ! 40: #include "eval.h" ! 41: #include <signal.h> ! 42: ! 43: #ifndef public ! 44: typedef unsigned int Address; ! 45: typedef unsigned char Byte; ! 46: typedef unsigned int Word; ! 47: ! 48: #define NREG 16 ! 49: ! 50: #define FRP 13 ! 51: #define STKP 14 ! 52: #define PROGCTR 15 ! 53: ! 54: #define CODESTART 0 ! 55: #define FUNCOFFSET 2 ! 56: ! 57: #define BITSPERBYTE 8 ! 58: #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) ! 59: ! 60: /* ! 61: * This magic macro enables us to look at the process' registers ! 62: * in its user structure. ! 63: */ ! 64: ! 65: #define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg))) ! 66: ! 67: #define nargspassed(frame) (((argn(-1, frame)&0xffff)-4)/4) ! 68: ! 69: #define SYSBASE 0xc0000000 /* base of system address space */ ! 70: #define physaddr(a) ((a) &~ 0xc0000000) ! 71: ! 72: #include "source.h" ! 73: #include "symbols.h" ! 74: #include <sys/param.h> ! 75: #include <machine/psl.h> ! 76: #include <sys/user.h> ! 77: #undef DELETE /* XXX */ ! 78: #include <sys/vm.h> ! 79: #include <machine/reg.h> ! 80: #include <machine/pte.h> ! 81: ! 82: Address pc; ! 83: Address prtaddr; ! 84: ! 85: #endif ! 86: ! 87: /* ! 88: * Indices into u. for use in collecting registers values. ! 89: */ ! 90: public int rloc[] = ! 91: { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, FP, SP, PC }; ! 92: ! 93: private Address printop(); ! 94: ! 95: Optab *ioptab[256]; /* index by opcode to optab */ ! 96: /* ! 97: * Initialize the opcode lookup table. ! 98: */ ! 99: public optab_init() ! 100: { ! 101: register Optab *p; ! 102: ! 103: for (p = optab; p->iname; p++) ! 104: ioptab[p->val & 0xff] = p; ! 105: } ! 106: ! 107: /* ! 108: * Decode and print the instructions within the given address range. ! 109: */ ! 110: public printinst(lowaddr, highaddr) ! 111: Address lowaddr, highaddr; ! 112: { ! 113: register Address addr; ! 114: ! 115: for (addr = lowaddr; addr <= highaddr; ) ! 116: addr = printop(addr); ! 117: prtaddr = addr; ! 118: } ! 119: ! 120: /* ! 121: * Another approach: print n instructions starting at the given address. ! 122: */ ! 123: public printninst(count, addr) ! 124: int count; ! 125: Address addr; ! 126: { ! 127: register Integer i; ! 128: register Address newaddr; ! 129: ! 130: if (count <= 0) ! 131: error("non-positive repetition count"); ! 132: for (newaddr = addr, i = 0; i < count; i++) ! 133: newaddr = printop(newaddr); ! 134: prtaddr = newaddr; ! 135: } ! 136: ! 137: /* ! 138: * Hacked version of adb's instruction decoder. ! 139: */ ! 140: private Address printop(addr) ! 141: Address addr; ! 142: { ! 143: register Optab *op; ! 144: Opcode ins; ! 145: unsigned char mode; ! 146: int argtype, amode, argno, argval, r; ! 147: String reg; ! 148: Boolean indexf; ! 149: short offset; ! 150: ! 151: argval = 0; ! 152: indexf = false; ! 153: printf("%08x ", addr); ! 154: iread(&ins, addr, sizeof(ins)); ! 155: addr += 1; ! 156: op = ioptab[ins]; ! 157: printf("%s", op->iname); ! 158: for (argno = 0; argno < op->numargs; argno++) { ! 159: if (indexf == true) ! 160: indexf = false; ! 161: else ! 162: printf(argno == 0 ? "\t" : ","); ! 163: argtype = op->argtype[argno]; ! 164: if (is_branch_disp(argtype)) ! 165: mode = 0xAF + (typelen(argtype) << 5); ! 166: else ! 167: iread(&mode, addr, sizeof(mode)), addr += 1; ! 168: reg = regname[regnm(mode)]; ! 169: amode = addrmode(mode); ! 170: switch (amode) { ! 171: ! 172: case LITSHORT: case LITUPTO31: ! 173: case LITUPTO47: case LITUPTO63: ! 174: if (ins == O_KCALL && mode >= 0 && mode < SYSSIZE && ! 175: systab[mode]) ! 176: printf("$%s", systab[mode]); ! 177: else ! 178: printf("$%x", mode); ! 179: argval = mode; ! 180: break; ! 181: ! 182: case INDEX: ! 183: printf("[%s]", reg); ! 184: indexf = true; ! 185: argno--; ! 186: break; ! 187: ! 188: case REG: ! 189: printf("%s", reg); ! 190: break; ! 191: ! 192: case REGDEF: ! 193: printf("(%s)", reg); ! 194: break; ! 195: ! 196: case AUTODEC: ! 197: printf("-(%s)", reg); ! 198: break; ! 199: ! 200: case AUTOINC: ! 201: r = mode & 0xf; ! 202: if (r == 0xf || r == 8 || r == 9) { ! 203: int size = (mode&03) + 1; ! 204: ! 205: /* immediate mode */ ! 206: printf("$"); ! 207: argval = printdisp(addr, size, ! 208: regname[PROGCTR], amode); ! 209: addr += size; ! 210: } else ! 211: printf("(%s)+", reg); ! 212: break; ! 213: ! 214: case AUTOINCDEF: ! 215: if ((mode&0xf) == 0xf) { ! 216: printf("*$"); ! 217: argval = printdisp(addr, 4, reg, amode); ! 218: addr += 4; ! 219: } else ! 220: printf("*(%s)+", reg); ! 221: break; ! 222: ! 223: case BYTEDISP: ! 224: argval = printdisp(addr, 1, reg, amode); ! 225: addr += 1; ! 226: break; ! 227: ! 228: case BYTEDISPDEF: ! 229: printf("*"); ! 230: argval = printdisp(addr, 1, reg, amode); ! 231: addr += 1; ! 232: break; ! 233: ! 234: case WORDDISP: ! 235: argval = printdisp(addr, 2, reg, amode); ! 236: addr += 2; ! 237: break; ! 238: ! 239: case WORDDISPDEF: ! 240: printf("*"); ! 241: argval = printdisp(addr, 2, reg, amode); ! 242: addr += 2; ! 243: break; ! 244: ! 245: case LONGDISP: ! 246: argval = printdisp(addr, 4, reg, amode); ! 247: addr += 4; ! 248: break; ! 249: ! 250: case LONGDISPDEF: ! 251: printf("*"); ! 252: argval = printdisp(addr, 4, reg, amode); ! 253: addr += 4; ! 254: break; ! 255: } ! 256: } ! 257: if (ins == O_CASEL) ! 258: for (argno = 0; argno <= argval; argno++) { ! 259: iread(&offset, addr, sizeof(offset)); ! 260: printf("\n\t\t%d", offset); ! 261: addr += 2; ! 262: } ! 263: printf("\n"); ! 264: return (addr); ! 265: } ! 266: ! 267: /* ! 268: * Print the displacement of an instruction that uses displacement ! 269: * addressing. ! 270: */ ! 271: private int printdisp(addr, nbytes, reg, mode) ! 272: Address addr; ! 273: int nbytes; ! 274: char *reg; ! 275: int mode; ! 276: { ! 277: char byte; ! 278: short hword; ! 279: int argval; ! 280: Symbol f; ! 281: ! 282: switch (nbytes) { ! 283: ! 284: case 1: ! 285: iread(&byte, addr, sizeof(byte)); ! 286: argval = byte; ! 287: break; ! 288: ! 289: case 2: ! 290: iread(&hword, addr, sizeof(hword)); ! 291: argval = hword; ! 292: break; ! 293: ! 294: case 4: ! 295: iread(&argval, addr, sizeof(argval)); ! 296: break; ! 297: } ! 298: if (reg == regname[PROGCTR] && mode >= BYTEDISP) ! 299: argval += addr + nbytes; ! 300: if (reg == regname[PROGCTR]) { ! 301: f = whatblock((Address) argval + 2); ! 302: if (codeloc(f) == argval + 2) ! 303: printf("%s", symname(f)); ! 304: else ! 305: printf("%x", argval); ! 306: } else { ! 307: if (varIsSet("$hexoffsets")) { ! 308: if (argval < 0) ! 309: printf("-%x(%s)", -(argval), reg); ! 310: else ! 311: printf("%x(%s)", argval, reg); ! 312: } else ! 313: printf("%d(%s)", argval, reg); ! 314: } ! 315: return (argval); ! 316: } ! 317: ! 318: /* ! 319: * Print the contents of the addresses within the given range ! 320: * according to the given format. ! 321: */ ! 322: typedef struct { ! 323: String name; ! 324: String printfstring; ! 325: int length; ! 326: } Format; ! 327: ! 328: private Format fmt[] = { ! 329: { "d", " %d", sizeof(short) }, ! 330: { "D", " %ld", sizeof(long) }, ! 331: { "o", " %o", sizeof(short) }, ! 332: { "O", " %lo", sizeof(long) }, ! 333: { "x", " %04x", sizeof(short) }, ! 334: { "X", " %08x", sizeof(long) }, ! 335: { "b", " \\%o", sizeof(char) }, ! 336: { "c", " '%c'", sizeof(char) }, ! 337: { "s", "%c", sizeof(char) }, ! 338: { "f", " %f", sizeof(float) }, ! 339: { "g", " %g", sizeof(double) }, ! 340: { nil, nil, 0 } ! 341: }; ! 342: ! 343: private Format *findformat(s) ! 344: String s; ! 345: { ! 346: register Format *f; ! 347: ! 348: for (f = &fmt[0]; f->name != nil && !streq(f->name, s); f++) ! 349: ; ! 350: if (f->name == nil) ! 351: error("bad print format \"%s\"", s); ! 352: return (f); ! 353: } ! 354: ! 355: public Address printdata(lowaddr, highaddr, format) ! 356: Address lowaddr; ! 357: Address highaddr; ! 358: String format; ! 359: { ! 360: register int n; ! 361: register Address addr; ! 362: register Format *f; ! 363: int value; ! 364: ! 365: if (lowaddr > highaddr) ! 366: error("first address larger than second"); ! 367: f = findformat(format); ! 368: n = 0; ! 369: value = 0; ! 370: for (addr = lowaddr; addr <= highaddr; addr += f->length) { ! 371: if (n == 0) ! 372: printf("%08x: ", addr); ! 373: dread(&value, addr, f->length); ! 374: printf(f->printfstring, value); ! 375: ++n; ! 376: if (n >= (16 div f->length)) { ! 377: putchar('\n'); ! 378: n = 0; ! 379: } ! 380: } ! 381: if (n != 0) ! 382: putchar('\n'); ! 383: prtaddr = addr; ! 384: return (addr); ! 385: } ! 386: ! 387: /* ! 388: * The other approach is to print n items starting with a given address. ! 389: */ ! 390: ! 391: public printndata(count, startaddr, format) ! 392: int count; ! 393: Address startaddr; ! 394: String format; ! 395: { ! 396: register int i, n; ! 397: register Address addr; ! 398: register Format *f; ! 399: register Boolean isstring; ! 400: char c; ! 401: union { ! 402: char charv; ! 403: short shortv; ! 404: int intv; ! 405: float floatv; ! 406: double doublev; ! 407: } value; ! 408: ! 409: if (count <= 0) ! 410: error("non-positive repetition count"); ! 411: f = findformat(format); ! 412: isstring = (Boolean) streq(f->name, "s"); ! 413: n = 0; ! 414: addr = startaddr; ! 415: value.intv = 0; ! 416: for (i = 0; i < count; i++) { ! 417: if (n == 0) ! 418: printf("%08x: ", addr); ! 419: if (isstring) { ! 420: putchar('"'); ! 421: dread(&c, addr, sizeof(char)); ! 422: while (c != '\0') { ! 423: printchar(c); ! 424: ++addr; ! 425: dread(&c, addr, sizeof(char)); ! 426: } ! 427: putchar('"'); ! 428: putchar('\n'); ! 429: n = 0; ! 430: addr += sizeof(String); ! 431: continue; ! 432: } ! 433: dread(&value, addr, f->length); ! 434: printf(f->printfstring, value); ! 435: ++n; ! 436: if (n >= (16 div f->length)) { ! 437: putchar('\n'); ! 438: n = 0; ! 439: } ! 440: addr += f->length; ! 441: } ! 442: if (n != 0) ! 443: putchar('\n'); ! 444: prtaddr = addr; ! 445: } ! 446: ! 447: /* ! 448: * Print out a value according to the given format. ! 449: */ ! 450: public printvalue(v, format) ! 451: long v; ! 452: String format; ! 453: { ! 454: Format *f; ! 455: char *p, *q; ! 456: ! 457: f = findformat(format); ! 458: if (streq(f->name, "s")) { ! 459: putchar('"'); ! 460: for (p = (char *) &v, q = p + sizeof(v); p < q; ++p) ! 461: printchar(*p); ! 462: putchar('"'); ! 463: } else ! 464: printf(f->printfstring, v); ! 465: putchar('\n'); ! 466: } ! 467: ! 468: /* ! 469: * Print out an execution time error. ! 470: * Assumes the source position of the error has been calculated. ! 471: * ! 472: * Have to check if the -r option was specified; if so then ! 473: * the object file information hasn't been read in yet. ! 474: */ ! 475: public printerror() ! 476: { ! 477: extern Integer sys_nsig; ! 478: extern String sys_siglist[]; ! 479: integer err; ! 480: ! 481: if (isfinished(process)) { ! 482: err = exitcode(process); ! 483: if (err) { ! 484: printf("\"%s\" terminated abnormally (exit code %d)\n", ! 485: objname, err); ! 486: erecover(); ! 487: } else ! 488: printf("\"%s\" terminated normally\n", objname); ! 489: } ! 490: if (runfirst) { ! 491: fprintf(stderr, "Entering debugger ...\n"); ! 492: init(); ! 493: } ! 494: err = errnum(process); ! 495: putchar('\n'); ! 496: printsig(err); ! 497: putchar(' '); ! 498: printloc(); ! 499: putchar('\n'); ! 500: if (curline > 0) ! 501: printlines(curline, curline); ! 502: else ! 503: printinst(pc, pc); ! 504: erecover(); ! 505: } ! 506: ! 507: /* ! 508: * Print out a signal. ! 509: */ ! 510: private String illinames[] = { ! 511: "reserved addressing fault", ! 512: "privileged instruction fault", ! 513: "reserved operand fault" ! 514: }; ! 515: #define NILLINAMES (sizeof (illinames) / sizeof (illinames[0])) ! 516: ! 517: private String fpenames[] = { ! 518: nil, ! 519: "integer overflow trap", ! 520: "integer divide by zero trap", ! 521: "floating point divide by zero trap", ! 522: "floating point overflow trap", ! 523: "floating point underflow trap", ! 524: }; ! 525: #define NFPENAMES (sizeof (fpenames) / sizeof (fpenames[0])) ! 526: ! 527: public printsig(signo) ! 528: integer signo; ! 529: { ! 530: integer code; ! 531: ! 532: if (signo < 0 or signo > sys_nsig) ! 533: printf("[signal %d]", signo); ! 534: else ! 535: printf("%s", sys_siglist[signo]); ! 536: code = errcode(process); ! 537: if (signo == SIGILL) ! 538: if (code >= 0 && code < NILLINAMES) ! 539: printf(" (%s)", illinames[code]); ! 540: if (signo == SIGFPE) ! 541: if (code > 0 and code < NFPENAMES) ! 542: printf(" (%s)", fpenames[code]); ! 543: } ! 544: ! 545: /* ! 546: * Note the termination of the program. We do this so as to avoid ! 547: * having the process exit, which would make the values of variables ! 548: * inaccessible. We do want to flush all output buffers here, ! 549: * otherwise it'll never get done. ! 550: */ ! 551: public endprogram() ! 552: { ! 553: Integer exitcode; ! 554: ! 555: stepto(nextaddr(pc, true)); ! 556: printnews(); ! 557: exitcode = argn(1, nil); ! 558: if (exitcode != 0) ! 559: printf("\nexecution completed (exit code %d)\n", exitcode); ! 560: else ! 561: printf("\nexecution completed\n"); ! 562: getsrcpos(); ! 563: erecover(); ! 564: } ! 565: ! 566: private Address getcall(); ! 567: /* ! 568: * Single step the machine a source line (or instruction if "inst_tracing" ! 569: * is true). If "isnext" is true, skip over procedure calls. ! 570: */ ! 571: public dostep(isnext) ! 572: Boolean isnext; ! 573: { ! 574: register Address addr; ! 575: register Lineno line; ! 576: String filename; ! 577: Address startaddr; ! 578: ! 579: startaddr = pc; ! 580: addr = nextaddr(pc, isnext); ! 581: if (!inst_tracing && nlhdr.nlines != 0) { ! 582: line = linelookup(addr); ! 583: for (; line == 0; line = linelookup(addr)) ! 584: addr = nextaddr(addr, isnext); ! 585: curline = line; ! 586: } else ! 587: curline = 0; ! 588: stepto(addr); ! 589: filename = srcfilename(addr); ! 590: setsource(filename); ! 591: } ! 592: ! 593: private Address findnextaddr(); ! 594: /* ! 595: * Compute the next address that will be executed from the given one. ! 596: * If "isnext" is true then consider a procedure call as straight line code. ! 597: * ! 598: * We must unfortunately do much of the same work that is necessary ! 599: * to print instructions. In addition we have to deal with branches. ! 600: * Unconditional branches we just follow, for conditional branches ! 601: * we continue execution to the current location and then single step ! 602: * the machine. We assume that the last argument in an instruction ! 603: * that branches is the branch address (or relative offset). ! 604: */ ! 605: public Address nextaddr(startaddr, isnext) ! 606: Address startaddr; ! 607: boolean isnext; ! 608: { ! 609: Address addr; ! 610: ! 611: addr = usignal(process); ! 612: if (addr == 0 or addr == 1) ! 613: addr = findnextaddr(startaddr, isnext); ! 614: return (addr); ! 615: } ! 616: ! 617: /* ! 618: * Determine if it's ok to skip function f entered by instruction ins. ! 619: * If so, we're going to compute the return address and step to it. ! 620: */ ! 621: private boolean skipfunc(ins, f) ! 622: Opcode ins; ! 623: Symbol f; ! 624: { ! 625: ! 626: return ((boolean) (!inst_tracing && nlhdr.nlines != 0 && ! 627: nosource(curfunc) && canskip(curfunc))); ! 628: } ! 629: ! 630: private Address findnextaddr(startaddr, isnext) ! 631: Address startaddr; ! 632: Boolean isnext; ! 633: { ! 634: register Address addr; ! 635: Optab *op; ! 636: Opcode ins; ! 637: unsigned char mode; ! 638: int argtype, amode, argno, argval, nib; ! 639: String r; ! 640: Boolean indexf; ! 641: enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; ! 642: ! 643: argval = 0; ! 644: indexf = false; ! 645: addr = startaddr; ! 646: iread(&ins, addr, sizeof(ins)); ! 647: switch (ins) { ! 648: ! 649: case O_CALLF: ! 650: case O_CALLS: ! 651: addrstatus = KNOWN; ! 652: stepto(addr); ! 653: pstep(process, DEFSIG); ! 654: addr = reg(PROGCTR); ! 655: pc = addr; ! 656: setcurfunc(whatblock(pc)); ! 657: if (not isbperr()) { ! 658: printstatus(); ! 659: /* NOTREACHED */ ! 660: } ! 661: bpact(); ! 662: if (isnext or skipfunc(ins, curfunc)) { ! 663: addrstatus = KNOWN; ! 664: addr = return_addr(); ! 665: stepto(addr); ! 666: bpact(); ! 667: } else ! 668: callnews(/* iscall = */ true); ! 669: break; ! 670: ! 671: case O_RET: ! 672: addrstatus = KNOWN; ! 673: stepto(addr); ! 674: callnews(/* iscall = */ false); ! 675: pstep(process, DEFSIG); ! 676: addr = reg(PROGCTR); ! 677: pc = addr; ! 678: if (not isbperr()) ! 679: printstatus(); ! 680: bpact(); ! 681: break; ! 682: ! 683: case O_BRB: ! 684: case O_BRW: ! 685: case O_JMP: ! 686: case O_BBSSI: ! 687: case O_BCC: ! 688: case O_BCS: ! 689: case O_BEQL: ! 690: case O_BGEQ: ! 691: case O_BGTR: ! 692: case O_BGTRU: ! 693: case O_BLEQ: ! 694: case O_BLEQU: ! 695: case O_BLSS: ! 696: case O_BNEQ: ! 697: case O_BVC: ! 698: case O_BVS: ! 699: case O_CASEL: ! 700: case O_AOBLSS: ! 701: case O_AOBLEQ: ! 702: addrstatus = KNOWN; ! 703: stepto(addr); ! 704: pstep(process, DEFSIG); ! 705: addr = reg(PROGCTR); ! 706: pc = addr; ! 707: if (not isbperr()) ! 708: printstatus(); ! 709: break; ! 710: ! 711: default: ! 712: addrstatus = SEQUENTIAL; ! 713: break; ! 714: } ! 715: if (addrstatus == KNOWN) ! 716: return (addr); ! 717: addr += 1; ! 718: op = ioptab[ins]; ! 719: for (argno = 0; argno < op->numargs; argno++) { ! 720: if (indexf == true) ! 721: indexf = false; ! 722: argtype = op->argtype[argno]; ! 723: if (is_branch_disp(argtype)) ! 724: mode = 0xAF + (typelen(argtype) << 5); ! 725: else ! 726: iread(&mode, addr, sizeof(mode)), addr += 1; ! 727: r = regname[regnm(mode)]; ! 728: amode = addrmode(mode); ! 729: switch (amode) { ! 730: ! 731: case LITSHORT: ! 732: case LITUPTO31: ! 733: case LITUPTO47: ! 734: case LITUPTO63: ! 735: argval = mode; ! 736: break; ! 737: ! 738: case INDEX: ! 739: indexf = true; ! 740: --argno; ! 741: break; ! 742: ! 743: case REG: ! 744: case REGDEF: ! 745: case AUTODEC: ! 746: break; ! 747: ! 748: case AUTOINC: ! 749: nib = mode & 0xf; ! 750: if (nib == 0xf || nib == 8 || nib == 9) { ! 751: int size = (mode&03)+1; ! 752: ! 753: argval = getdisp(addr, size, ! 754: regname[PROGCTR], amode); ! 755: addr += size; ! 756: } ! 757: break; ! 758: ! 759: case AUTOINCDEF: ! 760: if ((mode&0xf) != 0xf) ! 761: break; ! 762: argval = getdisp(addr, 4, r, amode); ! 763: addr += 4; ! 764: break; ! 765: ! 766: case BYTEDISP: ! 767: case BYTEDISPDEF: ! 768: argval = getdisp(addr, 1, r, amode); ! 769: addr += 1; ! 770: break; ! 771: ! 772: case WORDDISP: ! 773: case WORDDISPDEF: ! 774: argval = getdisp(addr, 2, r, amode); ! 775: addr += 2; ! 776: break; ! 777: ! 778: case LONGDISP: ! 779: case LONGDISPDEF: ! 780: argval = getdisp(addr, 4, r, amode); ! 781: addr += 4; ! 782: break; ! 783: } ! 784: } ! 785: if (ins == O_CALLF or ins == O_CALLS) ! 786: argval += 2; ! 787: if (addrstatus == BRANCH) ! 788: addr = argval; ! 789: return (addr); ! 790: } ! 791: ! 792: /* ! 793: * Get the displacement of an instruction that uses displacement addressing. ! 794: */ ! 795: private int getdisp(addr, nbytes, reg, mode) ! 796: Address addr; ! 797: int nbytes; ! 798: String reg; ! 799: int mode; ! 800: { ! 801: char byte; ! 802: short hword; ! 803: int argval; ! 804: ! 805: switch (nbytes) { ! 806: ! 807: case 1: ! 808: iread(&byte, addr, sizeof(byte)); ! 809: argval = byte; ! 810: break; ! 811: ! 812: case 2: ! 813: iread(&hword, addr, sizeof(hword)); ! 814: argval = hword; ! 815: break; ! 816: ! 817: case 4: ! 818: iread(&argval, addr, sizeof(argval)); ! 819: break; ! 820: } ! 821: if (reg == regname[PROGCTR] && mode >= BYTEDISP) ! 822: argval += addr + nbytes; ! 823: return (argval); ! 824: } ! 825: ! 826: #define BP_OP O_BPT /* breakpoint trap */ ! 827: #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ ! 828: ! 829: /* ! 830: * Setting a breakpoint at a location consists of saving ! 831: * the word at the location and poking a BP_OP there. ! 832: * ! 833: * We save the locations and words on a list for use in unsetting. ! 834: */ ! 835: typedef struct Savelist *Savelist; ! 836: ! 837: struct Savelist { ! 838: Address location; ! 839: Byte save; ! 840: Byte refcount; ! 841: Savelist link; ! 842: }; ! 843: ! 844: private Savelist savelist; ! 845: ! 846: /* ! 847: * Set a breakpoint at the given address. Only save the word there ! 848: * if it's not already a breakpoint. ! 849: */ ! 850: public setbp(addr) ! 851: Address addr; ! 852: { ! 853: Byte w, save; ! 854: register Savelist newsave, s; ! 855: ! 856: for (s = savelist; s != nil; s = s->link) ! 857: if (s->location == addr) { ! 858: s->refcount++; ! 859: return; ! 860: } ! 861: iread(&save, addr, sizeof(save)); ! 862: newsave = new(Savelist); ! 863: newsave->location = addr; ! 864: newsave->save = save; ! 865: newsave->refcount = 1; ! 866: newsave->link = savelist; ! 867: savelist = newsave; ! 868: w = BP_OP; ! 869: iwrite(&w, addr, sizeof(w)); ! 870: } ! 871: ! 872: /* ! 873: * Unset a breakpoint; unfortunately we have to search the SAVELIST ! 874: * to find the saved value. The assumption is that the SAVELIST will ! 875: * usually be quite small. ! 876: */ ! 877: public unsetbp(addr) ! 878: Address addr; ! 879: { ! 880: register Savelist s, prev; ! 881: ! 882: prev = nil; ! 883: for (s = savelist; s != nil; s = s->link) { ! 884: if (s->location == addr) { ! 885: iwrite(&s->save, addr, sizeof(s->save)); ! 886: s->refcount--; ! 887: if (s->refcount == 0) { ! 888: if (prev == nil) ! 889: savelist = s->link; ! 890: else ! 891: prev->link = s->link; ! 892: dispose(s); ! 893: } ! 894: return; ! 895: } ! 896: prev = s; ! 897: } ! 898: panic("unsetbp: couldn't find address %d", addr); ! 899: } ! 900: ! 901: /* ! 902: * Enter a procedure by creating and executing a call instruction. ! 903: */ ! 904: ! 905: #define CALLSIZE 7 /* size of call instruction */ ! 906: ! 907: public beginproc(p, argc) ! 908: Symbol p; ! 909: Integer argc; ! 910: { ! 911: char save[CALLSIZE]; ! 912: struct { ! 913: Opcode op; ! 914: unsigned char numargs; ! 915: unsigned char mode; ! 916: char addr[sizeof(long)]; /* unaligned long */ ! 917: } call; ! 918: long dest; ! 919: ! 920: if (4*argc+4 > 256) ! 921: error("too many parameters (max %d)", 256/4 - 1); ! 922: pc = 2; ! 923: iread(save, pc, sizeof(save)); ! 924: call.op = O_CALLF; ! 925: call.numargs = 4*argc+4; ! 926: call.mode = 0xef; /* longword relative */ ! 927: dest = codeloc(p) - 2 - (pc + CALLSIZE); ! 928: mov(&dest, call.addr, sizeof(call.addr)); ! 929: iwrite(&call, pc, sizeof(call)); ! 930: setreg(PROGCTR, pc); ! 931: pstep(process, DEFSIG); ! 932: iwrite(save, pc, sizeof(save)); ! 933: pc = reg(PROGCTR); ! 934: if (not isbperr()) ! 935: printstatus(); ! 936: } ! 937: ! 938: /* ! 939: * Special variables for debugging the kernel. ! 940: */ ! 941: ! 942: public integer masterpcbb; ! 943: public integer slr; ! 944: public struct pte *sbr; ! 945: private struct pcb pcb; ! 946: ! 947: public getpcb () ! 948: { ! 949: fseek(corefile, masterpcbb & ~0xc0000000, 0); ! 950: get(corefile, pcb); ! 951: printf("p0br %lx p0lr %lx p2br %lx p2lr %lx\n", ! 952: pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p2br, pcb.pcb_p2lr ! 953: ); ! 954: setreg(0, pcb.pcb_r0); ! 955: setreg(1, pcb.pcb_r1); ! 956: setreg(2, pcb.pcb_r2); ! 957: setreg(3, pcb.pcb_r3); ! 958: setreg(4, pcb.pcb_r4); ! 959: setreg(5, pcb.pcb_r5); ! 960: setreg(6, pcb.pcb_r6); ! 961: setreg(7, pcb.pcb_r7); ! 962: setreg(8, pcb.pcb_r8); ! 963: setreg(9, pcb.pcb_r9); ! 964: setreg(10, pcb.pcb_r10); ! 965: setreg(11, pcb.pcb_r11); ! 966: setreg(12, pcb.pcb_r12); ! 967: setreg(FRP, pcb.pcb_fp); ! 968: setreg(STKP, pcb.pcb_ksp); ! 969: setreg(PROGCTR, pcb.pcb_pc); ! 970: } ! 971: ! 972: public copyregs (savreg, reg) ! 973: Word savreg[], reg[]; ! 974: { ! 975: reg[0] = savreg[R0]; ! 976: reg[1] = savreg[R1]; ! 977: reg[2] = savreg[R2]; ! 978: reg[3] = savreg[R3]; ! 979: reg[4] = savreg[R4]; ! 980: reg[5] = savreg[R5]; ! 981: reg[6] = savreg[R6]; ! 982: reg[7] = savreg[R7]; ! 983: reg[8] = savreg[R8]; ! 984: reg[9] = savreg[R9]; ! 985: reg[10] = savreg[R10]; ! 986: reg[11] = savreg[R11]; ! 987: reg[12] = savreg[R12]; ! 988: reg[FRP] = savreg[FP]; ! 989: reg[STKP] = savreg[SP]; ! 990: reg[PROGCTR] = savreg[PC]; ! 991: } ! 992: ! 993: /* ! 994: * Map a virtual address to a physical address. ! 995: */ ! 996: ! 997: public Address vmap (addr) ! 998: Address addr; ! 999: { ! 1000: int oldaddr = addr, v; ! 1001: struct pte pte; ! 1002: ! 1003: addr &= ~0xc0000000; ! 1004: v = btop(addr); ! 1005: switch (oldaddr&0xc0000000) { ! 1006: ! 1007: case 0xc0000000: ! 1008: /* ! 1009: * In system space get system pte. If ! 1010: * valid or reclaimable then physical address ! 1011: * is combination of its page number and the page ! 1012: * offset of the original address. ! 1013: */ ! 1014: if (v >= slr) ! 1015: goto oor; ! 1016: addr = ((long)(sbr+v)) &~ 0xc0000000; ! 1017: goto simple; ! 1018: ! 1019: case 0x80000000: ! 1020: /* ! 1021: * In p2 spce must not be in shadow region. ! 1022: */ ! 1023: if (v < pcb.pcb_p2lr) ! 1024: goto oor; ! 1025: addr = (long)(pcb.pcb_p2br+v); ! 1026: break; ! 1027: ! 1028: case 0x40000000: ! 1029: /* ! 1030: * In p1 space everything is verboten (for now). ! 1031: */ ! 1032: goto oor; ! 1033: ! 1034: case 0x00000000: ! 1035: /* ! 1036: * In p0 space must not be off end of region. ! 1037: */ ! 1038: if (v >= pcb.pcb_p0lr) ! 1039: goto oor; ! 1040: addr = (long)(pcb.pcb_p0br+v); ! 1041: break; ! 1042: oor: ! 1043: error("address out of segment"); ! 1044: } ! 1045: /* ! 1046: * For p0/p1/p2 address, user-level page table should ! 1047: * be in kernel vm. Do second-level indirect by recursing. ! 1048: */ ! 1049: if ((addr & 0xc0000000) != 0xc0000000) ! 1050: error("bad p0br, p1br, or p2br in pcb"); ! 1051: addr = vmap(addr); ! 1052: simple: ! 1053: /* ! 1054: * Addr is now address of the pte of the page we ! 1055: * are interested in; get the pte and paste up the ! 1056: * physical address. ! 1057: */ ! 1058: fseek(corefile, addr, 0); ! 1059: if (fread(&pte, sizeof (pte), 1, corefile) != 1) ! 1060: error("page table botch"); ! 1061: /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ ! 1062: if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) ! 1063: error("page not valid/reclaimable"); ! 1064: return ((long)(ptob(pte.pg_pfnum) + (oldaddr & PGOFSET))); ! 1065: } ! 1066: ! 1067: /* ! 1068: * Extract a bit field from an integer. ! 1069: */ ! 1070: ! 1071: public integer extractField (s) ! 1072: Symbol s; ! 1073: { ! 1074: integer nbytes, nbits, n, r, off, len; ! 1075: ! 1076: off = s->symvalue.field.offset; ! 1077: len = s->symvalue.field.length; ! 1078: nbytes = size(s); ! 1079: n = 0; ! 1080: if (nbytes > sizeof(n)) { ! 1081: printf("[bad size in extractField -- word assumed]\n"); ! 1082: nbytes = sizeof(n); ! 1083: } ! 1084: popn(nbytes, ((char *) &n) + (sizeof(Word) - nbytes)); ! 1085: nbits = nbytes * BITSPERBYTE; ! 1086: r = n >> (nbits - ((off mod nbits) + len)); ! 1087: r &= ((1 << len) - 1); ! 1088: return r; ! 1089: } ! 1090: ! 1091: /* ! 1092: * Change the length of a value in memory according to a given difference ! 1093: * in the lengths of its new and old types. ! 1094: */ ! 1095: ! 1096: public loophole (oldlen, newlen) ! 1097: integer oldlen, newlen; ! 1098: { ! 1099: integer i, n; ! 1100: Stack *oldsp; ! 1101: ! 1102: n = newlen - oldlen; ! 1103: oldsp = sp - oldlen; ! 1104: if (n > 0) { ! 1105: for (i = oldlen - 1; i >= 0; i--) { ! 1106: oldsp[n + i] = oldsp[i]; ! 1107: } ! 1108: for (i = 0; i < n; i++) { ! 1109: oldsp[i] = '\0'; ! 1110: } ! 1111: } else { ! 1112: for (i = 0; i < newlen; i++) { ! 1113: oldsp[i] = oldsp[i - n]; ! 1114: } ! 1115: } ! 1116: sp += n; ! 1117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.