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