📄 vax.c
字号:
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)vax.c 5.8 (Berkeley) 6/1/90";#endif /* not lint *//* * Target machine dependent stuff. */#include "defs.h"#include "machine.h"#include "process.h"#include "runtime.h"#include "events.h"#include "main.h"#include "symbols.h"#include "source.h"#include "mappings.h"#include "object.h"#include "tree.h"#include "eval.h"#include "keywords.h"#include "ops.h"#ifndef publictypedef unsigned int Address;typedef unsigned char Byte;typedef unsigned int Word;#define NREG 16#define ARGP 12#define FRP 13#define STKP 14#define PROGCTR 15#define CODESTART 0#define FUNCOFFSET 2#define nargspassed(frame) argn(0, frame)#define BITSPERBYTE 8#define BITSPERWORD (BITSPERBYTE * sizeof(Word))/* * This magic macro enables us to look at the process' registers * in its user structure. */#define regloc(reg) (ctob(UPAGES) + (sizeof(Word) * (reg)))#include "source.h"#include "symbols.h"#include <signal.h>#include <sys/param.h>#include <machine/psl.h>#include <machine/pte.h>#include <sys/user.h>#undef DELETE /* XXX */#include <sys/vm.h>#include <machine/reg.h>Address pc;Address prtaddr;#endif/* * Indices into u. for use in collecting registers values. */public int rloc[] ={ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};private Address printop();private Optab *ioptab[256]; /* index by opcode to optab */private Optab *esctab[256]; /* for extended opcodes *//* * Initialize the opcode lookup table. */public optab_init(){ register Optab *p; for (p = optab; p->iname; p++) { if (p->format == O_ESCD) { esctab[p->val] = p; } else if (p->format != O_ESCD && p->format != O_ESCE) { ioptab[p->val] = p; } }}/* * Decode and print the instructions within the given address range. */public printinst(lowaddr, highaddr)Address lowaddr;Address highaddr;{ register Address addr; for (addr = lowaddr; addr <= highaddr; ) { addr = printop(addr); } prtaddr = addr;}/* * Another approach: print n instructions starting at the given address. */public printninst(count, addr)int count;Address addr;{ register Integer i; register Address newaddr; if (count <= 0) { error("non-positive repetition count"); } else { newaddr = addr; for (i = 0; i < count; i++) { newaddr = printop(newaddr); } prtaddr = newaddr; }}/* * Print the contents of the addresses within the given range * according to the given format. */typedef struct { String name; String printfstring; int length;} Format;private Format fmt[] = { { "d", " %d", sizeof(short) }, { "D", " %ld", sizeof(long) }, { "o", " %o", sizeof(short) }, { "O", " %lo", sizeof(long) }, { "x", " %04x", sizeof(short) }, { "X", " %08x", sizeof(long) }, { "b", " \\%o", sizeof(char) }, { "c", " '%c'", sizeof(char) }, { "s", "%c", sizeof(char) }, { "f", " %f", sizeof(float) }, { "g", " %g", sizeof(double) }, { nil, nil, 0 }};private Format *findformat(s)String s;{ register Format *f; f = &fmt[0]; while (f->name != nil and not streq(f->name, s)) { ++f; } if (f->name == nil) { error("bad print format \"%s\"", s); } return f;}/* * Retrieve and print out the appropriate data in the given format. * Floats have to be handled specially to allow the compiler to * convert them to doubles when passing to printf. */private printformat (f, addr)Format *f;Address addr;{ union { char charv; short shortv; int intv; float floatv; double doublev; } value; value.intv = 0; dread(&value, addr, f->length); if (streq(f->name, "f")) { printf(f->printfstring, value.floatv); } else { printf(f->printfstring, value); }}public Address printdata(lowaddr, highaddr, format)Address lowaddr;Address highaddr;String format;{ int n; register Address addr; Format *f; if (lowaddr > highaddr) { error("first address larger than second"); } f = findformat(format); n = 0; for (addr = lowaddr; addr <= highaddr; addr += f->length) { if (n == 0) { printf("%08x: ", addr); } printformat(f, addr); ++n; if (n >= (16 div f->length)) { printf("\n"); n = 0; } } if (n != 0) { printf("\n"); } prtaddr = addr; return addr;}/* * The other approach is to print n items starting with a given address. */public printndata(count, startaddr, format)int count;Address startaddr;String format;{ int i, n; Address addr; Format *f; Boolean isstring; char c; if (count <= 0) { error("non-positive repetition count"); } f = findformat(format); isstring = (Boolean) streq(f->name, "s"); n = 0; addr = startaddr; for (i = 0; i < count; i++) { if (n == 0) { printf("%08x: ", addr); } if (isstring) { printf("\""); dread(&c, addr, sizeof(char)); while (c != '\0') { printchar(c); ++addr; dread(&c, addr, sizeof(char)); } printf("\"\n"); n = 0; addr += sizeof(String); } else { printformat(f, addr); ++n; if (n >= (16 div f->length)) { printf("\n"); n = 0; } addr += f->length; } } if (n != 0) { printf("\n"); } prtaddr = addr;}/* * Print out a value according to the given format. */public printvalue(v, format)long v;String format;{ Format *f; char *p, *q; f = findformat(format); if (streq(f->name, "s")) { putchar('"'); p = (char *) &v; q = p + sizeof(v); while (p < q) { printchar(*p); ++p; } putchar('"'); } else { printf(f->printfstring, v); } putchar('\n');}/* * Print out an execution time error. * Assumes the source position of the error has been calculated. * * Have to check if the -r option was specified; if so then * the object file information hasn't been read in yet. */public printerror(){ extern Integer sys_nsig; extern String sys_siglist[]; integer err; if (isfinished(process)) { err = exitcode(process); if (err == 0) { printf("\"%s\" terminated normally\n", objname); } else { printf("\"%s\" terminated abnormally (exit code %d)\n", objname, err ); } erecover(); } err = errnum(process); putchar('\n'); printsig(err); putchar(' '); printloc(); putchar('\n'); if (curline > 0) { printlines(curline, curline); } else { printinst(pc, pc); } erecover();}/* * Print out a signal. */private String illinames[] = { "reserved addressing fault", "privileged instruction fault", "reserved operand fault"};private String fpenames[] = { nil, "integer overflow trap", "integer divide by zero trap", "floating overflow trap", "floating/decimal divide by zero trap", "floating underflow trap", "decimal overflow trap", "subscript out of range trap", "floating overflow fault", "floating divide by zero fault", "floating underflow fault"};public printsig (signo)integer signo;{ integer code; if (signo < 0 or signo > sys_nsig) { printf("[signal %d]", signo); } else { printf("%s", sys_siglist[signo]); } code = errcode(process); if (signo == SIGILL) { if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) { printf(" (%s)", illinames[code]); } } else if (signo == SIGFPE) { if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) { printf(" (%s)", fpenames[code]); } }}/* * Note the termination of the program. We do this so as to avoid * having the process exit, which would make the values of variables * inaccessible. We do want to flush all output buffers here, * otherwise it'll never get done. */public endprogram(){ Integer exitcode; stepto(nextaddr(pc, true)); printnews(); exitcode = argn(1, nil); if (exitcode != 0) { printf("\nexecution completed (exit code %d)\n", exitcode); } else { printf("\nexecution completed\n"); } getsrcpos(); erecover();}/* * Single step the machine a source line (or instruction if "inst_tracing" * is true). If "isnext" is true, skip over procedure calls. */private Address getcall();public dostep(isnext)Boolean isnext;{ register Address addr; register Lineno line; String filename; Address startaddr; startaddr = pc; addr = nextaddr(pc, isnext); if (not inst_tracing and nlhdr.nlines != 0) { line = linelookup(addr); while (line == 0) { addr = nextaddr(addr, isnext); line = linelookup(addr); } curline = line; } else { curline = 0; } stepto(addr); filename = srcfilename(addr); setsource(filename);}typedef char Bpinst;#define BP_OP O_BPT /* breakpoint trap */#define BP_ERRNO SIGTRAP /* signal received at a breakpoint *//* * Setting a breakpoint at a location consists of saving * the word at the location and poking a BP_OP there. * * We save the locations and words on a list for use in unsetting. */typedef struct Savelist *Savelist;struct Savelist { Address location; Bpinst save; short refcount; Savelist link;};private Savelist savelist;/* * Set a breakpoint at the given address. Only save the word there * if it's not already a breakpoint. */public setbp(addr)Address addr;{ Bpinst w, save; register Savelist newsave, s; for (s = savelist; s != nil; s = s->link) { if (s->location == addr) { s->refcount++; return; } } iread(&save, addr, sizeof(save)); newsave = new(Savelist); newsave->location = addr; newsave->save = save; newsave->refcount = 1; newsave->link = savelist; savelist = newsave; w = BP_OP; iwrite(&w, addr, sizeof(w));}/* * Unset a breakpoint; unfortunately we have to search the SAVELIST * to find the saved value. The assumption is that the SAVELIST will * usually be quite small. */public unsetbp(addr)Address addr;{ register Savelist s, prev; prev = nil; for (s = savelist; s != nil; s = s->link) { if (s->location == addr) { iwrite(&s->save, addr, sizeof(s->save)); s->refcount--; if (s->refcount == 0) { if (prev == nil) { savelist = s->link; } else { prev->link = s->link; } dispose(s); } return; } prev = s; } panic("unsetbp: couldn't find address %d", addr);}/* * VAX instruction decoder, derived from adb. */private Address printop(addr)Address addr;{ register Optab *op; VaxOpcode ins; unsigned char mode; int argtype, amode, argno, argval; String reg; Boolean indexf; short offset; argval = 0; indexf = false; printf("%08x ", addr); iread(&ins, addr, sizeof(ins)); addr += 1; if (ins == O_ESCF) { iread(&ins, addr, sizeof(ins)); addr += 1; op = ioptab[ins]; } else if (ins == O_ESCD) { iread(&ins, addr, sizeof(ins)); addr += 1; op = esctab[ins]; } else { op = ioptab[ins]; } if (op == nil) { printf("[unrecognized opcode %#0x]\n", ins); return addr; } printf("%s", op->iname); for (argno = 0; argno < op->numargs; argno++) { if (indexf == true) { indexf = false; } else if (argno == 0) { printf("\t"); } else { printf(","); } argtype = op->argtype[argno]; if (is_branch_disp(argtype)) { mode = 0xAF + (typelen(argtype) << 5); } else { iread(&mode, addr, sizeof(mode)); addr += 1; } reg = regname[regnm(mode)]; amode = addrmode(mode); switch (amode) { case LITSHORT: case LITUPTO31: case LITUPTO47: case LITUPTO63: if (typelen(argtype) == TYPF || typelen(argtype) == TYPD || typelen(argtype) == TYPG || typelen(argtype) == TYPH) printf("$%s", fltimm[mode]); else printf("$%x", mode); argval = mode; break; case INDEX: printf("[%s]", reg); indexf = true; argno--; break; case REG: printf("%s", reg); break; case REGDEF: printf("(%s)", reg); break; case AUTODEC: printf("-(%s)", reg); break; case AUTOINC: if (reg != regname[PROGCTR]) { printf("(%s)+", reg); } else { printf("$"); switch (typelen(argtype)) { case TYPB: argval = printdisp(addr, 1, reg, amode); addr += 1; break; case TYPW: argval = printdisp(addr, 2, reg, amode); addr += 2; break; case TYPL: argval = printdisp(addr, 4, reg, amode); addr += 4; break; case TYPF: iread(&argval, addr, sizeof(argval)); if ((argval & 0xffff007f) == 0x8000) { printf("[reserved operand]"); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -