/* Copyright (c) 1982 Regents of the University of California */
-static char sccsid[] = "@(#)vax.c 1.3 %G%";
+static char sccsid[] = "@(#)vax.c 1.13 (Berkeley) %G%";
+
+static char rcsid[] = "$Header: machine.c,v 1.5 84/12/26 10:40:05 linton Exp $";
/*
* 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 "keywords.h"
#include "ops.h"
#include <signal.h>
char byte;
short hword;
int argval;
+ Symbol f;
switch (nbytes) {
case 1:
argval += addr + nbytes;
}
if (reg == regname[PROGCTR]) {
- printf("%x", argval);
+ f = whatblock((Address) argval + 2);
+ if (codeloc(f) == argval + 2) {
+ printf("%s", symname(f));
+ } else {
+ printf("%x", argval);
+ }
} else {
- printf("%d(%s)", argval, reg);
+ if (varIsSet("$hexoffsets")) {
+ if (argval < 0) {
+ printf("-%x(%s)", -(argval), reg);
+ } else {
+ printf("%x(%s)", argval, reg);
+ }
+ } else {
+ printf("%d(%s)", argval, reg);
+ }
}
return argval;
}
{ "b", " \\%o", sizeof(char) },
{ "c", " '%c'", sizeof(char) },
{ "s", "%c", sizeof(char) },
- { "f", " %f", sizeof(double) },
+ { "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;
+}
+
public Address printdata(lowaddr, highaddr, format)
Address lowaddr;
Address highaddr;
if (lowaddr > highaddr) {
error("first address larger than second");
}
- f = &fmt[0];
- while (f->name != nil and not streq(f->name, format)) {
- ++f;
- }
- if (f->name == nil) {
- error("bad print format \"%s\"", format);
- }
+ f = findformat(format);
n = 0;
value = 0;
for (addr = lowaddr; addr <= highaddr; addr += f->length) {
register Address addr;
register Format *f;
register Boolean isstring;
- int value;
+ char c;
+ union {
+ char charv;
+ short shortv;
+ int intv;
+ float floatv;
+ double doublev;
+ } value;
if (count <= 0) {
error("non-positive repetition count");
}
- f = &fmt[0];
- while (f->name != nil and not streq(f->name, format)) {
- ++f;
- }
- if (f->name == nil) {
- error("bad print format \"%s\"", format);
- }
+ f = findformat(format);
isstring = (Boolean) streq(f->name, "s");
n = 0;
addr = startaddr;
- value = 0;
+ value.intv = 0;
for (i = 0; i < count; i++) {
if (n == 0) {
printf("%08x: ", addr);
}
if (isstring) {
putchar('"');
- dread(&value, addr, sizeof(char));
- while (value != '\0') {
- printchar((char) value);
+ dread(&c, addr, sizeof(char));
+ while (c != '\0') {
+ printchar(c);
++addr;
- dread(&value, addr, sizeof(char));
+ dread(&c, addr, sizeof(char));
}
putchar('"');
putchar('\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.
{
extern Integer sys_nsig;
extern String sys_siglist[];
- String filename;
- Integer err;
+ integer err;
if (isfinished(process)) {
- printf("\"%s\" exits with code %d\n", objname, exitcode(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();
}
if (runfirst) {
- fprintf(stderr, "Entering debugger ...");
+ fprintf(stderr, "Entering debugger ...\n");
init();
- fprintf(stderr, " type 'help' for help\n");
}
- curline = srcline(pc);
- curfunc = whatblock(pc);
- filename = srcfilename(pc);
- setsource(filename);
err = errnum(process);
- if (err == SIGINT) {
- printf("\n\ninterrupt ");
- printloc();
- } else if (err == SIGTRAP) {
- printf("\nerror ");
- printloc();
- } else {
- if (err < 0 or err > sys_nsig) {
- printf("\nsignal %d ", err);
- } else {
- printf("\n%s ", sys_siglist[err]);
- }
- printloc();
- }
+ putchar('\n');
+ printsig(err);
+ putchar(' ');
+ printloc();
putchar('\n');
if (curline > 0) {
printlines(curline, curline);
erecover();
}
-private printloc()
+/*
+ * Print out a signal.
+ */
+
+private String illinames[] = {
+ "reserved addressing fault",
+ "priviliged 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 undeflow fault"
+};
+
+public printsig (signo)
+integer signo;
{
- if (curline > 0) {
- if (nlhdr.nfiles > 1) {
- printf("at line %d in file %s", curline, cursource);
- } else {
- printf("at line %d", curline);
- }
+ integer code;
+
+ if (signo < 0 or signo > sys_nsig) {
+ printf("[signal %d]", signo);
} else {
- printf("in ");
- printname(stdout, curfunc);
- printf(" at 0x%x", pc);
+ 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]);
+ }
}
}
stepto(nextaddr(pc, true));
printnews();
exitcode = argn(1, nil);
- printf("\nexecution completed, exit code is %d\n", exitcode);
+ 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.
+ * is true). If "isnext" is true, skip over procedure calls.
*/
private Address getcall();
register Address addr;
register Lineno line;
String filename;
+ Address startaddr;
+ startaddr = pc;
addr = nextaddr(pc, isnext);
- if (not inst_tracing) {
+ 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);
- curline = line;
filename = srcfilename(addr);
setsource(filename);
}
* that branches is the branch address (or relative offset).
*/
+private Address findnextaddr();
+
public Address nextaddr(startaddr, isnext)
Address startaddr;
+boolean isnext;
+{
+ Address addr;
+
+ addr = usignal(process);
+ if (addr == 0 or addr == 1) {
+ addr = findnextaddr(startaddr, isnext);
+ }
+ return addr;
+}
+
+/*
+ * Determine if it's ok to skip function f entered by instruction ins.
+ * If so, we're going to compute the return address and step to it.
+ * Therefore we cannot skip over a function entered by a jsb or bsb,
+ * since the return address is not easily computed for them.
+ */
+
+private boolean skipfunc (ins, f)
+VaxOpcode ins;
+Symbol f;
+{
+ boolean b;
+
+ b = (boolean) (
+ ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
+ not inst_tracing and nlhdr.nlines != 0 and
+ nosource(curfunc) and canskip(curfunc)
+ );
+ return b;
+}
+
+private Address findnextaddr(startaddr, isnext)
+Address startaddr;
Boolean isnext;
{
register Address addr;
addr = startaddr;
iread(&ins, addr, sizeof(ins));
switch (ins) {
+ /*
+ * It used to be that unconditional jumps and branches were handled
+ * by taking their destination address as the next address. While
+ * saving the cost of starting up the process, this approach
+ * doesn't work when jumping indirect (since the value in the
+ * register might not yet have been set).
+ *
+ * So unconditional jumps and branches are now handled the same way
+ * as conditional jumps and branches.
+ *
case O_BRB:
case O_BRW:
- case O_JMP:
addrstatus = BRANCH;
break;
+ *
+ */
case O_BSBB:
case O_BSBW:
case O_JSB:
case O_CALLG:
case O_CALLS:
- if (isnext) {
- addrstatus = SEQUENTIAL;
- } else {
+ addrstatus = KNOWN;
+ stepto(addr);
+ pstep(process, DEFSIG);
+ addr = reg(PROGCTR);
+ pc = addr;
+ setcurfunc(whatblock(pc));
+ if (not isbperr()) {
+ printstatus();
+ /* NOTREACHED */
+ }
+ bpact();
+ if (isnext or skipfunc(ins, curfunc)) {
addrstatus = KNOWN;
+ addr = return_addr();
stepto(addr);
- pstep(process);
- addr = reg(PROGCTR);
- pc = addr;
+ bpact();
+ } else {
callnews(/* iscall = */ true);
- if (not isbperr()) {
- printstatus();
- } else {
- bpact();
- }
}
break;
case O_RSB:
case O_RET:
addrstatus = KNOWN;
- callnews(/* iscall = */ false);
- addr = return_addr();
stepto(addr);
+ callnews(/* iscall = */ false);
+ pstep(process, DEFSIG);
+ addr = reg(PROGCTR);
+ pc = addr;
+ if (not isbperr()) {
+ printstatus();
+ }
+ bpact();
break;
+ case O_BRB: case O_BRW:
+ case O_JMP: /* because it may be jmp (r1) */
case O_BNEQ: case O_BEQL: case O_BGTR:
case O_BLEQ: case O_BGEQ: case O_BLSS:
case O_BGTRU: case O_BLEQU: case O_BVC:
case O_SOBGEQ: case O_SOBGTR:
addrstatus = KNOWN;
stepto(addr);
- pstep(process);
+ pstep(process, DEFSIG);
addr = reg(PROGCTR);
pc = addr;
if (not isbperr()) {
return;
}
}
- iread(&save, addr, sizeof(addr));
+ iread(&save, addr, sizeof(save));
newsave = new(Savelist);
newsave->location = addr;
newsave->save = save;
panic("unsetbp: couldn't find address %d", addr);
}
-/*
- * Predicate to test if the reason the process stopped was because
- * of a breakpoint.
- */
-
-public Boolean isbperr()
-{
- return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP);
-}
-
/*
* Enter a procedure by creating and executing a call instruction.
*/
mov(&dest, call.addr, sizeof(call.addr));
iwrite(&call, pc, sizeof(call));
setreg(PROGCTR, pc);
- pstep(process);
+ pstep(process, DEFSIG);
iwrite(save, pc, sizeof(save));
pc = reg(PROGCTR);
if (not isbperr()) {