file reorg, pathnames.h, paths.h
[unix-history] / usr / src / old / dbx / process.c
index 23118e5..edb31aa 100644 (file)
@@ -1,6 +1,14 @@
-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
 
 
-static char sccsid[] = "@(#)process.c 1.12 %G%";
+#ifndef lint
+static char sccsid[] = "@(#)process.c  5.3 (Berkeley) %G%";
+#endif not lint
+
+static char rcsid[] = "$Header: process.c,v 1.4 88/01/10 00:49:31 donn Exp $";
 
 /*
  * Process management.
 
 /*
  * Process management.
@@ -23,8 +31,6 @@ static char sccsid[] = "@(#)process.c 1.12 %G%";
 #include "coredump.h"
 #include <signal.h>
 #include <errno.h>
 #include "coredump.h"
 #include <signal.h>
 #include <errno.h>
-#include <sys/param.h>
-#include <machine/reg.h>
 #include <sys/stat.h>
 
 #ifndef public
 #include <sys/stat.h>
 
 #ifndef public
@@ -44,11 +50,12 @@ Process process;
 #define FINISHED 0
 
 /*
 #define FINISHED 0
 
 /*
- * Cache-ing of instruction segment is done to reduce the number
- * of system calls.
+ * A cache of the instruction segment is kept to reduce the number
+ * of system calls.  Might be better just to read the entire
+ * code space into memory.
  */
 
  */
 
-#define CSIZE 1003       /* size of instruction cache */
+#define CACHESIZE 1003
 
 typedef struct {
     Word addr;
 
 typedef struct {
     Word addr;
@@ -66,10 +73,12 @@ struct Process {
     Word oreg[NREG];           /* registers when process last stopped */
     short status;              /* either STOPPED or FINISHED */
     short signo;               /* signal that stopped process */
     Word oreg[NREG];           /* registers when process last stopped */
     short status;              /* either STOPPED or FINISHED */
     short signo;               /* signal that stopped process */
+    short sigcode;             /* extra signal information */
     int exitval;               /* return value from exit() */
     long sigset;               /* bit array of traced signals */
     int exitval;               /* return value from exit() */
     long sigset;               /* bit array of traced signals */
-    CacheWord word[CSIZE];     /* text segment cache */
+    CacheWord word[CACHESIZE]; /* text segment cache */
     Ttyinfo ttyinfo;           /* process' terminal characteristics */
     Ttyinfo ttyinfo;           /* process' terminal characteristics */
+    Address sigstatus;         /* process' handler for current signal */
 };
 
 /*
 };
 
 /*
@@ -81,7 +90,7 @@ typedef enum { TEXTSEG, DATASEG } PioSeg;
 
 private struct Process pbuf;
 
 
 private struct Process pbuf;
 
-#define MAXNCMDARGS 100         /* maximum number of arguments to RUN */
+#define MAXNCMDARGS 1000         /* maximum number of arguments to RUN */
 
 extern int errno;
 
 
 extern int errno;
 
@@ -96,24 +105,36 @@ private String infile, outfile;
 
 public process_init()
 {
 
 public process_init()
 {
-    register Integer i;
-    Char buf[10];
+    register integer i;
+    char buf[10];
 
     process = &pbuf;
     process->status = (coredump) ? STOPPED : NOTSTARTED;
     setsigtrace();
 
     process = &pbuf;
     process->status = (coredump) ? STOPPED : NOTSTARTED;
     setsigtrace();
-    for (i = 0; i < NREG; i++) {
-       sprintf(buf, "$r%d", i);
-       defregname(identname(buf, false), i);
-    }
-    defregname(identname("$ap", true), ARGP);
+#   if vax || tahoe
+       for (i = 0; i < NREG; i++) {
+           sprintf(buf, "$r%d", i);
+           defregname(identname(buf, false), i);
+       }
+#      ifdef vax
+           defregname(identname("$ap", true), ARGP);
+#      endif
+#   else
+#       ifdef mc68000
+           for (i = 0; i < 8; i++) {
+               sprintf(buf, "$d%d", i);
+               defregname(identname(buf, false), i);
+               sprintf(buf, "$a%d", i);
+               defregname(identname(buf, false), i + 8);
+           }
+#       endif
+#   endif
     defregname(identname("$fp", true), FRP);
     defregname(identname("$sp", true), STKP);
     defregname(identname("$pc", true), PROGCTR);
     if (coredump) {
        coredump_readin(process->mask, process->reg, process->signo);
        pc = process->reg[PROGCTR];
     defregname(identname("$fp", true), FRP);
     defregname(identname("$sp", true), STKP);
     defregname(identname("$pc", true), PROGCTR);
     if (coredump) {
        coredump_readin(process->mask, process->reg, process->signo);
        pc = process->reg[PROGCTR];
-       getsrcpos();
     }
     arginit();
 }
     }
     arginit();
 }
@@ -170,13 +191,13 @@ String infile, outfile;
     } else {
        argv[argc] = nil;
     }
     } else {
        argv[argc] = nil;
     }
