aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/acid/Notes30
-rw-r--r--src/cmd/acid/acid.h11
-rw-r--r--src/cmd/acid/builtin.c166
-rw-r--r--src/cmd/acid/dbg.y3
-rw-r--r--src/cmd/acid/exec.c187
-rw-r--r--src/cmd/acid/expr.c129
-rw-r--r--src/cmd/acid/main.c114
-rw-r--r--src/cmd/acid/print.c4
-rw-r--r--src/cmd/acid/proc.c51
-rw-r--r--src/cmd/acid/util.c5
10 files changed, 526 insertions, 174 deletions
diff --git a/src/cmd/acid/Notes b/src/cmd/acid/Notes
index 597bf58c..90cfc2a5 100644
--- a/src/cmd/acid/Notes
+++ b/src/cmd/acid/Notes
@@ -20,6 +20,8 @@ map() returns 5-tuples: (name, filename, base, end, offset)
map() expects a 5-tuple too
+new acid maps() prints maps nicely.
+
strace expects a list of register names and values like
{"PC", *PC, "SP", *SP}
@@ -41,6 +43,34 @@ new builtin deltextfile(file) removes a file from the set of open text files.
both textfile and deltextfile update symbols.
+new types: register is something that when dereferenced gives you
+ the registers. the Ureg is no longer mapped at 0.
+ refconst is something that gives a constant when dereferenced.
+
+new builtin register("AX") creates register values
+new builtin refconst(0x123) creates refconst values
+
+new builtin var("foo") is equivalent to the variable foo
+ (it returns foo but can also be used as the lhs of an assignment).
+
+new acid function getregs() returns a list of the current values of registers.
+new acid function setregs() sets the current registers to those values.
+ note that getregs and setregs operate on register locations, not the
+ register values themselves.
+new acid function resetregs() sets registers to register("AX"), etc.
+new acid function clearregs() sets all registers to constant -1.
+
+the default register settings are as in resetregs(), not small numbers.
+the Ureg is not mapped at 0 anymore.
+
+new acid variables coretext, pids, systype, corefile, cmdline.
+
+new behavior: local variable lookup, stk, etc., use the acid values of registers
+ (*PC, *SP, and so on), so the thread support code can change the context
+ completely.
+
+unary + is applicable to more data types and prints more often.
+
====
yet to be done:
diff --git a/src/cmd/acid/acid.h b/src/cmd/acid/acid.h
index 44718009..866816e8 100644
--- a/src/cmd/acid/acid.h
+++ b/src/cmd/acid/acid.h
@@ -44,6 +44,7 @@ Extern int interactive;
Extern Node* code;
Extern int na;
Extern int wtflag;
+Extern Regs* acidregs;
Extern Regs* correg;
Extern Map* cormap;
Extern Map* symmap;
@@ -76,6 +77,8 @@ enum
TSTRING,
TLIST,
TCODE,
+ TREG,
+ TCON,
NUMT,
};
@@ -129,6 +132,8 @@ struct Store
String* string;
List* l;
Node* cc;
+ char* reg;
+ Node* con;
} u;
};
@@ -182,6 +187,7 @@ struct String
int len;
};
+int acidregsrw(Regs*, char*, ulong*, int);
List* addlist(List*, List*);
void addvarsym(Fhdr*);
List* al(int);
@@ -212,6 +218,7 @@ void gc(void);
char* getstatus(int);
void* gmalloc(long);
void indir(Map*, ulong, char, Node*);
+void indirreg(Regs*, char*, char, Node*);
void initexpr(void);
void initprint(void);
void installbuiltin(void);
@@ -257,7 +264,8 @@ void userinit(void);
void varreg(void);
void varsym(void);
void whatis(Lsym*);
-void windir(Map*, Node*, Node*, Node*);
+void windir(Map*, Node, Node*, Node*);
+void windirreg(Regs*, char*, Node*, Node*);
void yyerror(char*, ...);
int yylex(void);
int yyparse(void);
@@ -313,5 +321,6 @@ enum
OFMT,
OEVAL,
OWHAT,
+ OUPLUS,
NUMO,
};
diff --git a/src/cmd/acid/builtin.c b/src/cmd/acid/builtin.c
index 490c4521..316c4921 100644
--- a/src/cmd/acid/builtin.c
+++ b/src/cmd/acid/builtin.c
@@ -44,6 +44,9 @@ void regexp(Node*, Node*);
void textfile(Node*, Node*);
void deltextfile(Node*, Node*);
void stringn(Node*, Node*);
+void xregister(Node*, Node*);
+void refconst(Node*, Node*);
+void dolook(Node*, Node*);
typedef struct Btab Btab;
struct Btab
@@ -52,13 +55,12 @@ struct Btab
void (*fn)(Node*, Node*);
} tab[] =
{
+ "access", doaccess,
"atof", cvtatof,
"atoi", cvtatoi,
"deltextfile", deltextfile,
"error", doerror,
"file", getfile,
- "readfile", readfile,
- "access", doaccess,
"filepc", filepc,
"fnbound", funcbound,
"fmt", fmt,
@@ -76,8 +78,11 @@ struct Btab
"print", bprint,
"printto", printto,
"rc", rc,
+ "readfile", readfile,
"reason", reason,
+ "refconst", refconst,
"regexp", regexp,
+ "register", xregister,
"setproc", setproc,
"start", start,
"startstop", startstop,
@@ -87,6 +92,7 @@ struct Btab
"stringn", stringn,
"sysstop", sysstop,
"textfile", textfile,
+ "var", dolook,
"waitstop", waitstop,
0
};
@@ -317,6 +323,65 @@ xkill(Node *r, Node *args)
}
void
+xregister(Node *r, Node *args)
+{
+ Regdesc *rp;
+ Node res;
+
+ if(args == 0)
+ error("register(string): arg count");
+ expr(args, &res);
+ if(res.type != TSTRING)
+ error("register(string): arg type");
+
+ if((rp = regdesc(res.store.u.string->string)) == nil)
+ error("no such register");
+
+ r->op = OCONST;
+ r->type = TREG;
+ r->store.fmt = rp->format;
+ r->store.u.reg = rp->name;
+}
+
+void
+refconst(Node *r, Node *args)
+{
+ Node *n;
+
+ if(args == 0)
+ error("refconst(expr): arg count");
+
+ n = an(OCONST, ZN, ZN);
+ expr(args, n);
+
+ r->op = OCONST;
+ r->type = TCON;
+ r->store.u.con = n;
+}
+
+void
+dolook(Node *r, Node *args)
+{
+ Node res;
+ Lsym *l;
+
+ if(args == 0)
+ error("var(string): arg count");
+ expr(args, &res);
+ if(res.type != TSTRING)
+ error("var(string): arg type");
+
+ r->op = OCONST;
+ if((l = look(res.store.u.string->string)) == nil || l->v->set == 0){
+ r->type = TLIST;
+ r->store.u.l = nil;
+ }else{
+ r->type = l->v->type;
+ r->store = l->v->store;
+ }
+}
+
+void
status(Node *r, Node *args)
{
Node res;
@@ -350,7 +415,7 @@ reason(Node *r, Node *args)
r->op = OCONST;
r->type = TSTRING;
r->store.fmt = 's';
- r->store.u.string = strnode((*mach->exc)(cormap, correg));
+ r->store.u.string = strnode((*mach->exc)(cormap, acidregs));
}
void
@@ -367,7 +432,7 @@ follow(Node *r, Node *args)
if(res.type != TINT)
error("follow(addr): arg type");
- n = (*mach->foll)(cormap, correg, res.store.u.ival, f);
+ n = (*mach->foll)(cormap, acidregs, res.store.u.ival, f);
if (n < 0)
error("follow(addr): %r");
tail = &r->store.u.l;
@@ -953,7 +1018,7 @@ straceregrw(Regs *regs, char *name, ulong *val, int isr)
*val = sregs[i].val;
return 0;
}
- return rget(correg, name, val);
+ return rget(acidregs, name, val);
}
void
@@ -1058,6 +1123,65 @@ patom(char type, Store *res)
int i;
char buf[512];
extern char *typenames[];
+ Node *n;
+
+ switch(type){
+ case TREG:
+ Bprint(bout, "register(\"%s\")", res->u.reg);
+ return;
+ case TCON:
+ Bprint(bout, "refconst(");
+ n = res->u.con;
+ patom(n->type, &n->store);
+ Bprint(bout, ")");
+ return;
+ }
+
+ switch(res->fmt){
+ case 'c':
+ case 'C':
+ case 'r':
+ case 'B':
+ case 'b':
+ case 'X':
+ case 'x':
+ case 'W':
+ case 'D':
+ case 'd':
+ case 'u':
+ case 'U':
+ case 'Z':
+ case 'V':
+ case 'Y':
+ case 'o':
+ case 'O':
+ case 'q':
+ case 'Q':
+ case 'a':
+ case 'A':
+ case 'I':
+ case 'i':
+ if(type != TINT){
+ badtype:
+ Bprint(bout, "*%s\\%c*", typenames[(uchar)type], res->fmt);
+ return;
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ if(type != TFLOAT)
+ goto badtype;
+ break;
+
+ case 's':
+ case 'g':
+ case 'G':
+ case 'R':
+ if(type != TSTRING)
+ goto badtype;
+ break;
+ }
switch(res->fmt) {
case 'c':
@@ -1129,24 +1253,15 @@ patom(char type, Store *res)
break;
case 'f':
case 'F':
- if(type != TFLOAT)
- Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
- else
- Bprint(bout, "%g", res->u.fval);
+ Bprint(bout, "%g", res->u.fval);
break;
case 's':
case 'g':
case 'G':
- if(type != TSTRING)
- Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
- else
- Bwrite(bout, res->u.string->string, res->u.string->len);
+ Bwrite(bout, res->u.string->string, res->u.string->len);
break;
case 'R':
- if(type != TSTRING)
- Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
- else
- Bprint(bout, "%S", (Rune*)res->u.string->string);
+ Bprint(bout, "%S", (Rune*)res->u.string->string);
break;
case 'a':
case 'A':
@@ -1155,14 +1270,10 @@ patom(char type, Store *res)
break;
case 'I':
case 'i':
- if(type != TINT)
- Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]);
- else {
- if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
- Bprint(bout, "no instruction");
- else
- Bprint(bout, "%s", buf);
- }
+ if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0)
+ Bprint(bout, "no instruction");
+ else
+ Bprint(bout, "%s", buf);
break;
}
}
@@ -1406,6 +1517,7 @@ textfile(Node *r, Node *args)
unmapfile(corhdr, cormap);
mapfile(fp, base, cormap, nil);
free(correg);
+ correg = nil;
mapfile(corhdr, 0, cormap, &correg);
}
if(symopen(fp) < 0)
@@ -1476,8 +1588,6 @@ deltextfile(Node *r, Node *args)
error("symbol file %s not open", file);
}
-int xget1(Map *m, ulong addr, u8int *a, int n);
-
void
stringn(Node *r, Node *args)
{
@@ -1507,7 +1617,7 @@ stringn(Node *r, Node *args)
r->type = TSTRING;
for(i=0; i<n; i++){
- ret = xget1(cormap, addr, (uchar*)&buf[i], 1);
+ ret = get1(cormap, addr, (uchar*)&buf[i], 1);
if(ret < 0){
free(buf);
error("indir: %r");
diff --git a/src/cmd/acid/dbg.y b/src/cmd/acid/dbg.y
index afdf538c..3d1886c7 100644
--- a/src/cmd/acid/dbg.y
+++ b/src/cmd/acid/dbg.y
@@ -282,8 +282,7 @@ monexpr : term
}
| '+' monexpr
{
- $$ = con(0);
- $$ = an(OADD, $2, $$);
+ $$ = an(OUPLUS, $2, ZN);
}
| '-' monexpr
{
diff --git a/src/cmd/acid/exec.c b/src/cmd/acid/exec.c
index edf2690e..2022da53 100644
--- a/src/cmd/acid/exec.c
+++ b/src/cmd/acid/exec.c
@@ -202,56 +202,6 @@ convflt(Node *r, char *flt)
}
}
-static char*
-regbyoff(ulong addr)
-{
- Regdesc *r;
-
- if(mach == nil)
- error("no mach, no registers");
- for(r=mach->reglist; r->name; r++)
- if(r->offset == addr)
- return r->name;
- error("no register at %#lux", addr);
- return nil;
-}
-
-int
-xget1(Map *m, ulong addr, u8int *a, int n)
-{
- if(addr < 0x100 && correg)
- return lget1(m, correg, locreg(regbyoff(addr)), a, n);
- else
- return get1(m, addr, a, n);
-}
-
-int
-xget2(Map *m, ulong addr, u16int *a)
-{
- if(addr < 0x100 && correg)
- return lget2(m, correg, locreg(regbyoff(addr)), a);
- else
- return get2(m, addr, a);
-}
-
-int
-xget4(Map *m, ulong addr, u32int *a)
-{
- if(addr < 0x100 && correg)
- return lget4(m, correg, locreg(regbyoff(addr)), a);
- else
- return get4(m, addr, a);
-}
-
-int
-xget8(Map *m, ulong addr, u64int *a)
-{
- if(addr < 0x100 && correg)
- return lget8(m, correg, locreg(regbyoff(addr)), a);
- else
- return get8(m, addr, a);
-}
-
void
indir(Map *m, ulong addr, char fmt, Node *r)
{
@@ -272,7 +222,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 'C':
case 'b':
r->type = TINT;
- ret = xget1(m, addr, &cval, 1);
+ ret = get1(m, addr, &cval, 1);
if (ret < 0)
error("indir: %r");
r->store.u.ival = cval;
@@ -284,7 +234,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 'q':
case 'r':
r->type = TINT;
- ret = xget2(m, addr, &sval);
+ ret = get2(m, addr, &sval);
if (ret < 0)
error("indir: %r");
r->store.u.ival = sval;
@@ -298,7 +248,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 'O':
case 'Q':
r->type = TINT;
- ret = xget4(m, addr, &ival);
+ ret = get4(m, addr, &ival);
if (ret < 0)
error("indir: %r");
r->store.u.ival = ival;
@@ -308,7 +258,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 'Y':
case 'Z':
r->type = TINT;
- ret = xget8(m, addr, &vval);
+ ret = get8(m, addr, &vval);
if (ret < 0)
error("indir: %r");
r->store.u.ival = vval;
@@ -316,7 +266,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 's':
r->type = TSTRING;
for(i = 0; i < sizeof(buf)-1; i++) {
- ret = xget1(m, addr, (uchar*)&buf[i], 1);
+ ret = get1(m, addr, (uchar*)&buf[i], 1);
if (ret < 0)
error("indir: %r");
addr++;
@@ -331,7 +281,7 @@ indir(Map *m, ulong addr, char fmt, Node *r)
case 'R':
r->type = TSTRING;
for(i = 0; i < sizeof(buf)-2; i += 2) {
- ret = xget1(m, addr, (uchar*)&buf[i], 2);
+ ret = get1(m, addr, (uchar*)&buf[i], 2);
if (ret < 0)
error("indir: %r");
addr += 2;
@@ -351,14 +301,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
r->store.u.string = strnode(buf);
break;
case 'f':
- ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
+ ret = get1(m, addr, (uchar*)buf, mach->szfloat);
if (ret < 0)
error("indir: %r");
mach->ftoa32(buf, sizeof(buf), (void*) buf);
convflt(r, buf);
break;
case 'g':
- ret = xget1(m, addr, (uchar*)buf, mach->szfloat);
+ ret = get1(m, addr, (uchar*)buf, mach->szfloat);
if (ret < 0)
error("indir: %r");
mach->ftoa32(buf, sizeof(buf), (void*) buf);
@@ -366,14 +316,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
r->store.u.string = strnode(buf);
break;
case 'F':
- ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
+ ret = get1(m, addr, (uchar*)buf, mach->szdouble);
if (ret < 0)
error("indir: %r");
mach->ftoa64(buf, sizeof(buf), (void*) buf);
convflt(r, buf);
break;
case '3': /* little endian ieee 80 with hole in bytes 8&9 */
- ret = xget1(m, addr, (uchar*)reg, 10);
+ ret = get1(m, addr, (uchar*)reg, 10);
if (ret < 0)
error("indir: %r");
memmove(reg+10, reg+8, 2); /* open hole */
@@ -382,14 +332,14 @@ indir(Map *m, ulong addr, char fmt, Node *r)
convflt(r, buf);
break;
case '8': /* big-endian ieee 80 */
- ret = xget1(m, addr, (uchar*)reg, 10);
+ ret = get1(m, addr, (uchar*)reg, 10);
if (ret < 0)
error("indir: %r");
beieeeftoa80(buf, sizeof(buf), reg);
convflt(r, buf);
break;
case 'G':
- ret = xget1(m, addr, (uchar*)buf, mach->szdouble);
+ ret = get1(m, addr, (uchar*)buf, mach->szdouble);
if (ret < 0)
error("indir: %r");
mach->ftoa64(buf, sizeof(buf), (void*) buf);
@@ -400,21 +350,70 @@ indir(Map *m, ulong addr, char fmt, Node *r)
}
void
-windir(Map *m, Node *addr, Node *rval, Node *r)
+indirreg(Regs *regs, char *name, char fmt, Node *r)
+{
+ ulong val;
+
+ if(regs == 0)
+ error("no register set for *%s=", name);
+
+ r->op = OCONST;
+ r->store.fmt = fmt;
+ switch(fmt){
+ default:
+ error("bad pointer format '%c' for *%s", fmt, name);
+ case 'c':
+ case 'C':
+ case 'b':
+ case 'x':
+ case 'd':
+ case 'u':
+ case 'o':
+ case 'q':
+ case 'r':
+ case 'a':
+ case 'A':
+ case 'B':
+ case 'X':
+ case 'D':
+ case 'U':
+ case 'O':
+ case 'Q':
+ case 'V':
+ case 'W':
+ case 'Y':
+ case 'Z':
+ if(rget(regs, name, &val) < 0)
+ error("reading %s: %r", name);
+ r->type = TINT;
+ r->store.u.ival = val;
+ break;
+ case 'f':
+ case 'g':
+ case 'F':
+ case '3':
+ case '8':
+ case 'G':
+ error("floating point registers not supported");
+ break;
+ }
+}
+
+void
+windir(Map *m, Node aes, Node *rval, Node *r)
{
uchar cval;
ushort sval;
- Node res, aes;
+ Node res;
int ret;
if(m == 0)
error("no map for */@=");
- expr(rval, &res);
- expr(addr, &aes);
-
if(aes.type != TINT)
- error("bad type lhs of @/*");
+ error("bad type lhs of */@=");
+
+ expr(rval, &res);
if(m != cormap && wtflag == 0)
error("not in write mode");
@@ -466,6 +465,58 @@ windir(Map *m, Node *addr, Node *rval, Node *r)
}
void
+windirreg(Regs *regs, char *name, Node *rval, Node *r)
+{
+ Node res;
+
+ if(regs == 0)
+ error("no register set for *%s=", name);
+
+ expr(rval, &res);
+
+ r->type = res.type;
+ r->store.fmt = res.store.fmt;
+ r->store = res.store;
+
+ switch(res.store.fmt){
+ default:
+ error("bad format '%c' for *%s=", res.store.fmt, name);
+ case 'c':
+ case 'C':
+ case 'b':
+ case 'x':
+ case 'd':
+ case 'u':
+ case 'o':
+ case 'q':
+ case 'r':
+ case 'a':
+ case 'A':
+ case 'B':
+ case 'X':
+ case 'D':
+ case 'U':
+ case 'O':
+ case 'Q':
+ case 'V':
+ case 'W':
+ case 'Y':
+ case 'Z':
+ if(rput(regs, name, res.store.u.ival) < 0)
+ error("writing %s: %r", name);
+ break;
+ case 'f':
+ case 'g':
+ case 'F':
+ case '3':
+ case '8':
+ case 'G':
+ error("floating point registers not supported");
+ break;
+ }
+}
+
+void
call(char *fn, Node *parameters, Node *local, Node *body, Node *retexp)
{
int np, i;
diff --git a/src/cmd/acid/expr.c b/src/cmd/acid/expr.c
index 9cfac9e3..6a0430dc 100644
--- a/src/cmd/acid/expr.c
+++ b/src/cmd/acid/expr.c
@@ -63,11 +63,29 @@ fmtsize(Value *v)
}
}
-void
+Lsym*
chklval(Node *lp)
{
- if(lp->op != ONAME)
- error("need l-value");
+ Node res;
+ Lsym *s;
+
+ if(lp->op == ONAME)
+ return lp->sym;
+
+ if(lp->op == OCALL){
+ s = chklval(lp->left);
+ if(strcmp(s->name, "var") == 0
+ && (lp->builtin || s->proc == 0)){
+ if(lp->right == 0)
+ error("var(string): arg count");
+ expr(lp->right, &res);
+ if(res.type != TSTRING)
+ error("var(string): arg type");
+ return mkvar(res.store.u.string->string);
+ }
+ }
+ error("need l-value");
+ return nil;
}
void
@@ -107,12 +125,24 @@ oindm(Node *n, Node *res)
if(m == 0)
m = symmap;
expr(n->left, &l);
- if(l.type != TINT)
+ switch(l.type){
+ default:
error("bad type for *");
- if(m == 0)
- error("no map for *");
- indir(m, l.store.u.ival, l.store.fmt, res);
- res->store.comt = l.store.comt;
+ case TINT:
+ if(m == 0)
+ error("no map for *");
+ indir(m, l.store.u.ival, l.store.fmt, res);
+ res->store.comt = l.store.comt;
+ break;
+ case TREG:
+ indirreg(correg, l.store.u.reg, l.store.fmt, res);
+ res->store.comt = l.store.comt;
+ break;
+ case TCON:
+ *res = *l.store.u.con;
+ res->store.comt = l.store.comt;
+ break;
+ }
}
void
@@ -145,7 +175,7 @@ oframe(Node *n, Node *res)
while(*p && *p == '$')
p++;
lp = n->left;
- if(localaddr(cormap, correg, p, lp->sym->name, &ival) < 0)
+ if(localaddr(cormap, acidregs, p, lp->sym->name, &ival) < 0)
error("colon: %r");
res->store.u.ival = ival;
@@ -296,19 +326,24 @@ void
oasgn(Node *n, Node *res)
{
Node *lp, r;
+ Node aes;
Value *v;
lp = n->left;
switch(lp->op) {
case OINDM:
- windir(cormap, lp->left, n->right, res);
+ expr(lp->left, &aes);
+ if(aes.type == TREG)
+ windirreg(correg, aes.store.u.reg, n->right, res);
+ else
+ windir(cormap, aes, n->right, res);
break;
case OINDC:
- windir(symmap, lp->left, n->right, res);
+ expr(lp->left, &aes);
+ windir(symmap, aes, n->right, res);
break;
default:
- chklval(lp);
- v = lp->sym->v;
+ v = chklval(lp)->v;
expr(n->right, &r);
v->set = 1;
v->type = r.type;
@@ -871,8 +906,7 @@ oeinc(Node *n, Node *res)
{
Value *v;
- chklval(n->left);
- v = n->left->sym->v;
+ v = chklval(n->left)->v;
res->op = OCONST;
res->type = v->type;
switch(v->type) {
@@ -899,8 +933,7 @@ opinc(Node *n, Node *res)
{
Value *v;
- chklval(n->left);
- v = n->left->sym->v;
+ v = chklval(n->left)->v;
res->op = OCONST;
res->type = v->type;
res->store = v->store;
@@ -932,9 +965,7 @@ ocall(Node *n, Node *res)
res->type = TLIST;
res->store.u.l = 0;
- chklval(n->left);
- s = n->left->sym;
-
+ s = chklval(n->left);
if(n->builtin && !s->builtin){
error("no builtin %s", s->name);
return;
@@ -959,6 +990,12 @@ ofmt(Node *n, Node *res)
}
void
+ouplus(Node *n, Node *res)
+{
+ expr(n->left, res);
+}
+
+void
owhat(Node *n, Node *res)
{
res->op = OCONST; /* Default return value */
@@ -1021,6 +1058,7 @@ initexpop(void)
expop[OFMT] = ofmt;
expop[OEVAL] = oeval;
expop[OWHAT] = owhat;
+ expop[OUPLUS] = ouplus;
}
void
@@ -1030,3 +1068,54 @@ initexpr(void)
initexpop();
}
+int
+acidregsrw(Regs *r, char *name, ulong *u, int isr)
+{
+ Lsym *l;
+ Value *v;
+ Node *n;
+ ulong addr;
+ u32int u32;
+
+ if(!isr){
+ werrstr("cannot write registers");
+ return -1;
+ }
+ USED(r);
+ l = look(name);
+ if(l == nil){
+ werrstr("register %s not found", name);
+ return -1;
+ }
+ v = l->v;
+ switch(v->type){
+ default:
+ werrstr("*%s: bad type", name);
+ return -1;
+ case TREG:
+ if(correg == nil){
+ werrstr("*%s: register %s not mapped", name, v->store.u.reg);
+ return -1;
+ }
+ return rget(correg, v->store.u.reg, u);
+ case TCON:
+ n = v->store.u.con;
+ if(n->op != OCONST || n->type != TINT){
+ werrstr("*%s: bad register constant", name);
+ return -1;
+ }
+ *u = n->store.u.ival;
+ return 0;
+ case TINT:
+ if(cormap == nil){
+ werrstr("*%s: core not mapped", name);
+ return -1;
+ }
+ addr = v->store.u.ival;
+ /* XXX should use format to determine size */
+ if(get4(cormap, addr, &u32) < 0)
+ return -1;
+ *u = u32;
+ return 0;
+ }
+}
diff --git a/src/cmd/acid/main.c b/src/cmd/acid/main.c
index 87f59798..e885b01d 100644
--- a/src/cmd/acid/main.c
+++ b/src/cmd/acid/main.c
@@ -106,6 +106,8 @@ main(int argc, char *argv[])
pushfile(0);
loadvars();
installbuiltin();
+ acidregs = mallocz(sizeof *acidregs, 1);
+ acidregs->rw = acidregsrw;
if(mtype && machbyname(mtype) == 0)
print("unknown machine %s", mtype);
@@ -172,16 +174,29 @@ main(int argc, char *argv[])
*/
}
+void
+setstring(char *var, char *s)
+{
+ Lsym *l;
+ Value *v;
+
+ l = mkvar(var);
+ v = l->v;
+ v->store.fmt = 's';
+ v->set = 1;
+ v->store.u.string = strnode(s ? s : "");
+ v->type = TSTRING;
+}
+
static int
attachfiles(int argc, char **argv)
{
int fd;
volatile int pid;
- char *s;
+ char *s, *t;
int i, omode;
Fhdr *hdr;
Lsym *l;
- Value *v;
pid = 0;
interactive = 0;
@@ -220,7 +235,6 @@ attachfiles(int argc, char **argv)
}
fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
if(hdr->ftype == FCORE){
- fprint(2, "cmd: %s\n", hdr->cmd);
if(pid){
fprint(2, "already have pid %d; ignoring core %s\n", pid, argv[i]);
uncrackhdr(hdr);
@@ -252,12 +266,28 @@ attachfiles(int argc, char **argv)
symfil = s;
}
}
- /* XXX pull command from core */
+ if(corhdr){
+ /*
+ * prog gives only the basename of the command,
+ * so try the command line for a path.
+ */
+ if((s = strdup(corhdr->cmdline)) != nil){
+ t = strchr(s, ' ');
+ if(t)
+ *t = 0;
+ if((t = searchpath(s)) != nil){
+ fprint(2, "core: text %s\n", t);
+ symfil = t;
+ }
+ free(s);
+ }
+ }
if((symhdr = crackhdr(symfil, omode)) == nil){
fprint(2, "crackhdr %s: %r\n", symfil);
symfil = nil;
- }
+ }else
+ fprint(2, "%s: %s %s %s\n", symfil, symhdr->aname, symhdr->mname, symhdr->fname);
}
if(symhdr)
@@ -281,33 +311,15 @@ attachfiles(int argc, char **argv)
}
Run:
- l = mkvar("objtype");
- v = l->v;
- v->store.fmt = 's';
- v->set = 1;
- v->store.u.string = strnode(mach->name);
- v->type = TSTRING;
-
- l = mkvar("textfile");
- v = l->v;
- v->store.fmt = 's';
- v->set = 1;
- v->store.u.string = strnode(symfil ? symfil : "");
- v->type = TSTRING;
-
- l = mkvar("systype");
- v = l->v;
- v->store.fmt = 's';
- v->set = 1;
- v->store.u.string = strnode(symhdr ? symhdr->aname : "");
- v->type = TSTRING;
+ setstring("objtype", mach->name);
+ setstring("textfile", symfil);
+ setstring("systype", symhdr ? symhdr->aname : "");
+ setstring("corefile", corfil);
- l = mkvar("corefile");
- v = l->v;
- v->store.fmt = 's';
- v->set = 1;
- v->store.u.string = strnode(corfil ? corfil : "");
- v->type = TSTRING;
+ l = mkvar("pids");
+ l->v->set = 1;
+ l->v->type = TLIST;
+ l->v->store.u.l = nil;
if(pid)
sproc(pid);
@@ -320,6 +332,11 @@ Run:
void
setcore(Fhdr *hdr)
{
+ int i;
+ Lsym *l;
+ Value *v;
+ List **tail, *tl;
+
unmapproc(cormap);
unmapfile(corhdr, cormap);
free(correg);
@@ -331,6 +348,31 @@ setcore(Fhdr *hdr)
error("mapfile %s: %r", hdr->filename);
corhdr = hdr;
corfil = hdr->filename;
+
+ l = mkvar("pid");
+ v = l->v;
+ v->store.fmt = 'D';
+ v->set = 1;
+ v->store.u.ival = hdr->pid;
+
+ setstring("corefile", corfil);
+ setstring("cmdline", hdr->cmdline);
+
+ l = mkvar("pids");
+ l->v->set = 1;
+ l->v->type = TLIST;
+ l->v->store.u.l = nil;
+ tail = &l->v->store.u.l;
+ for(i=0; i<hdr->nthread; i++){
+ tl = al(TINT);
+ tl->store.u.ival = hdr->thread[i].id;
+ tl->store.fmt = 'X';
+ *tail = tl;
+ tail = &tl->next;
+ }
+
+ if(hdr->nthread)
+ sproc(hdr->thread[0].id);
}
void
@@ -338,16 +380,21 @@ die(void)
{
Lsym *s;
List *f;
+ int first;
Bprint(bout, "\n");
+ first = 1;
s = look("proclist");
if(s && s->v->type == TLIST) {
for(f = s->v->store.u.l; f; f = f->next){
detachproc((int)f->store.u.ival);
- Bprint(bout, "/bin/kill -9 %d\n", (int)f->store.u.ival);
+ Bprint(bout, "%s %d", first ? "/bin/kill -9" : "", (int)f->store.u.ival);
+ first = 0;
}
}
+ if(!first)
+ Bprint(bout, "\n");
exits(0);
}
@@ -545,6 +592,9 @@ gc(void)
case TCODE:
marktree(v->store.u.cc);
break;
+ case TCON:
+ marktree(v->store.u.con);
+ break;
}
}
}
diff --git a/src/cmd/acid/print.c b/src/cmd/acid/print.c
index 0c66e024..58acdfc9 100644
--- a/src/cmd/acid/print.c
+++ b/src/cmd/acid/print.c
@@ -401,6 +401,10 @@ pexpr(Node *n)
if(n->sym)
Bprint(bout, " %s", n->sym->name);
break;
+ case OUPLUS:
+ Bprint(bout, "+");
+ pexpr(l);
+ break;
}
}
diff --git a/src/cmd/acid/proc.c b/src/cmd/acid/proc.c
index a0aed614..02c44533 100644
--- a/src/cmd/acid/proc.c
+++ b/src/cmd/acid/proc.c
@@ -21,30 +21,39 @@ sproc(int xpid)
if(pid == xpid)
return;
- if(xpid <= 0)
- error("bad pid");
-
- unmapproc(cormap);
- unmapfile(corhdr, cormap);
- free(correg);
- correg = nil;
-
- if(mapproc(xpid, cormap, &correg) < 0)
- error("setproc %d: %r", xpid);
-
- /* XXX check text file here? */
-
+ if(corhdr){
+ free(correg);
+ correg = nil;
+ correg = coreregs(corhdr, xpid);
+ if(correg == nil)
+ error("no such pid in core dump");
+ }else{
+ /* XXX should only change register set here if cormap already mapped */
+ if(xpid <= 0)
+ error("bad pid");
+ unmapproc(cormap);
+ unmapfile(corhdr, cormap);
+ free(correg);
+ correg = nil;
+
+ if(mapproc(xpid, cormap, &correg) < 0)
+ error("setproc %d: %r", xpid);
+
+ /* XXX check text file here? */
+
+ for(i=0; i<cormap->nseg; i++){
+ if(cormap->seg[i].file == nil){
+ if(strcmp(cormap->seg[i].name, "data") == 0)
+ cormap->seg[i].name = "*data";
+ if(strcmp(cormap->seg[i].name, "text") == 0)
+ cormap->seg[i].name = "*text";
+ }
+ }
+ }
pid = xpid;
s = look("pid");
s->v->store.u.ival = pid;
- for(i=0; i<cormap->nseg; i++)
- if(cormap->seg[i].file == nil){
- if(strcmp(cormap->seg[i].name, "data") == 0)
- cormap->seg[i].name = "*data";
- if(strcmp(cormap->seg[i].name, "text") == 0)
- cormap->seg[i].name = "*text";
- }
install(pid);
}
@@ -165,6 +174,7 @@ install(int pid)
s->v->set = 1;
}
+/*
static int
installed(int pid)
{
@@ -175,6 +185,7 @@ installed(int pid)
return 1;
return 0;
}
+*/
void
deinstall(int pid)
diff --git a/src/cmd/acid/util.c b/src/cmd/acid/util.c
index 355fd5b7..3ea3c4c0 100644
--- a/src/cmd/acid/util.c
+++ b/src/cmd/acid/util.c
@@ -61,7 +61,6 @@ varsym(void)
continue;
addvarsym(fp);
}
-
if(l->v->store.u.l == nil)
print("no debugging symbols\n");
}
@@ -217,9 +216,9 @@ varreg(void)
l = mkvar(r->name);
v = l->v;
v->set = 1;
- v->store.u.ival = r->offset;
+ v->store.u.reg = r->name;
v->store.fmt = r->format;
- v->type = TINT;
+ v->type = TREG;
li = al(TSTRING);
li->store.u.string = strnode(r->name);