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