+    pstart(process, argv, infile, outfile);
     if (remade(objname)) {
        reinit(argv, infile, outfile);
     }
     if (remade(objname)) {
        reinit(argv, infile, outfile);
     }
-    pstart(process, argv, infile, outfile);
     if (process->status == STOPPED) {
     if (process->status == STOPPED) {
-       pc = 0;
-       curfunc = program;
+       pc = CODESTART;
+       setcurfunc(program);
        if (objsize != 0) {
            cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));
            event_once(cond, buildcmdlist(build(O_ENDX)));
        if (objsize != 0) {
            cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));
            event_once(cond, buildcmdlist(build(O_ENDX)));
@@ -219,9 +240,12 @@ private setsigtrace()
     psigtrace(p, SIGHUP, false);
     psigtrace(p, SIGKILL, false);
     psigtrace(p, SIGALRM, false);
     psigtrace(p, SIGHUP, false);
     psigtrace(p, SIGKILL, false);
     psigtrace(p, SIGALRM, false);
-    psigtrace(p, SIGTSTP, false);
-    psigtrace(p, SIGCONT, false);
+#   ifdef SIGTSTP
+       psigtrace(p, SIGTSTP, false);
+       psigtrace(p, SIGCONT, false);
+#   endif
     psigtrace(p, SIGCHLD, false);
     psigtrace(p, SIGCHLD, false);
+    psigtrace(p, SIGWINCH, false);
 }
 
 /*
 }
 
 /*
@@ -303,12 +327,11 @@ typedef int Intfunc();
 private Intfunc *dbintr;
 private intr();
 
 private Intfunc *dbintr;
 private intr();
 
-#define succeeds    == true
-#define fails       == false
-
 public cont(signo)
 public cont(signo)
-int signo;
+integer signo;
 {
 {
+    integer s;
+
     dbintr = signal(SIGINT, intr);
     if (just_started) {
        just_started = false;
     dbintr = signal(SIGINT, intr);
     if (just_started) {
        just_started = false;
@@ -319,14 +342,16 @@ int signo;
        isstopped = false;
        stepover();
     }
        isstopped = false;
        stepover();
     }
+    s = signo;
     for (;;) {
        if (single_stepping) {
            printnews();
        } else {
            setallbps();
     for (;;) {
        if (single_stepping) {
            printnews();
        } else {
            setallbps();
-           resume(signo);
+           resume(s);
            unsetallbps();
            unsetallbps();
-           if (bpact() fails) {
+           s = DEFSIG;
+           if (not isbperr() or not bpact()) {
                printstatus();
            }
        }
                printstatus();
            }
        }
@@ -336,12 +361,12 @@ int signo;
 }
 
 /*
 }
 
 /*
- * This routine is called if we get an interrupt while "running" px
+ * This routine is called if we get an interrupt while "running"
  * but actually in the debugger.  Could happen, for example, while
  * processing breakpoints.
  *
  * We basically just want to keep going; the assumption is
  * but actually in the debugger.  Could happen, for example, while
  * processing breakpoints.
  *
  * We basically just want to keep going; the assumption is
- * that when the process resumes it will get the interrupt
+ * that when the process resumes it will get the interrupt,
  * which will then be handled.
  */
 
  * which will then be handled.
  */
 
@@ -365,22 +390,17 @@ int signo;
     register Process p;
 
     p = process;
     register Process p;
 
     p = process;
