URI: 
       tdebugger - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 84114f06650ba3db950532b1d0cd1d7e18b4b6be
   DIR parent a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46
  HTML Author: rsc <devnull@localhost>
       Date:   Mon, 19 Apr 2004 19:30:50 +0000
       
       debugger
       
       Diffstat:
         A src/cmd/db/command.c                |     311 +++++++++++++++++++++++++++++++
         A src/cmd/db/defs.h                   |     111 ++++++++++++++++++++++++++++++
         A src/cmd/db/expr.c                   |     397 +++++++++++++++++++++++++++++++
         A src/cmd/db/fns.h                    |      91 +++++++++++++++++++++++++++++++
         A src/cmd/db/format.c                 |     388 ++++++++++++++++++++++++++++++
         A src/cmd/db/input.c                  |     169 +++++++++++++++++++++++++++++++
         A src/cmd/db/main.c                   |     262 +++++++++++++++++++++++++++++++
         A src/cmd/db/mkfile                   |      26 ++++++++++++++++++++++++++
         A src/cmd/db/output.c                 |     159 +++++++++++++++++++++++++++++++
         A src/cmd/db/pcs.c                    |     177 +++++++++++++++++++++++++++++++
         A src/cmd/db/print.c                  |     406 +++++++++++++++++++++++++++++++
         A src/cmd/db/regs.c                   |      44 +++++++++++++++++++++++++++++++
         A src/cmd/db/runpcs.c                 |     205 ++++++++++++++++++++++++++++++
         A src/cmd/db/setup.c                  |     145 +++++++++++++++++++++++++++++++
         A src/cmd/db/trcrun.c                 |     288 +++++++++++++++++++++++++++++++
       
       15 files changed, 3179 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/src/cmd/db/command.c b/src/cmd/db/command.c
       t@@ -0,0 +1,311 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +char        BADEQ[] = "unexpected `='";
       +
       +BOOL        executing;
       +extern        char        *lp;
       +
       +char        eqformat[ARB] = "z";
       +char        stformat[ARB] = "zMi";
       +
       +ADDR        ditto;
       +
       +ADDR        dot;
       +WORD        dotinc;
       +WORD        adrval, cntval, loopcnt;
       +int        adrflg, cntflg;
       +
       +/* command decoding */
       +
       +int
       +command(char *buf, int defcom)
       +{
       +        char        *reg;
       +        char        savc;
       +        char        *savlp=lp;
       +        char        savlc = lastc;
       +        char        savpc = peekc;
       +        static char lastcom = '=', savecom = '=';
       +
       +        if (defcom == 0)
       +                defcom = lastcom;
       +        if (buf) {
       +                if (*buf==EOR)
       +                        return(FALSE);
       +                clrinp();
       +                lp=buf;
       +        }
       +        do {
       +                adrflg=expr(0);                /* first address */
       +                if (adrflg){
       +                        dot=expv;
       +                        ditto=expv;
       +                }
       +                adrval=dot;
       +
       +                if (rdc()==',' && expr(0)) {        /* count */
       +                        cntflg=TRUE;
       +                        cntval=expv;
       +                } else {
       +                        cntflg=FALSE;
       +                        cntval=1;
       +                        reread();
       +                }
       +
       +                if (!eol(rdc()))
       +                        lastcom=lastc;                /* command */
       +                else {
       +                        if (adrflg==0)
       +                                dot=inkdot(dotinc);
       +                        reread();
       +                        lastcom=defcom;
       +                }
       +                switch(lastcom) {
       +                case '/':
       +                case '=':
       +                case '?':
       +                        savecom = lastcom;
       +                        acommand(lastcom);
       +                        break;
       +
       +                case '>':
       +                        lastcom = savecom; 
       +                        savc=rdc();
       +                        if (reg=regname(savc))
       +                                rput(correg, reg, dot);
       +                        else        
       +                                error("bad variable");
       +                        break;
       +
       +                case '!':
       +                        lastcom=savecom;
       +                        shell(); 
       +                        break;
       +
       +                case '$':
       +                        lastcom=savecom;
       +                        printdollar(nextchar()); 
       +                        break;
       +
       +                case ':':
       +                        if (!executing) { 
       +                                executing=TRUE;
       +                                subpcs(nextchar());
       +                                executing=FALSE;
       +                                lastcom=savecom;
       +                        }
       +                        break;
       +
       +                case 0:
       +                        prints(DBNAME);
       +                        break;
       +
       +                default: 
       +                        error("bad command");
       +                }
       +                flushbuf();
       +        } while (rdc()==';');
       +        if (buf == 0)
       +                reread();
       +        else {
       +                clrinp();
       +                lp=savlp;
       +                lastc = savlc;
       +                peekc = savpc;
       +        }
       +
       +        if(adrflg)
       +                return dot;
       +        return 1;
       +}
       +
       +/*
       + * [/?][wml]
       + */
       +
       +void
       +acommand(int pc)
       +{
       +        int eqcom;
       +        Map *map;
       +        char *fmt;
       +        char buf[512];
       +
       +        if (pc == '=') {
       +                eqcom = 1;
       +                fmt = eqformat;
       +                map = dotmap;
       +        } else {
       +                eqcom = 0;
       +                fmt = stformat;
       +                if (pc == '/')
       +                        map = cormap;
       +                else
       +                        map = symmap;
       +        }
       +        if (!map) {
       +                sprint(buf, "no map for %c", pc);
       +                error(buf);
       +        }
       +
       +        switch (rdc())
       +        {
       +        case 'm':
       +                if (eqcom)
       +                        error(BADEQ); 
       +                cmdmap(map);
       +                break;
       +
       +        case 'L':
       +        case 'l':
       +                if (eqcom)
       +                        error(BADEQ); 
       +                cmdsrc(lastc, map);
       +                break;
       +
       +        case 'W':
       +        case 'w':
       +                if (eqcom)
       +                        error(BADEQ); 
       +                cmdwrite(lastc, map);
       +                break;
       +
       +        default:
       +                reread();
       +                getformat(fmt);
       +                scanform(cntval, !eqcom, fmt, map, eqcom);
       +        }
       +}
       +
       +void
       +cmdsrc(int c, Map *map)
       +{
       +        u32int w;
       +        long locval, locmsk;
       +        ADDR savdot;
       +        ushort sh;
       +        char buf[512];
       +        int ret;
       +
       +        if (c == 'L')
       +                dotinc = 4;
       +        else
       +                dotinc = 2;
       +        savdot=dot;
       +        expr(1); 
       +        locval=expv;
       +        if (expr(0))
       +                locmsk=expv; 
       +        else
       +                locmsk = ~0;
       +        if (c == 'L')
       +                while ((ret = get4(map, dot, &w)) > 0 &&  (w&locmsk) != locval)
       +                        dot = inkdot(dotinc);
       +        else
       +                while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval)
       +                        dot = inkdot(dotinc);
       +        if (ret < 0) { 
       +                dot=savdot; 
       +                error("%r");
       +        }
       +        symoff(buf, 512, dot, CANY);
       +        dprint(buf);
       +}
       +
       +static char badwrite[] = "can't write process memory or text image";
       +
       +void
       +cmdwrite(int wcom, Map *map)
       +{
       +        ADDR savdot;
       +        char *format;
       +        int pass;
       +
       +        if (wcom == 'w')
       +                format = "x";
       +        else
       +                format = "X";
       +        expr(1);
       +        pass = 0;
       +        do {
       +                pass++;  
       +                savdot=dot;
       +                exform(1, 1, format, map, 0, pass);
       +                dot=savdot;
       +                if (wcom == 'W') {
       +                        if (put4(map, dot, expv) <= 0)
       +                                error(badwrite);
       +                } else {
       +                        if (put2(map, dot, expv) <= 0)
       +                                error(badwrite);
       +                }
       +                savdot=dot;
       +                dprint("=%8t"); 
       +                exform(1, 0, format, map, 0, pass);
       +                newline();
       +        } while (expr(0));
       +        dot=savdot;
       +}
       +
       +/*
       + * collect a register name; return register offset
       + * this is not what i'd call a good division of labour
       + */
       +
       +char *
       +regname(int regnam)
       +{
       +        static char buf[64];
       +        char *p;
       +        int c;
       +
       +        p = buf;
       +        *p++ = regnam;
       +        while (isalnum(c = readchar())) {
       +                if (p >= buf+sizeof(buf)-1)
       +                        error("register name too long");
       +                *p++ = c;
       +        }
       +        *p = 0;
       +        reread();
       +        return (buf);
       +}
       +
       +/*
       + * shell escape
       + */
       +
       +void
       +shell(void)
       +{
       +        int        rc, unixpid;
       +        char *argp = lp;
       +
       +        while (lastc!=EOR)
       +                rdc();
       +        if ((unixpid=fork())==0) {
       +                *lp=0;
       +                execl("/bin/rc", "rc", "-c", argp, 0);
       +                exits("execl");                                /* botch */
       +        } else if (unixpid == -1) {
       +                error("cannot fork");
       +        } else {
       +                mkfault = 0;
       +                while ((rc = waitpid()) != unixpid){
       +                        if(rc == -1 && mkfault){
       +                                mkfault = 0;
       +                                continue;
       +                        }
       +                        break;
       +                }
       +                prints("!"); 
       +                reread();
       +        }
       +}
   DIR diff --git a/src/cmd/db/defs.h b/src/cmd/db/defs.h
       t@@ -0,0 +1,111 @@
       +/*
       + * db - common definitions
       + * something of a grab-bag
       + */
       +
       +#include <u.h>
       +#include <libc.h>
       +#include <bio.h>
       +#include <ctype.h>
       +
       +#include <mach.h>
       +
       +typedef long WORD;
       +typedef ulong ADDR;
       +
       +#define        HUGEINT        0x7fffffff        /* enormous WORD */
       +
       +#define        MAXOFF        0x1000000
       +#define        INCDIR        "/usr/lib/adb"
       +#define        DBNAME        "db\n"
       +#define CMD_VERBS        "?/=>!$: \t"
       +
       +typedef        int        BOOL;
       +
       +#define MAXPOS        80
       +#define MAXLIN        128
       +#define        ARB        512
       +#define MAXCOM        64
       +#define MAXARG        32
       +#define LINSIZ        4096
       +#define        MAXSYM        255
       +
       +#define EOR        '\n'
       +#define SPC        ' '
       +#define TB        '\t'
       +
       +#define        STDIN        0
       +#define        STDOUT        1
       +
       +#define        TRUE        (-1)
       +#define        FALSE        0
       +
       +
       +/*
       + * run modes
       + */
       +
       +#define        SINGLE        1
       +#define        CONTIN        2
       +
       +/*
       + * breakpoints
       + */
       +
       +#define        BKPTCLR        0        /* not a real breakpoint */
       +#define BKPTSET        1        /* real, ready to trap */
       +#define BKPTSKIP 2        /* real, skip over it next time */
       +#define        BKPTTMP        3        /* temporary; clear when it happens */
       +
       +struct bkpt {
       +        ADDR        loc;
       +        uchar        save[4];
       +        int        count;
       +        int        initcnt;
       +        int        flag;
       +        char        comm[MAXCOM];
       +        struct bkpt *nxtbkpt;
       +};
       +typedef struct bkpt        BKPT;
       +
       +#define        BADREG        (-1)
       +
       +/*
       + * common globals
       + */
       +
       +extern        WORD        adrval;
       +extern        vlong        expv;
       +extern        int        adrflg;
       +extern        WORD        cntval;
       +extern        int        cntflg;
       +extern        WORD        loopcnt;
       +extern        ADDR        maxoff;
       +extern        ADDR        localval;
       +extern        ADDR        maxfile;
       +extern        ADDR        maxstor;
       +
       +extern        ADDR        dot;
       +extern        WORD        dotinc;
       +
       +extern        int        xargc;
       +
       +extern        BOOL        wtflag;
       +extern        char        *corfil, *symfil;
       +extern        BOOL        mkfault;
       +extern        BOOL        regdirty;
       +
       +extern        int        pid;
       +extern        int        pcsactive;
       +#define        NNOTE 10
       +extern        int        nnote;
       +extern        char        note[NNOTE][ERRMAX];
       +
       +extern        int        ending;
       +extern        Fhdr        *corhdr, *symhdr;
       +extern        Map        *cormap, *symmap, *dotmap;
       +extern        Regs        *correg;
       +
       +extern        BKPT        *bkpthead;
       +extern        int        kflag;
       +extern        int        lastc, peekc;
   DIR diff --git a/src/cmd/db/expr.c b/src/cmd/db/expr.c
       t@@ -0,0 +1,397 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +static long        dbround(long, long);
       +
       +extern        ADDR        ditto;
       +vlong        expv;
       +
       +static WORD
       +ascval(void)
       +{
       +        Rune r;
       +
       +        if (readchar() == 0)
       +                return (0);
       +        r = lastc;
       +        while(quotchar())        /*discard chars to ending quote */
       +                ;
       +        return((WORD) r);
       +}
       +
       +/*
       + * read a floating point number
       + * the result must fit in a WORD
       + */
       +
       +static WORD
       +fpin(char *buf)
       +{
       +        union {
       +                WORD w;
       +                float f;
       +        } x;
       +
       +        x.f = atof(buf);
       +        return (x.w);
       +}
       +
       +WORD
       +defval(WORD w)
       +{
       +        if (expr(0))
       +                return (expv);
       +        else
       +                return (w);
       +}
       +
       +int
       +expr(int a)
       +{        /* term | term dyadic expr |  */
       +        int        rc;
       +        WORD        lhs;
       +
       +        rdc();
       +        reread();
       +        rc=term(a);
       +        while (rc) {
       +                lhs = expv;
       +                switch ((int)readchar()) {
       +
       +                case '+':
       +                        term(a|1);
       +                        expv += lhs;
       +                        break;
       +
       +                case '-':
       +                        term(a|1);
       +                        expv = lhs - expv;
       +                        break;
       +
       +                case '#':
       +                        term(a|1);
       +                        expv = dbround(lhs,expv);
       +                        break;
       +
       +                case '*':
       +                        term(a|1);
       +                        expv *= lhs;
       +                        break;
       +
       +                case '%':
       +                        term(a|1);
       +                        if(expv != 0)
       +                                expv = lhs/expv;
       +                        else{
       +                                if(lhs)
       +                                        expv = 1;
       +                                else
       +                                        expv = 0;
       +                        }
       +                        break;
       +
       +                case '&':
       +                        term(a|1);
       +                        expv &= lhs;
       +                        break;
       +
       +                case '|':
       +                        term(a|1);
       +                        expv |= lhs;
       +                        break;
       +
       +                case ')':
       +                        if ((a&2)==0)
       +                                error("unexpected `)'");
       +
       +                default:
       +                        reread();
       +                        return(rc);
       +                }
       +        }
       +        return(rc);
       +}
       +
       +int
       +term(int a)
       +{        /* item | monadic item | (expr) | */
       +        u32int u;
       +
       +        switch ((int)readchar()) {
       +
       +        case '*':
       +                term(a|1);
       +                if (get4(cormap, (ADDR)expv, &u) < 0)
       +                        error("%r");
       +                expv = u;
       +                return(1);
       +
       +        case '@':
       +                term(a|1);
       +                if (get4(symmap, (ADDR)expv, &u) < 0)
       +                        error("%r");
       +                expv = u;
       +                return(1);
       +
       +        case '-':
       +                term(a|1);
       +                expv = -expv;
       +                return(1);
       +
       +        case '~':
       +                term(a|1);
       +                expv = ~expv;
       +                return(1);
       +
       +        case '(':
       +                expr(2);
       +                if (readchar()!=')')
       +                        error("syntax error: `)' expected");
       +                return(1);
       +
       +        default:
       +                reread();
       +                return(item(a));
       +        }
       +}
       +
       +int
       +item(int a)
       +{        /* name [ . local ] | number | . | ^  | <register | 'x | | */
       +        char        *base;
       +        char        savc;
       +        ulong u;
       +        Symbol s;
       +        char gsym[MAXSYM], lsym[MAXSYM];
       +
       +        readchar();
       +        if (isfileref()) {
       +                readfname(gsym);
       +                rdc();                        /* skip white space */
       +                if (lastc == ':') {        /* it better be */
       +                        rdc();                /* skip white space */
       +                        if (!getnum(readchar))
       +                                error("bad number");
       +                        if (expv == 0)
       +                                expv = 1;        /* file begins at line 1 */
       +                        if(file2pc(gsym, expv, &u) < 0)
       +                                error("%r");
       +                        expv = u;
       +                        return 1;
       +                }
       +                error("bad file location");
       +        } else if (symchar(0)) {        
       +                readsym(gsym);
       +                if (lastc=='.') {
       +                        readchar();        /* ugh */
       +                        if (lastc == '.') {
       +                                lsym[0] = '.';
       +                                readchar();
       +                                readsym(lsym+1);
       +                        } else if (symchar(0)) {
       +                                readsym(lsym);
       +                        } else
       +                                lsym[0] = 0;
       +                        if (localaddr(cormap, correg, gsym, lsym, &u) < 0)
       +                                error("%r");
       +                        expv = u;
       +                }
       +                else {
       +                        if (lookupsym(0, gsym, &s) < 0)
       +                                error("symbol not found");
       +                        if (s.loc.type != LADDR)
       +                                error("symbol not kept in memory");
       +                        expv = s.loc.addr;
       +                }
       +                reread();
       +        } else if (getnum(readchar)) {
       +                ;
       +        } else if (lastc=='.') {        
       +                readchar();
       +                if (!symchar(0) && lastc != '.') {
       +                        expv = dot;
       +                } else {
       +                        if (findsym(locaddr(dbrget(cormap, mach->pc)), CTEXT, &s) < 0)
       +                                error("no current function");
       +                        if (lastc == '.') {
       +                                lsym[0] = '.';
       +                                readchar();
       +                                readsym(lsym+1);
       +                        } else
       +                                readsym(lsym);
       +                        if (localaddr(cormap, correg, s.name, lsym, &u) < 0)
       +                                error("%r");
       +                        expv = u;
       +                }        
       +                reread();
       +        } else if (lastc=='"') {
       +                expv=ditto;
       +        } else if (lastc=='+') {
       +                expv=inkdot(dotinc);
       +        } else if (lastc=='^') {
       +                expv=inkdot(-dotinc);
       +        } else if (lastc=='<') {
       +                savc=rdc();
       +                base = regname(savc);
       +                expv = dbrget(cormap, base);
       +        }
       +        else if (lastc=='\'')
       +                expv = ascval();
       +        else if (a)
       +                error("address expected");
       +        else {        
       +                reread();
       +                return(0);
       +        }
       +        return(1);
       +}
       +
       +#define        MAXBASE        16
       +
       +/* service routines for expression reading */
       +int
       +getnum(int (*rdf)(void))
       +{
       +        char *cp;
       +        int base, d;
       +        BOOL fpnum;
       +        char num[MAXLIN];
       +
       +        base = 0;
       +        fpnum = FALSE;
       +        if (lastc == '#') {
       +                base = 16;
       +                (*rdf)();
       +        }
       +        if (convdig(lastc) >= MAXBASE)
       +                return (0);
       +        if (lastc == '0')
       +                switch ((*rdf)()) {
       +                case 'x':
       +                case 'X':
       +                        base = 16;
       +                        (*rdf)();
       +                        break;
       +
       +                case 't':
       +                case 'T':
       +                        base = 10;
       +                        (*rdf)();
       +                        break;
       +
       +                case 'o':
       +                case 'O':
       +                        base = 8;
       +                        (*rdf)();
       +                        break;
       +                default:
       +                        if (base == 0)
       +                                base = 8;
       +                        break;
       +                }
       +        if (base == 0)
       +                base = 10;
       +        expv = 0;
       +        for (cp = num, *cp = lastc; ;(*rdf)()) {
       +                if ((d = convdig(lastc)) < base) {
       +                        expv *= base;
       +                        expv += d;
       +                        *cp++ = lastc;
       +                }
       +                else if (lastc == '.') {
       +                        fpnum = TRUE;
       +                        *cp++ = lastc;
       +                } else {
       +                        reread();
       +                        break;
       +                }
       +        }
       +        if (fpnum)
       +                expv = fpin(num);
       +        return (1);
       +}
       +
       +void
       +readsym(char *isymbol)
       +{
       +        char        *p;
       +        Rune r;
       +
       +        p = isymbol;
       +        do {
       +                if (p < &isymbol[MAXSYM-UTFmax-1]){
       +                        r = lastc;
       +                        p += runetochar(p, &r);
       +                }
       +                readchar();
       +        } while (symchar(1));
       +        *p = 0;
       +}
       +
       +void
       +readfname(char *filename)
       +{
       +        char        *p;
       +        Rune        c;
       +
       +        /* snarf chars until un-escaped char in terminal char set */
       +        p = filename;
       +        do {
       +                if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
       +                        p += runetochar(p, &c);
       +                readchar();
       +        } while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
       +        *p = 0;
       +        reread();
       +}
       +
       +int
       +convdig(int c)
       +{
       +        if (isdigit(c))
       +                return(c-'0');
       +        else if (!isxdigit(c))
       +                return(MAXBASE);
       +        else if (isupper(c))
       +                return(c-'A'+10);
       +        else
       +                return(c-'a'+10);
       +}
       +
       +int
       +symchar(int dig)
       +{
       +        if (lastc=='\\') {
       +                readchar();
       +                return(TRUE);
       +        }
       +        return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
       +}
       +
       +static long
       +dbround(long a, long b)
       +{
       +        long w;
       +
       +        w = (a/b)*b;
       +        if (a!=w)
       +                w += b;
       +        return(w);
       +}
       +
       +ulong
       +dbrget(Map *map, char *name)
       +{
       +        ulong u;
       +
       +        USED(map);
       +        if(rget(correg, name, &u) < 0)
       +                return ~(ulong)0;
       +        return u;
       +}
   DIR diff --git a/src/cmd/db/fns.h b/src/cmd/db/fns.h
       t@@ -0,0 +1,91 @@
       +void                acommand(int);
       +void                attachprocess(void);
       +void                bkput(BKPT*, int);
       +void                bpwait(void);
       +int                charpos(void);
       +void                chkerr(void);
       +void                clrinp(void);
       +void                cmdmap(Map*);
       +void                cmdsrc(int, Map*);
       +void                cmdwrite(int, Map*);
       +int                command(char*, int);
       +int                convdig(int);
       +void                ctrace(int);
       +WORD                defval(WORD);
       +void                delbp(void);
       +ulong        dbrget(Map*, char*);
       +void                done(void);
       +int                dprint(char*, ...);
       +Map*                dumbmap(int);
       +void                endline(void);
       +void                endpcs(void);
       +int                eol(int);
       +void                error(char*);
       +void                errors(char*, char*);
       +void                execbkpt(BKPT*, int);
       +char*                exform(int, int, char*, Map*, int, int);
       +int                expr(int);
       +/*
       +void                fixregs(Map*);
       +void                adjustreg(char*, ulong, long);
       +*/
       +void                flush(void);
       +void                flushbuf(void);
       +char*                getfname(void);
       +void                getformat(char*);
       +int                getnum(int (*)(void));
       +void                grab(void);
       +void                iclose(int, int);
       +ADDR                inkdot(long);
       +int                isfileref(void);
       +int                item(int);
       +void                killpcs(void);
       +void                kmsys(void);
       +void                main(int, char**);
       +int                mapimage(void);
       +void                newline(void);
       +int                nextchar(void);
       +void                notes(void);
       +void                oclose(void);
       +void                outputinit(void);
       +void                printc(int);
       +void                printdollar(int);
       +void                printesc(int);
       +void                printlocals(Symbol*, Regs*);
       +void                printmap(char*, Map*);
       +void                printparams(Symbol*, Regs*);
       +void                printpc(void);
       +void                printregs(int);
       +void                prints(char*);
       +void                printsource(long);
       +void                printsym(void);
       +void                printsyscall(void);
       +int                quotchar(void);
       +int                rdc(void);
       +int                readchar(void);
       +void                readsym(char*);
       +void                redirin(int, char*);
       +void                redirout(char*);
       +void                readfname(char *);
       +void                reread(void);
       +char*                regname(int);
       +//vlong                rget(Map*, char*);
       +Regdesc*        rname(char*);
       +//void                rput(Map*, char*, vlong);
       +int                runpcs(int, int);
       +void                runrun(int);
       +void                runstep(ulong, int);
       +BKPT*                scanbkpt(ADDR adr);
       +void                scanform(long, int, char*, Map*, int);
       +void                setbp(void);
       +void                setcor(void);
       +void                setsym(void);
       +void                setup(void);
       +void                setvec(void);
       +void                shell(void);
       +void                startpcs(void);
       +void                subpcs(int);
       +int                symchar(int);
       +int                term(int);
       +void                ungrab(void);
       +int                valpr(long, int);
   DIR diff --git a/src/cmd/db/format.c b/src/cmd/db/format.c
       t@@ -0,0 +1,388 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +void
       +scanform(long icount, int prt, char *ifp, Map *map, int literal)
       +{
       +        char        *fp;
       +        char        c;
       +        int        fcount;
       +        ADDR        savdot;
       +        int firstpass;
       +
       +        firstpass = 1;
       +        while (icount) {
       +                fp=ifp;
       +                savdot=dot;
       +                /*now loop over format*/
       +                while (*fp) {
       +                        if (!isdigit(*fp))
       +                                fcount = 1;
       +                        else {
       +                                fcount = 0;
       +                                while (isdigit(c = *fp++)) {
       +                                        fcount *= 10;
       +                                        fcount += c-'0';
       +                                }
       +                                fp--;
       +                        }
       +                        if (*fp==0)
       +                                break;
       +                        fp=exform(fcount,prt,fp,map,literal,firstpass);
       +                        firstpass = 0;
       +                }
       +                dotinc=dot-savdot;
       +                dot=savdot;
       +                if (--icount)
       +                        dot=inkdot(dotinc);
       +        }
       +}
       +
       +char *
       +exform(int fcount, int prt, char *ifp, Map *map, int literal, int firstpass)
       +{
       +        /* execute single format item `fcount' times
       +         * sets `dotinc' and moves `dot'
       +         * returns address of next format item
       +         */
       +        vlong        v;
       +        WORD        w;
       +        ulong        savdot;
       +        u16int        u2;
       +        u32int        u4;
       +        u64int        u8;
       +        char        *fp;
       +        char        c, modifier;
       +        int        i;
       +        ushort sh, *sp;
       +        uchar ch, *cp;
       +        Symbol s;
       +        char buf[512];
       +        extern int printcol;
       +
       +        fp = 0;
       +        while (fcount > 0) {
       +                fp = ifp;
       +                c = *fp;
       +                modifier = *fp++;
       +                if (firstpass) {
       +                        firstpass = 0;
       +                        if (!literal  && (c == 'i' || c == 'I' || c == 'M')
       +                                        && (dot & (mach->pcquant-1))) {
       +                                dprint("warning: instruction not aligned");
       +                                printc('\n');
       +                        }
       +                        if (prt && modifier != 'a' && modifier != 'A') {
       +                                symoff(buf, 512, dot, CANY);
       +                                dprint("%s%c%16t", buf, map==symmap? '?':'/');
       +                        }
       +                }
       +                if (printcol==0 && modifier != 'a' && modifier != 'A')
       +                        dprint("\t\t");
       +                switch(modifier) {
       +
       +                case SPC:
       +                case TB:
       +                        dotinc = 0;
       +                        break;
       +
       +                case 't':
       +                case 'T':
       +                        dprint("%*t", fcount);
       +                        dotinc = 0;
       +                        return(fp);
       +
       +                case 'a':
       +                        symoff(buf, sizeof(buf), dot, CANY);
       +                        dprint("%s%c%16t", buf, map==symmap? '?':'/');
       +                        dotinc = 0;
       +                        break;
       +
       +                case 'A':
       +                        dprint("%#lux%10t", dot);
       +                        dotinc = 0;
       +                        break;
       +
       +                case 'p':
       +                        if (get4(map, dot, &u4) < 0)
       +                                error("%r");
       +                        w = u4;
       +                        symoff(buf, sizeof(buf), w, CANY);
       +                        dprint("%s%16t", buf);
       +                        dotinc = mach->szaddr;
       +                        break;
       +
       +                case 'u':
       +                case 'd':
       +                case 'x':
       +                case 'o':
       +                case 'q':
       +                        if (literal)
       +                                u2 = (ushort) dot;
       +                        else if (get2(map, dot, &u2) < 0)
       +                                error("%r");
       +                        w = u2;
       +                        dotinc = 2;
       +                        if (c == 'u')
       +                                dprint("%-8lud", w);
       +                        else if (c == 'x')
       +                                dprint("%-8#lux", w);
       +                        else if (c == 'd')
       +                                dprint("%-8ld", w);
       +                        else if (c == 'o')
       +                                dprint("%-8#luo", w);
       +                        else if (c == 'q')
       +                                dprint("%-8#lo", w);
       +                        break;
       +
       +                case 'U':
       +                case 'D':
       +                case 'X':
       +                case 'O':
       +                case 'Q':
       +                        if (literal)
       +                                u4 = (long) dot;
       +                        else if (get4(map, dot, &u4) < 0)
       +                                error("%r");
       +                        dotinc = 4;
       +                        if (c == 'U')
       +                                dprint("%-16lud", u4);
       +                        else if (c == 'X')
       +                                dprint("%-16#lux", u4);
       +                        else if (c == 'D')
       +                                dprint("%-16ld", u4);
       +                        else if (c == 'O')
       +                                dprint("%-#16luo", u4);
       +                        else if (c == 'Q')
       +                                dprint("%-#16lo", u4);
       +                        break;
       +                case 'Z':
       +                case 'V':
       +                case 'Y':
       +                        if (literal)
       +                                v = dot;
       +                        else if (get8(map, dot, &u8) < 0)
       +                                error("%r");
       +                        dotinc = 8;
       +                        if (c == 'Y')
       +                                dprint("%-20#llux", u8);
       +                        else if (c == 'V')
       +                                dprint("%-20lld", u8);
       +                        else if (c == 'Z')
       +                                dprint("%-20llud", u8);
       +                        break;
       +                case 'B':
       +                case 'b':
       +                case 'c':
       +                case 'C':
       +                        if (literal)
       +                                ch = (uchar) dot;
       +                        else if (get1(map, dot, &ch, 1)  < 0)
       +                                error("%r");
       +                        if (modifier == 'C')
       +                                printesc(ch);
       +                        else if (modifier == 'B' || modifier == 'b')
       +                                dprint("%-8#lux", (long) ch);
       +                        else
       +                                printc(ch);
       +                        dotinc = 1;
       +                        break;
       +
       +                case 'r':
       +                        if (literal)
       +                                sh = (ushort) dot;
       +                        else if (get2(map, dot, &sh) < 0)
       +                                error("%r");
       +                        dprint("%C", sh);
       +                        dotinc = 2;
       +                        break;
       +
       +                case 'R':
       +                        if (literal) {
       +                                sp = (u16int*)(void*)&dot;
       +                                dprint("%C%C", sp[0], sp[1]);
       +                                endline();
       +                                dotinc = 4;
       +                                break;
       +                        }
       +                        savdot=dot;
       +                        while ((i = get2(map, dot, &u2) > 0) && u2) {
       +                                dot=inkdot(2);
       +                                dprint("%C", u2);
       +                                endline();
       +                        }
       +                        if (i < 0)
       +                                error("%r");
       +                        dotinc = dot-savdot+2;
       +                        dot=savdot;
       +                        break;
       +
       +                case 's':
       +                        if (literal) {
       +                                cp = (uchar*)(void*)&dot;
       +                                for (i = 0; i < 4; i++)
       +                                        buf[i] = cp[i];
       +                                buf[i] = 0;
       +                                dprint("%s", buf);
       +                                endline();
       +                                dotinc = 4;
       +                                break;
       +                        }
       +                        savdot = dot;
       +                        for(;;){
       +                                i = 0;
       +                                do{
       +                                        if (get1(map, dot, (uchar*)(void*)&buf[i], 1) < 0)
       +                                                error("%r");
       +                                        dot = inkdot(1);
       +                                        i++;
       +                                }while(!fullrune(buf, i));
       +                                if(buf[0] == 0)
       +                                        break;
       +                                buf[i] = 0;
       +                                dprint("%s", buf);
       +                                endline();
       +                        }
       +                        dotinc = dot-savdot+1;
       +                        dot = savdot;
       +                        break;
       +
       +                case 'S':
       +                        if (literal) {
       +                                cp = (uchar*) &dot;
       +                                for (i = 0; i < 4; i++)
       +                                        printesc(cp[i]);
       +                                endline();
       +                                dotinc = 4;
       +                                break;
       +                        }
       +                        savdot=dot;
       +                        while ((i = get1(map, dot, &ch, 1) > 0) && ch) {
       +                                dot=inkdot(1);
       +                                printesc(ch);
       +                                endline();
       +                        }
       +                        if (i < 0)
       +                                error("%r");
       +                        dotinc = dot-savdot+1;
       +                        dot=savdot;
       +                        break;
       +
       +
       +                case 'I':
       +                case 'i':
       +                        dotinc = mach->das(map, dot, modifier, buf, sizeof(buf));
       +                        if (dotinc < 0)
       +                                error("%r");
       +                        dprint("%s\n", buf);
       +                        break;
       +
       +                case 'M':
       +                        dotinc = mach->hexinst(map, dot, buf, sizeof(buf));
       +                        if (dotinc < 0)
       +                                error("%r");
       +                        dprint("%s", buf);
       +                        if (*fp) {
       +                                dotinc = 0;
       +                                dprint("%48t");
       +                        } else
       +                                dprint("\n");
       +                        break;
       +
       +                case 'f':
       +                        /* BUG: 'f' and 'F' assume szdouble is sizeof(vlong) in the literal case */
       +                        if (literal) {
       +                                v = mach->swap8((ulong)dot);
       +                                memmove(buf, &v, mach->szfloat);
       +                        }else if (get1(map, dot, (uchar*)buf, mach->szfloat) < 0)
       +                                error("%r");
       +                        mach->ftoa32(buf, sizeof(buf), (void*) buf);
       +                        dprint("%s\n", buf);
       +                        dotinc = mach->szfloat;
       +                        break;
       +
       +                case 'F':
       +                        /* BUG: 'f' and 'F' assume szdouble is sizeof(vlong) in the literal case */
       +                        if (literal) {
       +                                v = mach->swap8(dot);
       +                                memmove(buf, &v, mach->szdouble);
       +                        }else if (get1(map, dot, (uchar*)buf, mach->szdouble) < 0)
       +                                error("%r");
       +                        mach->ftoa64(buf, sizeof(buf), (void*) buf);
       +                        dprint("%s\n", buf);
       +                        dotinc = mach->szdouble;
       +                        break;
       +
       +                case 'n':
       +                case 'N':
       +                        printc('\n');
       +                        dotinc=0;
       +                        break;
       +
       +                case '"':
       +                        dotinc=0;
       +                        while (*fp != '"' && *fp)
       +                                printc(*fp++);
       +                        if (*fp)
       +                                fp++;
       +                        break;
       +
       +                case '^':
       +                        dot=inkdot(-dotinc*fcount);
       +                        return(fp);
       +
       +                case '+':
       +                        dot=inkdot((WORD)fcount);
       +                        return(fp);
       +
       +                case '-':
       +                        dot=inkdot(-(WORD)fcount);
       +                        return(fp);
       +
       +                case 'z':
       +                        if (findsym(locaddr(dot), CTEXT, &s) >= 0)
       +                                dprint("%s() ", s.name);
       +                        printsource(dot);
       +                        printc(EOR);
       +                        return fp;
       +
       +                default:
       +                        error("bad modifier");
       +                }
       +                if (map->seg[0].fd >= 0)
       +                        dot=inkdot(dotinc);
       +                fcount--;
       +                endline();
       +        }
       +
       +        return(fp);
       +}
       +
       +void
       +printesc(int c)
       +{
       +        static char hex[] = "0123456789abcdef";
       +
       +        if (c < SPC || c >= 0177)
       +                dprint("\\x%c%c", hex[(c&0xF0)>>4], hex[c&0xF]);
       +        else
       +                printc(c);
       +}
       +
       +ADDR
       +inkdot(WORD incr)
       +{
       +        ADDR        newdot;
       +
       +        newdot=dot+incr;
       +        if ((incr >= 0 && newdot < dot)
       +        ||  (incr < 0 && newdot > dot))
       +                error("address wraparound");
       +        return(newdot);
       +}
   DIR diff --git a/src/cmd/db/input.c b/src/cmd/db/input.c
       t@@ -0,0 +1,169 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +Rune        line[LINSIZ];
       +extern        int        infile;
       +Rune        *lp;
       +int        peekc,lastc = EOR;
       +int        eof;
       +
       +/* input routines */
       +
       +int
       +eol(int c)
       +{
       +        return(c==EOR || c==';');
       +}
       +
       +int
       +rdc(void)
       +{
       +        do {
       +                readchar();
       +        } while (lastc==SPC || lastc==TB);
       +        return(lastc);
       +}
       +
       +void
       +reread(void)
       +{
       +        peekc = lastc;
       +}
       +
       +void
       +clrinp(void)
       +{
       +        flush();
       +        lp = 0;
       +        peekc = 0;
       +}
       +
       +int
       +readrune(int fd, Rune *r)
       +{
       +        char buf[UTFmax];
       +        int i;
       +
       +        for(i=0; i<UTFmax && !fullrune(buf, i); i++)
       +                if(read(fd, buf+i, 1) <= 0)
       +                        return -1;
       +        chartorune(r, buf);
       +        return 1;
       +}
       +
       +int
       +readchar(void)
       +{
       +        Rune *p;
       +
       +        if (eof)
       +                lastc=0;
       +        else if (peekc) {
       +                lastc = peekc;
       +                peekc = 0;
       +        }
       +        else {
       +                if (lp==0) {
       +                        for (p = line; p < &line[LINSIZ-1]; p++) {
       +                                eof = readrune(infile, p) <= 0;
       +                                if (mkfault) {
       +                                        eof = 0;
       +                                        error(0);
       +                                }
       +                                if (eof) {
       +                                        p--;
       +                                        break;
       +                                }
       +                                if (*p == EOR) {
       +                                        if (p <= line)
       +                                                break;
       +                                        if (p[-1] != '\\')
       +                                                break;
       +                                        p -= 2;
       +                                }
       +                        }
       +                        p[1] = 0;
       +                        lp = line;
       +                }
       +                if ((lastc = *lp) != 0)
       +                        lp++;
       +        }
       +        return(lastc);
       +}
       +
       +int
       +nextchar(void)
       +{
       +        if (eol(rdc())) {
       +                reread();
       +                return(0);
       +        }
       +        return(lastc);
       +}
       +
       +int
       +quotchar(void)
       +{
       +        if (readchar()=='\\')
       +                return(readchar());
       +        else if (lastc=='\'')
       +                return(0);
       +        else
       +                return(lastc);
       +}
       +
       +void
       +getformat(char *deformat)
       +{
       +        char *fptr;
       +        BOOL        quote;
       +        Rune r;
       +
       +        fptr=deformat;
       +        quote=FALSE;
       +        while ((quote ? readchar()!=EOR : !eol(readchar()))){
       +                r = lastc;
       +                fptr += runetochar(fptr, &r);
       +                if (lastc == '"')
       +                        quote = ~quote;
       +        }
       +        lp--;
       +        if (fptr!=deformat)
       +                *fptr = '\0';
       +}
       +
       +/*
       + *        check if the input line if of the form:
       + *                <filename>:<digits><verb> ...
       + *
       + *        we handle this case specially because we have to look ahead
       + *        at the token after the colon to decide if it is a file reference
       + *        or a colon-command with a symbol name prefix. 
       + */
       +
       +int
       +isfileref(void)
       +{
       +        Rune *cp;
       +
       +        for (cp = lp-1; *cp && !strchr(CMD_VERBS, *cp); cp++)
       +                if (*cp == '\\' && cp[1])        /* escape next char */
       +                        cp++;
       +        if (*cp && cp > lp-1) {
       +                while (*cp == ' ' || *cp == '\t')
       +                        cp++;
       +                if (*cp++ == ':') {
       +                        while (*cp == ' ' || *cp == '\t')
       +                                cp++;
       +                        if (isdigit(*cp))
       +                                return 1;
       +                }
       +        }
       +        return 0;
       +}
   DIR diff --git a/src/cmd/db/main.c b/src/cmd/db/main.c
       t@@ -0,0 +1,262 @@
       +/*
       + * db - main command loop and error/interrupt handling
       + */
       +#include "defs.h"
       +#include "fns.h"
       +
       +int wtflag = OREAD;
       +BOOL kflag;
       +
       +BOOL mkfault;
       +ADDR maxoff;
       +
       +int xargc;                /* bullshit */
       +
       +extern        BOOL        executing;
       +extern        int        infile;
       +int        exitflg;
       +extern        int        eof;
       +
       +int        alldigs(char*);
       +void        fault(void*, char*);
       +
       +extern        char        *Ipath;
       +jmp_buf env;
       +static char *errmsg;
       +
       +Fhdr *symhdr, *corhdr;
       +
       +void
       +usage(void)
       +{
       +        fprint(2, "usage: db [-kw] [-m machine] [-I dir] [symfile] [pid]\n");
       +        exits("usage");
       +}
       +
       +void
       +main(int argc, char **argv)
       +{
       +        int i, omode;
       +        char *s;
       +        char *name;
       +        Fhdr *hdr;
       +
       +        name = 0;
       +        outputinit();
       +        maxoff = MAXOFF;
       +        omode = OREAD;
       +        ARGBEGIN{
       +        default:
       +                usage();
       +        case 'A':
       +                abort();
       +        case 'k':
       +                kflag = 1;
       +                break;
       +        case 'w':
       +                omode = ORDWR;
       +                break;
       +        case 'I':
       +                s = ARGF();
       +                if(s == 0)
       +                        dprint("missing -I argument\n");
       +                else
       +                        Ipath = s;
       +                break;
       +        case 'm':
       +                name = ARGF();
       +                if(name == 0)
       +                        dprint("missing -m argument\n");
       +                break;
       +        }ARGEND
       +
       +        /*
       +         * Unix and Plan 9 differ on what the right order of pid, text, and core is.
       +         * I never remember anyway.  Let's just accept them in any order.
       +         */
       +        for(i=0; i<argc; i++){
       +                if(alldigs(argv[i])){
       +                        if(pid){
       +                                dprint("already have pid %d; ignoring pid %d\n", pid, argv[i]);
       +                                continue;
       +                        }
       +                        if(corhdr){
       +                                dprint("already have core %s; ignoring pid %d\n", corfil, pid);
       +                                continue;
       +                        }
       +                        pid = atoi(argv[i]);
       +                        continue;
       +                }
       +                if((hdr = crackhdr(argv[i], omode)) == nil){
       +                        dprint("crackhdr %s: %r\n", argv[i]);
       +                        continue;
       +                }
       +                dprint("%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
       +                if(hdr->ftype == FCORE){
       +                        if(pid){
       +                                dprint("already have pid %d; ignoring core %s\n", pid, argv[i]);
       +                                uncrackhdr(hdr);
       +                                continue;
       +                        }
       +                        if(corhdr){
       +                                dprint("already have core %s; ignoring core %s\n", corfil, argv[i]);
       +                                uncrackhdr(hdr);
       +                                continue;
       +                        }
       +                        corhdr = hdr;
       +                        corfil = argv[i];
       +                }else{
       +                        if(symhdr){
       +                                dprint("already have text %s; ignoring text %s\n", symfil, argv[i]);
       +                                uncrackhdr(hdr);
       +                                continue;
       +                        }
       +                        symhdr = hdr;
       +                        symfil = argv[i];
       +                }
       +        }
       +
       +        if(symhdr==nil){
       +                symfil = "a.out";
       +                if(pid){
       +                        if((s = proctextfile(pid)) != nil){
       +                                dprint("pid %d: text %s\n", pid, s);
       +                                symfil = s;
       +                        }
       +                }
       +                /* XXX pull command from core */
       +
       +                if((symhdr = crackhdr(symfil, omode)) == nil){
       +                        dprint("crackhdr %s: %r\n", symfil);
       +                        symfil = nil;
       +                }
       +        }
       +
       +        if(!mach)
       +                mach = machcpu;
       +
       +        /*
       +         * Set up maps.
       +         */
       +        symmap = allocmap();
       +        cormap = allocmap();
       +        if(symmap == nil || cormap == nil)
       +                sysfatal("allocating maps: %r");
       +
       +        if(symhdr){
       +                if(mapfile(symhdr, 0, symmap, nil) < 0)
       +                        dprint("mapping %s: %r\n", symfil);
       +                mapfile(symhdr, 0, cormap, nil);
       +        }
       +
       +        dotmap = dumbmap(-1);
       +
       +        /*
       +         * show initial state and drop into the execution loop.
       +         */
       +        notify(fault);
       +        setsym();
       +        if(setjmp(env) == 0){
       +                if (pid || corhdr)
       +                        setcor();        /* could get error */
       +                if (correg) {
       +                        dprint("%s\n", mach->exc(cormap, correg));
       +                        printpc();
       +                }
       +        }
       +
       +        setjmp(env);
       +        if (executing)
       +                delbp();
       +        executing = FALSE;
       +        for (;;) {
       +                flushbuf();
       +                if (errmsg) {
       +                        dprint(errmsg);
       +                        printc('\n');
       +                        errmsg = 0;
       +                        exitflg = 0;
       +                }
       +                if (mkfault) {
       +                        mkfault=0;
       +                        printc('\n');
       +                        prints(DBNAME);
       +                }
       +                clrinp();
       +                rdc();
       +                reread();
       +                if (eof) {
       +                        if (infile == STDIN)
       +                                done();
       +                        iclose(-1, 0);
       +                        eof = 0;
       +                        longjmp(env, 1);
       +                }
       +                exitflg = 0;
       +                command(0, 0);
       +                reread();
       +                if (rdc() != '\n')
       +                        error("newline expected");
       +        }
       +}
       +
       +int
       +alldigs(char *s)
       +{
       +        while(*s){
       +                if(*s<'0' || '9'<*s)
       +                        return 0;
       +                s++;
       +        }
       +        return 1;
       +}
       +
       +void
       +done(void)
       +{
       +        if (pid)
       +                endpcs();
       +        exits(exitflg? "error": 0);
       +}
       +
       +/*
       + * An error occurred; save the message for later printing,
       + * close open files, and reset to main command loop.
       + */
       +void
       +error(char *n)
       +{
       +        errmsg = n;
       +        iclose(0, 1);
       +        oclose();
       +        flush();
       +        delbp();
       +        ending = 0;
       +        longjmp(env, 1);
       +}
       +
       +void
       +errors(char *m, char *n)
       +{
       +        static char buf[128];
       +
       +        sprint(buf, "%s: %s", m, n);
       +        error(buf);
       +}
       +
       +/*
       + * An interrupt occurred;
       + * seek to the end of the current file
       + * and remember that there was a fault.
       + */
       +void
       +fault(void *a, char *s)
       +{
       +        USED(a);
       +        if(strncmp(s, "interrupt", 9) == 0){
       +                seek(infile, 0L, 2);
       +                mkfault++;
       +                noted(NCONT);
       +        }
       +        noted(NDFLT);
       +}
   DIR diff --git a/src/cmd/db/mkfile b/src/cmd/db/mkfile
       t@@ -0,0 +1,26 @@
       +<$PLAN9/src/mkhdr
       +
       +TARG=db
       +OFILES=\
       +        command.$O\
       +        expr.$O\
       +        format.$O\
       +        input.$O\
       +        main.$O\
       +        output.$O\
       +        pcs.$O\
       +        runpcs.$O\
       +        regs.$O\
       +        trcrun.$O\
       +        print.$O\
       +        setup.$O\
       +
       +HFILES=defs.h\
       +        fns.h\
       +
       +SHORTLIB=mach bio 9
       +
       +<$PLAN9/src/mkone
       +
       +CFLAGS=$CFLAGS -I../libmach2
       +
   DIR diff --git a/src/cmd/db/output.c b/src/cmd/db/output.c
       t@@ -0,0 +1,159 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +int        printcol = 0;
       +int        infile = STDIN;
       +int        maxpos = MAXPOS;
       +
       +Biobuf        bstdout;
       +
       +void
       +printc(int c)
       +{
       +        dprint("%c", c);
       +}
       +
       +/* was move to next f1-sized tab stop; now just print a tab */
       +int
       +tconv(Fmt *f)
       +{
       +        return fmtstrcpy(f, "\t");
       +}
       +
       +void
       +flushbuf(void)
       +{
       +         if (printcol != 0)
       +                printc(EOR);
       +}
       +
       +void
       +prints(char *s)
       +{
       +        dprint("%s",s);
       +}
       +
       +void
       +newline(void)
       +{
       +        printc(EOR);
       +}
       +
       +#define        MAXIFD        5
       +struct {
       +        int        fd;
       +        int        r9;
       +} istack[MAXIFD];
       +int        ifiledepth;
       +
       +void
       +iclose(int stack, int err)
       +{
       +        if (err) {
       +                if (infile) {
       +                        close(infile);
       +                        infile=STDIN;
       +                }
       +                while (--ifiledepth >= 0)
       +                        if (istack[ifiledepth].fd)
       +                                close(istack[ifiledepth].fd);
       +                ifiledepth = 0;
       +        } else if (stack == 0) {
       +                if (infile) {
       +                        close(infile);
       +                        infile=STDIN;
       +                }
       +        } else if (stack > 0) {
       +                if (ifiledepth >= MAXIFD)
       +                        error("$<< nested too deeply");
       +                istack[ifiledepth].fd = infile;
       +                ifiledepth++;
       +                infile = STDIN;
       +        } else {
       +                if (infile) {
       +                        close(infile); 
       +                        infile=STDIN;
       +                }
       +                if (ifiledepth > 0) {
       +                        infile = istack[--ifiledepth].fd;
       +                }
       +        }
       +}
       +
       +void
       +oclose(void)
       +{
       +        flushbuf();
       +        Bterm(&bstdout);
       +        Binit(&bstdout, 1, OWRITE);
       +}
       +
       +void
       +redirout(char *file)
       +{
       +        int fd;
       +
       +        if (file == 0){
       +                oclose();
       +                return;
       +        }
       +        flushbuf();
       +        if ((fd = open(file, 1)) >= 0)
       +                seek(fd, 0L, 2);
       +        else if ((fd = create(file, 1, 0666)) < 0)
       +                error("cannot create");
       +        Bterm(&bstdout);
       +        Binit(&bstdout, fd, OWRITE);
       +}
       +
       +void
       +endline(void)
       +{
       +
       +        if (maxpos <= printcol)
       +                newline();
       +}
       +
       +void
       +flush(void)
       +{
       +        Bflush(&bstdout);
       +}
       +
       +int
       +dprint(char *fmt, ...)
       +{
       +        int n, w;
       +        char *p;
       +         char buf[4096];
       +        Rune r;
       +        va_list arg;
       +
       +        if(mkfault)
       +                return -1;
       +        va_start(arg, fmt);
       +        n = vseprint(buf, buf+sizeof buf, fmt, arg) - buf;
       +        va_end(arg);
       +        Bwrite(&bstdout, buf, n);
       +        for(p=buf; *p; p+=w){
       +                w = chartorune(&r, p);
       +                if(r == '\n')
       +                        printcol = 0;
       +                else
       +                        printcol++;
       +        }
       +        return n;
       +}
       +
       +void
       +outputinit(void)
       +{
       +        Binit(&bstdout, 1, OWRITE);
       +        fmtinstall('t', tconv);
       +}
   DIR diff --git a/src/cmd/db/pcs.c b/src/cmd/db/pcs.c
       t@@ -0,0 +1,177 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +char        NOPCS[] = "no process";
       +
       +/* sub process control */
       +
       +void
       +subpcs(int modif)
       +{
       +        int        check;
       +        int        runmode;
       +        int        keepnote;
       +        int        n, r;
       +        ulong line, curr;
       +        BKPT *bk;
       +        char *comptr;
       +
       +        runmode=SINGLE;
       +        r = 0;
       +        keepnote=0;
       +        loopcnt=cntval;
       +        switch (modif) {
       +
       +                /* delete breakpoint */
       +        case 'd': 
       +        case 'D':
       +                if ((bk=scanbkpt(dot)) == 0)
       +                        error("no breakpoint set");
       +                bk->flag=BKPTCLR;
       +                return;
       +
       +                /* set breakpoint */
       +        case 'b': 
       +        case 'B':
       +                if (bk=scanbkpt(dot))
       +                        bk->flag=BKPTCLR;
       +                for (bk=bkpthead; bk; bk=bk->nxtbkpt)
       +                        if (bk->flag == BKPTCLR)
       +                                break;
       +                if (bk==0) {
       +                        bk = (BKPT *)malloc(sizeof(*bk));
       +                        if (bk == 0)
       +                                error("too many breakpoints");
       +                        bk->nxtbkpt=bkpthead;
       +                        bkpthead=bk;
       +                }
       +                bk->loc = dot;
       +                bk->initcnt = bk->count = cntval;
       +                bk->flag = modif == 'b' ? BKPTSET : BKPTTMP;
       +                check=MAXCOM-1;
       +                comptr=bk->comm;
       +                rdc();
       +                reread();
       +                do {
       +                        *comptr++ = readchar();
       +                } while (check-- && lastc!=EOR);
       +                *comptr=0;
       +                if(bk->comm[0] != EOR && cntflg == FALSE)
       +                        bk->initcnt = bk->count = HUGEINT;
       +                reread();
       +                if (check)
       +                        return;
       +                error("bkpt command too long");
       +
       +                /* exit */
       +        case 'k' :
       +        case 'K':
       +                if (pid == 0)
       +                        error(NOPCS);
       +                dprint("%d: killed", pid);
       +                pcsactive = 1;        /* force 'kill' ctl */
       +                endpcs();
       +                return;
       +
       +                /* run program */
       +        case 'r': 
       +        case 'R':
       +                endpcs();
       +                setup();
       +                runmode = CONTIN;
       +                break;
       +
       +                /* single step */
       +        case 's': 
       +                if (pid == 0) {
       +                        setup();
       +                        loopcnt--;
       +                }
       +                runmode=SINGLE;
       +                keepnote=defval(1);
       +                break;
       +        case 'S':
       +                if (pid == 0) {
       +                        setup();
       +                        loopcnt--;
       +                }
       +                keepnote=defval(1);
       +                if(pc2line(dbrget(cormap, mach->pc), &line) < 0)
       +                        error("%r");
       +                n = loopcnt;
       +                dprint("%s: running\n", symfil);
       +                flush();
       +                for (loopcnt = 1; n > 0; loopcnt = 1) {
       +                        r = runpcs(SINGLE, keepnote);
       +                        if(pc2line(dot, &curr) < 0)
       +                                error("%r");
       +                        if (line != curr) {        /* on a new line of c */
       +                                line = curr;
       +                                n--;
       +                        }
       +                }
       +                loopcnt = 0;
       +                break;
       +                /* continue with optional note */
       +        case 'c': 
       +        case 'C': 
       +                if (pid==0)
       +                        error(NOPCS);
       +                runmode=CONTIN;
       +                keepnote=defval(1);
       +                break;
       +
       +        case 'n':        /* deal with notes */
       +                if (pid==0)
       +                        error(NOPCS);
       +                n=defval(-1);
       +                if(n>=0 && n<nnote){
       +                        nnote--;
       +                        memmove(note[n], note[n+1], (nnote-n)*sizeof(note[0]));
       +                }
       +                notes();
       +                return;
       +
       +        case 'h':        /* halt the current process */
       +                if (adrflg && adrval == 0) {
       +                        if (pid == 0)
       +                                error(NOPCS);
       +                        ungrab();
       +                }
       +                else {
       +                        grab();
       +                        dprint("stopped at%16t");
       +                        goto Return;
       +                }
       +                return;
       +
       +        case 'x':        /* continue executing the current process */
       +                if (pid == 0)
       +                        error(NOPCS);
       +                ungrab();
       +                return;
       +
       +        default:
       +                error("bad `:' command");
       +        }
       +
       +        if (loopcnt>0) {
       +                dprint("%s: running\n", symfil);
       +                flush();
       +                r = runpcs(runmode,keepnote);
       +        }
       +        if (r)
       +                dprint("breakpoint%16t");
       +        else
       +                dprint("stopped at%16t");
       +    Return:
       +        delbp();
       +        printpc();
       +        notes();
       +}
   DIR diff --git a/src/cmd/db/print.c b/src/cmd/db/print.c
       t@@ -0,0 +1,406 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +#include "defs.h"
       +#include "fns.h"
       +
       +extern        int        infile;
       +extern        int        outfile;
       +extern        int        maxpos;
       +
       +/* general printing routines ($) */
       +
       +char        *Ipath = INCDIR;
       +static        int        tracetype;
       +static void        printfp(Map*, int);
       +
       +/*
       + *        callback on stack trace
       + */
       +static int
       +ptrace(Map *map, Regs *regs, ulong pc, ulong nextpc, Symbol *sym, int depth)
       +{
       +        char buf[512];
       +
       +        USED(map);
       +        if(sym){
       +                dprint("%s(", sym->name);
       +                printparams(sym, regs);
       +                dprint(") ");
       +        }else
       +                dprint("%#lux ", pc);
       +        printsource(pc);
       +
       +        dprint(" called from ");
       +        symoff(buf, 512, nextpc, CTEXT);
       +        dprint("%s ", buf);
       +/*        printsource(nextpc); */
       +        dprint("\n");
       +        if(tracetype == 'C' && sym)
       +                printlocals(sym, regs);
       +        return depth<40;
       +}
       +
       +static ulong *adrregvals;
       +
       +static int
       +adrrw(Regs *regs, char *name, ulong *val, int isr)
       +{
       +        int i;
       +
       +        if((i = windindex(name)) == -1)
       +                return correg->rw(correg, name, val, isr);
       +        if(isr){
       +                *val = adrregvals[i];
       +                return 0;
       +        }
       +        werrstr("saved registers are immutable");
       +        return -1;
       +}
       +
       +Regs*
       +adrregs(void)
       +{
       +        int i;
       +        static Regs r;
       +        static u32int x;
       +
       +        if(adrregvals== nil){
       +                adrregvals = malloc(mach->nwindreg*sizeof(adrregvals[0]));
       +                if(adrregvals == nil)
       +                        error("%r");
       +        }
       +        for(i=0; i<mach->nwindreg; i++){
       +                if(get4(cormap, adrval+4*i, &x) < 0)
       +                        error("%r");
       +                adrregvals[i] = x;
       +        }
       +        r.rw = adrrw;
       +        return &r;
       +}
       +
       +void
       +printdollar(int modif)
       +{
       +        int        i;
       +        u32int u4;
       +        BKPT *bk;
       +        Symbol s;
       +        int        stack;
       +        char        *fname;
       +        char buf[512];
       +        Regs *r;
       +
       +        if (cntflg==0)
       +                cntval = -1;
       +        switch (modif) {
       +
       +        case '<':
       +                if (cntval == 0) {
       +                        while (readchar() != EOR)
       +                                ;
       +                        reread();
       +                        break;
       +                }
       +                if (rdc() == '<')
       +                        stack = 1;
       +                else {
       +                        stack = 0;
       +                        reread();
       +                }
       +                fname = getfname();
       +                redirin(stack, fname);
       +                break;
       +
       +        case '>':
       +                fname = getfname();
       +                redirout(fname);
       +                break;
       +
       +        case 'a':
       +                attachprocess();
       +                break;
       +
       +        case 'k':
       +                kmsys();
       +                break;
       +
       +        case 'q':
       +        case 'Q':
       +                done();
       +
       +        case 'w':
       +                maxpos=(adrflg?adrval:MAXPOS);
       +                break;
       +
       +        case 'S':
       +                printsym();
       +                break;
       +
       +        case 's':
       +                maxoff=(adrflg?adrval:MAXOFF);
       +                break;
       +
       +        case 'm':
       +                printmap("? map", symmap);
       +                printmap("/ map", cormap);
       +                break;
       +
       +        case 0:
       +        case '?':
       +                if (pid)
       +                        dprint("pid = %d\n",pid);
       +                else
       +                        prints("no process\n");
       +                flushbuf();
       +
       +        case 'r':
       +        case 'R':
       +                printregs(modif);
       +                return;
       +
       +        case 'f':
       +        case 'F':
       +                printfp(cormap, modif);
       +                return;
       +
       +        case 'c':
       +        case 'C':
       +                tracetype = modif;
       +                if (adrflg)
       +                        r = adrregs();
       +                else
       +                        r = correg;
       +                if(stacktrace(cormap, correg, ptrace) <= 0)
       +                        error("no stack frame");
       +                break;
       +
       +                /*print externals*/
       +        case 'e':
       +                for (i = 0; indexsym(i, &s)>=0; i++) {
       +                        if (s.class==CDATA)
       +                        if (s.loc.type==LADDR)
       +                        if (get4(cormap, s.loc.addr, &u4) > 0)
       +                                dprint("%s/%12t%#lux\n", s.name, (ulong)u4);
       +                }
       +                break;
       +
       +                /*print breakpoints*/
       +        case 'b':
       +        case 'B':
       +                for (bk=bkpthead; bk; bk=bk->nxtbkpt)
       +                        if (bk->flag) {
       +                                symoff(buf, 512, (WORD)bk->loc, CTEXT);
       +                                dprint(buf);
       +                                if (bk->count != 1)
       +                                        dprint(",%d", bk->count);
       +                                dprint(":%c %s", bk->flag == BKPTTMP ? 'B' : 'b', bk->comm);
       +                        }
       +                break;
       +
       +        case 'M':
       +                fname = getfname();
       +                if (machbyname(fname) == 0)
       +                        dprint("unknown name\n");;
       +                break;
       +        default:
       +                error("bad `$' command");
       +        }
       +
       +}
       +
       +char *
       +getfname(void)
       +{
       +        static char fname[ARB];
       +        char *p;
       +
       +        if (rdc() == EOR) {
       +                reread();
       +                return (0);
       +        }
       +        p = fname;
       +        do {
       +                *p++ = lastc;
       +                if (p >= &fname[ARB-1])
       +                        error("filename too long");
       +        } while (rdc() != EOR);
       +        *p = 0;
       +        reread();
       +        return (fname);
       +}
       +
       +static void
       +printfp(Map *map, int modif)
       +{
       +        Regdesc *rp;
       +        int i;
       +        int ret;
       +        char buf[512];
       +
       +        for (i = 0, rp = mach->reglist; rp->name; rp += ret) {
       +                ret = 1;
       +                if (!(rp->flags&RFLT))
       +                        continue;
       +                ret = fpformat(map, rp, buf, sizeof(buf), modif);
       +                if (ret < 0) {
       +                        werrstr("Register %s: %r", rp->name);
       +                        error("%r");
       +                }
       +                        /* double column print */
       +                if (i&0x01)
       +                        dprint("%40t%-8s%-12s\n", rp->name, buf);
       +                else
       +                        dprint("\t%-8s%-12s", rp->name, buf);
       +                i++;
       +        }
       +}
       +
       +void
       +redirin(int stack, char *file)
       +{
       +        char pfile[ARB];
       +
       +        if (file == 0) {
       +                iclose(-1, 0);
       +                return;
       +        }
       +        iclose(stack, 0);
       +        if ((infile = open(file, 0)) < 0) {
       +                strcpy(pfile, Ipath);
       +                strcat(pfile, "/");
       +                strcat(pfile, file);
       +                if ((infile = open(pfile, 0)) < 0) {
       +                        infile = STDIN;
       +                        error("cannot open");
       +                }
       +        }
       +}
       +
       +void
       +printmap(char *s, Map *map)
       +{
       +        int i;
       +
       +        if (!map)
       +                return;
       +        if (map == symmap)
       +                dprint("%s%12t`%s'\n", s, symfil==nil ? "-" : symfil);
       +        else if (map == cormap)
       +                dprint("%s%12t`%s'\n", s, corfil==nil ? "-" : corfil);
       +        else
       +                dprint("%s\n", s);
       +        for (i = 0; i < map->nseg; i++) {
       +                dprint("%s%8t%-16#lux %-16#lux %-16#lux %s\n", map->seg[i].name,
       +                        map->seg[i].base, map->seg[i].base+map->seg[i].size, map->seg[i].offset,
       +                        map->seg[i].file ? map->seg[i].file : "");
       +        }
       +}
       +
       +/*
       + *        dump the raw symbol table
       + */
       +void
       +printsym(void)
       +{
       +        int i;
       +        Symbol *sp, s;
       +
       +        for (i=0; indexsym(i, &s)>=0; i++){
       +                sp = &s;
       +                switch(sp->type) {
       +                case 't':
       +                case 'l':
       +                        dprint("%8#lux t %s\n", sp->loc.addr, sp->name);
       +                        break;
       +                case 'T':
       +                case 'L':
       +                        dprint("%8#lux T %s\n", sp->loc.addr, sp->name);
       +                        break;
       +                case 'D':
       +                case 'd':
       +                case 'B':
       +                case 'b':
       +                case 'a':
       +                case 'p':
       +                case 'm':
       +                        dprint("%8#lux %c %s\n", sp->loc.addr, sp->type, sp->name);
       +                        break;
       +                default:
       +                        break;
       +                }
       +        }
       +}
       +
       +#define        STRINGSZ        128
       +
       +/*
       + *        print the value of dot as file:line
       + */
       +void
       +printsource(long dot)
       +{
       +        char str[STRINGSZ];
       +
       +        if (fileline(dot, str, STRINGSZ) >= 0)
       +                dprint("%s", str);
       +}
       +
       +void
       +printpc(void)
       +{
       +        char buf[512];
       +        ulong u;
       +
       +        if(rget(correg, mach->pc, &u) < 0)
       +                error("%r");
       +        dot = u;
       +        if(dot){
       +                printsource((long)dot);
       +                printc(' ');
       +                symoff(buf, sizeof(buf), (long)dot, CTEXT);
       +                dprint("%s/", buf);
       +                if (mach->das(cormap, dot, 'i', buf, sizeof(buf)) < 0)
       +                        error("%r");
       +                dprint("%16t%s\n", buf);
       +        }
       +}
       +
       +void
       +printlocals(Symbol *fn, Regs *regs)
       +{
       +        int i;
       +        u32int v;
       +        Symbol s;
       +
       +        for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
       +                if (s.class != CAUTO)
       +                        continue;
       +                if(lget4(cormap, correg, s.loc, &v) >= 0)
       +                        dprint("%8t%s.%s/%10t%#lux\n", fn->name, s.name, v);
       +                else
       +                        dprint("%8t%s.%s/%10t?\n", fn->name, s.name);
       +        }
       +}
       +
       +void
       +printparams(Symbol *fn, Regs *regs)
       +{
       +        int i;
       +        Symbol s;
       +        u32int v;
       +        int first = 0;
       +
       +        for (i = 0; indexlsym(fn, i, &s)>=0; i++) {
       +                if (s.class != CPARAM)
       +                        continue;
       +                if (first++)
       +                        dprint(", ");
       +                if(lget4(cormap, correg, s.loc, &v) >= 0)
       +                        dprint("%s=%#lux", s.name, v);
       +                else
       +                        dprint("%s=?", s.name);
       +        }
       +}
   DIR diff --git a/src/cmd/db/regs.c b/src/cmd/db/regs.c
       t@@ -0,0 +1,44 @@
       +/*
       + * code to keep track of registers
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +/*
       + * print the registers
       + */
       +void
       +printregs(int c)
       +{
       +        Regdesc *rp;
       +        int i;
       +        ulong u;
       +
       +        if(correg == nil){
       +                dprint("registers not mapped\n");
       +                return;
       +        }
       +
       +        for (i = 1, rp = mach->reglist; rp->name; rp++, i++) {
       +                if ((rp->flags & RFLT)) {
       +                        if (c != 'R')
       +                                continue;
       +                        if (rp->format == '8' || rp->format == '3')
       +                                continue;
       +                }
       +                rget(correg, rp->name, &u);
       +                if(rp->format == 'Y')
       +                        dprint("%-8s %-20#llux", rp->name, (uvlong)u);
       +                else
       +                        dprint("%-8s %-12#lux", rp->name, (ulong)u);
       +                if ((i % 3) == 0) {
       +                        dprint("\n");
       +                        i = 0;
       +                }
       +        }
       +        if (i != 1)
       +                dprint("\n");
       +        dprint ("%s\n", mach->exc(cormap, correg));
       +        printpc();
       +}
   DIR diff --git a/src/cmd/db/runpcs.c b/src/cmd/db/runpcs.c
       t@@ -0,0 +1,205 @@
       +/*
       + *
       + *        debugger
       + *
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +BKPT *bkpthead;
       +
       +BOOL bpin;
       +
       +int pid;
       +int nnote;
       +int ending;
       +char note[NNOTE][ERRMAX];
       +
       +/* service routines for sub process control */
       +
       +int
       +runpcs(int runmode, int keepnote)
       +{
       +        int rc;
       +        BKPT *bkpt;
       +        ADDR x;
       +
       +        rc = 0;
       +        if (adrflg)
       +                rput(correg, mach->pc, dot);
       +        if(rget(correg, mach->pc, &dot) < 0)
       +                error("%r");
       +        flush();
       +        while (--loopcnt >= 0) {
       +                if(loopcnt != 0)
       +                        printpc();
       +                if (runmode == SINGLE) {
       +                        bkpt = scanbkpt(dot);
       +                        if (bkpt) {
       +                                switch(bkpt->flag){
       +                                case BKPTTMP:
       +                                        bkpt->flag = BKPTCLR;
       +                                        break;
       +                                case BKPTSKIP:
       +                                        bkpt->flag = BKPTSET;
       +                                        break;
       +                                }
       +                        }
       +                        runstep(dot, keepnote);
       +                } else {
       +                        if(rget(correg, mach->pc, &x) < 0)
       +                                error("%r");
       +                        if ((bkpt = scanbkpt(x)) != 0) {
       +                                execbkpt(bkpt, keepnote);
       +                                keepnote = 0;
       +                        }
       +                        setbp();
       +                        runrun(keepnote);
       +                }
       +                keepnote = 0;
       +                delbp();
       +                if(rget(correg, mach->pc, &dot) < 0)
       +                        error("%r");
       +                /* real note? */
       +                if (nnote > 0) {
       +                        keepnote = 1;
       +                        rc = 0;
       +                        continue;
       +                }
       +                bkpt = scanbkpt(dot);
       +                if(bkpt == 0){
       +                        keepnote = 0;
       +                        rc = 0;
       +                        continue;
       +                }
       +                /* breakpoint */
       +                if (bkpt->flag == BKPTTMP)
       +                        bkpt->flag = BKPTCLR;
       +                else if (bkpt->flag == BKPTSKIP) {
       +                        execbkpt(bkpt, keepnote);
       +                        keepnote = 0;
       +                        loopcnt++;        /* we didn't really stop */
       +                        continue;
       +                }
       +                else {
       +                        bkpt->flag = BKPTSKIP;
       +                        --bkpt->count;
       +                        if ((bkpt->comm[0] == EOR || command(bkpt->comm, ':') != 0)
       +                        &&  bkpt->count != 0) {
       +                                execbkpt(bkpt, keepnote);
       +                                keepnote = 0;
       +                                loopcnt++;
       +                                continue;
       +                        }
       +                        bkpt->count = bkpt->initcnt;
       +                }
       +                rc = 1;
       +        }
       +        return(rc);
       +}
       +
       +/*
       + * finish the process off;
       + * kill if still running
       + */
       +
       +void
       +endpcs(void)
       +{
       +        BKPT *bk;
       +
       +        if(ending)
       +                return;
       +        ending = 1;
       +        if (pid) {
       +                if(pcsactive){
       +                        killpcs();
       +                        pcsactive = 0;
       +                }
       +                pid=0;
       +                nnote=0;
       +                for (bk=bkpthead; bk; bk = bk->nxtbkpt)
       +                        if (bk->flag == BKPTTMP)
       +                                bk->flag = BKPTCLR;
       +                        else if (bk->flag != BKPTCLR)
       +                                bk->flag = BKPTSET;
       +        }
       +        bpin = FALSE;
       +        ending = 0;
       +}
       +
       +/*
       + * start up the program to be debugged in a child
       + */
       +
       +void
       +setup(void)
       +{
       +
       +        nnote = 0;
       +        startpcs();
       +        bpin = FALSE;
       +        pcsactive = 1;
       +}
       +
       +/*
       + * skip over a breakpoint:
       + * remove breakpoints, then single step
       + * so we can put it back
       + */
       +void
       +execbkpt(BKPT *bk, int keepnote)
       +{
       +        runstep(bk->loc, keepnote);
       +        bk->flag = BKPTSET;
       +}
       +
       +/*
       + * find the breakpoint at adr, if any
       + */
       +
       +BKPT *
       +scanbkpt(ADDR adr)
       +{
       +        BKPT *bk;
       +
       +        for (bk = bkpthead; bk; bk = bk->nxtbkpt)
       +                if (bk->flag != BKPTCLR && bk->loc == adr)
       +                        break;
       +        return(bk);
       +}
       +
       +/*
       + * remove all breakpoints from the process' address space
       + */
       +
       +void
       +delbp(void)
       +{
       +        BKPT *bk;
       +
       +        if (bpin == FALSE || pid == 0)
       +                return;
       +        for (bk = bkpthead; bk; bk = bk->nxtbkpt)
       +                if (bk->flag != BKPTCLR)
       +                        bkput(bk, 0);
       +        bpin = FALSE;
       +}
       +
       +/*
       + * install all the breakpoints
       + */
       +
       +void
       +setbp(void)
       +{
       +        BKPT *bk;
       +
       +        if (bpin == TRUE || pid == 0)
       +                return;
       +        for (bk = bkpthead; bk; bk = bk->nxtbkpt)
       +                if (bk->flag != BKPTCLR)
       +                        bkput(bk, 1);
       +        bpin = TRUE;
       +}
   DIR diff --git a/src/cmd/db/setup.c b/src/cmd/db/setup.c
       t@@ -0,0 +1,145 @@
       +/*
       + * init routines
       + */
       +#include "defs.h"
       +#include "fns.h"
       +
       +char        *symfil;
       +char        *corfil;
       +
       +Map        *symmap;
       +Map        *cormap;
       +Regs        *correg;
       +Map        *dotmap;
       +
       +void
       +setsym(void)
       +{
       +        if(symhdr && syminit(symhdr) < 0)
       +                dprint("syminit: %r\n");
       +/*
       +        Symbol s;
       +        if (mach->sbreg && lookup(0, mach->sbreg, &s) < 0)
       +                mach->sb = s.loc.addr;
       +*/
       +}
       +
       +void
       +setcor(void)
       +{
       +        unmapproc(cormap);
       +        unmapfile(corhdr, cormap);
       +        free(correg);
       +        correg = nil;
       +
       +        if (pid > 0) {
       +                if (mapproc(pid, cormap, &correg) < 0)
       +                        dprint("mapproc %d: %r\n", pid);
       +        } else {
       +                if (corhdr) {
       +                        if (mapfile(corhdr, 0, cormap, &correg) < 0)
       +                                dprint("mapfile %s: %r\n", corfil);
       +                } else
       +                        dprint("no core image\n");
       +        }
       +        kmsys();
       +        return;
       +}
       +
       +Map*
       +dumbmap(int fd)
       +{
       +        Map *dumb;
       +        Seg s;
       +
       +        dumb = allocmap();
       +        memset(&s, 0, sizeof s);
       +        s.fd = fd;
       +        s.base = 0;
       +        s.offset = 0;
       +        s.size = 0xFFFFFFFF;
       +        s.name = "data";
       +        s.file = "<dumb>";
       +        if(addseg(dumb, s) < 0){
       +                freemap(dumb);
       +                return nil;
       +        }
       +        if(mach == nil)
       +                mach = machcpu;
       +        return dumb;
       +}
       +
       +/*
       + * set up maps for a direct process image (/proc)
       + */
       +void
       +cmdmap(Map *map)
       +{
       +        int i;
       +        char name[MAXSYM];
       +
       +        rdc();
       +        readsym(name);
       +        i = findseg(map, name, nil);
       +        if (i < 0)        /* not found */
       +                error("Invalid map name");
       +
       +        if (expr(0)) {
       +        //        if (strcmp(name, "text") == 0)
       +        //                textseg(expv, &fhdr);
       +                map->seg[i].base = expv;
       +        } else
       +                error("Invalid base address"); 
       +        if (expr(0))
       +                map->seg[i].size = expv - map->seg[i].base;
       +        else
       +                error("Invalid end address"); 
       +        if (expr(0))
       +                map->seg[i].offset = expv; 
       +        else
       +                error("Invalid file offset"); 
       +/*
       +        if (rdc()=='?' && map == cormap) {
       +                if (fcor)
       +                        close(fcor);
       +                fcor=fsym;
       +                corfil = symfil;
       +                cormap = symmap;
       +        } else if (lastc == '/' && map == symmap) {
       +                if (fsym)
       +                        close(fsym);
       +                fsym=fcor;
       +                symfil=corfil;
       +                symmap=cormap;
       +        } else
       +                reread();
       +*/
       +}
       +
       +void
       +kmsys(void)
       +{
       +        int i;
       +
       +        i = findseg(symmap, "text", symfil);
       +        if (i >= 0) {
       +                symmap->seg[i].base = symmap->seg[i].base&~mach->ktmask;
       +                symmap->seg[i].size = -symmap->seg[i].base;
       +        }
       +        i = findseg(symmap, "data", symfil);
       +        if (i >= 0) {
       +                symmap->seg[i].base = symmap->seg[i].base&~mach->ktmask;
       +                symmap->seg[i].size = -symmap->seg[i].base;
       +        }
       +}
       +
       +void
       +attachprocess(void)
       +{
       +        if (!adrflg) {
       +                dprint("used pid$a\n");
       +                return;
       +        }
       +        pid = adrval;
       +        setcor();
       +}
   DIR diff --git a/src/cmd/db/trcrun.c b/src/cmd/db/trcrun.c
       t@@ -0,0 +1,288 @@
       +/*
       + * functions for running the debugged process
       + */
       +
       +#include "defs.h"
       +#include "fns.h"
       +
       +
       +int child;
       +int msgfd = -1;
       +int notefd = -1;
       +int pcspid = -1;
       +int pcsactive = 0;
       +
       +void
       +setpcs(void)
       +{
       +        char buf[128];
       +
       +        if(pid && pid != pcspid){
       +                if(msgfd >= 0){
       +                        close(msgfd);
       +                        msgfd = -1;
       +                }
       +                if(notefd >= 0){
       +                        close(notefd);
       +                        notefd = -1;
       +                }
       +                pcspid = -1;
       +                sprint(buf, "/proc/%d/ctl", pid);
       +                msgfd = open(buf, OWRITE);
       +                if(msgfd < 0)
       +                        error("can't open control file");
       +                sprint(buf, "/proc/%d/note", pid);
       +                notefd = open(buf, ORDWR);
       +                if(notefd < 0)
       +                        error("can't open note file");
       +                pcspid = pid;
       +        }
       +}
       +
       +void
       +msgpcs(char *msg)
       +{
       +        char err[ERRMAX];
       +
       +        setpcs();
       +        if(write(msgfd, msg, strlen(msg)) < 0 && !ending){
       +                errstr(err, sizeof err);
       +                if(strcmp(err, "interrupted") != 0)
       +                        endpcs();
       +                errors("can't write control file", err);
       +        }
       +}
       +
       +/*
       + * empty the note buffer and toss pending breakpoint notes
       + */
       +void
       +unloadnote(void)
       +{
       +        char err[ERRMAX];
       +
       +        setpcs();
       +        for(; nnote<NNOTE; nnote++){
       +                switch(read(notefd, note[nnote], sizeof note[nnote])){
       +                case -1:
       +                        errstr(err, sizeof err);
       +                        if(strcmp(err, "interrupted") != 0)
       +                                endpcs();
       +                        errors("can't read note file", err);
       +                case 0:
       +                        return;
       +                }
       +                note[nnote][ERRMAX-1] = '\0';
       +                if(strncmp(note[nnote], "sys: breakpoint", 15) == 0)
       +                        --nnote;
       +        }
       +}
       +
       +/*
       + * reload the note buffer
       + */
       +void
       +loadnote(void)
       +{
       +        int i;
       +        char err[ERRMAX];
       +
       +        setpcs();
       +        for(i=0; i<nnote; i++){
       +                if(write(notefd, note[i], strlen(note[i])) < 0){
       +                        errstr(err, sizeof err);
       +                        if(strcmp(err, "interrupted") != 0)
       +                                endpcs();
       +                        errors("can't write note file", err);
       +                }
       +        }
       +        nnote = 0;
       +}
       +
       +void
       +notes(void)
       +{
       +        int n;
       +
       +        if(nnote == 0)
       +                return;
       +        dprint("notes:\n");
       +        for(n=0; n<nnote; n++)
       +                dprint("%d:\t%s\n", n, note[n]);
       +}
       +
       +void
       +killpcs(void)
       +{
       +        msgpcs("kill");
       +}
       +
       +void
       +grab(void)
       +{
       +        flush();
       +        msgpcs("stop");
       +        bpwait();
       +}
       +
       +void
       +ungrab(void)
       +{
       +        msgpcs("start");
       +}
       +
       +void
       +doexec(void)
       +{
       +        char *argl[MAXARG];
       +        char args[LINSIZ];
       +        char *p;
       +        char **ap;
       +        char *thisarg;
       +
       +        ap = argl;
       +        p = args;
       +        *ap++ = symfil;
       +        for (rdc(); lastc != EOR;) {
       +                thisarg = p;
       +                if (lastc == '<' || lastc == '>') {
       +                        *p++ = lastc;
       +                        rdc();
       +                }
       +                while (lastc != EOR && lastc != SPC && lastc != TB) {
       +                        *p++ = lastc;
       +                        readchar();
       +                }
       +                if (lastc == SPC || lastc == TB)
       +                        rdc();
       +                *p++ = 0;
       +                if (*thisarg == '<') {
       +                        close(0);
       +                        if (open(&thisarg[1], OREAD) < 0) {
       +                                print("%s: cannot open\n", &thisarg[1]);
       +                                _exits(0);
       +                        }
       +                }
       +                else if (*thisarg == '>') {
       +                        close(1);
       +                        if (create(&thisarg[1], OWRITE, 0666) < 0) {
       +                                print("%s: cannot create\n", &thisarg[1]);
       +                                _exits(0);
       +                        }
       +                }
       +                else
       +                        *ap++ = thisarg;
       +        }
       +        *ap = 0;
       +        exec(symfil, argl);
       +        perror(symfil);
       +}
       +
       +char        procname[100];
       +
       +void
       +startpcs(void)
       +{
       +        if ((pid = fork()) == 0) {
       +                pid = getpid();
       +                msgpcs("hang");
       +                doexec();
       +                exits(0);
       +        }
       +
       +        if (pid == -1)
       +                error("can't fork");
       +        child++;
       +        sprint(procname, "/proc/%d/mem", pid);
       +        corfil = procname;
       +        msgpcs("waitstop");
       +        bpwait();
       +        if (adrflg)
       +                rput(correg, mach->pc, adrval);
       +        while (rdc() != EOR)
       +                ;
       +        reread();
       +}
       +
       +void
       +runstep(ulong loc, int keepnote)
       +{
       +        int nfoll;
       +        ulong foll[3];
       +        BKPT bkpt[3];
       +        int i;
       +
       +        if(mach->foll == 0){
       +                dprint("stepping unimplemented; assuming not a branch\n");
       +                nfoll = 1;
       +                foll[0] = loc+mach->pcquant;
       +        }else {
       +                nfoll = mach->foll(cormap, correg, loc, foll);
       +                if (nfoll < 0)
       +                        error("%r");
       +        }
       +        memset(bkpt, 0, sizeof bkpt);
       +        for(i=0; i<nfoll; i++){
       +                if(foll[i] == loc)
       +                        error("can't single step: next instruction is dot");
       +                bkpt[i].loc = foll[i];
       +                bkput(&bkpt[i], 1);
       +        }
       +        runrun(keepnote);
       +        for(i=0; i<nfoll; i++)
       +                bkput(&bkpt[i], 0);
       +}
       +
       +void
       +bpwait(void)
       +{
       +        setcor();
       +        unloadnote();
       +}
       +
       +void
       +runrun(int keepnote)
       +{
       +        int on;
       +
       +        on = nnote;
       +        unloadnote();
       +        if(on != nnote){
       +                notes();
       +                error("not running: new notes pending");
       +        }
       +        if(keepnote)
       +                loadnote();
       +        else
       +                nnote = 0;
       +        flush();
       +        msgpcs("startstop");
       +        bpwait();
       +}
       +
       +void
       +bkput(BKPT *bp, int install)
       +{
       +        char buf[256];
       +        ulong loc;
       +        int ret;
       +
       +        errstr(buf, sizeof buf);
       +/*
       +        if(mach->bpfix)
       +                loc = (*mach->bpfix)(bp->loc);
       +        else
       +*/
       +        loc = bp->loc;
       +        if(install){
       +                ret = get1(cormap, loc, bp->save, mach->bpsize);
       +                if (ret > 0)
       +                        ret = put1(cormap, loc, mach->bpinst, mach->bpsize);
       +        }else
       +                ret = put1(cormap, loc, bp->save, mach->bpsize);
       +        if(ret < 0){
       +                sprint(buf, "can't set breakpoint at %#llux: %r", bp->loc);
       +                print(buf);
       +                read(0, buf, 100);
       +        }
       +}