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