-    if (traceexec) {
-       printf("execution resumes at pc 0x%x\n", process->reg[PROGCTR]);
-       fflush(stdout);
-    }
     pcont(p, signo);
     pc = process->reg[PROGCTR];
     pcont(p, signo);
     pc = process->reg[PROGCTR];
-    if (traceexec) {
-       printf("execution stops at pc 0x%x on sig %d\n",
-           process->reg[PROGCTR], p->signo);
-       fflush(stdout);
-    }
     if (p->status != STOPPED) {
        if (p->signo != 0) {
            error("program terminated by signal %d", p->signo);
        } else if (not runfirst) {
     if (p->status != STOPPED) {
        if (p->signo != 0) {
            error("program terminated by signal %d", p->signo);
        } else if (not runfirst) {
-           error("program unexpectedly exited with %d", p->exitval);
+           if (p->exitval == 0) {
+               error("program exited");
+           } else {
+               error("program exited with code %d", p->exitval);
+           }
        }
     }
 }
        }
     }
 }
@@ -410,14 +430,60 @@ public stepc()
 
 public next()
 {
 
 public next()
 {
+    Address oldfrp, newfrp;
+
     if (not isstopped) {
        error("can't continue execution");
     }
     isstopped = false;
     if (not isstopped) {
        error("can't continue execution");
     }
     isstopped = false;
-    dostep(true);
+    oldfrp = reg(FRP);
+    do {
+       dostep(true);
+       pc = reg(PROGCTR);
+       newfrp = reg(FRP);
+    } while (newfrp < oldfrp and newfrp != 0);
     isstopped = true;
 }
 
     isstopped = true;
 }
 
+/*
+ * Continue execution until the current function returns, or,
+ * if the given argument is non-nil, until execution returns to
+ * somewhere within the given function.
+ */
+
+public rtnfunc (f)
+Symbol f;
+{
+    Address addr;
+    Symbol t;
+
+    if (not isstopped) {
+       error("can't continue execution");
+    } else if (f != nil and not isactive(f)) {
+       error("%s is not active", symname(f));
+    } else {
+       addr = return_addr();
+       if (addr == nil) {
+           error("no place to return to");
+       } else {
+           isstopped = false;
+           contto(addr);
+           if (f != nil) {
+               for (;;) {
+                   t = whatblock(pc);
+                   addr = return_addr();
+               if (t == f or addr == nil) break;
+                   contto(addr);
+               }
+           }
+           if (not bpact()) {
+               isstopped = true;
+               printstatus();
+           }
+       }
+    }
+}
+
 /*
  * Single-step over the current machine instruction.
  *
 /*
  * Single-step over the current machine instruction.
  *
@@ -427,10 +493,13 @@ public next()
  * source line.
  */
 
  * source line.
  */
 
-private stepover()
+public stepover()
 {
     Boolean b;
 
 {
     Boolean b;
 
+    if (traceexec) {
+       printf("!! stepping over 0x%x\n", process->reg[PROGCTR]);
+    }
     if (single_stepping) {
        dostep(false);
     } else {
     if (single_stepping) {
        dostep(false);
     } else {
@@ -439,22 +508,54 @@ private stepover()
        dostep(false);
        inst_tracing = b;
     }
        dostep(false);
        inst_tracing = b;
     }
+    if (traceexec) {
+       printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]);
+    }
 }
 
 /*
 }
 
 /*
- * Resume execution up to the given address.  It is assumed that
- * no breakpoints exist between the current address and the one
- * we're stepping to.  This saves us from setting all the breakpoints.
+ * Resume execution up to the given address.  We can either ignore
+ * breakpoints (stepto) or catch them (contto).
  */
 
 public stepto(addr)
 Address addr;
 {
  */
 
 public stepto(addr)
 Address addr;
 {
-    setbp(addr);
-    resume(DEFSIG);
-    unsetbp(addr);
-    if (not isbperr()) {
-       printstatus();
+    xto(addr, false);
+}
+
+private contto (addr)
+Address addr;
+{
+    xto(addr, true);
+}
+
+private xto (addr, catchbps)
+Address addr;
+boolean catchbps;
+{
+    Address curpc;
+
+    if (catchbps) {
+       stepover();
+    }
+    curpc = process->reg[PROGCTR];
+    if (addr != curpc) {
+       if (traceexec) {
+           printf("!! stepping from 0x%x to 0x%x\n", curpc, addr);
+       }
+       if (catchbps) {
+           setallbps();
+       }
+       setbp(addr);
+       resume(DEFSIG);
+       unsetbp(addr);
+       if (catchbps) {
+           unsetallbps();
+       }
+       if (not isbperr()) {
+           printstatus();
+       }
     }
 }
 
     }
 }
 
