137da2899SCharles.Forsyth #include "dat.h"
237da2899SCharles.Forsyth #include "fns.h"
337da2899SCharles.Forsyth #include "error.h"
437da2899SCharles.Forsyth #include <interp.h>
537da2899SCharles.Forsyth #include <isa.h>
637da2899SCharles.Forsyth #include "runt.h"
737da2899SCharles.Forsyth
837da2899SCharles.Forsyth /*
937da2899SCharles.Forsyth * Enable the heap device for environments that allow debugging =>
1037da2899SCharles.Forsyth * Must be 1 for a production environment.
1137da2899SCharles.Forsyth */
1237da2899SCharles.Forsyth int SECURE = 0;
1337da2899SCharles.Forsyth
1437da2899SCharles.Forsyth enum
1537da2899SCharles.Forsyth {
1637da2899SCharles.Forsyth Qdir,
1737da2899SCharles.Forsyth Qctl,
1837da2899SCharles.Forsyth Qdbgctl,
1937da2899SCharles.Forsyth Qheap,
2037da2899SCharles.Forsyth Qns,
2137da2899SCharles.Forsyth Qnsgrp,
2237da2899SCharles.Forsyth Qpgrp,
2337da2899SCharles.Forsyth Qstack,
2437da2899SCharles.Forsyth Qstatus,
2537da2899SCharles.Forsyth Qtext,
2637da2899SCharles.Forsyth Qwait,
2737da2899SCharles.Forsyth Qfd,
2837da2899SCharles.Forsyth Qexception,
2937da2899SCharles.Forsyth };
3037da2899SCharles.Forsyth
3137da2899SCharles.Forsyth /*
3237da2899SCharles.Forsyth * must be in same order as enum
3337da2899SCharles.Forsyth */
3437da2899SCharles.Forsyth Dirtab progdir[] =
3537da2899SCharles.Forsyth {
3637da2899SCharles.Forsyth "ctl", {Qctl}, 0, 0200,
3737da2899SCharles.Forsyth "dbgctl", {Qdbgctl}, 0, 0600,
3837da2899SCharles.Forsyth "heap", {Qheap}, 0, 0600,
3937da2899SCharles.Forsyth "ns", {Qns}, 0, 0400,
4037da2899SCharles.Forsyth "nsgrp", {Qnsgrp}, 0, 0444,
4137da2899SCharles.Forsyth "pgrp", {Qpgrp}, 0, 0444,
4237da2899SCharles.Forsyth "stack", {Qstack}, 0, 0400,
4337da2899SCharles.Forsyth "status", {Qstatus}, 0, 0444,
4437da2899SCharles.Forsyth "text", {Qtext}, 0, 0000,
4537da2899SCharles.Forsyth "wait", {Qwait}, 0, 0400,
4637da2899SCharles.Forsyth "fd", {Qfd}, 0, 0400,
4737da2899SCharles.Forsyth "exception", {Qexception}, 0, 0400,
4837da2899SCharles.Forsyth };
4937da2899SCharles.Forsyth
5037da2899SCharles.Forsyth enum
5137da2899SCharles.Forsyth {
5237da2899SCharles.Forsyth CMkill,
5337da2899SCharles.Forsyth CMkillgrp,
5437da2899SCharles.Forsyth CMrestricted,
5537da2899SCharles.Forsyth CMexceptions,
5637da2899SCharles.Forsyth CMprivate
5737da2899SCharles.Forsyth };
5837da2899SCharles.Forsyth
5937da2899SCharles.Forsyth static
6037da2899SCharles.Forsyth Cmdtab progcmd[] = {
6137da2899SCharles.Forsyth CMkill, "kill", 1,
6237da2899SCharles.Forsyth CMkillgrp, "killgrp", 1,
6337da2899SCharles.Forsyth CMrestricted, "restricted", 1,
6437da2899SCharles.Forsyth CMexceptions, "exceptions", 2,
6537da2899SCharles.Forsyth CMprivate, "private", 1,
6637da2899SCharles.Forsyth };
6737da2899SCharles.Forsyth
6837da2899SCharles.Forsyth enum
6937da2899SCharles.Forsyth {
7037da2899SCharles.Forsyth CDstep,
7137da2899SCharles.Forsyth CDtoret,
7237da2899SCharles.Forsyth CDcont,
7337da2899SCharles.Forsyth CDstart,
7437da2899SCharles.Forsyth CDstop,
7537da2899SCharles.Forsyth CDunstop,
7637da2899SCharles.Forsyth CDmaim,
7737da2899SCharles.Forsyth CDbpt
7837da2899SCharles.Forsyth };
7937da2899SCharles.Forsyth
8037da2899SCharles.Forsyth static
8137da2899SCharles.Forsyth Cmdtab progdbgcmd[] = {
8237da2899SCharles.Forsyth CDstep, "step", 0, /* known below to be first, to cope with stepN */
8337da2899SCharles.Forsyth CDtoret, "toret", 1,
8437da2899SCharles.Forsyth CDcont, "cont", 1,
8537da2899SCharles.Forsyth CDstart, "start", 1,
8637da2899SCharles.Forsyth CDstop, "stop", 1,
8737da2899SCharles.Forsyth CDunstop, "unstop", 1,
8837da2899SCharles.Forsyth CDmaim, "maim", 1,
8937da2899SCharles.Forsyth CDbpt, "bpt", 4,
9037da2899SCharles.Forsyth };
9137da2899SCharles.Forsyth
9237da2899SCharles.Forsyth typedef struct Heapqry Heapqry;
9337da2899SCharles.Forsyth struct Heapqry
9437da2899SCharles.Forsyth {
9537da2899SCharles.Forsyth char fmt;
9637da2899SCharles.Forsyth ulong addr;
9737da2899SCharles.Forsyth ulong module;
9837da2899SCharles.Forsyth int count;
9937da2899SCharles.Forsyth };
10037da2899SCharles.Forsyth
10137da2899SCharles.Forsyth typedef struct Bpt Bpt;
10237da2899SCharles.Forsyth
10337da2899SCharles.Forsyth struct Bpt
10437da2899SCharles.Forsyth {
10537da2899SCharles.Forsyth Bpt *next;
10637da2899SCharles.Forsyth int pc;
10737da2899SCharles.Forsyth char *file;
10837da2899SCharles.Forsyth char path[1];
10937da2899SCharles.Forsyth };
11037da2899SCharles.Forsyth
11137da2899SCharles.Forsyth typedef struct Progctl Progctl;
11237da2899SCharles.Forsyth struct Progctl
11337da2899SCharles.Forsyth {
11437da2899SCharles.Forsyth Rendez r;
11537da2899SCharles.Forsyth int ref;
11637da2899SCharles.Forsyth Proc *debugger; /* waiting for dbgxec */
11737da2899SCharles.Forsyth char *msg; /* reply from dbgxec */
11837da2899SCharles.Forsyth int step; /* instructions to try */
11937da2899SCharles.Forsyth int stop; /* stop running the program */
12037da2899SCharles.Forsyth Bpt* bpts; /* active breakpoints */
12137da2899SCharles.Forsyth Queue* q; /* status queue */
12237da2899SCharles.Forsyth };
12337da2899SCharles.Forsyth
12437da2899SCharles.Forsyth #define QSHIFT 4 /* location in qid of pid */
12537da2899SCharles.Forsyth #define QID(q) (((ulong)(q).path&0x0000000F)>>0)
12637da2899SCharles.Forsyth #define QPID(pid) (((pid)<<QSHIFT))
12737da2899SCharles.Forsyth #define PID(q) ((q).vers)
12837da2899SCharles.Forsyth #define PATH(q) ((ulong)(q).path&~((1<<QSHIFT)-1))
12937da2899SCharles.Forsyth
13037da2899SCharles.Forsyth static char *progstate[] = /* must correspond to include/interp.h */
13137da2899SCharles.Forsyth {
13237da2899SCharles.Forsyth "alt", /* blocked in alt instruction */
13337da2899SCharles.Forsyth "send", /* waiting to send */
13437da2899SCharles.Forsyth "recv", /* waiting to recv */
13537da2899SCharles.Forsyth "debug", /* debugged */
13637da2899SCharles.Forsyth "ready", /* ready to be scheduled */
13737da2899SCharles.Forsyth "release", /* interpreter released */
13837da2899SCharles.Forsyth "exiting", /* exit because of kill or error */
13937da2899SCharles.Forsyth "broken", /* thread crashed */
14037da2899SCharles.Forsyth };
14137da2899SCharles.Forsyth
14237da2899SCharles.Forsyth static void dbgstep(Progctl*, Prog*, int);
14337da2899SCharles.Forsyth static void dbgstart(Prog*);
14437da2899SCharles.Forsyth static void freebpts(Bpt*);
14537da2899SCharles.Forsyth static Bpt* delbpt(Bpt*, char*, int);
14637da2899SCharles.Forsyth static Bpt* setbpt(Bpt*, char*, int);
14737da2899SCharles.Forsyth static void mntscan(Mntwalk*, Pgrp*);
14837da2899SCharles.Forsyth extern Type *Trdchan;
14937da2899SCharles.Forsyth extern Type *Twrchan;
15037da2899SCharles.Forsyth extern Module* modules;
15137da2899SCharles.Forsyth static char Emisalign[] = "misaligned address";
15237da2899SCharles.Forsyth
15337da2899SCharles.Forsyth static int
proggen(Chan * c,char * name,Dirtab * tab,int ntab,int s,Dir * dp)15437da2899SCharles.Forsyth proggen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
15537da2899SCharles.Forsyth {
15637da2899SCharles.Forsyth Qid qid;
15737da2899SCharles.Forsyth Prog *p;
15837da2899SCharles.Forsyth char *e;
15937da2899SCharles.Forsyth Osenv *o;
16037da2899SCharles.Forsyth ulong pid, path, perm, len;
16137da2899SCharles.Forsyth
16237da2899SCharles.Forsyth USED(ntab);
16337da2899SCharles.Forsyth
16437da2899SCharles.Forsyth if(s == DEVDOTDOT){
16537da2899SCharles.Forsyth mkqid(&qid, Qdir, 0, QTDIR);
16637da2899SCharles.Forsyth devdir(c, qid, "#p", 0, eve, DMDIR|0555, dp);
16737da2899SCharles.Forsyth return 1;
16837da2899SCharles.Forsyth }
16937da2899SCharles.Forsyth
17037da2899SCharles.Forsyth if((ulong)c->qid.path == Qdir) {
17137da2899SCharles.Forsyth if(name != nil){
17237da2899SCharles.Forsyth /* ignore s and use name to find pid */
17337da2899SCharles.Forsyth pid = strtoul(name, &e, 0);
17437da2899SCharles.Forsyth if(pid == 0 || *e != '\0')
17537da2899SCharles.Forsyth return -1;
17637da2899SCharles.Forsyth acquire();
17737da2899SCharles.Forsyth p = progpid(pid);
17837da2899SCharles.Forsyth if(p == nil){
17937da2899SCharles.Forsyth release();
18037da2899SCharles.Forsyth return -1;
18137da2899SCharles.Forsyth }
18237da2899SCharles.Forsyth }else{
18337da2899SCharles.Forsyth acquire();
18437da2899SCharles.Forsyth p = progn(s);
18537da2899SCharles.Forsyth if(p == nil) {
18637da2899SCharles.Forsyth release();
18737da2899SCharles.Forsyth return -1;
18837da2899SCharles.Forsyth }
18937da2899SCharles.Forsyth pid = p->pid;
19037da2899SCharles.Forsyth }
19137da2899SCharles.Forsyth o = p->osenv;
19237da2899SCharles.Forsyth sprint(up->genbuf, "%lud", pid);
19337da2899SCharles.Forsyth if(name != nil && strcmp(name, up->genbuf) != 0){
19437da2899SCharles.Forsyth release();
19537da2899SCharles.Forsyth return -1;
19637da2899SCharles.Forsyth }
19737da2899SCharles.Forsyth mkqid(&qid, pid<<QSHIFT, pid, QTDIR);
19837da2899SCharles.Forsyth devdir(c, qid, up->genbuf, 0, o->user, DMDIR|0555, dp);
19937da2899SCharles.Forsyth release();
20037da2899SCharles.Forsyth return 1;
20137da2899SCharles.Forsyth }
20237da2899SCharles.Forsyth
20337da2899SCharles.Forsyth if(s >= nelem(progdir))
20437da2899SCharles.Forsyth return -1;
20537da2899SCharles.Forsyth tab = &progdir[s];
20637da2899SCharles.Forsyth path = PATH(c->qid);
20737da2899SCharles.Forsyth
20837da2899SCharles.Forsyth acquire();
20937da2899SCharles.Forsyth p = progpid(PID(c->qid));
21037da2899SCharles.Forsyth if(p == nil) {
21137da2899SCharles.Forsyth release();
21237da2899SCharles.Forsyth return -1;
21337da2899SCharles.Forsyth }
21437da2899SCharles.Forsyth
21537da2899SCharles.Forsyth o = p->osenv;
21637da2899SCharles.Forsyth
21737da2899SCharles.Forsyth perm = tab->perm;
21837da2899SCharles.Forsyth if((perm & 7) == 0)
21937da2899SCharles.Forsyth perm = (perm|(perm>>3)|(perm>>6)) & o->pgrp->progmode;
22037da2899SCharles.Forsyth
22137da2899SCharles.Forsyth len = tab->length;
22237da2899SCharles.Forsyth mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
22337da2899SCharles.Forsyth devdir(c, qid, tab->name, len, o->user, perm, dp);
22437da2899SCharles.Forsyth release();
22537da2899SCharles.Forsyth return 1;
22637da2899SCharles.Forsyth }
22737da2899SCharles.Forsyth
22837da2899SCharles.Forsyth static Chan*
progattach(char * spec)22937da2899SCharles.Forsyth progattach(char *spec)
23037da2899SCharles.Forsyth {
23137da2899SCharles.Forsyth return devattach('p', spec);
23237da2899SCharles.Forsyth }
23337da2899SCharles.Forsyth
23437da2899SCharles.Forsyth static Walkqid*
progwalk(Chan * c,Chan * nc,char ** name,int nname)23537da2899SCharles.Forsyth progwalk(Chan *c, Chan *nc, char **name, int nname)
23637da2899SCharles.Forsyth {
23737da2899SCharles.Forsyth return devwalk(c, nc, name, nname, 0, 0, proggen);
23837da2899SCharles.Forsyth }
23937da2899SCharles.Forsyth
24037da2899SCharles.Forsyth static int
progstat(Chan * c,uchar * db,int n)24137da2899SCharles.Forsyth progstat(Chan *c, uchar *db, int n)
24237da2899SCharles.Forsyth {
24337da2899SCharles.Forsyth return devstat(c, db, n, 0, 0, proggen);
24437da2899SCharles.Forsyth }
24537da2899SCharles.Forsyth
24637da2899SCharles.Forsyth static Chan*
progopen(Chan * c,int omode)24737da2899SCharles.Forsyth progopen(Chan *c, int omode)
24837da2899SCharles.Forsyth {
24937da2899SCharles.Forsyth Prog *p;
25037da2899SCharles.Forsyth Osenv *o;
25137da2899SCharles.Forsyth Progctl *ctl;
25237da2899SCharles.Forsyth int perm;
25337da2899SCharles.Forsyth
25437da2899SCharles.Forsyth if(c->qid.type & QTDIR)
25537da2899SCharles.Forsyth return devopen(c, omode, 0, 0, proggen);
25637da2899SCharles.Forsyth
25737da2899SCharles.Forsyth acquire();
25837da2899SCharles.Forsyth if (waserror()) {
25937da2899SCharles.Forsyth release();
26037da2899SCharles.Forsyth nexterror();
26137da2899SCharles.Forsyth }
26237da2899SCharles.Forsyth p = progpid(PID(c->qid));
26337da2899SCharles.Forsyth if(p == nil)
26437da2899SCharles.Forsyth error(Ethread);
26537da2899SCharles.Forsyth o = p->osenv;
26637da2899SCharles.Forsyth perm = progdir[QID(c->qid)-1].perm;
26737da2899SCharles.Forsyth if((perm & 7) == 0)
26837da2899SCharles.Forsyth perm = (perm|(perm>>3)|(perm>>6)) & o->pgrp->progmode;
26937da2899SCharles.Forsyth devpermcheck(o->user, perm, omode);
27037da2899SCharles.Forsyth omode = openmode(omode);
27137da2899SCharles.Forsyth
27237da2899SCharles.Forsyth switch(QID(c->qid)){
27337da2899SCharles.Forsyth default:
27437da2899SCharles.Forsyth error(Egreg);
27537da2899SCharles.Forsyth case Qnsgrp:
27637da2899SCharles.Forsyth case Qpgrp:
27737da2899SCharles.Forsyth case Qtext:
27837da2899SCharles.Forsyth case Qstatus:
27937da2899SCharles.Forsyth case Qstack:
28037da2899SCharles.Forsyth case Qctl:
28137da2899SCharles.Forsyth case Qfd:
28237da2899SCharles.Forsyth case Qexception:
28337da2899SCharles.Forsyth break;
28437da2899SCharles.Forsyth case Qwait:
28537da2899SCharles.Forsyth c->aux = qopen(1024, Qmsg, nil, nil);
28637da2899SCharles.Forsyth if(c->aux == nil)
28737da2899SCharles.Forsyth error(Enomem);
28837da2899SCharles.Forsyth o->childq = c->aux;
28937da2899SCharles.Forsyth break;
29037da2899SCharles.Forsyth case Qns:
29137da2899SCharles.Forsyth c->aux = malloc(sizeof(Mntwalk));
29237da2899SCharles.Forsyth if(c->aux == nil)
29337da2899SCharles.Forsyth error(Enomem);
29437da2899SCharles.Forsyth break;
29537da2899SCharles.Forsyth case Qheap:
296*cb6deeccSforsyth if(SECURE || p->group->flags&Pprivatemem || omode != ORDWR)
29737da2899SCharles.Forsyth error(Eperm);
29837da2899SCharles.Forsyth c->aux = malloc(sizeof(Heapqry));
29937da2899SCharles.Forsyth if(c->aux == nil)
30037da2899SCharles.Forsyth error(Enomem);
30137da2899SCharles.Forsyth break;
30237da2899SCharles.Forsyth case Qdbgctl:
303*cb6deeccSforsyth if(SECURE || p->group->flags&Pprivatemem || omode != ORDWR)
30437da2899SCharles.Forsyth error(Eperm);
30537da2899SCharles.Forsyth ctl = malloc(sizeof(Progctl));
30637da2899SCharles.Forsyth if(ctl == nil)
30737da2899SCharles.Forsyth error(Enomem);
30837da2899SCharles.Forsyth ctl->q = qopen(1024, Qmsg, nil, nil);
30937da2899SCharles.Forsyth if(ctl->q == nil) {
31037da2899SCharles.Forsyth free(ctl);
31137da2899SCharles.Forsyth error(Enomem);
31237da2899SCharles.Forsyth }
31337da2899SCharles.Forsyth ctl->bpts = nil;
31437da2899SCharles.Forsyth ctl->ref = 1;
31537da2899SCharles.Forsyth c->aux = ctl;
31637da2899SCharles.Forsyth break;
31737da2899SCharles.Forsyth }
31837da2899SCharles.Forsyth if(p->state != Pexiting)
31937da2899SCharles.Forsyth c->qid.vers = p->pid;
32037da2899SCharles.Forsyth
32137da2899SCharles.Forsyth poperror();
32237da2899SCharles.Forsyth release();
32337da2899SCharles.Forsyth c->offset = 0;
32437da2899SCharles.Forsyth c->mode = omode;
32537da2899SCharles.Forsyth c->flag |= COPEN;
32637da2899SCharles.Forsyth return c;
32737da2899SCharles.Forsyth }
32837da2899SCharles.Forsyth
32937da2899SCharles.Forsyth static int
progwstat(Chan * c,uchar * db,int n)33037da2899SCharles.Forsyth progwstat(Chan *c, uchar *db, int n)
33137da2899SCharles.Forsyth {
33237da2899SCharles.Forsyth Dir d;
33337da2899SCharles.Forsyth Prog *p;
33437da2899SCharles.Forsyth char *u;
33537da2899SCharles.Forsyth Osenv *o;
33637da2899SCharles.Forsyth
33737da2899SCharles.Forsyth if(c->qid.type&QTDIR)
33837da2899SCharles.Forsyth error(Eperm);
33937da2899SCharles.Forsyth acquire();
34037da2899SCharles.Forsyth p = progpid(PID(c->qid));
34137da2899SCharles.Forsyth if(p == nil) {
34237da2899SCharles.Forsyth release();
34337da2899SCharles.Forsyth error(Ethread);
34437da2899SCharles.Forsyth }
34537da2899SCharles.Forsyth
34637da2899SCharles.Forsyth u = up->env->user;
34737da2899SCharles.Forsyth o = p->osenv;
34837da2899SCharles.Forsyth if(strcmp(u, o->user) != 0 && strcmp(u, eve) != 0) {
34937da2899SCharles.Forsyth release();
35037da2899SCharles.Forsyth error(Eperm);
35137da2899SCharles.Forsyth }
35237da2899SCharles.Forsyth
35337da2899SCharles.Forsyth n = convM2D(db, n, &d, nil);
35437da2899SCharles.Forsyth if(n == 0){
35537da2899SCharles.Forsyth release();
35637da2899SCharles.Forsyth error(Eshortstat);
35737da2899SCharles.Forsyth }
35837da2899SCharles.Forsyth if(d.mode != ~0UL)
35937da2899SCharles.Forsyth o->pgrp->progmode = d.mode&0777;
36037da2899SCharles.Forsyth release();
36137da2899SCharles.Forsyth return n;
36237da2899SCharles.Forsyth }
36337da2899SCharles.Forsyth
36437da2899SCharles.Forsyth static void
closedbgctl(Progctl * ctl,Prog * p)36537da2899SCharles.Forsyth closedbgctl(Progctl *ctl, Prog *p)
36637da2899SCharles.Forsyth {
36737da2899SCharles.Forsyth Osenv *o;
36837da2899SCharles.Forsyth
36937da2899SCharles.Forsyth if(ctl->ref-- > 1)
37037da2899SCharles.Forsyth return;
37137da2899SCharles.Forsyth freebpts(ctl->bpts);
37237da2899SCharles.Forsyth if(p != nil){
37337da2899SCharles.Forsyth o = p->osenv;
37437da2899SCharles.Forsyth if(o->debug == ctl){
37537da2899SCharles.Forsyth o->debug = nil;
37637da2899SCharles.Forsyth p->xec = xec;
37737da2899SCharles.Forsyth }
37837da2899SCharles.Forsyth }
37937da2899SCharles.Forsyth qfree(ctl->q);
38037da2899SCharles.Forsyth free(ctl);
38137da2899SCharles.Forsyth }
38237da2899SCharles.Forsyth
38337da2899SCharles.Forsyth static void
progclose(Chan * c)38437da2899SCharles.Forsyth progclose(Chan *c)
38537da2899SCharles.Forsyth {
38637da2899SCharles.Forsyth int i;
38737da2899SCharles.Forsyth Prog *f;
38837da2899SCharles.Forsyth Osenv *o;
38937da2899SCharles.Forsyth Progctl *ctl;
39037da2899SCharles.Forsyth
39137da2899SCharles.Forsyth switch(QID(c->qid)) {
39237da2899SCharles.Forsyth case Qns:
39337da2899SCharles.Forsyth case Qheap:
39437da2899SCharles.Forsyth free(c->aux);
39537da2899SCharles.Forsyth break;
39637da2899SCharles.Forsyth case Qdbgctl:
39737da2899SCharles.Forsyth if((c->flag & COPEN) == 0)
39837da2899SCharles.Forsyth return;
39937da2899SCharles.Forsyth ctl = c->aux;
40037da2899SCharles.Forsyth acquire();
40137da2899SCharles.Forsyth closedbgctl(ctl, progpid(PID(c->qid)));
40237da2899SCharles.Forsyth release();
40337da2899SCharles.Forsyth break;
40437da2899SCharles.Forsyth case Qwait:
40537da2899SCharles.Forsyth acquire();
40637da2899SCharles.Forsyth i = 0;
40737da2899SCharles.Forsyth for(;;) {
40837da2899SCharles.Forsyth f = progn(i++);
40937da2899SCharles.Forsyth if(f == nil)
41037da2899SCharles.Forsyth break;
41137da2899SCharles.Forsyth o = f->osenv;
41237da2899SCharles.Forsyth if(o->waitq == c->aux)
41337da2899SCharles.Forsyth o->waitq = nil;
41437da2899SCharles.Forsyth if(o->childq == c->aux)
41537da2899SCharles.Forsyth o->childq = nil;
41637da2899SCharles.Forsyth }
41737da2899SCharles.Forsyth release();
41837da2899SCharles.Forsyth qfree(c->aux);
41937da2899SCharles.Forsyth }
42037da2899SCharles.Forsyth }
42137da2899SCharles.Forsyth
42237da2899SCharles.Forsyth static int
progsize(Prog * p)42337da2899SCharles.Forsyth progsize(Prog *p)
42437da2899SCharles.Forsyth {
42537da2899SCharles.Forsyth int size;
42637da2899SCharles.Forsyth Frame *f;
42737da2899SCharles.Forsyth uchar *fp;
42837da2899SCharles.Forsyth Modlink *m;
42937da2899SCharles.Forsyth
43037da2899SCharles.Forsyth m = p->R.M;
43137da2899SCharles.Forsyth size = 0;
43237da2899SCharles.Forsyth if(m->MP != H)
43337da2899SCharles.Forsyth size += hmsize(D2H(m->MP));
43437da2899SCharles.Forsyth if(m->prog != nil)
43537da2899SCharles.Forsyth size += msize(m->prog);
43637da2899SCharles.Forsyth
43737da2899SCharles.Forsyth fp = p->R.FP;
43837da2899SCharles.Forsyth while(fp != nil) {
43937da2899SCharles.Forsyth f = (Frame*)fp;
44037da2899SCharles.Forsyth fp = f->fp;
44137da2899SCharles.Forsyth if(f->mr != nil) {
44237da2899SCharles.Forsyth if(f->mr->MP != H)
44337da2899SCharles.Forsyth size += hmsize(D2H(f->mr->MP));
44437da2899SCharles.Forsyth if(f->mr->prog != nil)
44537da2899SCharles.Forsyth size += msize(f->mr->prog);
44637da2899SCharles.Forsyth }
44737da2899SCharles.Forsyth if(f->t == nil)
44837da2899SCharles.Forsyth size += msize(SEXTYPE(f));
44937da2899SCharles.Forsyth }
45037da2899SCharles.Forsyth return size/1024;
45137da2899SCharles.Forsyth }
45237da2899SCharles.Forsyth
45337da2899SCharles.Forsyth static long
progoffset(long offset,char * va,int * np)45437da2899SCharles.Forsyth progoffset(long offset, char *va, int *np)
45537da2899SCharles.Forsyth {
45637da2899SCharles.Forsyth if(offset > 0) {
45737da2899SCharles.Forsyth offset -= *np;
45837da2899SCharles.Forsyth if(offset < 0) {
45937da2899SCharles.Forsyth memmove(va, va+*np+offset, -offset);
46037da2899SCharles.Forsyth *np = -offset;
46137da2899SCharles.Forsyth }
46237da2899SCharles.Forsyth else
46337da2899SCharles.Forsyth *np = 0;
46437da2899SCharles.Forsyth }
46537da2899SCharles.Forsyth return offset;
46637da2899SCharles.Forsyth }
46737da2899SCharles.Forsyth
46837da2899SCharles.Forsyth static int
progqidwidth(Chan * c)46937da2899SCharles.Forsyth progqidwidth(Chan *c)
47037da2899SCharles.Forsyth {
47137da2899SCharles.Forsyth char buf[32];
47237da2899SCharles.Forsyth
47337da2899SCharles.Forsyth return sprint(buf, "%lud", c->qid.vers);
47437da2899SCharles.Forsyth }
47537da2899SCharles.Forsyth
47637da2899SCharles.Forsyth int
progfdprint(Chan * c,int fd,int w,char * s,int ns)47737da2899SCharles.Forsyth progfdprint(Chan *c, int fd, int w, char *s, int ns)
47837da2899SCharles.Forsyth {
47937da2899SCharles.Forsyth int n;
48037da2899SCharles.Forsyth
48137da2899SCharles.Forsyth if(w == 0)
48237da2899SCharles.Forsyth w = progqidwidth(c);
48337da2899SCharles.Forsyth n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
48437da2899SCharles.Forsyth fd,
48537da2899SCharles.Forsyth &"r w rw"[(c->mode&3)<<1],
48637da2899SCharles.Forsyth devtab[c->type]->dc, c->dev,
48737da2899SCharles.Forsyth c->qid.path, w, c->qid.vers, c->qid.type,
48837da2899SCharles.Forsyth c->iounit, c->offset, c->name->s);
48937da2899SCharles.Forsyth return n;
49037da2899SCharles.Forsyth }
49137da2899SCharles.Forsyth
49237da2899SCharles.Forsyth static int
progfds(Osenv * o,char * va,int count,long offset)49337da2899SCharles.Forsyth progfds(Osenv *o, char *va, int count, long offset)
49437da2899SCharles.Forsyth {
49537da2899SCharles.Forsyth Fgrp *f;
49637da2899SCharles.Forsyth Chan *c;
49737da2899SCharles.Forsyth int n, i, w, ww;
49837da2899SCharles.Forsyth
49937da2899SCharles.Forsyth f = o->fgrp; /* f is not locked because we've acquired */
50037da2899SCharles.Forsyth n = readstr(0, va, count, o->pgrp->dot->name->s);
50137da2899SCharles.Forsyth n += snprint(va+n, count-n, "\n");
50237da2899SCharles.Forsyth offset = progoffset(offset, va, &n);
50337da2899SCharles.Forsyth /* compute width of qid.path */
50437da2899SCharles.Forsyth w = 0;
50537da2899SCharles.Forsyth for(i = 0; i <= f->maxfd; i++) {
50637da2899SCharles.Forsyth c = f->fd[i];
50737da2899SCharles.Forsyth if(c == nil)
50837da2899SCharles.Forsyth continue;
50937da2899SCharles.Forsyth ww = progqidwidth(c);
51037da2899SCharles.Forsyth if(ww > w)
51137da2899SCharles.Forsyth w = ww;
51237da2899SCharles.Forsyth }
51337da2899SCharles.Forsyth for(i = 0; i <= f->maxfd; i++) {
51437da2899SCharles.Forsyth c = f->fd[i];
51537da2899SCharles.Forsyth if(c == nil)
51637da2899SCharles.Forsyth continue;
51737da2899SCharles.Forsyth n += progfdprint(c, i, w, va+n, count-n);
51837da2899SCharles.Forsyth offset = progoffset(offset, va, &n);
51937da2899SCharles.Forsyth }
52037da2899SCharles.Forsyth return n;
52137da2899SCharles.Forsyth }
52237da2899SCharles.Forsyth
52337da2899SCharles.Forsyth Inst *
pc2dispc(Inst * pc,Module * mod)52437da2899SCharles.Forsyth pc2dispc(Inst *pc, Module *mod)
52537da2899SCharles.Forsyth {
52637da2899SCharles.Forsyth ulong l, u, m, v;
52737da2899SCharles.Forsyth ulong *tab = mod->pctab;
52837da2899SCharles.Forsyth
52937da2899SCharles.Forsyth v = (ulong)pc - (ulong)mod->prog;
53037da2899SCharles.Forsyth l = 0;
53137da2899SCharles.Forsyth u = mod->nprog-1;
53237da2899SCharles.Forsyth while(l < u){
53337da2899SCharles.Forsyth m = (l+u+1)/2;
53437da2899SCharles.Forsyth if(tab[m] < v)
53537da2899SCharles.Forsyth l = m;
53637da2899SCharles.Forsyth else if(tab[m] > v)
53737da2899SCharles.Forsyth u = m-1;
53837da2899SCharles.Forsyth else
53937da2899SCharles.Forsyth l = u = m;
54037da2899SCharles.Forsyth }
54137da2899SCharles.Forsyth if(l == u && tab[u] <= v && u != mod->nprog-1 && tab[u+1] > v)
54237da2899SCharles.Forsyth return &mod->prog[u];
54337da2899SCharles.Forsyth return 0;
54437da2899SCharles.Forsyth }
54537da2899SCharles.Forsyth
54637da2899SCharles.Forsyth static int
progstack(REG * reg,int state,char * va,int count,long offset)54737da2899SCharles.Forsyth progstack(REG *reg, int state, char *va, int count, long offset)
54837da2899SCharles.Forsyth {
54937da2899SCharles.Forsyth int n;
55037da2899SCharles.Forsyth Frame *f;
55137da2899SCharles.Forsyth Inst *pc;
55237da2899SCharles.Forsyth uchar *fp;
55337da2899SCharles.Forsyth Modlink *m;
55437da2899SCharles.Forsyth
55537da2899SCharles.Forsyth n = 0;
55637da2899SCharles.Forsyth m = reg->M;
55737da2899SCharles.Forsyth fp = reg->FP;
55837da2899SCharles.Forsyth pc = reg->PC;
55937da2899SCharles.Forsyth
56037da2899SCharles.Forsyth /*
56137da2899SCharles.Forsyth * all states other than debug and ready block,
56237da2899SCharles.Forsyth * but interp has already advanced the PC
56337da2899SCharles.Forsyth */
56437da2899SCharles.Forsyth if(!m->compiled && state != Pready && state != Pdebug && pc > m->prog)
56537da2899SCharles.Forsyth pc--;
56637da2899SCharles.Forsyth if(m->compiled && m->m->pctab != nil)
56737da2899SCharles.Forsyth pc = pc2dispc(pc, m->m);
56837da2899SCharles.Forsyth
56937da2899SCharles.Forsyth while(fp != nil) {
57037da2899SCharles.Forsyth f = (Frame*)fp;
57137da2899SCharles.Forsyth n += snprint(va+n, count-n, "%.8lux %.8lux %.8lux %.8lux %d %s\n",
57237da2899SCharles.Forsyth (ulong)f, /* FP */
57337da2899SCharles.Forsyth (ulong)(pc - m->prog), /* PC in dis instructions */
57437da2899SCharles.Forsyth (ulong)m->MP, /* MP */
57537da2899SCharles.Forsyth (ulong)m->prog, /* Code for module */
57637da2899SCharles.Forsyth m->compiled && m->m->pctab == nil, /* True if native assembler: fool stack utility for now */
57737da2899SCharles.Forsyth m->m->path); /* File system path */
57837da2899SCharles.Forsyth
57937da2899SCharles.Forsyth if(offset > 0) {
58037da2899SCharles.Forsyth offset -= n;
58137da2899SCharles.Forsyth if(offset < 0) {
58237da2899SCharles.Forsyth memmove(va, va+n+offset, -offset);
58337da2899SCharles.Forsyth n = -offset;
58437da2899SCharles.Forsyth }
58537da2899SCharles.Forsyth else
58637da2899SCharles.Forsyth n = 0;
58737da2899SCharles.Forsyth }
58837da2899SCharles.Forsyth
58937da2899SCharles.Forsyth pc = f->lr;
59037da2899SCharles.Forsyth fp = f->fp;
59137da2899SCharles.Forsyth if(f->mr != nil)
59237da2899SCharles.Forsyth m = f->mr;
59337da2899SCharles.Forsyth if(!m->compiled)
59437da2899SCharles.Forsyth pc--;
59537da2899SCharles.Forsyth else if(m->m->pctab != nil)
59637da2899SCharles.Forsyth pc = pc2dispc(pc, m->m)-1;
59737da2899SCharles.Forsyth }
59837da2899SCharles.Forsyth return n;
59937da2899SCharles.Forsyth }
60037da2899SCharles.Forsyth
60137da2899SCharles.Forsyth static int
calldepth(REG * reg)60237da2899SCharles.Forsyth calldepth(REG *reg)
60337da2899SCharles.Forsyth {
60437da2899SCharles.Forsyth int n;
60537da2899SCharles.Forsyth uchar *fp;
60637da2899SCharles.Forsyth
60737da2899SCharles.Forsyth n = 0;
60837da2899SCharles.Forsyth for(fp = reg->FP; fp != nil; fp = ((Frame*)fp)->fp)
60937da2899SCharles.Forsyth n++;
61037da2899SCharles.Forsyth return n;
61137da2899SCharles.Forsyth }
61237da2899SCharles.Forsyth
61337da2899SCharles.Forsyth static int
progheap(Heapqry * hq,char * va,int count,ulong offset)61437da2899SCharles.Forsyth progheap(Heapqry *hq, char *va, int count, ulong offset)
61537da2899SCharles.Forsyth {
61637da2899SCharles.Forsyth WORD *w;
61737da2899SCharles.Forsyth void *p;
61837da2899SCharles.Forsyth List *hd;
61937da2899SCharles.Forsyth Array *a;
62037da2899SCharles.Forsyth char *fmt, *str;
62137da2899SCharles.Forsyth Module *m;
62237da2899SCharles.Forsyth Modlink *ml;
62337da2899SCharles.Forsyth Channel *c;
62437da2899SCharles.Forsyth ulong addr;
62537da2899SCharles.Forsyth String *ss;
62637da2899SCharles.Forsyth union { REAL r; LONG l; WORD w[2]; } rock;
62737da2899SCharles.Forsyth int i, s, n, len, signed_off;
62837da2899SCharles.Forsyth Type *t;
62937da2899SCharles.Forsyth
63037da2899SCharles.Forsyth n = 0;
63137da2899SCharles.Forsyth s = 0;
63237da2899SCharles.Forsyth signed_off = offset;
63337da2899SCharles.Forsyth addr = hq->addr;
63437da2899SCharles.Forsyth for(i = 0; i < hq->count; i++) {
63537da2899SCharles.Forsyth switch(hq->fmt) {
63637da2899SCharles.Forsyth case 'W':
63737da2899SCharles.Forsyth if(addr & 3)
63837da2899SCharles.Forsyth return -1;
63937da2899SCharles.Forsyth n += snprint(va+n, count-n, "%d\n", *(WORD*)addr);
64037da2899SCharles.Forsyth s = sizeof(WORD);
64137da2899SCharles.Forsyth break;
64237da2899SCharles.Forsyth case 'B':
64337da2899SCharles.Forsyth n += snprint(va+n, count-n, "%d\n", *(BYTE*)addr);
64437da2899SCharles.Forsyth s = sizeof(BYTE);
64537da2899SCharles.Forsyth break;
64637da2899SCharles.Forsyth case 'V':
64737da2899SCharles.Forsyth if(addr & 3)
64837da2899SCharles.Forsyth return -1;
64937da2899SCharles.Forsyth w = (WORD*)addr;
65037da2899SCharles.Forsyth rock.w[0] = w[0];
65137da2899SCharles.Forsyth rock.w[1] = w[1];
65237da2899SCharles.Forsyth n += snprint(va+n, count-n, "%lld\n", rock.l);
65337da2899SCharles.Forsyth s = sizeof(LONG);
65437da2899SCharles.Forsyth break;
65537da2899SCharles.Forsyth case 'R':
65637da2899SCharles.Forsyth if(addr & 3)
65737da2899SCharles.Forsyth return -1;
65837da2899SCharles.Forsyth w = (WORD*)addr;
65937da2899SCharles.Forsyth rock.w[0] = w[0];
66037da2899SCharles.Forsyth rock.w[1] = w[1];
66137da2899SCharles.Forsyth n += snprint(va+n, count-n, "%g\n", rock.r);
66237da2899SCharles.Forsyth s = sizeof(REAL);
66337da2899SCharles.Forsyth break;
66437da2899SCharles.Forsyth case 'I':
66537da2899SCharles.Forsyth if(addr & 3)
66637da2899SCharles.Forsyth return -1;
66737da2899SCharles.Forsyth for(m = modules; m != nil; m = m->link)
66837da2899SCharles.Forsyth if(m == (Module*)hq->module)
66937da2899SCharles.Forsyth break;
67037da2899SCharles.Forsyth if(m == nil)
67137da2899SCharles.Forsyth error(Ebadctl);
67237da2899SCharles.Forsyth addr = (ulong)(m->prog+addr);
67337da2899SCharles.Forsyth n += snprint(va+n, count-n, "%D\n", (Inst*)addr);
67437da2899SCharles.Forsyth s = sizeof(Inst);
67537da2899SCharles.Forsyth break;
67637da2899SCharles.Forsyth case 'P':
67737da2899SCharles.Forsyth if(addr & 3)
67837da2899SCharles.Forsyth return -1;
67937da2899SCharles.Forsyth p = *(void**)addr;
68037da2899SCharles.Forsyth fmt = "nil\n";
68137da2899SCharles.Forsyth if(p != H)
68237da2899SCharles.Forsyth fmt = "%lux\n";
68337da2899SCharles.Forsyth n += snprint(va+n, count-n, fmt, p);
68437da2899SCharles.Forsyth s = sizeof(WORD);
68537da2899SCharles.Forsyth break;
68637da2899SCharles.Forsyth case 'L':
68737da2899SCharles.Forsyth if(addr & 3)
68837da2899SCharles.Forsyth return -1;
68937da2899SCharles.Forsyth hd = *(List**)addr;
69037da2899SCharles.Forsyth if(hd == H || D2H(hd)->t != &Tlist)
69137da2899SCharles.Forsyth return -1;
69237da2899SCharles.Forsyth n += snprint(va+n, count-n, "%lux.%lux\n", (ulong)&hd->tail, (ulong)hd->data);
69337da2899SCharles.Forsyth s = sizeof(WORD);
69437da2899SCharles.Forsyth break;
69537da2899SCharles.Forsyth case 'A':
69637da2899SCharles.Forsyth if(addr & 3)
69737da2899SCharles.Forsyth return -1;
69837da2899SCharles.Forsyth a = *(Array**)addr;
69937da2899SCharles.Forsyth if(a == H)
70037da2899SCharles.Forsyth n += snprint(va+n, count-n, "nil\n");
70137da2899SCharles.Forsyth else {
70237da2899SCharles.Forsyth if(D2H(a)->t != &Tarray)
70337da2899SCharles.Forsyth return -1;
70437da2899SCharles.Forsyth n += snprint(va+n, count-n, "%d.%lux\n", a->len, (ulong)a->data);
70537da2899SCharles.Forsyth }
70637da2899SCharles.Forsyth s = sizeof(WORD);
70737da2899SCharles.Forsyth break;
70837da2899SCharles.Forsyth case 'C':
70937da2899SCharles.Forsyth if(addr & 3)
71037da2899SCharles.Forsyth return -1;
71137da2899SCharles.Forsyth ss = *(String**)addr;
71237da2899SCharles.Forsyth if(ss == H)
71337da2899SCharles.Forsyth ss = &snil;
71437da2899SCharles.Forsyth else
71537da2899SCharles.Forsyth if(D2H(ss)->t != &Tstring)
71637da2899SCharles.Forsyth return -1;
71737da2899SCharles.Forsyth n += snprint(va+n, count-n, "%d.", abs(ss->len));
71837da2899SCharles.Forsyth str = string2c(ss);
71937da2899SCharles.Forsyth len = strlen(str);
72037da2899SCharles.Forsyth if(count-n < len)
72137da2899SCharles.Forsyth len = count-n;
72237da2899SCharles.Forsyth if(len > 0) {
72337da2899SCharles.Forsyth memmove(va+n, str, len);
72437da2899SCharles.Forsyth n += len;
72537da2899SCharles.Forsyth }
72637da2899SCharles.Forsyth break;
72737da2899SCharles.Forsyth case 'M':
72837da2899SCharles.Forsyth if(addr & 3)
72937da2899SCharles.Forsyth return -1;
73037da2899SCharles.Forsyth ml = *(Modlink**)addr;
73137da2899SCharles.Forsyth fmt = ml == H ? "nil\n" : "%lux\n";
73237da2899SCharles.Forsyth n += snprint(va+n, count-n, fmt, ml->MP);
73337da2899SCharles.Forsyth s = sizeof(WORD);
73437da2899SCharles.Forsyth break;
73537da2899SCharles.Forsyth case 'c':
73637da2899SCharles.Forsyth if(addr & 3)
73737da2899SCharles.Forsyth return -1;
73837da2899SCharles.Forsyth c = *(Channel**)addr;
73937da2899SCharles.Forsyth if(c == H)
74037da2899SCharles.Forsyth n += snprint(va+n, count-n, "nil\n");
74137da2899SCharles.Forsyth else{
74237da2899SCharles.Forsyth t = D2H(c)->t;
74337da2899SCharles.Forsyth if(t != &Tchannel && t != Trdchan && t != Twrchan)
74437da2899SCharles.Forsyth return -1;
74537da2899SCharles.Forsyth if(c->buf == H)
74637da2899SCharles.Forsyth n += snprint(va+n, count-n, "0.%lux\n", (ulong)c);
74737da2899SCharles.Forsyth else
74837da2899SCharles.Forsyth n += snprint(va+n, count-n, "%d.%lux.%d.%d\n", c->buf->len, (ulong)c->buf->data, c->front, c->size);
74937da2899SCharles.Forsyth }
75037da2899SCharles.Forsyth break;
75137da2899SCharles.Forsyth
75237da2899SCharles.Forsyth }
75337da2899SCharles.Forsyth addr += s;
75437da2899SCharles.Forsyth if(signed_off > 0) {
75537da2899SCharles.Forsyth signed_off -= n;
75637da2899SCharles.Forsyth if(signed_off < 0) {
75737da2899SCharles.Forsyth memmove(va, va+n+signed_off, -signed_off);
75837da2899SCharles.Forsyth n = -signed_off;
75937da2899SCharles.Forsyth }
76037da2899SCharles.Forsyth else
76137da2899SCharles.Forsyth n = 0;
76237da2899SCharles.Forsyth }
76337da2899SCharles.Forsyth }
76437da2899SCharles.Forsyth return n;
76537da2899SCharles.Forsyth }
76637da2899SCharles.Forsyth
76737da2899SCharles.Forsyth WORD
modstatus(REG * r,char * ptr,int len)76837da2899SCharles.Forsyth modstatus(REG *r, char *ptr, int len)
76937da2899SCharles.Forsyth {
77037da2899SCharles.Forsyth Inst *PC;
77137da2899SCharles.Forsyth Frame *f;
77237da2899SCharles.Forsyth
77337da2899SCharles.Forsyth if(r->M->m->name[0] == '$') {
77437da2899SCharles.Forsyth f = (Frame*)r->FP;
77537da2899SCharles.Forsyth snprint(ptr, len, "%s[%s]", f->mr->m->name, r->M->m->name);
77637da2899SCharles.Forsyth if(f->mr->compiled)
77737da2899SCharles.Forsyth return (WORD)f->lr;
77837da2899SCharles.Forsyth return f->lr - f->mr->prog;
77937da2899SCharles.Forsyth }
78037da2899SCharles.Forsyth memmove(ptr, r->M->m->name, len);
78137da2899SCharles.Forsyth if(r->M->compiled)
78237da2899SCharles.Forsyth return (WORD)r->PC;
78337da2899SCharles.Forsyth PC = r->PC;
78437da2899SCharles.Forsyth /* should really check for blocked states */
78537da2899SCharles.Forsyth if(PC > r->M->prog)
78637da2899SCharles.Forsyth PC--;
78737da2899SCharles.Forsyth return PC - r->M->prog;
78837da2899SCharles.Forsyth }
78937da2899SCharles.Forsyth
79037da2899SCharles.Forsyth static void
int2flag(int flag,char * s)79137da2899SCharles.Forsyth int2flag(int flag, char *s)
79237da2899SCharles.Forsyth {
79337da2899SCharles.Forsyth if(flag == 0){
79437da2899SCharles.Forsyth *s = '\0';
79537da2899SCharles.Forsyth return;
79637da2899SCharles.Forsyth }
79737da2899SCharles.Forsyth *s++ = '-';
79837da2899SCharles.Forsyth if(flag & MAFTER)
79937da2899SCharles.Forsyth *s++ = 'a';
80037da2899SCharles.Forsyth if(flag & MBEFORE)
80137da2899SCharles.Forsyth *s++ = 'b';
80237da2899SCharles.Forsyth if(flag & MCREATE)
80337da2899SCharles.Forsyth *s++ = 'c';
80437da2899SCharles.Forsyth if(flag & MCACHE)
80537da2899SCharles.Forsyth *s++ = 'C';
80637da2899SCharles.Forsyth *s = '\0';
80737da2899SCharles.Forsyth }
80837da2899SCharles.Forsyth
80937da2899SCharles.Forsyth static char*
progtime(ulong msec,char * buf,char * ebuf)81037da2899SCharles.Forsyth progtime(ulong msec, char *buf, char *ebuf)
81137da2899SCharles.Forsyth {
81237da2899SCharles.Forsyth int tenths, sec;
81337da2899SCharles.Forsyth
81437da2899SCharles.Forsyth tenths = msec/100;
81537da2899SCharles.Forsyth sec = tenths/10;
81637da2899SCharles.Forsyth seprint(buf, ebuf, "%4d:%2.2d.%d", sec/60, sec%60, tenths%10);
81737da2899SCharles.Forsyth return buf;
81837da2899SCharles.Forsyth }
81937da2899SCharles.Forsyth
82037da2899SCharles.Forsyth static long
progread(Chan * c,void * va,long n,vlong offset)82137da2899SCharles.Forsyth progread(Chan *c, void *va, long n, vlong offset)
82237da2899SCharles.Forsyth {
82337da2899SCharles.Forsyth int i;
82437da2899SCharles.Forsyth Prog *p;
82537da2899SCharles.Forsyth Osenv *o;
82637da2899SCharles.Forsyth Mntwalk *mw;
82737da2899SCharles.Forsyth ulong grpid;
82837da2899SCharles.Forsyth char *a = va;
82937da2899SCharles.Forsyth Progctl *ctl;
83037da2899SCharles.Forsyth char mbuf[64], timebuf[12];
83137da2899SCharles.Forsyth char flag[10];
83237da2899SCharles.Forsyth
83337da2899SCharles.Forsyth if(c->qid.type & QTDIR)
83437da2899SCharles.Forsyth return devdirread(c, a, n, 0, 0, proggen);
83537da2899SCharles.Forsyth
83637da2899SCharles.Forsyth switch(QID(c->qid)){
83737da2899SCharles.Forsyth case Qdbgctl:
83837da2899SCharles.Forsyth ctl = c->aux;
83937da2899SCharles.Forsyth return qread(ctl->q, va, n);
84037da2899SCharles.Forsyth case Qstatus:
84137da2899SCharles.Forsyth acquire();
84237da2899SCharles.Forsyth p = progpid(PID(c->qid));
84337da2899SCharles.Forsyth if(p == nil || p->state == Pexiting || p->R.M == H) {
84437da2899SCharles.Forsyth release();
84537da2899SCharles.Forsyth snprint(up->genbuf, sizeof(up->genbuf), "%8lud %8d %10s %s %10s %5dK %s",
84637da2899SCharles.Forsyth PID(c->qid),
84737da2899SCharles.Forsyth 0,
84837da2899SCharles.Forsyth eve,
84937da2899SCharles.Forsyth progtime(0, timebuf, timebuf+sizeof(timebuf)),
85037da2899SCharles.Forsyth progstate[Pexiting],
85137da2899SCharles.Forsyth 0,
85237da2899SCharles.Forsyth "[$Sys]");
85337da2899SCharles.Forsyth return readstr(offset, va, n, up->genbuf);
85437da2899SCharles.Forsyth }
85537da2899SCharles.Forsyth modstatus(&p->R, mbuf, sizeof(mbuf));
85637da2899SCharles.Forsyth o = p->osenv;
85737da2899SCharles.Forsyth snprint(up->genbuf, sizeof(up->genbuf), "%8d %8d %10s %s %10s %5dK %s",
85837da2899SCharles.Forsyth p->pid,
85937da2899SCharles.Forsyth p->group!=nil? p->group->id: 0,
86037da2899SCharles.Forsyth o->user,
86137da2899SCharles.Forsyth progtime(p->ticks, timebuf, timebuf+sizeof(timebuf)),
86237da2899SCharles.Forsyth progstate[p->state],
86337da2899SCharles.Forsyth progsize(p),
86437da2899SCharles.Forsyth mbuf);
86537da2899SCharles.Forsyth release();
86637da2899SCharles.Forsyth return readstr(offset, va, n, up->genbuf);
86737da2899SCharles.Forsyth case Qwait:
86837da2899SCharles.Forsyth return qread(c->aux, va, n);
86937da2899SCharles.Forsyth case Qns:
87037da2899SCharles.Forsyth acquire();
87137da2899SCharles.Forsyth if(waserror()){
87237da2899SCharles.Forsyth release();
87337da2899SCharles.Forsyth nexterror();
87437da2899SCharles.Forsyth }
87537da2899SCharles.Forsyth p = progpid(PID(c->qid));
87637da2899SCharles.Forsyth if(p == nil)
87737da2899SCharles.Forsyth error(Ethread);
87837da2899SCharles.Forsyth mw = c->aux;
87937da2899SCharles.Forsyth if(mw->cddone){
88037da2899SCharles.Forsyth poperror();
88137da2899SCharles.Forsyth release();
88237da2899SCharles.Forsyth return 0;
88337da2899SCharles.Forsyth }
88437da2899SCharles.Forsyth o = p->osenv;
88537da2899SCharles.Forsyth mntscan(mw, o->pgrp);
88637da2899SCharles.Forsyth if(mw->mh == 0) {
88737da2899SCharles.Forsyth mw->cddone = 1;
88837da2899SCharles.Forsyth i = snprint(a, n, "cd %s\n", o->pgrp->dot->name->s);
88937da2899SCharles.Forsyth poperror();
89037da2899SCharles.Forsyth release();
89137da2899SCharles.Forsyth return i;
89237da2899SCharles.Forsyth }
89337da2899SCharles.Forsyth int2flag(mw->cm->mflag, flag);
89437da2899SCharles.Forsyth if(strcmp(mw->cm->to->name->s, "#M") == 0){
89537da2899SCharles.Forsyth i = snprint(a, n, "mount %s %s %s %s\n", flag,
89637da2899SCharles.Forsyth mw->cm->to->mchan->name->s,
89737da2899SCharles.Forsyth mw->mh->from->name->s, mw->cm->spec? mw->cm->spec : "");
89837da2899SCharles.Forsyth }else
89937da2899SCharles.Forsyth i = snprint(a, n, "bind %s %s %s\n", flag,
90037da2899SCharles.Forsyth mw->cm->to->name->s, mw->mh->from->name->s);
90137da2899SCharles.Forsyth poperror();
90237da2899SCharles.Forsyth release();
90337da2899SCharles.Forsyth return i;
90437da2899SCharles.Forsyth case Qnsgrp:
90537da2899SCharles.Forsyth acquire();
90637da2899SCharles.Forsyth p = progpid(PID(c->qid));
90737da2899SCharles.Forsyth if(p == nil) {
90837da2899SCharles.Forsyth release();
90937da2899SCharles.Forsyth error(Ethread);
91037da2899SCharles.Forsyth }
91137da2899SCharles.Forsyth grpid = ((Osenv *)p->osenv)->pgrp->pgrpid;
91237da2899SCharles.Forsyth release();
91337da2899SCharles.Forsyth return readnum(offset, va, n, grpid, NUMSIZE);
91437da2899SCharles.Forsyth case Qpgrp:
91537da2899SCharles.Forsyth acquire();
91637da2899SCharles.Forsyth p = progpid(PID(c->qid));
91737da2899SCharles.Forsyth if(p == nil) {
91837da2899SCharles.Forsyth release();
91937da2899SCharles.Forsyth error(Ethread);
92037da2899SCharles.Forsyth }
92137da2899SCharles.Forsyth grpid = p->group!=nil? p->group->id: 0;
92237da2899SCharles.Forsyth release();
92337da2899SCharles.Forsyth return readnum(offset, va, n, grpid, NUMSIZE);
92437da2899SCharles.Forsyth case Qstack:
92537da2899SCharles.Forsyth acquire();
92637da2899SCharles.Forsyth p = progpid(PID(c->qid));
92737da2899SCharles.Forsyth if(p == nil || p->state == Pexiting) {
92837da2899SCharles.Forsyth release();
92937da2899SCharles.Forsyth error(Ethread);
93037da2899SCharles.Forsyth }
93137da2899SCharles.Forsyth if(p->state == Pready) {
93237da2899SCharles.Forsyth release();
93337da2899SCharles.Forsyth error(Estopped);
93437da2899SCharles.Forsyth }
93537da2899SCharles.Forsyth n = progstack(&p->R, p->state, va, n, offset);
93637da2899SCharles.Forsyth release();
93737da2899SCharles.Forsyth return n;
93837da2899SCharles.Forsyth case Qheap:
93937da2899SCharles.Forsyth acquire();
94037da2899SCharles.Forsyth if(waserror()){
94137da2899SCharles.Forsyth release();
94237da2899SCharles.Forsyth nexterror();
94337da2899SCharles.Forsyth }
94437da2899SCharles.Forsyth n = progheap(c->aux, va, n, offset);
94537da2899SCharles.Forsyth if(n == -1)
94637da2899SCharles.Forsyth error(Emisalign);
94737da2899SCharles.Forsyth poperror();
94837da2899SCharles.Forsyth release();
94937da2899SCharles.Forsyth return n;
95037da2899SCharles.Forsyth case Qfd:
95137da2899SCharles.Forsyth acquire();
95237da2899SCharles.Forsyth if(waserror()) {
95337da2899SCharles.Forsyth release();
95437da2899SCharles.Forsyth nexterror();
95537da2899SCharles.Forsyth }
95637da2899SCharles.Forsyth p = progpid(PID(c->qid));
95737da2899SCharles.Forsyth if(p == nil)
95837da2899SCharles.Forsyth error(Ethread);
95937da2899SCharles.Forsyth o = p->osenv;
96037da2899SCharles.Forsyth n = progfds(o, va, n, offset);
96137da2899SCharles.Forsyth poperror();
96237da2899SCharles.Forsyth release();
96337da2899SCharles.Forsyth return n;
96437da2899SCharles.Forsyth case Qexception:
96537da2899SCharles.Forsyth acquire();
96637da2899SCharles.Forsyth p = progpid(PID(c->qid));
96737da2899SCharles.Forsyth if(p == nil) {
96837da2899SCharles.Forsyth release();
96937da2899SCharles.Forsyth error(Ethread);
97037da2899SCharles.Forsyth }
97137da2899SCharles.Forsyth if(p->exstr == nil)
97237da2899SCharles.Forsyth up->genbuf[0] = 0;
97337da2899SCharles.Forsyth else
97437da2899SCharles.Forsyth snprint(up->genbuf, sizeof(up->genbuf), p->exstr);
97537da2899SCharles.Forsyth release();
97637da2899SCharles.Forsyth return readstr(offset, va, n, up->genbuf);
97737da2899SCharles.Forsyth }
97837da2899SCharles.Forsyth error(Egreg);
97937da2899SCharles.Forsyth return 0;
98037da2899SCharles.Forsyth }
98137da2899SCharles.Forsyth
98237da2899SCharles.Forsyth static void
mntscan(Mntwalk * mw,Pgrp * pg)98337da2899SCharles.Forsyth mntscan(Mntwalk *mw, Pgrp *pg)
98437da2899SCharles.Forsyth {
98537da2899SCharles.Forsyth Mount *t;
98637da2899SCharles.Forsyth Mhead *f;
98737da2899SCharles.Forsyth int nxt, i;
98837da2899SCharles.Forsyth ulong last, bestmid;
98937da2899SCharles.Forsyth
99037da2899SCharles.Forsyth rlock(&pg->ns);
99137da2899SCharles.Forsyth
99237da2899SCharles.Forsyth nxt = 0;
99337da2899SCharles.Forsyth bestmid = ~0;
99437da2899SCharles.Forsyth
99537da2899SCharles.Forsyth last = 0;
99637da2899SCharles.Forsyth if(mw->mh)
99737da2899SCharles.Forsyth last = mw->cm->mountid;
99837da2899SCharles.Forsyth
99937da2899SCharles.Forsyth for(i = 0; i < MNTHASH; i++) {
100037da2899SCharles.Forsyth for(f = pg->mnthash[i]; f; f = f->hash) {
100137da2899SCharles.Forsyth for(t = f->mount; t; t = t->next) {
100237da2899SCharles.Forsyth if(mw->mh == 0 ||
100337da2899SCharles.Forsyth (t->mountid > last && t->mountid < bestmid)) {
100437da2899SCharles.Forsyth mw->cm = t;
100537da2899SCharles.Forsyth mw->mh = f;
100637da2899SCharles.Forsyth bestmid = mw->cm->mountid;
100737da2899SCharles.Forsyth nxt = 1;
100837da2899SCharles.Forsyth }
100937da2899SCharles.Forsyth }
101037da2899SCharles.Forsyth }
101137da2899SCharles.Forsyth }
101237da2899SCharles.Forsyth if(nxt == 0)
101337da2899SCharles.Forsyth mw->mh = 0;
101437da2899SCharles.Forsyth
101537da2899SCharles.Forsyth runlock(&pg->ns);
101637da2899SCharles.Forsyth }
101737da2899SCharles.Forsyth
101837da2899SCharles.Forsyth static long
progwrite(Chan * c,void * va,long n,vlong offset)101937da2899SCharles.Forsyth progwrite(Chan *c, void *va, long n, vlong offset)
102037da2899SCharles.Forsyth {
102137da2899SCharles.Forsyth Prog *p, *f;
102237da2899SCharles.Forsyth Heapqry *hq;
102337da2899SCharles.Forsyth char buf[512];
102437da2899SCharles.Forsyth Progctl *ctl;
102537da2899SCharles.Forsyth char *b;
102637da2899SCharles.Forsyth int i, pc;
102737da2899SCharles.Forsyth Cmdbuf *cb;
102837da2899SCharles.Forsyth Cmdtab *ct;
102937da2899SCharles.Forsyth
103037da2899SCharles.Forsyth USED(offset);
103137da2899SCharles.Forsyth USED(va);
103237da2899SCharles.Forsyth
103337da2899SCharles.Forsyth if(c->qid.type & QTDIR)
103437da2899SCharles.Forsyth error(Eisdir);
103537da2899SCharles.Forsyth
103637da2899SCharles.Forsyth acquire();
103737da2899SCharles.Forsyth if(waserror()) {
103837da2899SCharles.Forsyth release();
103937da2899SCharles.Forsyth nexterror();
104037da2899SCharles.Forsyth }
104137da2899SCharles.Forsyth p = progpid(PID(c->qid));
104237da2899SCharles.Forsyth if(p == nil)
104337da2899SCharles.Forsyth error(Ethread);
104437da2899SCharles.Forsyth
104537da2899SCharles.Forsyth switch(QID(c->qid)){
104637da2899SCharles.Forsyth case Qctl:
104737da2899SCharles.Forsyth cb = parsecmd(va, n);
104837da2899SCharles.Forsyth if(waserror()){
104937da2899SCharles.Forsyth free(cb);
105037da2899SCharles.Forsyth nexterror();
105137da2899SCharles.Forsyth }
105237da2899SCharles.Forsyth ct = lookupcmd(cb, progcmd, nelem(progcmd));
105337da2899SCharles.Forsyth switch(ct->index){
105437da2899SCharles.Forsyth case CMkillgrp:
105537da2899SCharles.Forsyth killgrp(p, "killed");
105637da2899SCharles.Forsyth break;
105737da2899SCharles.Forsyth case CMkill:
105837da2899SCharles.Forsyth killprog(p, "killed");
105937da2899SCharles.Forsyth break;
106037da2899SCharles.Forsyth case CMrestricted:
106137da2899SCharles.Forsyth p->flags |= Prestrict;
106237da2899SCharles.Forsyth break;
106337da2899SCharles.Forsyth case CMexceptions:
106437da2899SCharles.Forsyth if(p->group->id != p->pid)
106537da2899SCharles.Forsyth error(Eperm);
106637da2899SCharles.Forsyth if(strcmp(cb->f[1], "propagate") == 0)
106737da2899SCharles.Forsyth p->flags |= Ppropagate;
106837da2899SCharles.Forsyth else if(strcmp(cb->f[1], "notifyleader") == 0)
106937da2899SCharles.Forsyth p->flags |= Pnotifyleader;
107037da2899SCharles.Forsyth else
107137da2899SCharles.Forsyth error(Ebadctl);
107237da2899SCharles.Forsyth break;
107337da2899SCharles.Forsyth case CMprivate:
1074*cb6deeccSforsyth p->group->flags |= Pprivatemem;
107537da2899SCharles.Forsyth break;
107637da2899SCharles.Forsyth }
107737da2899SCharles.Forsyth poperror();
107837da2899SCharles.Forsyth free(cb);
107937da2899SCharles.Forsyth break;
108037da2899SCharles.Forsyth case Qdbgctl:
108137da2899SCharles.Forsyth cb = parsecmd(va, n);
108237da2899SCharles.Forsyth if(waserror()){
108337da2899SCharles.Forsyth free(cb);
108437da2899SCharles.Forsyth nexterror();
108537da2899SCharles.Forsyth }
108637da2899SCharles.Forsyth if(cb->nf == 1 && strncmp(cb->f[0], "step", 4) == 0)
108737da2899SCharles.Forsyth ct = progdbgcmd;
108837da2899SCharles.Forsyth else
108937da2899SCharles.Forsyth ct = lookupcmd(cb, progdbgcmd, nelem(progdbgcmd));
109037da2899SCharles.Forsyth switch(ct->index){
109137da2899SCharles.Forsyth case CDstep:
109237da2899SCharles.Forsyth if(cb->nf == 1)
109337da2899SCharles.Forsyth i = strtoul(cb->f[0]+4, nil, 0);
109437da2899SCharles.Forsyth else
109537da2899SCharles.Forsyth i = strtoul(cb->f[1], nil, 0);
109637da2899SCharles.Forsyth dbgstep(c->aux, p, i);
109737da2899SCharles.Forsyth break;
109837da2899SCharles.Forsyth case CDtoret:
109937da2899SCharles.Forsyth f = currun();
110037da2899SCharles.Forsyth i = calldepth(&p->R);
110137da2899SCharles.Forsyth while(f->kill == nil) {
110237da2899SCharles.Forsyth dbgstep(c->aux, p, 1024);
110337da2899SCharles.Forsyth if(i > calldepth(&p->R))
110437da2899SCharles.Forsyth break;
110537da2899SCharles.Forsyth }
110637da2899SCharles.Forsyth break;
110737da2899SCharles.Forsyth case CDcont:
110837da2899SCharles.Forsyth f = currun();
110937da2899SCharles.Forsyth while(f->kill == nil)
111037da2899SCharles.Forsyth dbgstep(c->aux, p, 1024);
111137da2899SCharles.Forsyth break;
111237da2899SCharles.Forsyth case CDstart:
111337da2899SCharles.Forsyth dbgstart(p);
111437da2899SCharles.Forsyth break;
111537da2899SCharles.Forsyth case CDstop:
111637da2899SCharles.Forsyth ctl = c->aux;
111737da2899SCharles.Forsyth ctl->stop = 1;
111837da2899SCharles.Forsyth break;
111937da2899SCharles.Forsyth case CDunstop:
112037da2899SCharles.Forsyth ctl = c->aux;
112137da2899SCharles.Forsyth ctl->stop = 0;
112237da2899SCharles.Forsyth break;
112337da2899SCharles.Forsyth case CDbpt:
112437da2899SCharles.Forsyth pc = strtoul(cb->f[3], nil, 10);
112537da2899SCharles.Forsyth ctl = c->aux;
112637da2899SCharles.Forsyth if(strcmp(cb->f[1], "set") == 0)
112737da2899SCharles.Forsyth ctl->bpts = setbpt(ctl->bpts, cb->f[2], pc);
112837da2899SCharles.Forsyth else if(strcmp(cb->f[1], "del") == 0)
112937da2899SCharles.Forsyth ctl->bpts = delbpt(ctl->bpts, cb->f[2], pc);
113037da2899SCharles.Forsyth else
113137da2899SCharles.Forsyth error(Ebadctl);
113237da2899SCharles.Forsyth break;
113337da2899SCharles.Forsyth case CDmaim:
113437da2899SCharles.Forsyth p->kill = "maim";
113537da2899SCharles.Forsyth break;
113637da2899SCharles.Forsyth }
113737da2899SCharles.Forsyth poperror();
113837da2899SCharles.Forsyth free(cb);
113937da2899SCharles.Forsyth break;
114037da2899SCharles.Forsyth case Qheap:
114137da2899SCharles.Forsyth /*
114237da2899SCharles.Forsyth * Heap query:
114337da2899SCharles.Forsyth * addr.Fn
114437da2899SCharles.Forsyth * pc+module.In
114537da2899SCharles.Forsyth */
114637da2899SCharles.Forsyth i = n;
114737da2899SCharles.Forsyth if(i > sizeof(buf)-1)
114837da2899SCharles.Forsyth i = sizeof(buf)-1;
114937da2899SCharles.Forsyth memmove(buf, va, i);
115037da2899SCharles.Forsyth buf[i] = '\0';
115137da2899SCharles.Forsyth hq = c->aux;
115237da2899SCharles.Forsyth hq->addr = strtoul(buf, &b, 0);
115337da2899SCharles.Forsyth if(*b == '+')
115437da2899SCharles.Forsyth hq->module = strtoul(b, &b, 0);
115537da2899SCharles.Forsyth if(*b++ != '.')
115637da2899SCharles.Forsyth error(Ebadctl);
115737da2899SCharles.Forsyth hq->fmt = *b++;
115837da2899SCharles.Forsyth hq->count = strtoul(b, nil, 0);
115937da2899SCharles.Forsyth break;
116037da2899SCharles.Forsyth default:
116137da2899SCharles.Forsyth print("unknown qid in procwrite\n");
116237da2899SCharles.Forsyth error(Egreg);
116337da2899SCharles.Forsyth }
116437da2899SCharles.Forsyth poperror();
116537da2899SCharles.Forsyth release();
116637da2899SCharles.Forsyth return n;
116737da2899SCharles.Forsyth }
116837da2899SCharles.Forsyth
116937da2899SCharles.Forsyth static Bpt*
setbpt(Bpt * bpts,char * path,int pc)117037da2899SCharles.Forsyth setbpt(Bpt *bpts, char *path, int pc)
117137da2899SCharles.Forsyth {
117237da2899SCharles.Forsyth int n;
117337da2899SCharles.Forsyth Bpt *b;
117437da2899SCharles.Forsyth
117537da2899SCharles.Forsyth n = strlen(path);
117637da2899SCharles.Forsyth b = mallocz(sizeof *b + n, 0);
117737da2899SCharles.Forsyth if(b == nil)
117837da2899SCharles.Forsyth return bpts;
117937da2899SCharles.Forsyth b->pc = pc;
118037da2899SCharles.Forsyth memmove(b->path, path, n+1);
118137da2899SCharles.Forsyth b->file = b->path;
118237da2899SCharles.Forsyth path = strrchr(b->path, '/');
118337da2899SCharles.Forsyth if(path != nil)
118437da2899SCharles.Forsyth b->file = path + 1;
118537da2899SCharles.Forsyth b->next = bpts;
118637da2899SCharles.Forsyth return b;
118737da2899SCharles.Forsyth }
118837da2899SCharles.Forsyth
118937da2899SCharles.Forsyth static Bpt*
delbpt(Bpt * bpts,char * path,int pc)119037da2899SCharles.Forsyth delbpt(Bpt *bpts, char *path, int pc)
119137da2899SCharles.Forsyth {
119237da2899SCharles.Forsyth Bpt *b, **last;
119337da2899SCharles.Forsyth
119437da2899SCharles.Forsyth last = &bpts;
119537da2899SCharles.Forsyth for(b = bpts; b != nil; b = b->next){
119637da2899SCharles.Forsyth if(b->pc == pc && strcmp(b->path, path) == 0) {
119737da2899SCharles.Forsyth *last = b->next;
119837da2899SCharles.Forsyth free(b);
119937da2899SCharles.Forsyth break;
120037da2899SCharles.Forsyth }
120137da2899SCharles.Forsyth last = &b->next;
120237da2899SCharles.Forsyth }
120337da2899SCharles.Forsyth return bpts;
120437da2899SCharles.Forsyth }
120537da2899SCharles.Forsyth
120637da2899SCharles.Forsyth static void
freebpts(Bpt * b)120737da2899SCharles.Forsyth freebpts(Bpt *b)
120837da2899SCharles.Forsyth {
120937da2899SCharles.Forsyth Bpt *next;
121037da2899SCharles.Forsyth
121137da2899SCharles.Forsyth for(; b != nil; b = next){
121237da2899SCharles.Forsyth next = b->next;
121337da2899SCharles.Forsyth free(b);
121437da2899SCharles.Forsyth }
121537da2899SCharles.Forsyth }
121637da2899SCharles.Forsyth
121737da2899SCharles.Forsyth static void
telldbg(Progctl * ctl,char * msg)121837da2899SCharles.Forsyth telldbg(Progctl *ctl, char *msg)
121937da2899SCharles.Forsyth {
122037da2899SCharles.Forsyth kstrcpy(ctl->msg, msg, ERRMAX);
122137da2899SCharles.Forsyth ctl->debugger = nil;
122237da2899SCharles.Forsyth Wakeup(&ctl->r);
122337da2899SCharles.Forsyth }
122437da2899SCharles.Forsyth
122537da2899SCharles.Forsyth static void
dbgstart(Prog * p)122637da2899SCharles.Forsyth dbgstart(Prog *p)
122737da2899SCharles.Forsyth {
122837da2899SCharles.Forsyth Osenv *o;
122937da2899SCharles.Forsyth Progctl *ctl;
123037da2899SCharles.Forsyth
123137da2899SCharles.Forsyth o = p->osenv;
123237da2899SCharles.Forsyth ctl = o->debug;
123337da2899SCharles.Forsyth if(ctl != nil && ctl->debugger != nil)
123437da2899SCharles.Forsyth error("prog debugged");
123537da2899SCharles.Forsyth if(p->state == Pdebug)
123637da2899SCharles.Forsyth addrun(p);
123737da2899SCharles.Forsyth o->debug = nil;
123837da2899SCharles.Forsyth p->xec = xec;
123937da2899SCharles.Forsyth }
124037da2899SCharles.Forsyth
124137da2899SCharles.Forsyth static int
xecdone(void * vc)124237da2899SCharles.Forsyth xecdone(void *vc)
124337da2899SCharles.Forsyth {
124437da2899SCharles.Forsyth Progctl *ctl = vc;
124537da2899SCharles.Forsyth
124637da2899SCharles.Forsyth return ctl->debugger == nil;
124737da2899SCharles.Forsyth }
124837da2899SCharles.Forsyth
124937da2899SCharles.Forsyth static void
dbgstep(Progctl * vctl,Prog * p,int n)125037da2899SCharles.Forsyth dbgstep(Progctl *vctl, Prog *p, int n)
125137da2899SCharles.Forsyth {
125237da2899SCharles.Forsyth Osenv * volatile o;
125337da2899SCharles.Forsyth Progctl * volatile ctl;
125437da2899SCharles.Forsyth char buf[ERRMAX+20], *msg;
125537da2899SCharles.Forsyth
125637da2899SCharles.Forsyth if(p == currun())
125737da2899SCharles.Forsyth error("cannot step yourself");
125837da2899SCharles.Forsyth
125937da2899SCharles.Forsyth if(p->state == Pbroken)
126037da2899SCharles.Forsyth error("prog broken");
126137da2899SCharles.Forsyth
126237da2899SCharles.Forsyth ctl = vctl;
126337da2899SCharles.Forsyth if(ctl->debugger != nil)
126437da2899SCharles.Forsyth error("prog already debugged");
126537da2899SCharles.Forsyth
126637da2899SCharles.Forsyth o = p->osenv;
126737da2899SCharles.Forsyth if(o->debug == nil) {
126837da2899SCharles.Forsyth o->debug = ctl;
126937da2899SCharles.Forsyth p->xec = dbgxec;
127037da2899SCharles.Forsyth }else if(o->debug != ctl)
127137da2899SCharles.Forsyth error("prog already debugged");
127237da2899SCharles.Forsyth
127337da2899SCharles.Forsyth ctl->step = n;
127437da2899SCharles.Forsyth if(p->state == Pdebug)
127537da2899SCharles.Forsyth addrun(p);
127637da2899SCharles.Forsyth ctl->debugger = up;
127737da2899SCharles.Forsyth strcpy(buf, "child: ");
127837da2899SCharles.Forsyth msg = buf+7;
127937da2899SCharles.Forsyth ctl->msg = msg;
128037da2899SCharles.Forsyth
128137da2899SCharles.Forsyth /*
128237da2899SCharles.Forsyth * wait for reply from dbgxec; release is okay because prog is now
128337da2899SCharles.Forsyth * debugged, cannot exit.
128437da2899SCharles.Forsyth */
128537da2899SCharles.Forsyth if(waserror()){
128637da2899SCharles.Forsyth acquire();
128737da2899SCharles.Forsyth ctl->debugger = nil;
128837da2899SCharles.Forsyth ctl->msg = nil;
128937da2899SCharles.Forsyth o->debug = nil;
129037da2899SCharles.Forsyth p->xec = xec;
129137da2899SCharles.Forsyth nexterror();
129237da2899SCharles.Forsyth }
129337da2899SCharles.Forsyth release();
129437da2899SCharles.Forsyth Sleep(&ctl->r, xecdone, ctl);
129537da2899SCharles.Forsyth poperror();
129637da2899SCharles.Forsyth acquire();
129737da2899SCharles.Forsyth if(msg[0] != '\0')
129837da2899SCharles.Forsyth error(buf);
129937da2899SCharles.Forsyth }
130037da2899SCharles.Forsyth
130137da2899SCharles.Forsyth void
dbgexit(Prog * kid,int broken,char * estr)130237da2899SCharles.Forsyth dbgexit(Prog *kid, int broken, char *estr)
130337da2899SCharles.Forsyth {
130437da2899SCharles.Forsyth int n;
130537da2899SCharles.Forsyth Osenv *e;
130637da2899SCharles.Forsyth Progctl *ctl;
130737da2899SCharles.Forsyth char buf[ERRMAX+20];
130837da2899SCharles.Forsyth
130937da2899SCharles.Forsyth e = kid->osenv;
131037da2899SCharles.Forsyth ctl = e->debug;
131137da2899SCharles.Forsyth e->debug = nil;
131237da2899SCharles.Forsyth kid->xec = xec;
131337da2899SCharles.Forsyth
131437da2899SCharles.Forsyth if(broken)
131537da2899SCharles.Forsyth n = snprint(buf, sizeof(buf), "broken: %s", estr);
131637da2899SCharles.Forsyth else
131737da2899SCharles.Forsyth n = snprint(buf, sizeof(buf), "exited");
131837da2899SCharles.Forsyth if(ctl->debugger)
131937da2899SCharles.Forsyth telldbg(ctl, buf);
132037da2899SCharles.Forsyth qproduce(ctl->q, buf, n);
132137da2899SCharles.Forsyth }
132237da2899SCharles.Forsyth
132337da2899SCharles.Forsyth static void
dbgaddrun(Prog * p)132437da2899SCharles.Forsyth dbgaddrun(Prog *p)
132537da2899SCharles.Forsyth {
132637da2899SCharles.Forsyth Osenv *o;
132737da2899SCharles.Forsyth
132837da2899SCharles.Forsyth p->state = Pdebug;
132937da2899SCharles.Forsyth p->addrun = nil;
133037da2899SCharles.Forsyth o = p->osenv;
133137da2899SCharles.Forsyth if(o->rend != nil)
133237da2899SCharles.Forsyth Wakeup(o->rend);
133337da2899SCharles.Forsyth o->rend = nil;
133437da2899SCharles.Forsyth }
133537da2899SCharles.Forsyth
133637da2899SCharles.Forsyth static int
bdone(void * vp)133737da2899SCharles.Forsyth bdone(void *vp)
133837da2899SCharles.Forsyth {
133937da2899SCharles.Forsyth Prog *p = vp;
134037da2899SCharles.Forsyth
134137da2899SCharles.Forsyth return p->addrun == nil;
134237da2899SCharles.Forsyth }
134337da2899SCharles.Forsyth
134437da2899SCharles.Forsyth static void
dbgblock(Prog * p)134537da2899SCharles.Forsyth dbgblock(Prog *p)
134637da2899SCharles.Forsyth {
134737da2899SCharles.Forsyth Osenv *o;
134837da2899SCharles.Forsyth Progctl *ctl;
134937da2899SCharles.Forsyth
135037da2899SCharles.Forsyth o = p->osenv;
135137da2899SCharles.Forsyth ctl = o->debug;
135237da2899SCharles.Forsyth qproduce(ctl->q, progstate[p->state], strlen(progstate[p->state]));
135337da2899SCharles.Forsyth pushrun(p);
135437da2899SCharles.Forsyth p->addrun = dbgaddrun;
135537da2899SCharles.Forsyth o->rend = &up->sleep;
135637da2899SCharles.Forsyth
135737da2899SCharles.Forsyth /*
135837da2899SCharles.Forsyth * bdone(p) is safe after release because p is being debugged,
135937da2899SCharles.Forsyth * so cannot exit.
136037da2899SCharles.Forsyth */
136137da2899SCharles.Forsyth if(waserror()){
136237da2899SCharles.Forsyth acquire();
136337da2899SCharles.Forsyth nexterror();
136437da2899SCharles.Forsyth }
136537da2899SCharles.Forsyth release();
136637da2899SCharles.Forsyth if(o->rend != nil)
136737da2899SCharles.Forsyth Sleep(o->rend, bdone, p);
136837da2899SCharles.Forsyth poperror();
136937da2899SCharles.Forsyth acquire();
137037da2899SCharles.Forsyth if(p->kill != nil)
137137da2899SCharles.Forsyth error(p->kill);
137237da2899SCharles.Forsyth ctl = o->debug;
137337da2899SCharles.Forsyth if(ctl != nil)
137437da2899SCharles.Forsyth qproduce(ctl->q, "run", 3);
137537da2899SCharles.Forsyth }
137637da2899SCharles.Forsyth
137737da2899SCharles.Forsyth void
dbgxec(Prog * p)137837da2899SCharles.Forsyth dbgxec(Prog *p)
137937da2899SCharles.Forsyth {
138037da2899SCharles.Forsyth Bpt *b;
138137da2899SCharles.Forsyth Prog *kid;
138237da2899SCharles.Forsyth Osenv *env;
138337da2899SCharles.Forsyth Progctl *ctl;
138437da2899SCharles.Forsyth int op, pc, n;
138537da2899SCharles.Forsyth char buf[ERRMAX+10];
138637da2899SCharles.Forsyth extern void (*dec[])(void);
138737da2899SCharles.Forsyth
138837da2899SCharles.Forsyth env = p->osenv;
138937da2899SCharles.Forsyth ctl = env->debug;
139037da2899SCharles.Forsyth ctl->ref++;
139137da2899SCharles.Forsyth if(waserror()){
139237da2899SCharles.Forsyth closedbgctl(ctl, p);
139337da2899SCharles.Forsyth nexterror();
139437da2899SCharles.Forsyth }
139537da2899SCharles.Forsyth
139637da2899SCharles.Forsyth R = p->R;
139737da2899SCharles.Forsyth R.MP = R.M->MP;
139837da2899SCharles.Forsyth
139937da2899SCharles.Forsyth R.IC = p->quanta;
140037da2899SCharles.Forsyth if((ulong)R.IC > ctl->step)
140137da2899SCharles.Forsyth R.IC = ctl->step;
140237da2899SCharles.Forsyth if(ctl->stop)
140337da2899SCharles.Forsyth R.IC = 0;
140437da2899SCharles.Forsyth
140537da2899SCharles.Forsyth
140637da2899SCharles.Forsyth buf[0] = '\0';
140737da2899SCharles.Forsyth
140837da2899SCharles.Forsyth if(R.IC != 0 && R.M->compiled) {
140937da2899SCharles.Forsyth comvec();
141037da2899SCharles.Forsyth if(p != currun())
141137da2899SCharles.Forsyth dbgblock(p);
141237da2899SCharles.Forsyth goto save;
141337da2899SCharles.Forsyth }
141437da2899SCharles.Forsyth
141537da2899SCharles.Forsyth while(R.IC != 0) {
141637da2899SCharles.Forsyth if(0)
141737da2899SCharles.Forsyth print("step: %lux: %s %4ld %D\n",
141837da2899SCharles.Forsyth (ulong)p, R.M->m->name, R.PC-R.M->prog, R.PC);
141937da2899SCharles.Forsyth
142037da2899SCharles.Forsyth dec[R.PC->add]();
142137da2899SCharles.Forsyth op = R.PC->op;
142237da2899SCharles.Forsyth R.PC++;
142337da2899SCharles.Forsyth optab[op]();
142437da2899SCharles.Forsyth
142537da2899SCharles.Forsyth /*
142637da2899SCharles.Forsyth * check notification about new progs
142737da2899SCharles.Forsyth */
142837da2899SCharles.Forsyth if(op == ISPAWN || op == IMSPAWN) {
142937da2899SCharles.Forsyth /* pick up the kid from the end of the run queue */
143037da2899SCharles.Forsyth kid = delruntail(Pdebug);
143137da2899SCharles.Forsyth n = snprint(buf, sizeof buf, "new %d", kid->pid);
143237da2899SCharles.Forsyth qproduce(ctl->q, buf, n);
143337da2899SCharles.Forsyth buf[0] = '\0';
143437da2899SCharles.Forsyth }
143537da2899SCharles.Forsyth if(op == ILOAD) {
143637da2899SCharles.Forsyth n = snprint(buf, sizeof buf, "load %s", string2c(*(String**)R.s));
143737da2899SCharles.Forsyth qproduce(ctl->q, buf, n);
143837da2899SCharles.Forsyth buf[0] = '\0';
143937da2899SCharles.Forsyth }
144037da2899SCharles.Forsyth
144137da2899SCharles.Forsyth /*
144237da2899SCharles.Forsyth * check for returns at big steps
144337da2899SCharles.Forsyth */
144437da2899SCharles.Forsyth if(op == IRET)
144537da2899SCharles.Forsyth R.IC = 1;
144637da2899SCharles.Forsyth
144737da2899SCharles.Forsyth /*
144837da2899SCharles.Forsyth * check for blocked progs
144937da2899SCharles.Forsyth */
145037da2899SCharles.Forsyth if(R.IC == 1 && p != currun())
145137da2899SCharles.Forsyth dbgblock(p);
145237da2899SCharles.Forsyth if(ctl->stop)
145337da2899SCharles.Forsyth R.IC = 1;
145437da2899SCharles.Forsyth R.IC--;
145537da2899SCharles.Forsyth
145637da2899SCharles.Forsyth if(ctl->bpts == nil)
145737da2899SCharles.Forsyth continue;
145837da2899SCharles.Forsyth
145937da2899SCharles.Forsyth pc = R.PC - R.M->prog;
146037da2899SCharles.Forsyth for(b = ctl->bpts; b != nil; b = b->next) {
146137da2899SCharles.Forsyth if(pc == b->pc &&
146237da2899SCharles.Forsyth (strcmp(R.M->m->path, b->path) == 0 ||
146337da2899SCharles.Forsyth strcmp(R.M->m->path, b->file) == 0)) {
146437da2899SCharles.Forsyth strcpy(buf, "breakpoint");
146537da2899SCharles.Forsyth goto save;
146637da2899SCharles.Forsyth }
146737da2899SCharles.Forsyth }
146837da2899SCharles.Forsyth }
146937da2899SCharles.Forsyth save:
147037da2899SCharles.Forsyth if(ctl->stop)
147137da2899SCharles.Forsyth strcpy(buf, "stopped");
147237da2899SCharles.Forsyth
147337da2899SCharles.Forsyth p->R = R;
147437da2899SCharles.Forsyth
147537da2899SCharles.Forsyth if(env->debug == nil) {
147637da2899SCharles.Forsyth poperror();
147737da2899SCharles.Forsyth return;
147837da2899SCharles.Forsyth }
147937da2899SCharles.Forsyth
148037da2899SCharles.Forsyth if(p == currun())
148137da2899SCharles.Forsyth delrun(Pdebug);
148237da2899SCharles.Forsyth
148337da2899SCharles.Forsyth telldbg(env->debug, buf);
148437da2899SCharles.Forsyth poperror();
148537da2899SCharles.Forsyth closedbgctl(env->debug, p);
148637da2899SCharles.Forsyth }
148737da2899SCharles.Forsyth
148837da2899SCharles.Forsyth Dev progdevtab = {
148937da2899SCharles.Forsyth 'p',
149037da2899SCharles.Forsyth "prog",
149137da2899SCharles.Forsyth
149237da2899SCharles.Forsyth devinit,
149337da2899SCharles.Forsyth progattach,
149437da2899SCharles.Forsyth progwalk,
149537da2899SCharles.Forsyth progstat,
149637da2899SCharles.Forsyth progopen,
149737da2899SCharles.Forsyth devcreate,
149837da2899SCharles.Forsyth progclose,
149937da2899SCharles.Forsyth progread,
150037da2899SCharles.Forsyth devbread,
150137da2899SCharles.Forsyth progwrite,
150237da2899SCharles.Forsyth devbwrite,
150337da2899SCharles.Forsyth devremove,
150437da2899SCharles.Forsyth progwstat
150537da2899SCharles.Forsyth };
1506