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