@@ -463,14 +564,19 @@ Address addr;
  * This routine does not return.
  */
 
  * This routine does not return.
  */
 
-public printstatus()
+public printstatus ()
 {
     int status;
 
     if (process->status == FINISHED) {
        exit(0);
     } else {
 {
     int status;
 
     if (process->status == FINISHED) {
        exit(0);
     } else {
-       curfunc = whatblock(pc);
+       if (runfirst) {
+           fprintf(stderr, "\nEntering debugger ...\n");
+           printheading();
+           init();
+       }
+       setcurfunc(whatblock(pc));
        getsrcpos();
        if (process->signo == SIGINT) {
            isstopped = true;
        getsrcpos();
        if (process->signo == SIGINT) {
            isstopped = true;
@@ -486,7 +592,6 @@ public printstatus()
            }
            erecover();
        } else {
            }
            erecover();
        } else {
-           fixbps();
            fixintr();
            isstopped = true;
            printerror();
            fixintr();
            isstopped = true;
            printerror();
@@ -529,20 +634,53 @@ Process p;
 }
 
 /*
 }
 
 /*
- * Return the signal number which stopped the process.
+ * Predicate to test if the reason the process stopped was because
+ * of a breakpoint.  If so, as a side effect clear the local copy of
+ * signal handler associated with process.  We must do this so as to
+ * not confuse future stepping or continuing by possibly concluding
+ * the process should continue with a SIGTRAP handler.
+ */
+
+public boolean isbperr()
+{
+    Process p;
+    boolean b;
+
+    p = process;
+    if (p->status == STOPPED and p->signo == SIGTRAP) {
+       b = true;
+       p->sigstatus = 0;
+    } else {
+       b = false;
+    }
+    return b;
+}
+
+/*
+ * Return the signal number that stopped the process.
  */
 
  */
 
-public Integer errnum(p)
+public integer errnum (p)
 Process p;
 {
     return p->signo;
 }
 
 Process p;
 {
     return p->signo;
 }
 
+/*
+ * Return the signal code associated with the signal.
+ */
+
+public integer errcode (p)
+Process p;
+{
+    return p->sigcode;
+}
+
 /*
  * Return the termination code of the process.
  */
 
 /*
  * Return the termination code of the process.
  */
 
-public Integer exitcode(p)
+public integer exitcode (p)
 Process p;
 {
     return p->exitval;
 Process p;
 {
     return p->exitval;
@@ -616,14 +754,16 @@ int nbytes;
 {
     Intfunc *f;
 
 {
     Intfunc *f;
 
-    f = onsyserr(EIO, read_err);
     badaddr = addr;
     if (coredump) {
     badaddr = addr;
     if (coredump) {
+       f = onsyserr(EFAULT, read_err);
        coredump_readdata(buff, addr, nbytes);
        coredump_readdata(buff, addr, nbytes);
+       onsyserr(EFAULT, f);
     } else {
     } else {
+       f = onsyserr(EIO, read_err);
        pio(process, PREAD, DATASEG, buff, addr, nbytes);
        pio(process, PREAD, DATASEG, buff, addr, nbytes);
+       onsyserr(EIO, f);
     }
     }
-    onsyserr(EIO, f);
 }
 
 /*
 }
 
 /*
@@ -668,15 +808,8 @@ private write_err()
  * Ptrace interface.
  */
 
  * Ptrace interface.
  */
 
-/*
- * This magic macro enables us to look at the process' registers
- * in its user structure.
- */
-
-#define regloc(reg)     (ctob(UPAGES) + ( sizeof(int) * (reg) ))
-
 #define WMASK           (~(sizeof(Word) - 1))
 #define WMASK           (~(sizeof(Word) - 1))
-#define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE))
+#define cachehash(addr) ((unsigned) ((addr >> 2) % CACHESIZE))
 
 #define FIRSTSIG        SIGINT
 #define LASTSIG         SIGQUIT
 
 #define FIRSTSIG        SIGINT
 #define LASTSIG         SIGQUIT
@@ -699,6 +832,14 @@ private write_err()
 #define SSTEP   9       /* continue for approximately one instruction */
 #define PKILL   8       /* terminate the process */
 
 #define SSTEP   9       /* continue for approximately one instruction */
 #define PKILL   8       /* terminate the process */
 
+#ifdef IRIS
+#   define readreg(p, r)       ptrace(10, p->pid, r, 0)
+#   define writereg(p, r, v)   ptrace(11, p->pid, r, v)
+#else
+#   define readreg(p, r)       ptrace(UREAD, p->pid, regloc(r), 0);
+#   define writereg(p, r, v)   ptrace(UWRITE, p->pid, regloc(r), v);
+#endif
+
 /*
  * Start up a new process by forking and exec-ing the
  * given argument list, returning when the process is loaded
 /*
  * Start up a new process by forking and exec-ing the
  * given argument list, returning when the process is loaded
@@ -717,52 +858,57 @@ String infile;
 String outfile;
 {
     int status;
 String outfile;
 {
     int status;
-    Fileid in, out;
 
 
-    if (p->pid != 0) {                 /* child already running? */
-       ptrace(PKILL, p->pid, 0, 0);    /* ... kill it! */
-       pwait(p->pid, &status);         /* wait for it to exit */
-       unptraced(p->pid);
+    if (p->pid != 0) {
+       pterm(p);
+       cacheflush(p);
     }
     }
+    fflush(stdout);
     psigtrace(p, SIGTRAP, true);
     psigtrace(p, SIGTRAP, true);
-    p->pid = vfork();
+#   ifdef IRIS
+       p->pid = fork();
+#   else
+       p->pid = vfork();
+#   endif
     if (p->pid == -1) {
        panic("can't fork");
     }
     if (ischild(p->pid)) {
     if (p->pid == -1) {
        panic("can't fork");
     }
     if (ischild(p->pid)) {
+       nocatcherrs();
        traceme();
        if (infile != nil) {
        traceme();
        if (infile != nil) {
-           in = open(infile, 0);
-           if (in == -1) {
-               write(2, "can't read ", 11);
-               write(2, infile, strlen(infile));
-               write(2, "\n", 1);
-               _exit(1);
-           }
-           fswap(0, in);
+           infrom(infile);
        }
        if (outfile != nil) {
        }
        if (outfile != nil) {
-           out = creat(outfile, 0666);
-           if (out == -1) {
-               write(2, "can't write ", 12);
-               write(2, outfile, strlen(outfile));
-               write(2, "\n", 1);
-               _exit(1);
-           }
-           fswap(1, out);
+           outto(outfile);
        }
        execv(argv[0], argv);
        }
        execv(argv[0], argv);
-       write(2, "can't exec ", 11);
-       write(2, argv[0], strlen(argv[0]));
-       write(2, "\n", 1);
        _exit(1);
     }
     pwait(p->pid, &status);
     getinfo(p, status);
     if (p->status != STOPPED) {
        _exit(1);
     }
     pwait(p->pid, &status);
     getinfo(p, status);
     if (p->status != STOPPED) {
-       error("program could not begin execution");
+       beginerrmsg();
+       fprintf(stderr, "warning: cannot execute %s\n", argv[0]);
+    } else {
+       ptraced(p->pid);
+    }
+}
+
+/*
+ * Terminate a ptrace'd process.
+ */
+
+public pterm (p)
+Process p;
+{
+    integer status;
+
+    if (p != nil and p->pid != 0) {
+       ptrace(PKILL, p->pid, 0, 0);
+       pwait(p->pid, &status);
+       unptraced(p->pid);
     }
     }
-    ptraced(p->pid);
 }
 
 /*
 }
 
 /*
@@ -779,13 +925,19 @@ private pcont(p, signo)
 Process p;
 int signo;
 {
 Process p;
 int signo;
 {
-    int status;
+    int s, status;
 
     if (p->pid == 0) {
 
     if (p->pid == 0) {
-       error("program not active");
+       error("program is not active");
     }
     }
+    s = signo;
     do {
     do {
-       setinfo(p, signo);
+       setinfo(p, s);
+       if (traceexec) {
+           printf("!! pcont from 0x%x with signal %d (%d)\n",
+               p->reg[PROGCTR], s, p->signo);
+           fflush(stdout);
+       }
        sigs_off();
        if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {
            panic("error %d trying to continue process", errno);
        sigs_off();
        if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {
            panic("error %d trying to continue process", errno);
@@ -793,24 +945,68 @@ int signo;
        pwait(p->pid, &status);
        sigs_on();
        getinfo(p, status);
        pwait(p->pid, &status);
        sigs_on();
        getinfo(p, status);
+       if (p->status == STOPPED and traceexec and not istraced(p)) {
+           printf("!! ignored signal %d at 0x%x\n",
+               p->signo, p->reg[PROGCTR]);
+           fflush(stdout);
+       }
+       s = p->signo;
     } while (p->status == STOPPED and not istraced(p));
     } while (p->status == STOPPED and not istraced(p));
+    if (traceexec) {
+       printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo);
+       fflush(stdout);
+    }
 }
 
 /*
  * Single step as best ptrace can.
  */
 
 }
 
 /*
  * Single step as best ptrace can.
  */
 
-public pstep(p)
+public pstep(p, signo)
 Process p;
 Process p;
+integer signo;
 {
 {
-    int status;
+    int s, status;
 
 
-    setinfo(p, DEFSIG);
-    sigs_off();
-    ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo);
-    pwait(p->pid, &status);
-    sigs_on();
-    getinfo(p, status);
+    s = signo;
+    do {
+       setinfo(p, s);
+       if (traceexec) {
+           printf("!! pstep from 0x%x with signal %d (%d)\n",
+               p->reg[PROGCTR], s, p->signo);
+           fflush(stdout);
+       }
+       sigs_off();
+       if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) {
+           panic("error %d trying to step process", errno);
+       }
+       pwait(p->pid, &status);
+       sigs_on();
+       getinfo(p, status);
+#      if mc68000 || m68000
+           if (p->status == STOPPED and p->signo == SIGTRAP) {
+               p->reg[PROGCTR] += 2;
+           }
+#      endif
+       if (p->status == STOPPED and traceexec and not istraced(p)) {
+           printf("!! pstep ignored signal %d at 0x%x\n",
+               p->signo, p->reg[PROGCTR]);
+           fflush(stdout);
+       }
+       s = p->signo;
+    } while (p->status == STOPPED and not istraced(p));
+    if (traceexec) {
+       printf("!! pstep to 0x%x on signal %d\n",
+           p->reg[PROGCTR], p->signo);
+       fflush(stdout);
+    }
+    if (p->status != STOPPED) {
+       if (p->exitval == 0) {
+           error("program exited\n");
+       } else {
+           error("program exited with code %d\n", p->exitval);
+       }
+    }
 }
 
 /*
 }
 
 /*
@@ -876,31 +1072,43 @@ private sigs_on()
  * Get process information from user area.
  */
 
  * Get process information from user area.
  */
 
-private int rloc[] ={
-    R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
-};
-
-private getinfo(p, status)
+private getinfo (p, status)
 register Process p;
 register int status;
 {
     register int i;
 register Process p;
 register int status;
 {
     register int i;
+    Address addr;
 
     p->signo = (status&0177);
     p->exitval = ((status >> 8)&0377);
     if (p->signo != STOPPED) {
        p->status = FINISHED;
        p->pid = 0;
 
     p->signo = (status&0177);
     p->exitval = ((status >> 8)&0377);
     if (p->signo != STOPPED) {
        p->status = FINISHED;
        p->pid = 0;
+       p->reg[PROGCTR] = 0;
     } else {
        p->status = p->signo;
        p->signo = p->exitval;
        p->exitval = 0;
     } else {
        p->status = p->signo;
        p->signo = p->exitval;
        p->exitval = 0;
-       p->mask = ptrace(UREAD, p->pid, regloc(PS), 0);
+#       ifdef IRIS
+           p->mask = readreg(p, RPS);
+#       else
+           p->sigcode = ptrace(UREAD, p->pid, &((struct user *)0)->u_code, 0);
+           p->mask = readreg(p, PS);
+#       endif
        for (i = 0; i < NREG; i++) {
        for (i = 0; i < NREG; i++) {
-           p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0);
+           p->reg[i] = readreg(p, rloc[i]);
            p->oreg[i] = p->reg[i];
        }
            p->oreg[i] = p->reg[i];
        }
+#       ifdef mc68000
+           if (p->status == STOPPED and p->signo == SIGTRAP and
+               p->reg[PROGCTR] > CODESTART
+           ) {
+               p->reg[PROGCTR] -= 2;
+           }
+#       endif
        savetty(stdout, &(p->ttyinfo));
        savetty(stdout, &(p->ttyinfo));
+       addr = (Address) &(((struct user *) 0)->u_signal[p->signo]);
+       p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0);
     }
 }
 
     }
 }
 
