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