121608Sdist /* 221608Sdist * Copyright (c) 1983 Regents of the University of California. 321608Sdist * All rights reserved. The Berkeley software License Agreement 421608Sdist * specifies the terms and conditions for redistribution. 521608Sdist */ 69668Slinton 721608Sdist #ifndef lint 8*26344Ssam static char sccsid[] = "@(#)vax.c 5.3 (Berkeley) 02/23/86"; 921608Sdist #endif not lint 109668Slinton 1118222Slinton static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $"; 1218222Slinton 139668Slinton /* 149668Slinton * Target machine dependent stuff. 159668Slinton */ 169668Slinton 179668Slinton #include "defs.h" 189668Slinton #include "machine.h" 199668Slinton #include "process.h" 2016612Ssam #include "runtime.h" 219668Slinton #include "events.h" 229668Slinton #include "main.h" 239668Slinton #include "symbols.h" 249668Slinton #include "source.h" 259668Slinton #include "mappings.h" 269668Slinton #include "object.h" 2718222Slinton #include "keywords.h" 289693Slinton #include "ops.h" 299668Slinton #include <signal.h> 309668Slinton 319668Slinton #ifndef public 329668Slinton typedef unsigned int Address; 339668Slinton typedef unsigned char Byte; 349668Slinton typedef unsigned int Word; 359668Slinton 369668Slinton #define NREG 16 379668Slinton 389668Slinton #define ARGP 12 399668Slinton #define FRP 13 409668Slinton #define STKP 14 419668Slinton #define PROGCTR 15 429668Slinton 439668Slinton #define BITSPERBYTE 8 449668Slinton #define BITSPERWORD (BITSPERBYTE * sizeof(Word)) 459668Slinton 469668Slinton #define nargspassed(frame) argn(0, frame) 4726336Ssam /* 4826336Ssam * Extract a field's value from the integer i. The value 4926336Ssam * is placed in i in such as way as the first bit of the 5026336Ssam * field is contained in the first byte of the integer. 5126336Ssam */ 5226336Ssam #define extractfield(i, s) \ 5326336Ssam ((i >> ((s)->symvalue.field.offset mod BITSPERBYTE)) & \ 5426336Ssam ((1 << (s)->symvalue.field.length) - 1)) 5526336Ssam /* 5626336Ssam * Expand/contract the expression stack to reflect a type 5726336Ssam * rename operation. We pad with zeros when expanding, 5826336Ssam * otherwise we just pull the stack pointer back. 5926336Ssam */ 6026336Ssam #define typerename(oldsize, newsize) { \ 6126336Ssam int len = newsize - oldsize; \ 6226336Ssam if (len > 0) \ 6326336Ssam bzero(sp, len); \ 6426336Ssam sp += len; \ 6526336Ssam } 669668Slinton 6726336Ssam #define SYSBASE 0x80000000 /* base of system address space */ 6826336Ssam #define physaddr(a) ((a) & 0x7fffffff) 6926336Ssam 709668Slinton #include "source.h" 719668Slinton #include "symbols.h" 72*26344Ssam #include <sys/param.h> 73*26344Ssam #include <sys/dir.h> 74*26344Ssam #include <machine/psl.h> 75*26344Ssam #include <machine/pte.h> 76*26344Ssam #include <sys/user.h> 77*26344Ssam #include <sys/vm.h> 78*26344Ssam #include <machine/reg.h> 799668Slinton 809668Slinton Address pc; 819668Slinton Address prtaddr; 829668Slinton 839668Slinton #endif 849668Slinton 859668Slinton private Address printop(); 869668Slinton 879668Slinton /* 88*26344Ssam * Indices into u. for use in collecting registers values. 89*26344Ssam */ 90*26344Ssam public int rloc[] = 91*26344Ssam { R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC }; 92*26344Ssam 93*26344Ssam /* 949668Slinton * Decode and print the instructions within the given address range. 959668Slinton */ 969668Slinton 979668Slinton public printinst(lowaddr, highaddr) 989668Slinton Address lowaddr; 999668Slinton Address highaddr; 1009668Slinton { 1019668Slinton register Address addr; 1029668Slinton 1039668Slinton for (addr = lowaddr; addr <= highaddr; ) { 1049668Slinton addr = printop(addr); 1059668Slinton } 1069668Slinton prtaddr = addr; 1079668Slinton } 1089668Slinton 1099668Slinton /* 1109668Slinton * Another approach: print n instructions starting at the given address. 1119668Slinton */ 1129668Slinton 1139668Slinton public printninst(count, addr) 1149668Slinton int count; 1159668Slinton Address addr; 1169668Slinton { 1179668Slinton register Integer i; 1189668Slinton register Address newaddr; 1199668Slinton 1209668Slinton if (count <= 0) { 1219668Slinton error("non-positive repetition count"); 1229668Slinton } else { 1239668Slinton newaddr = addr; 1249668Slinton for (i = 0; i < count; i++) { 1259668Slinton newaddr = printop(newaddr); 1269668Slinton } 1279668Slinton prtaddr = newaddr; 1289668Slinton } 1299668Slinton } 1309668Slinton 13126336Ssam optab_init() 13226336Ssam { 13326336Ssam 13426336Ssam } 13526336Ssam 1369668Slinton /* 1379668Slinton * Hacked version of adb's VAX instruction decoder. 1389668Slinton */ 1399668Slinton 1409668Slinton private Address printop(addr) 1419668Slinton Address addr; 1429668Slinton { 1439668Slinton Optab op; 1449668Slinton VaxOpcode ins; 1459668Slinton unsigned char mode; 1469668Slinton int argtype, amode, argno, argval; 1479668Slinton String reg; 1489668Slinton Boolean indexf; 1499668Slinton short offset; 1509668Slinton 1519668Slinton argval = 0; 1529668Slinton indexf = false; 1539668Slinton printf("%08x ", addr); 1549668Slinton iread(&ins, addr, sizeof(ins)); 1559668Slinton addr += 1; 1569668Slinton op = optab[ins]; 1579668Slinton printf("%s", op.iname); 1589668Slinton for (argno = 0; argno < op.numargs; argno++) { 1599668Slinton if (indexf == true) { 1609668Slinton indexf = false; 1619668Slinton } else if (argno == 0) { 1629668Slinton printf("\t"); 1639668Slinton } else { 1649668Slinton printf(","); 1659668Slinton } 1669668Slinton argtype = op.argtype[argno]; 1679668Slinton if (is_branch_disp(argtype)) { 1689668Slinton mode = 0xAF + (typelen(argtype) << 5); 1699668Slinton } else { 1709668Slinton iread(&mode, addr, sizeof(mode)); 1719668Slinton addr += 1; 1729668Slinton } 1739668Slinton reg = regname[regnm(mode)]; 1749668Slinton amode = addrmode(mode); 1759668Slinton switch (amode) { 1769668Slinton case LITSHORT: 1779668Slinton case LITUPTO31: 1789668Slinton case LITUPTO47: 1799668Slinton case LITUPTO63: 1809668Slinton if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD) 1819668Slinton printf("$%s", fltimm[mode]); 1829668Slinton else 1839668Slinton printf("$%x", mode); 1849668Slinton argval = mode; 1859668Slinton break; 1869668Slinton 1879668Slinton case INDEX: 1889668Slinton printf("[%s]", reg); 1899668Slinton indexf = true; 1909668Slinton argno--; 1919668Slinton break; 1929668Slinton 1939668Slinton case REG: 1949668Slinton printf("%s", reg); 1959668Slinton break; 1969668Slinton 1979668Slinton case REGDEF: 1989668Slinton printf("(%s)", reg); 1999668Slinton break; 2009668Slinton 2019668Slinton case AUTODEC: 2029668Slinton printf("-(%s)", reg); 2039668Slinton break; 2049668Slinton 2059668Slinton case AUTOINC: 2069668Slinton if (reg != regname[PROGCTR]) { 2079668Slinton printf("(%s)+", reg); 2089668Slinton } else { 2099668Slinton printf("$"); 2109668Slinton switch (typelen(argtype)) { 2119668Slinton case TYPB: 2129668Slinton argval = printdisp(addr, 1, reg, amode); 2139668Slinton addr += 1; 2149668Slinton break; 2159668Slinton 2169668Slinton case TYPW: 2179668Slinton argval = printdisp(addr, 2, reg, amode); 2189668Slinton addr += 2; 2199668Slinton break; 2209668Slinton 2219668Slinton case TYPL: 2229668Slinton argval = printdisp(addr, 4, reg, amode); 2239668Slinton addr += 4; 2249668Slinton break; 2259668Slinton 2269668Slinton case TYPF: 2279668Slinton iread(&argval, addr, sizeof(argval)); 2289668Slinton printf("%06x", argval); 2299668Slinton addr += 4; 2309668Slinton break; 2319668Slinton 2329668Slinton case TYPQ: 2339668Slinton case TYPD: 2349668Slinton iread(&argval, addr, sizeof(argval)); 2359668Slinton printf("%06x", argval); 2369668Slinton iread(&argval, addr+4, sizeof(argval)); 2379668Slinton printf("%06x", argval); 2389668Slinton addr += 8; 2399668Slinton break; 2409668Slinton } 2419668Slinton } 2429668Slinton break; 2439668Slinton 2449668Slinton case AUTOINCDEF: 2459668Slinton if (reg == regname[PROGCTR]) { 2469668Slinton printf("*$"); 2479668Slinton argval = printdisp(addr, 4, reg, amode); 2489668Slinton addr += 4; 2499668Slinton } else { 2509668Slinton printf("*(%s)+", reg); 2519668Slinton } 2529668Slinton break; 2539668Slinton 2549668Slinton case BYTEDISP: 2559668Slinton argval = printdisp(addr, 1, reg, amode); 2569668Slinton addr += 1; 2579668Slinton break; 2589668Slinton 2599668Slinton case BYTEDISPDEF: 2609668Slinton printf("*"); 2619668Slinton argval = printdisp(addr, 1, reg, amode); 2629668Slinton addr += 1; 2639668Slinton break; 2649668Slinton 2659668Slinton case WORDDISP: 2669668Slinton argval = printdisp(addr, 2, reg, amode); 2679668Slinton addr += 2; 2689668Slinton break; 2699668Slinton 2709668Slinton case WORDDISPDEF: 2719668Slinton printf("*"); 2729668Slinton argval = printdisp(addr, 2, reg, amode); 2739668Slinton addr += 2; 2749668Slinton break; 2759668Slinton 2769668Slinton case LONGDISP: 2779668Slinton argval = printdisp(addr, 4, reg, amode); 2789668Slinton addr += 4; 2799668Slinton break; 2809668Slinton 2819668Slinton case LONGDISPDEF: 2829668Slinton printf("*"); 2839668Slinton argval = printdisp(addr, 4, reg, amode); 2849668Slinton addr += 4; 2859668Slinton break; 2869668Slinton } 2879668Slinton } 2889668Slinton if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { 2899668Slinton for (argno = 0; argno <= argval; argno++) { 2909668Slinton iread(&offset, addr, sizeof(offset)); 2919668Slinton printf("\n\t\t%d", offset); 2929668Slinton addr += 2; 2939668Slinton } 2949668Slinton } 2959668Slinton printf("\n"); 2969668Slinton return addr; 2979668Slinton } 2989668Slinton 2999668Slinton /* 3009668Slinton * Print the displacement of an instruction that uses displacement 3019668Slinton * addressing. 3029668Slinton */ 3039668Slinton 3049668Slinton private int printdisp(addr, nbytes, reg, mode) 3059668Slinton Address addr; 3069668Slinton int nbytes; 3079668Slinton char *reg; 3089668Slinton int mode; 3099668Slinton { 3109668Slinton char byte; 3119668Slinton short hword; 3129668Slinton int argval; 31314338Slinton Symbol f; 3149668Slinton 3159668Slinton switch (nbytes) { 3169668Slinton case 1: 3179668Slinton iread(&byte, addr, sizeof(byte)); 3189668Slinton argval = byte; 3199668Slinton break; 3209668Slinton 3219668Slinton case 2: 3229668Slinton iread(&hword, addr, sizeof(hword)); 3239668Slinton argval = hword; 3249668Slinton break; 3259668Slinton 3269668Slinton case 4: 3279668Slinton iread(&argval, addr, sizeof(argval)); 3289668Slinton break; 3299668Slinton } 3309668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 3319668Slinton argval += addr + nbytes; 3329668Slinton } 3339668Slinton if (reg == regname[PROGCTR]) { 33414338Slinton f = whatblock((Address) argval + 2); 33514338Slinton if (codeloc(f) == argval + 2) { 33614338Slinton printf("%s", symname(f)); 33714338Slinton } else { 33814338Slinton printf("%x", argval); 33914338Slinton } 3409668Slinton } else { 34118222Slinton if (varIsSet("$hexoffsets")) { 34218222Slinton if (argval < 0) { 34318222Slinton printf("-%x(%s)", -(argval), reg); 34418222Slinton } else { 34518222Slinton printf("%x(%s)", argval, reg); 34618222Slinton } 34718222Slinton } else { 34818222Slinton printf("%d(%s)", argval, reg); 34918222Slinton } 3509668Slinton } 3519668Slinton return argval; 3529668Slinton } 3539668Slinton 3549668Slinton /* 3559668Slinton * Print the contents of the addresses within the given range 3569668Slinton * according to the given format. 3579668Slinton */ 3589668Slinton 3599668Slinton typedef struct { 3609668Slinton String name; 3619668Slinton String printfstring; 3629668Slinton int length; 3639668Slinton } Format; 3649668Slinton 3659668Slinton private Format fmt[] = { 3669668Slinton { "d", " %d", sizeof(short) }, 3679668Slinton { "D", " %ld", sizeof(long) }, 3689668Slinton { "o", " %o", sizeof(short) }, 3699668Slinton { "O", " %lo", sizeof(long) }, 3709668Slinton { "x", " %04x", sizeof(short) }, 3719668Slinton { "X", " %08x", sizeof(long) }, 3729668Slinton { "b", " \\%o", sizeof(char) }, 3739668Slinton { "c", " '%c'", sizeof(char) }, 3749668Slinton { "s", "%c", sizeof(char) }, 37514338Slinton { "f", " %f", sizeof(float) }, 3769668Slinton { "g", " %g", sizeof(double) }, 3779668Slinton { nil, nil, 0 } 3789668Slinton }; 3799668Slinton 38011174Slinton private Format *findformat(s) 38111174Slinton String s; 38211174Slinton { 38311174Slinton register Format *f; 38411174Slinton 38511174Slinton f = &fmt[0]; 38611174Slinton while (f->name != nil and not streq(f->name, s)) { 38711174Slinton ++f; 38811174Slinton } 38911174Slinton if (f->name == nil) { 39011174Slinton error("bad print format \"%s\"", s); 39111174Slinton } 39211174Slinton return f; 39311174Slinton } 39411174Slinton 3959668Slinton public Address printdata(lowaddr, highaddr, format) 3969668Slinton Address lowaddr; 3979668Slinton Address highaddr; 3989668Slinton String format; 3999668Slinton { 4009668Slinton register int n; 4019668Slinton register Address addr; 4029668Slinton register Format *f; 4039668Slinton int value; 4049668Slinton 4059668Slinton if (lowaddr > highaddr) { 4069668Slinton error("first address larger than second"); 4079668Slinton } 40811174Slinton f = findformat(format); 4099668Slinton n = 0; 4109668Slinton value = 0; 4119668Slinton for (addr = lowaddr; addr <= highaddr; addr += f->length) { 4129668Slinton if (n == 0) { 4139668Slinton printf("%08x: ", addr); 4149668Slinton } 4159668Slinton dread(&value, addr, f->length); 4169668Slinton printf(f->printfstring, value); 4179668Slinton ++n; 4189668Slinton if (n >= (16 div f->length)) { 4199668Slinton putchar('\n'); 4209668Slinton n = 0; 4219668Slinton } 4229668Slinton } 4239668Slinton if (n != 0) { 4249668Slinton putchar('\n'); 4259668Slinton } 4269668Slinton prtaddr = addr; 4279668Slinton return addr; 4289668Slinton } 4299668Slinton 4309668Slinton /* 4319668Slinton * The other approach is to print n items starting with a given address. 4329668Slinton */ 4339668Slinton 4349668Slinton public printndata(count, startaddr, format) 4359668Slinton int count; 4369668Slinton Address startaddr; 4379668Slinton String format; 4389668Slinton { 4399668Slinton register int i, n; 4409668Slinton register Address addr; 4419668Slinton register Format *f; 4429668Slinton register Boolean isstring; 44314338Slinton char c; 44414338Slinton union { 44514338Slinton char charv; 44614338Slinton short shortv; 44714338Slinton int intv; 44814338Slinton float floatv; 44914338Slinton double doublev; 45014338Slinton } value; 4519668Slinton 4529668Slinton if (count <= 0) { 4539668Slinton error("non-positive repetition count"); 4549668Slinton } 45511174Slinton f = findformat(format); 4569668Slinton isstring = (Boolean) streq(f->name, "s"); 4579668Slinton n = 0; 4589668Slinton addr = startaddr; 45914338Slinton value.intv = 0; 4609668Slinton for (i = 0; i < count; i++) { 4619668Slinton if (n == 0) { 4629668Slinton printf("%08x: ", addr); 4639668Slinton } 4649668Slinton if (isstring) { 4659668Slinton putchar('"'); 46614338Slinton dread(&c, addr, sizeof(char)); 46714338Slinton while (c != '\0') { 46814338Slinton printchar(c); 4699668Slinton ++addr; 47014338Slinton dread(&c, addr, sizeof(char)); 4719668Slinton } 4729668Slinton putchar('"'); 4739668Slinton putchar('\n'); 4749668Slinton n = 0; 4759668Slinton addr += sizeof(String); 4769668Slinton } else { 4779668Slinton dread(&value, addr, f->length); 4789668Slinton printf(f->printfstring, value); 4799668Slinton ++n; 4809668Slinton if (n >= (16 div f->length)) { 4819668Slinton putchar('\n'); 4829668Slinton n = 0; 4839668Slinton } 4849668Slinton addr += f->length; 4859668Slinton } 4869668Slinton } 4879668Slinton if (n != 0) { 4889668Slinton putchar('\n'); 4899668Slinton } 4909668Slinton prtaddr = addr; 4919668Slinton } 4929668Slinton 4939668Slinton /* 49411174Slinton * Print out a value according to the given format. 49511174Slinton */ 49611174Slinton 49711174Slinton public printvalue(v, format) 49811174Slinton long v; 49911174Slinton String format; 50011174Slinton { 50111174Slinton Format *f; 50211174Slinton char *p, *q; 50311174Slinton 50411174Slinton f = findformat(format); 50511174Slinton if (streq(f->name, "s")) { 50611174Slinton putchar('"'); 50711174Slinton p = (char *) &v; 50811174Slinton q = p + sizeof(v); 50911174Slinton while (p < q) { 51011174Slinton printchar(*p); 51111174Slinton ++p; 51211174Slinton } 51311174Slinton putchar('"'); 51411174Slinton } else { 51511174Slinton printf(f->printfstring, v); 51611174Slinton } 51711174Slinton putchar('\n'); 51811174Slinton } 51911174Slinton 52011174Slinton /* 5219668Slinton * Print out an execution time error. 5229842Slinton * Assumes the source position of the error has been calculated. 5239668Slinton * 5249668Slinton * Have to check if the -r option was specified; if so then 5259668Slinton * the object file information hasn't been read in yet. 5269668Slinton */ 5279668Slinton 5289668Slinton public printerror() 5299668Slinton { 5309668Slinton extern Integer sys_nsig; 5319668Slinton extern String sys_siglist[]; 53218222Slinton integer err; 5339668Slinton 5349668Slinton if (isfinished(process)) { 53516932Ssam err = exitcode(process); 53618222Slinton if (err == 0) { 53718222Slinton printf("\"%s\" terminated normally\n", objname); 53818222Slinton } else { 53918222Slinton printf("\"%s\" terminated abnormally (exit code %d)\n", 54018222Slinton objname, err 54118222Slinton ); 54218222Slinton } 5439668Slinton erecover(); 5449668Slinton } 5459668Slinton if (runfirst) { 54618222Slinton fprintf(stderr, "Entering debugger ...\n"); 5479668Slinton init(); 5489668Slinton } 5499668Slinton err = errnum(process); 5509668Slinton putchar('\n'); 55116932Ssam printsig(err); 55218222Slinton putchar(' '); 55316932Ssam printloc(); 55416932Ssam putchar('\n'); 5559668Slinton if (curline > 0) { 5569668Slinton printlines(curline, curline); 5579668Slinton } else { 5589668Slinton printinst(pc, pc); 5599668Slinton } 5609668Slinton erecover(); 5619668Slinton } 5629668Slinton 56318222Slinton /* 56418222Slinton * Print out a signal. 56518222Slinton */ 56618222Slinton 56716932Ssam private String illinames[] = { 56818222Slinton "reserved addressing fault", 56918222Slinton "priviliged instruction fault", 57018222Slinton "reserved operand fault" 57116932Ssam }; 57218222Slinton 57316932Ssam private String fpenames[] = { 57418222Slinton nil, 57518222Slinton "integer overflow trap", 57618222Slinton "integer divide by zero trap", 57718222Slinton "floating overflow trap", 57818222Slinton "floating/decimal divide by zero trap", 57918222Slinton "floating underflow trap", 58018222Slinton "decimal overflow trap", 58118222Slinton "subscript out of range trap", 58218222Slinton "floating overflow fault", 58318222Slinton "floating divide by zero fault", 58418222Slinton "floating undeflow fault" 58516932Ssam }; 58616932Ssam 58718222Slinton public printsig (signo) 58818222Slinton integer signo; 58916932Ssam { 59018222Slinton integer code; 59116932Ssam 59218222Slinton if (signo < 0 or signo > sys_nsig) { 59318222Slinton printf("[signal %d]", signo); 59418222Slinton } else { 59518222Slinton printf("%s", sys_siglist[signo]); 59616932Ssam } 59718222Slinton code = errcode(process); 59818222Slinton if (signo == SIGILL) { 59918222Slinton if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { 60018222Slinton printf(" (%s)", illinames[code]); 60118222Slinton } 60218222Slinton } else if (signo == SIGFPE) { 60318222Slinton if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { 60418222Slinton printf(" (%s)", fpenames[code]); 60518222Slinton } 60618222Slinton } 60716932Ssam } 60816932Ssam 6099668Slinton /* 6109668Slinton * Note the termination of the program. We do this so as to avoid 6119668Slinton * having the process exit, which would make the values of variables 6129668Slinton * inaccessible. We do want to flush all output buffers here, 6139668Slinton * otherwise it'll never get done. 6149668Slinton */ 6159668Slinton 6169668Slinton public endprogram() 6179668Slinton { 6189668Slinton Integer exitcode; 6199668Slinton 6209668Slinton stepto(nextaddr(pc, true)); 6219668Slinton printnews(); 6229668Slinton exitcode = argn(1, nil); 62318222Slinton if (exitcode != 0) { 62418222Slinton printf("\nexecution completed (exit code %d)\n", exitcode); 62518222Slinton } else { 62618222Slinton printf("\nexecution completed\n"); 62718222Slinton } 6289668Slinton getsrcpos(); 6299668Slinton erecover(); 6309668Slinton } 6319668Slinton 6329668Slinton /* 6339668Slinton * Single step the machine a source line (or instruction if "inst_tracing" 63410621Slinton * is true). If "isnext" is true, skip over procedure calls. 6359668Slinton */ 6369668Slinton 6379668Slinton private Address getcall(); 6389668Slinton 6399668Slinton public dostep(isnext) 6409668Slinton Boolean isnext; 6419668Slinton { 6429668Slinton register Address addr; 6439668Slinton register Lineno line; 6449668Slinton String filename; 64518222Slinton Address startaddr; 6469668Slinton 64716612Ssam startaddr = pc; 6489668Slinton addr = nextaddr(pc, isnext); 64910621Slinton if (not inst_tracing and nlhdr.nlines != 0) { 6509668Slinton line = linelookup(addr); 6519668Slinton while (line == 0) { 65218222Slinton addr = nextaddr(addr, isnext); 6539668Slinton line = linelookup(addr); 6549668Slinton } 65510621Slinton curline = line; 65610621Slinton } else { 65710621Slinton curline = 0; 6589668Slinton } 6599668Slinton stepto(addr); 6609668Slinton filename = srcfilename(addr); 6619668Slinton setsource(filename); 6629668Slinton } 6639668Slinton 6649668Slinton /* 6659668Slinton * Compute the next address that will be executed from the given one. 6669668Slinton * If "isnext" is true then consider a procedure call as straight line code. 6679668Slinton * 6689668Slinton * We must unfortunately do much of the same work that is necessary 6699668Slinton * to print instructions. In addition we have to deal with branches. 6709668Slinton * Unconditional branches we just follow, for conditional branches 6719668Slinton * we continue execution to the current location and then single step 6729668Slinton * the machine. We assume that the last argument in an instruction 6739668Slinton * that branches is the branch address (or relative offset). 6749668Slinton */ 6759668Slinton 67618222Slinton private Address findnextaddr(); 67718222Slinton 6789668Slinton public Address nextaddr(startaddr, isnext) 6799668Slinton Address startaddr; 68016612Ssam boolean isnext; 68116612Ssam { 68216612Ssam Address addr; 68316612Ssam 68416612Ssam addr = usignal(process); 68516612Ssam if (addr == 0 or addr == 1) { 68616612Ssam addr = findnextaddr(startaddr, isnext); 68716612Ssam } 68816612Ssam return addr; 68916612Ssam } 69016612Ssam 69118222Slinton /* 69218222Slinton * Determine if it's ok to skip function f entered by instruction ins. 69318222Slinton * If so, we're going to compute the return address and step to it. 69418222Slinton * Therefore we cannot skip over a function entered by a jsb or bsb, 69518222Slinton * since the return address is not easily computed for them. 69618222Slinton */ 69718222Slinton 69818222Slinton private boolean skipfunc (ins, f) 69918222Slinton VaxOpcode ins; 70018222Slinton Symbol f; 70118222Slinton { 70218222Slinton boolean b; 70318222Slinton 70418222Slinton b = (boolean) ( 70518222Slinton ins != O_JSB and ins != O_BSBB and ins != O_BSBW and 70618222Slinton not inst_tracing and nlhdr.nlines != 0 and 70718222Slinton nosource(curfunc) and canskip(curfunc) 70818222Slinton ); 70918222Slinton return b; 71018222Slinton } 71118222Slinton 71216612Ssam private Address findnextaddr(startaddr, isnext) 71316612Ssam Address startaddr; 7149668Slinton Boolean isnext; 7159668Slinton { 7169668Slinton register Address addr; 7179668Slinton Optab op; 7189668Slinton VaxOpcode ins; 7199668Slinton unsigned char mode; 7209668Slinton int argtype, amode, argno, argval; 7219668Slinton String r; 7229668Slinton Boolean indexf; 7239668Slinton enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus; 7249668Slinton 7259668Slinton argval = 0; 7269668Slinton indexf = false; 7279668Slinton addr = startaddr; 7289668Slinton iread(&ins, addr, sizeof(ins)); 7299668Slinton switch (ins) { 73018222Slinton /* 73118222Slinton * It used to be that unconditional jumps and branches were handled 73218222Slinton * by taking their destination address as the next address. While 73318222Slinton * saving the cost of starting up the process, this approach 73418222Slinton * doesn't work when jumping indirect (since the value in the 73518222Slinton * register might not yet have been set). 73618222Slinton * 73718222Slinton * So unconditional jumps and branches are now handled the same way 73818222Slinton * as conditional jumps and branches. 73918222Slinton * 7409668Slinton case O_BRB: 7419668Slinton case O_BRW: 7429668Slinton addrstatus = BRANCH; 7439668Slinton break; 74418222Slinton * 74518222Slinton */ 7469668Slinton 7479668Slinton case O_BSBB: 7489668Slinton case O_BSBW: 7499668Slinton case O_JSB: 7509668Slinton case O_CALLG: 7519668Slinton case O_CALLS: 75218222Slinton addrstatus = KNOWN; 75318222Slinton stepto(addr); 75418222Slinton pstep(process, DEFSIG); 75518222Slinton addr = reg(PROGCTR); 75618222Slinton pc = addr; 75718222Slinton setcurfunc(whatblock(pc)); 75818222Slinton if (not isbperr()) { 75918222Slinton printstatus(); 76018222Slinton /* NOTREACHED */ 76118222Slinton } 76218222Slinton bpact(); 76318222Slinton if (isnext or skipfunc(ins, curfunc)) { 7649668Slinton addrstatus = KNOWN; 76518222Slinton addr = return_addr(); 7669668Slinton stepto(addr); 76711864Slinton bpact(); 76818222Slinton } else { 76918222Slinton callnews(/* iscall = */ true); 7709668Slinton } 7719668Slinton break; 7729668Slinton 7739668Slinton case O_RSB: 7749668Slinton case O_RET: 7759668Slinton addrstatus = KNOWN; 77618222Slinton stepto(addr); 7779668Slinton callnews(/* iscall = */ false); 77818222Slinton pstep(process, DEFSIG); 77918222Slinton addr = reg(PROGCTR); 78018222Slinton pc = addr; 78118222Slinton if (not isbperr()) { 78218222Slinton printstatus(); 78316612Ssam } 78411874Slinton bpact(); 7859668Slinton break; 7869668Slinton 78718222Slinton case O_BRB: case O_BRW: 78816612Ssam case O_JMP: /* because it may be jmp (r1) */ 7899668Slinton case O_BNEQ: case O_BEQL: case O_BGTR: 7909668Slinton case O_BLEQ: case O_BGEQ: case O_BLSS: 7919668Slinton case O_BGTRU: case O_BLEQU: case O_BVC: 7929668Slinton case O_BVS: case O_BCC: case O_BCS: 7939668Slinton case O_CASEB: case O_CASEW: case O_CASEL: 7949668Slinton case O_BBS: case O_BBC: case O_BBSS: case O_BBCS: 7959668Slinton case O_BBSC: case O_BBCC: case O_BBSSI: 7969668Slinton case O_BBCCI: case O_BLBS: case O_BLBC: 7979668Slinton case O_ACBL: case O_AOBLSS: case O_AOBLEQ: 7989668Slinton case O_SOBGEQ: case O_SOBGTR: 7999668Slinton addrstatus = KNOWN; 8009668Slinton stepto(addr); 80116612Ssam pstep(process, DEFSIG); 8029668Slinton addr = reg(PROGCTR); 8039668Slinton pc = addr; 8049668Slinton if (not isbperr()) { 8059668Slinton printstatus(); 8069668Slinton } 8079668Slinton break; 8089668Slinton 8099668Slinton default: 8109668Slinton addrstatus = SEQUENTIAL; 8119668Slinton break; 8129668Slinton } 8139668Slinton if (addrstatus != KNOWN) { 8149668Slinton addr += 1; 8159668Slinton op = optab[ins]; 8169668Slinton for (argno = 0; argno < op.numargs; argno++) { 8179668Slinton if (indexf == true) { 8189668Slinton indexf = false; 8199668Slinton } 8209668Slinton argtype = op.argtype[argno]; 8219668Slinton if (is_branch_disp(argtype)) { 8229668Slinton mode = 0xAF + (typelen(argtype) << 5); 8239668Slinton } else { 8249668Slinton iread(&mode, addr, sizeof(mode)); 8259668Slinton addr += 1; 8269668Slinton } 8279668Slinton r = regname[regnm(mode)]; 8289668Slinton amode = addrmode(mode); 8299668Slinton switch (amode) { 8309668Slinton case LITSHORT: 8319668Slinton case LITUPTO31: 8329668Slinton case LITUPTO47: 8339668Slinton case LITUPTO63: 8349668Slinton argval = mode; 8359668Slinton break; 8369668Slinton 8379668Slinton case INDEX: 8389668Slinton indexf = true; 8399668Slinton --argno; 8409668Slinton break; 8419668Slinton 8429668Slinton case REG: 8439668Slinton case REGDEF: 8449668Slinton case AUTODEC: 8459668Slinton break; 8469668Slinton 8479668Slinton case AUTOINC: 8489668Slinton if (r == regname[PROGCTR]) { 8499668Slinton switch (typelen(argtype)) { 8509668Slinton case TYPB: 8519668Slinton argval = getdisp(addr, 1, r, amode); 8529668Slinton addr += 1; 8539668Slinton break; 8549668Slinton 8559668Slinton case TYPW: 8569668Slinton argval = getdisp(addr, 2, r, amode); 8579668Slinton addr += 2; 8589668Slinton break; 8599668Slinton 8609668Slinton case TYPL: 8619668Slinton argval = getdisp(addr, 4, r, amode); 8629668Slinton addr += 4; 8639668Slinton break; 8649668Slinton 8659668Slinton case TYPF: 8669668Slinton iread(&argval, addr, sizeof(argval)); 8679668Slinton addr += 4; 8689668Slinton break; 8699668Slinton 8709668Slinton case TYPQ: 8719668Slinton case TYPD: 8729668Slinton iread(&argval, addr+4, sizeof(argval)); 8739668Slinton addr += 8; 8749668Slinton break; 8759668Slinton } 8769668Slinton } 8779668Slinton break; 8789668Slinton 8799668Slinton case AUTOINCDEF: 8809668Slinton if (r == regname[PROGCTR]) { 8819668Slinton argval = getdisp(addr, 4, r, amode); 8829668Slinton addr += 4; 8839668Slinton } 8849668Slinton break; 8859668Slinton 8869668Slinton case BYTEDISP: 8879668Slinton case BYTEDISPDEF: 8889668Slinton argval = getdisp(addr, 1, r, amode); 8899668Slinton addr += 1; 8909668Slinton break; 8919668Slinton 8929668Slinton case WORDDISP: 8939668Slinton case WORDDISPDEF: 8949668Slinton argval = getdisp(addr, 2, r, amode); 8959668Slinton addr += 2; 8969668Slinton break; 8979668Slinton 8989668Slinton case LONGDISP: 8999668Slinton case LONGDISPDEF: 9009668Slinton argval = getdisp(addr, 4, r, amode); 9019668Slinton addr += 4; 9029668Slinton break; 9039668Slinton } 9049668Slinton } 9059668Slinton if (ins == O_CALLS or ins == O_CALLG) { 9069668Slinton argval += 2; 9079668Slinton } 9089668Slinton if (addrstatus == BRANCH) { 9099668Slinton addr = argval; 9109668Slinton } 9119668Slinton } 9129668Slinton return addr; 9139668Slinton } 9149668Slinton 9159668Slinton /* 9169668Slinton * Get the displacement of an instruction that uses displacement addressing. 9179668Slinton */ 9189668Slinton 9199668Slinton private int getdisp(addr, nbytes, reg, mode) 9209668Slinton Address addr; 9219668Slinton int nbytes; 9229668Slinton String reg; 9239668Slinton int mode; 9249668Slinton { 9259668Slinton char byte; 9269668Slinton short hword; 9279668Slinton int argval; 9289668Slinton 9299668Slinton switch (nbytes) { 9309668Slinton case 1: 9319668Slinton iread(&byte, addr, sizeof(byte)); 9329668Slinton argval = byte; 9339668Slinton break; 9349668Slinton 9359668Slinton case 2: 9369668Slinton iread(&hword, addr, sizeof(hword)); 9379668Slinton argval = hword; 9389668Slinton break; 9399668Slinton 9409668Slinton case 4: 9419668Slinton iread(&argval, addr, sizeof(argval)); 9429668Slinton break; 9439668Slinton } 9449668Slinton if (reg == regname[PROGCTR] && mode >= BYTEDISP) { 9459668Slinton argval += addr + nbytes; 9469668Slinton } 9479668Slinton return argval; 9489668Slinton } 9499668Slinton 9509668Slinton #define BP_OP O_BPT /* breakpoint trap */ 9519668Slinton #define BP_ERRNO SIGTRAP /* signal received at a breakpoint */ 9529668Slinton 9539668Slinton /* 9549668Slinton * Setting a breakpoint at a location consists of saving 9559668Slinton * the word at the location and poking a BP_OP there. 9569668Slinton * 9579668Slinton * We save the locations and words on a list for use in unsetting. 9589668Slinton */ 9599668Slinton 9609668Slinton typedef struct Savelist *Savelist; 9619668Slinton 9629668Slinton struct Savelist { 9639668Slinton Address location; 9649668Slinton Byte save; 9659668Slinton Byte refcount; 9669668Slinton Savelist link; 9679668Slinton }; 9689668Slinton 9699668Slinton private Savelist savelist; 9709668Slinton 9719668Slinton /* 9729668Slinton * Set a breakpoint at the given address. Only save the word there 9739668Slinton * if it's not already a breakpoint. 9749668Slinton */ 9759668Slinton 9769668Slinton public setbp(addr) 9779668Slinton Address addr; 9789668Slinton { 9799668Slinton Byte w; 9809668Slinton Byte save; 9819668Slinton register Savelist newsave, s; 9829668Slinton 9839668Slinton for (s = savelist; s != nil; s = s->link) { 9849668Slinton if (s->location == addr) { 9859668Slinton s->refcount++; 9869668Slinton return; 9879668Slinton } 9889668Slinton } 98911174Slinton iread(&save, addr, sizeof(save)); 9909668Slinton newsave = new(Savelist); 9919668Slinton newsave->location = addr; 9929668Slinton newsave->save = save; 9939668Slinton newsave->refcount = 1; 9949668Slinton newsave->link = savelist; 9959668Slinton savelist = newsave; 9969668Slinton w = BP_OP; 9979668Slinton iwrite(&w, addr, sizeof(w)); 9989668Slinton } 9999668Slinton 10009668Slinton /* 10019668Slinton * Unset a breakpoint; unfortunately we have to search the SAVELIST 10029668Slinton * to find the saved value. The assumption is that the SAVELIST will 10039668Slinton * usually be quite small. 10049668Slinton */ 10059668Slinton 10069668Slinton public unsetbp(addr) 10079668Slinton Address addr; 10089668Slinton { 10099668Slinton register Savelist s, prev; 10109668Slinton 10119668Slinton prev = nil; 10129668Slinton for (s = savelist; s != nil; s = s->link) { 10139668Slinton if (s->location == addr) { 10149668Slinton iwrite(&s->save, addr, sizeof(s->save)); 10159668Slinton s->refcount--; 10169668Slinton if (s->refcount == 0) { 10179668Slinton if (prev == nil) { 10189668Slinton savelist = s->link; 10199668Slinton } else { 10209668Slinton prev->link = s->link; 10219668Slinton } 10229668Slinton dispose(s); 10239668Slinton } 10249668Slinton return; 10259668Slinton } 10269668Slinton prev = s; 10279668Slinton } 10289668Slinton panic("unsetbp: couldn't find address %d", addr); 10299668Slinton } 10309668Slinton 10319668Slinton /* 10329668Slinton * Enter a procedure by creating and executing a call instruction. 10339668Slinton */ 10349668Slinton 10359668Slinton #define CALLSIZE 7 /* size of call instruction */ 10369668Slinton 10379668Slinton public beginproc(p, argc) 10389668Slinton Symbol p; 10399668Slinton Integer argc; 10409668Slinton { 10419668Slinton char save[CALLSIZE]; 10429668Slinton struct { 10439668Slinton VaxOpcode op; 10449668Slinton unsigned char numargs; 10459668Slinton unsigned char mode; 10469668Slinton char addr[sizeof(long)]; /* unaligned long */ 10479668Slinton } call; 10489668Slinton long dest; 10499668Slinton 10509668Slinton pc = 2; 10519668Slinton iread(save, pc, sizeof(save)); 10529668Slinton call.op = O_CALLS; 10539668Slinton call.numargs = argc; 10549668Slinton call.mode = 0xef; 10559668Slinton dest = codeloc(p) - 2 - (pc + 7); 10569668Slinton mov(&dest, call.addr, sizeof(call.addr)); 10579668Slinton iwrite(&call, pc, sizeof(call)); 10589668Slinton setreg(PROGCTR, pc); 105916612Ssam pstep(process, DEFSIG); 10609668Slinton iwrite(save, pc, sizeof(save)); 10619668Slinton pc = reg(PROGCTR); 10629668Slinton if (not isbperr()) { 10639668Slinton printstatus(); 10649668Slinton } 10659668Slinton } 106626336Ssam 106726336Ssam /* 106826336Ssam * Special variables for debugging the kernel. 106926336Ssam */ 107026336Ssam 107126336Ssam public integer masterpcbb; 107226336Ssam public integer slr; 107326336Ssam public struct pte *sbr; 107426336Ssam public struct pcb pcb; 107526336Ssam 107626336Ssam public getpcb () 107726336Ssam { 107826336Ssam fseek(corefile, physaddr(masterpcbb), 0); 107926336Ssam get(corefile, pcb); 108026336Ssam pcb.pcb_p0lr &= ~AST_CLR; 108126336Ssam printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", 108226336Ssam pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr 108326336Ssam ); 108426336Ssam setreg(0, pcb.pcb_r0); 108526336Ssam setreg(1, pcb.pcb_r1); 108626336Ssam setreg(2, pcb.pcb_r2); 108726336Ssam setreg(3, pcb.pcb_r3); 108826336Ssam setreg(4, pcb.pcb_r4); 108926336Ssam setreg(5, pcb.pcb_r5); 109026336Ssam setreg(6, pcb.pcb_r6); 109126336Ssam setreg(7, pcb.pcb_r7); 109226336Ssam setreg(8, pcb.pcb_r8); 109326336Ssam setreg(9, pcb.pcb_r9); 109426336Ssam setreg(10, pcb.pcb_r10); 109526336Ssam setreg(11, pcb.pcb_r11); 109626336Ssam setreg(ARGP, pcb.pcb_ap); 109726336Ssam setreg(FRP, pcb.pcb_fp); 109826336Ssam setreg(STKP, pcb.pcb_ksp); 109926336Ssam setreg(PROGCTR, pcb.pcb_pc); 110026336Ssam } 110126336Ssam 110226336Ssam public copyregs (savreg, reg) 110326336Ssam Word savreg[], reg[]; 110426336Ssam { 110526336Ssam reg[0] = savreg[R0]; 110626336Ssam reg[1] = savreg[R1]; 110726336Ssam reg[2] = savreg[R2]; 110826336Ssam reg[3] = savreg[R3]; 110926336Ssam reg[4] = savreg[R4]; 111026336Ssam reg[5] = savreg[R5]; 111126336Ssam reg[6] = savreg[R6]; 111226336Ssam reg[7] = savreg[R7]; 111326336Ssam reg[8] = savreg[R8]; 111426336Ssam reg[9] = savreg[R9]; 111526336Ssam reg[10] = savreg[R10]; 111626336Ssam reg[11] = savreg[R11]; 111726336Ssam reg[ARGP] = savreg[AP]; 111826336Ssam reg[FRP] = savreg[FP]; 111926336Ssam reg[STKP] = savreg[SP]; 112026336Ssam reg[PROGCTR] = savreg[PC]; 112126336Ssam } 112226336Ssam 112326336Ssam /* 112426336Ssam * Map a virtual address to a physical address. 112526336Ssam */ 112626336Ssam 112726336Ssam public Address vmap (addr) 112826336Ssam Address addr; 112926336Ssam { 113026336Ssam Address r; 113126336Ssam integer v, n; 113226336Ssam struct pte pte; 113326336Ssam 113426336Ssam r = addr & ~0xc0000000; 113526336Ssam v = btop(r); 113626336Ssam switch (addr&0xc0000000) { 113726336Ssam case 0xc0000000: 113826336Ssam case 0x80000000: 113926336Ssam /* 114026336Ssam * In system space, so get system pte. 114126336Ssam * If it is valid or reclaimable then the physical address 114226336Ssam * is the combination of its page number and the page offset 114326336Ssam * of the original address. 114426336Ssam */ 114526336Ssam if (v >= slr) { 114626336Ssam error("address %x out of segment", addr); 114726336Ssam } 114826336Ssam r = ((long) (sbr + v)) & ~0x80000000; 114926336Ssam goto simple; 115026336Ssam 115126336Ssam case 0x40000000: 115226336Ssam /* 115326336Ssam * In p1 space, must not be in shadow region. 115426336Ssam */ 115526336Ssam if (v < pcb.pcb_p1lr) { 115626336Ssam error("address %x out of segment", addr); 115726336Ssam } 115826336Ssam r = (Address) (pcb.pcb_p1br + v); 115926336Ssam break; 116026336Ssam 116126336Ssam case 0x00000000: 116226336Ssam /* 116326336Ssam * In p0 space, must not be off end of region. 116426336Ssam */ 116526336Ssam if (v >= pcb.pcb_p0lr) { 116626336Ssam error("address %x out of segment", addr); 116726336Ssam } 116826336Ssam r = (Address) (pcb.pcb_p0br + v); 116926336Ssam break; 117026336Ssam 117126336Ssam default: 117226336Ssam /* do nothing */ 117326336Ssam break; 117426336Ssam } 117526336Ssam /* 117626336Ssam * For p0/p1 address, user-level page table should be in 117726336Ssam * kernel virtual memory. Do second-level indirect by recursing. 117826336Ssam */ 117926336Ssam if ((r & 0x80000000) == 0) { 118026336Ssam error("bad p0br or p1br in pcb"); 118126336Ssam } 118226336Ssam r = vmap(r); 118326336Ssam simple: 118426336Ssam /* 118526336Ssam * "r" is now the address of the pte of the page 118626336Ssam * we are interested in; get the pte and paste up the physical address. 118726336Ssam */ 118826336Ssam fseek(corefile, r, 0); 118926336Ssam n = fread(&pte, sizeof(pte), 1, corefile); 119026336Ssam if (n != 1) { 119126336Ssam error("page table botch (fread at %x returns %d)", r, n); 119226336Ssam } 119326336Ssam if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { 119426336Ssam error("page no valid or reclamable"); 119526336Ssam } 119626336Ssam return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); 119726336Ssam } 1198