@@ -908,7 +1116,7 @@ register int status;
  * Set process's user area information from given process structure.
  */
 
  * Set process's user area information from given process structure.
  */
 
-private setinfo(p, signo)
+private setinfo (p, signo)
 register Process p;
 int signo;
 {
 register Process p;
 int signo;
 {
@@ -916,7 +1124,7 @@ int signo;
     register int r;
 
     if (signo == DEFSIG) {
     register int r;
 
     if (signo == DEFSIG) {
-       if (istraced(p)) {
+       if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) {
            p->signo = 0;
        }
     } else {
            p->signo = 0;
        }
     } else {
@@ -924,12 +1132,29 @@ int signo;
     }
     for (i = 0; i < NREG; i++) {
        if ((r = p->reg[i]) != p->oreg[i]) {
     }
     for (i = 0; i < NREG; i++) {
        if ((r = p->reg[i]) != p->oreg[i]) {
-           ptrace(UWRITE, p->pid, regloc(rloc[i]), r);
+           writereg(p, rloc[i], r);
        }
     }
     restoretty(stdout, &(p->ttyinfo));
 }
 
        }
     }
     restoretty(stdout, &(p->ttyinfo));
 }
 
+/*
+ * Return the address associated with the current signal.
+ * (Plus two since the address points to the beginning of a procedure).
+ */
+
+public Address usignal (p)
+Process p;
+{
+    Address r;
+
+    r = p->sigstatus;
+    if (r != 0 and r != 1) {
+       r += FUNCOFFSET;
+    }
+    return r;
+}
+
 /*
  * Structure for reading and writing by words, but dealing with bytes.
  */
 /*
  * Structure for reading and writing by words, but dealing with bytes.
  */
@@ -988,6 +1213,28 @@ int nbytes;
     byteoff = (nbytes&(~WMASK));
     nbytes -= byteoff;
     bufend = cp + nbytes;
     byteoff = (nbytes&(~WMASK));
     nbytes -= byteoff;
     bufend = cp + nbytes;
+#ifdef tahoe
+    if (((int)cp)&WMASK) {
+       /*
+        * Must copy a byte at a time, buffer not word addressable.
+        */
+       while (cp < bufend) {
+           if (op == PREAD) {
+               w.pword = fetch(p, seg, newaddr);
+               for (i = 0; i < sizeof(Word); i++)
+                   *cp++ = w.pbyte[i];
+           } else {
+               for (i = 0; i < sizeof(Word); i++)
+                   w.pbyte[i] = *cp++;
+               store(p, seg, newaddr, w.pword);
+           }
+           newaddr += sizeof(Word);
+       }
+    } else {
+    /*
+     * Buffer, word aligned, act normally...
+     */
+#endif
     while (cp < bufend) {
        if (op == PREAD) {
            *((Word *) cp) = fetch(p, seg, newaddr);
     while (cp < bufend) {
        if (op == PREAD) {
            *((Word *) cp) = fetch(p, seg, newaddr);
@@ -997,6 +1244,9 @@ int nbytes;
        cp += sizeof(Word);
        newaddr += sizeof(Word);
     }
        cp += sizeof(Word);
        newaddr += sizeof(Word);
     }
+#ifdef tahoe
+    }
+#endif
     if (byteoff > 0) {
        w.pword = fetch(p, seg, newaddr);
        for (i = 0; i < byteoff; i++) {
     if (byteoff > 0) {
        w.pword = fetch(p, seg, newaddr);
        for (i = 0; i < byteoff; i++) {
@@ -1090,18 +1340,69 @@ Word data;
     }
 }
 
     }
 }
 
+/*
+ * Flush the instruction cache associated with a process.
+ */
+
+private cacheflush (p)
+Process p;
+{
+    bzero(p->word, sizeof(p->word));
+}
+
 public printptraceinfo()
 {
     printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);
 }
 
 /*
 public printptraceinfo()
 {
     printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);
 }
 
 /*
- * Swap file numbers so as to redirect standard input and output.
+ * Redirect input.
+ * Assuming this is called from a child, we should be careful to avoid
+ * (possibly) shared standard I/O buffers.
+ */
+
+private infrom (filename)
+String filename;
+{
+    Fileid in;
+
+    in = open(filename, 0);
+    if (in == -1) {
+       write(2, "can't read ", 11);
+       write(2, filename, strlen(filename));
+       write(2, "\n", 1);
+       _exit(1);
+    }
+    fswap(0, in);
+}
+
+/*
+ * Redirect standard output.
+ * Same assumptions as for "infrom" above.
+ */
+
+private outto (filename)
+String filename;
+{
+    Fileid out;
+
+    out = creat(filename, 0666);
+    if (out == -1) {
+       write(2, "can't write ", 12);
+       write(2, filename, strlen(filename));
+       write(2, "\n", 1);
+       _exit(1);
+    }
+    fswap(1, out);
+}
+
+/*
+ * Swap file numbers, useful for redirecting standard input or output.
  */
 
 private fswap(oldfd, newfd)
  */
 
 private fswap(oldfd, newfd)
-int oldfd;
-int newfd;
+Fileid oldfd;
+Fileid newfd;
 {
     if (oldfd != newfd) {
        close(oldfd);
 {
     if (oldfd != newfd) {
        close(oldfd);
@@ -1109,3 +1410,104 @@ int newfd;
        close(newfd);
     }
 }
        close(newfd);
     }
 }
+
+/*
+ * Signal name manipulation.
+ */
+
+private String signames[NSIG] = {
+    0,
+    "HUP", "INT", "QUIT", "ILL", "TRAP",
+    "IOT", "EMT", "FPE", "KILL", "BUS",
+    "SEGV", "SYS", "PIPE", "ALRM", "TERM",
+    0, "STOP", "TSTP", "CONT", "CHLD",
+    "TTIN", "TTOU", "TINT", "XCPU", "XFSZ",
+    "VTALRM", "PROF", "WINCH", "USR1", "USR2"
+};
+
+/*
+ * Get the signal number associated with a given name.
+ * The name is first translated to upper case if necessary.
+ */
+
+public integer siglookup (s)
+String s;
+{
+    register char *p, *q;
+    char buf[100];
+    integer i;
+
+    p = s;
+    q = buf;
+    while (*p != '\0') {
+       if (*p >= 'a' and *p <= 'z') {
+           *q = (*p - 'a') + 'A';
+       } else {
+           *q = *p;
+       }
+       ++p;
+       ++q;
+    }
+    *q = '\0';
+    p = buf;
+    if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') {
+       p += 3;
+    }
+    i = 1;
+    for (;;) {
+       if (i >= sizeof(signames) div sizeof(signames[0])) {
+           error("signal \"%s\" unknown", s);
+           i = 0;
+           break;
+       }
+       if (signames[i] != nil and streq(signames[i], p)) {
+           break;
+       }
+       ++i;
+    }
+    return i;
+}
+
+/*
+ * Print all signals being ignored by the debugger.
+ * These signals are auotmatically
+ * passed on to the debugged process.
+ */
+
+public printsigsignored (p)
+Process p;
+{
+    printsigs(~p->sigset);
+}
+
+/*
+ * Print all signals being intercepted by
+ * the debugger for the specified process.
+ */
+
+public printsigscaught(p)
+Process p;
+{
+    printsigs(p->sigset);
+}
+
+private printsigs (set)
+integer set;
+{
+    integer s;
+    char separator[2];
+
+    separator[0] = '\0';
+    for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) {
+       if (set & setrep(s)) {
+           if (signames[s] != nil) {
+               printf("%s%s", separator, signames[s]);
+               separator[0] = ' ';
+               separator[1] = '\0';
+           }
+       }
+    }
+    if (separator[0] == ' ') {
+       putchar('\n');
+    }
+}