diff 96ac4cdaa40a473766aa985120764dfe9863cd67 uncommitted --- a//sys/include/dtracy.h +++ b//sys/include/dtracy.h @@ -223,9 +223,10 @@ /* filled in by caller of dtptrigger */ u64int arg[10]; /* filled in by dtptrigger */ - int machno; - int epid; - u64int ts; + int machno; + int epid; + u64int ts; + int ptag; DTChan *ch; }; @@ -304,6 +305,7 @@ DTV_ARG9, DTV_PID, DTV_MACHNO, + DTV_PTAG, DTV_TIME, DTV_PROBE, DTNVARS, --- a//sys/src/9/port/devdtracy.c +++ b//sys/src/9/port/devdtracy.c @@ -82,7 +82,8 @@ static DTKChan * dtklook(vlong n) { - if((uvlong)n >= ndtktab) return nil; + if((uvlong)n >= ndtktab) + return nil; return dtktab[n]; } #define QIDPATH(q,e) ((q) + 1 << 8 | (e)) @@ -97,7 +98,8 @@ int i; p = malloc(sizeof(DTKChan)); - if(p == nil) error(Enomem); + if(p == nil) + error(Enomem); for(i = 0; i < ndtktab; i++) if(dtktab[i] == nil){ dtktab[i] = p; @@ -106,7 +108,8 @@ } if(i == ndtktab){ newtab = realloc(dtktab, (ndtktab + 1) * sizeof(DTKChan *)); - if(newtab == nil) error(Enomem); + if(newtab == nil) + error(Enomem); dtktab = newtab; dtktab[ndtktab] = p; p->idx = ndtktab++; @@ -132,7 +135,8 @@ dtracyinit(void) { dtracyen = getconf("*dtracy") != nil; - if(!dtracyen) return; + if(!dtracyen) + return; machlocks = smalloc(sizeof(Lock) * conf.nmach); dtinit(conf.nmach); } @@ -156,10 +160,14 @@ return 1; } if(c->qid.path == Qdir){ - if(s-- == 0) goto clone; - if(s-- == 0) goto probes; - if(s >= ndtktab) return -1; - if(dtklook(s) == nil) return 0; + if(s-- == 0) + goto clone; + if(s-- == 0) + goto probes; + if(s >= ndtktab) + return -1; + if(dtklook(s) == nil) + return 0; sprint(up->genbuf, "%d", s); devdir(c, (Qid){QIDPATH(s, Qdir), 0, QTDIR}, up->genbuf, 0, eve, DMDIR|0555, dp); return 1; @@ -228,7 +236,8 @@ nexterror(); } if(c->qid.path == Qclone){ - if(!iseve()) error(Eperm); + if(!iseve()) + error(Eperm); p = dtknew(); c->qid.path = QIDPATH(p->idx, Qctl); } @@ -236,11 +245,14 @@ p = nil; }else{ p = dtklook(SLOT(c->qid)); - if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist); - if(FILE(c->qid) != Qdir && !iseve()) error(Eperm); + if(SLOT(c->qid) >= 0 && p == nil) + error(Enonexist); + if(FILE(c->qid) != Qdir && !iseve()) + error(Eperm); } ch = devopen(c, omode, nil, 0, dtracygen); - if(p != nil) p->ref++; + if(p != nil) + p->ref++; qunlock(&dtracylock); poperror(); ch->aux = smalloc(sizeof(DTKAux)); @@ -309,8 +321,10 @@ for(;;){ rc = lockedread(c, a, n, readf); - if(rc < 0) return -1; - if(rc > 0) break; + if(rc < 0) + return -1; + if(rc > 0) + break; tsleep(&up->sleep, return0, 0, 250); } m = rc; @@ -317,7 +331,8 @@ for(i = 0; i < 3 && m < n/2; i++){ tsleep(&up->sleep, return0, 0, 50); rc = lockedread(c, (uchar *)a + m, n - m, readf); - if(rc < 0) break; + if(rc < 0) + break; m += rc; } return m; @@ -365,7 +380,8 @@ error(Egreg); } p = dtklook(SLOT(c->qid)); - if(p == nil) error(Enonexist); + if(p == nil) + error(Enonexist); switch(FILE(c->qid)){ case Qdir: rc = devdirread(c, a, n, nil, 0, dtracygen); @@ -418,7 +434,8 @@ error(Egreg); } p = dtklook(SLOT(c->qid)); - if(p == nil) error(Enonexist); + if(p == nil) + error(Enonexist); switch(FILE(c->qid)){ case Qdir: error(Eperm); @@ -550,6 +567,8 @@ switch(v){ case DTV_PID: return up != nil ? up->pid : 0; + case DTV_PTAG: + return up != nil ? up->ptag : 0; default: return 0; } @@ -563,8 +582,11 @@ uintptr a; a = addr; - if(len == 0) return 0; - if(a != addr || a > -(uintptr)len || len < 0) return -1; - if(up == nil || up->privatemem || a >= KZERO) return -1; + if(len == 0) + return 0; + if(a != addr || a > -(uintptr)len || len < 0) + return -1; + if(up == nil || up->privatemem || a >= KZERO) + return -1; return peek((void *)a, buf, len) > 0 ? -1 : 0; } --- a//sys/src/cmd/dtracy/act.c +++ b//sys/src/cmd/dtracy/act.c @@ -11,6 +11,7 @@ Clause *clause; Clause **clauses; int nclauses; +int aggid; /* we could just rely on the types in the expression tree but i'm paranoid */ typedef struct Val Val; @@ -106,6 +107,7 @@ clause->stats = erealloc(clause->stats, sizeof(Stat) * (clause->nstats + 1)); s = &clause->stats[clause->nstats++]; + memset(s, 0, sizeof(Stat)); s->type = type; va_start(va, type); @@ -173,8 +175,10 @@ int n; Fmt f; - if(narg <= 0) sysfatal("printf() needs an argument"); - if((*arg)->type != OSTR) sysfatal("printf() format string must be a literal"); + if(narg <= 0) + sysfatal("printf() needs an argument"); + if((*arg)->type != OSTR) + sysfatal("printf() format string must be a literal"); fmt = (*arg)->str; fmtstrinit(&f); n = 1; @@ -185,13 +189,16 @@ fmt++; again: switch(*fmt){ - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case 'u': case '+': case '-': case ',': case '#': case ' ': case '.': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'u': case '+': case '-': case ',': case '#': + case ' ': case '.': fmtrune(&f, *fmt); fmt++; goto again; case 'x': case 'X': case 'o': case 'b': case 'd': - if(n >= narg) sysfatal("printf() too few arguments"); + if(n >= narg) + sysfatal("printf() too few arguments"); if(arg[n]->typ->type != TYPINT) sysfatal("%d: print() %%%c with non-integer", arg[n]->line, *fmt); arg[n] = tracegen(arg[n], g, recoff); @@ -201,7 +208,8 @@ fmtrune(&f, *fmt); break; case 's': - if(n >= narg) sysfatal("printf() too few arguments"); + if(n >= narg) + sysfatal("printf() too few arguments"); if(arg[n]->typ->type != TYPSTRING) sysfatal("%d: print() %%s with non-string", arg[n]->line); arg[n] = tracegen(arg[n], g, recoff); @@ -208,16 +216,19 @@ n++; fmtrune(&f, *fmt); break; - case 0: sysfatal("printf() missing verb"); - default: sysfatal("printf() unknown verb %%%c", *fmt); + case 0: + sysfatal("printf() missing verb"); + break; + default: + sysfatal("printf() unknown verb %%%c", *fmt); + break; } } - if(n < narg) sysfatal("printf() too many arguments"); + if(n < narg) + sysfatal("printf() too many arguments"); (*arg)->str = fmtstrflush(&f); } -int aggid; - int allagg(Clause *c) { @@ -328,22 +339,26 @@ for(;;) switch(*fmt++){ case 'c': - if(p + 1 > e) return nil; + if(p + 1 > e) + return nil; *va_arg(va, u8int *) = p[0]; p += 1; break; case 's': - if(p + 2 > e) return nil; + if(p + 2 > e) + return nil; *va_arg(va, u16int *) = p[0] | p[1] << 8; p += 2; break; case 'i': - if(p + 4 > e) return nil; + if(p + 4 > e) + return nil; *va_arg(va, u32int *) = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; p += 4; break; case 'v': - if(p + 8 > e) return nil; + if(p + 8 > e) + return nil; vl = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; vl |= (uvlong)p[4] << 32 | (uvlong)p[5] << 40 | (uvlong)p[6] << 48 | (uvlong)p[7] << 56; *va_arg(va, u64int *) = vl; @@ -376,14 +391,23 @@ q = unpack(p + 4, e, "v", &v); assert(q != nil); return mkval(VALINT, v); + case DTV_PTAG: + q = unpack(p + 12, e, "i", &i); + assert(q != nil); + return mkval(VALINT, i); case DTV_PROBE: return mkval(VALSTR, en->probe); - default: sysfatal("receval: unknown variable %d", n->type); return mkval(VALINT, 0LL); + default: + sysfatal("receval: unknown variable %d", n->type); + return mkval(VALINT, 0LL); } break; - default: sysfatal("receval: unknown symbol type %d", n->type); return mkval(VALINT, 0LL); + default: + sysfatal("receval: unknown symbol type %d", n->type); + return mkval(VALINT, 0LL); } - case ONUM: return mkval(VALINT, n->num); + case ONUM: + return mkval(VALINT, n->num); case OBIN: a = receval(n->n1, p, e, en); b = receval(n->n2, p, e, en); @@ -402,11 +426,24 @@ switch(n->typ->type){ case TYPINT: switch(n->typ->size){ - case 1: q = unpack(p + n->num, e, "c", &c); v = n->typ->sign ? (s8int)c : (u8int)c; break; - case 2: q = unpack(p + n->num, e, "s", &s); v = n->typ->sign ? (s16int)s : (u16int)s; break; - case 4: q = unpack(p + n->num, e, "i", &i); v = n->typ->sign ? (s32int)i : (u32int)i; break; - case 8: q = unpack(p + n->num, e, "v", &v); break; - default: q = nil; + case 1: + q = unpack(p + n->num, e, "c", &c); + v = n->typ->sign ? (s8int)c : (u8int)c; + break; + case 2: + q = unpack(p + n->num, e, "s", &s); + v = n->typ->sign ? (s16int)s : (u16int)s; + break; + case 4: + q = unpack(p + n->num, e, "i", &i); + v = n->typ->sign ? (s32int)i : (u32int)i; + break; + case 8: + q = unpack(p + n->num, e, "v", &v); + break; + default: + q = nil; + break; } assert(q != nil); return mkval(VALINT, v); @@ -460,7 +497,8 @@ for(s = cl->stats; s < cl->stats + cl->nstats; s++) switch(s->type){ - case STATEXPR: break; + case STATEXPR: + break; case STATPRINT: for(i = 0; i < s->narg; i++){ v = receval(s->arg[i], p, e, en); @@ -471,7 +509,8 @@ case VALSTR: Bprint(bp, "%s", v.s); break; - default: sysfatal("parseclause: unknown val type %d", s->type); + default: + sysfatal("parseclause: unknown val type %d", s->type); } Bprint(bp, "%c", i == s->narg - 1 ? '\n' : ' '); } @@ -479,7 +518,8 @@ case STATPRINTF: execprintf(s->arg, s->narg, p, e, en); break; - case STATAGG: break; + case STATAGG: + break; default: sysfatal("parseclause: unknown type %d", s->type); } @@ -490,24 +530,23 @@ parsefault(uchar *p0, uchar *e) { uchar *p; - u32int epid; + u64int addr; + u32int pid, epid; u8int type, dummy; u16int n; Enab *en; p = unpack(p0, e, "csci", &type, &n, &dummy, &epid); - if(p == nil) return nil; + if(p == nil) + return nil; en = epidlookup(epid); switch(type){ - case DTFILL: { - u32int pid; - u64int addr; - + case DTFILL: p = unpack(p, e, "iv", &pid, &addr); - if(p == nil) return nil; + if(p == nil) + return nil; fprint(2, "dtracy: illegal access: probe=%s, pid=%d, addr=%#llx\n", en != nil ? en->probe : nil, pid, addr); break; - } default: fprint(2, "dtracy: unknown fault type %#.2ux\n", type); } @@ -517,24 +556,29 @@ int parsebuf(uchar *p, int n, Biobuf *bp) { - uchar *e; - u32int epid; + uchar *h, *e; + u32int epid, ptag; u64int ts; Enab *en; e = p + n; while(p < e){ - p = unpack(p, e, "iv", &epid, &ts); - if(p == nil) goto err; + h = p; + p = unpack(p, e, "ivi", &epid, &ts, &ptag); + if(p == nil) + goto err; if(epid == (u32int)-1){ p = parsefault(p, e); - if(p == nil) goto err; + if(p == nil) + goto err; continue; } en = epidlookup(epid); - if(en == nil) goto err; - if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1; - p += en->reclen - 12; + if(en == nil) + goto err; + if(parseclause(en->cl, h, h + en->reclen, en, bp) < 0) + return -1; + p = h + en->reclen; } return 0; err: @@ -613,24 +657,42 @@ p = f->width; n = va_arg(f->args, Node *); switch(n->type){ - case OSYM: fmtprint(f, "%s", n->sym->name); break; - case ONUM: fmtprint(f, "%lld", n->num); break; - case OSTR: fmtstring(f, n->str); break; + case OSYM: + fmtprint(f, "%s", n->sym->name); + break; + case ONUM: + fmtprint(f, "%lld", n->num); + break; + case OSTR: + fmtstring(f, n->str); + break; case OBIN: if(n->op >= nelem(optab) || optab[n->op].name == nil) fmtprint(f, "(%*ε ??op%d %*ε)", PREDUNARY, n->n1, n->op, PREDUNARY, n->n2); else{ op = &optab[n->op]; - if(op->pred < p) fmtrune(f, '('); + if(op->pred < p) + fmtrune(f, '('); fmtprint(f, "%*ε %s %*ε", op->pred + (op->flags & PRECRIGHT), n->n1, op->name, op->pred + (~op->flags & PRECRIGHT), n->n2); - if(op->pred < p) fmtrune(f, ')'); + if(op->pred < p) + fmtrune(f, ')'); } break; - case OLNOT: fmtprint(f, "!%*ε", PREDUNARY, n->n1); break; - case OTERN: fmtprint(f, "%2ε ? %1ε : %1ε", n->n1, n->n2, n->n3); break; - case ORECORD: fmtprint(f, "record(%ε, %τ, %d)", n->n1, n->typ, (int)n->num); break; - case OCAST: fmtprint(f, "(%τ) %*ε", n->typ, PREDUNARY, n->n1); break; - default: fmtprint(f, "??? %α", n->type); + case OLNOT: + fmtprint(f, "!%*ε", PREDUNARY, n->n1); + break; + case OTERN: + fmtprint(f, "%2ε ? %1ε : %1ε", n->n1, n->n2, n->n3); + break; + case ORECORD: + fmtprint(f, "record(%ε, %τ, %d)", n->n1, n->typ, (int)n->num); + break; + case OCAST: + fmtprint(f, "(%τ) %*ε", n->typ, PREDUNARY, n->n1); + break; + default: + fmtprint(f, "??? %α", n->type); + break; } return 0; } @@ -643,6 +705,7 @@ Clause *c; DTClause *d; DTAct *a; + char *k; for(i = 0; i < nclauses; i++){ c = clauses[i]; @@ -668,11 +731,13 @@ dumpexpr(a->p, "\t\t\t"); break; case ACTAGGKEY: - print("\t\taggregation key (%s,%d,%d)\n", a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type], a->agg.keysize, (u16int)a->agg.id); + k = a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type]; + print("\t\taggregation key (%s,%d,%d)\n", k, a->agg.keysize, (u16int)a->agg.id); dumpexpr(a->p, "\t\t\t"); break; case ACTAGGVAL: - print("\t\taggregation value (%s,%d,%d)\n", a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type], a->agg.keysize, (u16int)a->agg.id); + k = a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type]; + print("\t\taggregation value (%s,%d,%d)\n", k, a->agg.keysize, (u16int)a->agg.id); dumpexpr(a->p, "\t\t\t"); break; case ACTCANCEL: --- a//sys/src/cmd/dtracy/cgen.c +++ b//sys/src/cmd/dtracy/cgen.c @@ -182,7 +182,9 @@ rt = regalloc(); emit(DTE(DTE_LDV, n->sym->idx, rt, 0)); return rt; - default: sysfatal("egen: unknown symbol type %d", n->sym->type); return 0; + default: + sysfatal("egen: unknown symbol type %d", n->sym->type); + return 0; } case OBIN: switch(/*oper*/n->op){ @@ -204,7 +206,9 @@ case OPLT: op = DTE_SLT; break; case OPLE: op = DTE_SLE; break; case OPXNOR: op = DTE_XNOR; break; - default: sysfatal("egen: unknown op %d", n->op); return 0; + default: + sysfatal("egen: unknown op %d", n->op); + return 0; } r1 = egen(n->n1); r2 = egen(n->n2); @@ -238,9 +242,12 @@ default: sysfatal("egen: don't know how to cast %τ to %τ", n->n1->typ, n->typ); } + return 0; case ORECORD: case OSTR: - default: sysfatal("egen: unknown type %α", n->type); return 0; + default: + sysfatal("egen: unknown type %α", n->type); + return 0; } } @@ -307,7 +314,8 @@ n->num = *recoff; *recoff += n->typ->size; return n; - default: sysfatal("tracegen: unknown type %α", n->type); return nil; + default: + sysfatal("tracegen: unknown type %α", n->type); return nil; } return n; } --- a//sys/src/cmd/dtracy/dtracy.c +++ b//sys/src/cmd/dtracy/dtracy.c @@ -29,7 +29,8 @@ void *v; v = malloc(n); - if(v == nil) sysfatal("malloc: %r"); + if(v == nil) + sysfatal("malloc: %r"); memset(v, 0, n); setmalloctag(v, getcallerpc(&n)); return v; @@ -40,7 +41,8 @@ { v = realloc(v, n); if(n != 0){ - if(v == nil) sysfatal("realloc: %r"); + if(v == nil) + sysfatal("realloc: %r"); setrealloctag(v, getcallerpc(&v)); } return v; @@ -85,6 +87,7 @@ defvar("pid", DTV_PID, type(TYPINT, 4, 1)); defvar("machno", DTV_MACHNO, type(TYPINT, 4, 1)); defvar("time", DTV_TIME, type(TYPINT, 8, 0)); + defvar("ptag", DTV_PTAG, type(TYPINT, 4, 1)); defvar("probe", DTV_PROBE, type(TYPSTRING)); } @@ -97,9 +100,11 @@ snprint(buf, sizeof(buf), "%s/clone", dtracyroot); ctlfd = open(buf, ORDWR); - if(ctlfd < 0) return -1; + if(ctlfd < 0) + return -1; n = read(ctlfd, buf, sizeof(buf) - 1); - if(n < 0) return -1; + if(n < 0) + return -1; buf[n] = 0; dtracyno = strtol(buf, &p, 10); if(p == buf || *p != 0){ @@ -108,7 +113,8 @@ } snprint(buf, sizeof(buf), "%s/%d/buf", dtracyroot, dtracyno); buffd = open(buf, OREAD); - if(buffd < 0) return -1; + if(buffd < 0) + return -1; return 0; } @@ -125,7 +131,8 @@ prog = fmtstrflush(&f); snprint(buf, sizeof(buf), "%s/%d/prog", dtracyroot, dtracyno); fd = open(buf, OWRITE); - if(fd < 0) return -1; + if(fd < 0) + return -1; if(write(fd, prog, strlen(prog)) < 0){ close(fd); return -1; @@ -145,7 +152,8 @@ snprint(buf, sizeof(buf), "%s/%d/epid", dtracyroot, dtracyno); bp = Bopen(buf, OREAD); - if(bp == nil) return -1; + if(bp == nil) + return -1; for(; s = Brdstr(bp, '\n', 1), s != nil; free(s)){ if(tokenize(s, f, nelem(f)) != 4) goto err; @@ -185,13 +193,17 @@ extern int interrupted; switch(rfork(RFPROC|RFMEM)){ - case -1: sysfatal("rfork: %r"); - case 0: return; - default: break; + case -1: + sysfatal("rfork: %r"); + case 0: + return; + default: + break; } snprint(buf, sizeof(buf), "%s/%d/aggbuf", dtracyroot, dtracyno); buffd = open(buf, OREAD); - if(buffd < 0) sysfatal("open: %r"); + if(buffd < 0) + sysfatal("open: %r"); agginit(); atnotify(aggnote, 1); while(!interrupted){ @@ -251,7 +263,8 @@ sysfatal("epidread: %r"); fprint(ctlfd, "go"); out = Bfdopen(1, OWRITE); - if(out == nil) sysfatal("Bfdopen: %r"); + if(out == nil) + sysfatal("Bfdopen: %r"); if(aggid > 0) aggproc(); for(;;) --- a//sys/src/cmd/dtracy/lex.c +++ b//sys/src/cmd/dtracy/lex.c @@ -131,15 +131,22 @@ if(ch == '*'){ s1: ch = getch(); - if(ch < 0) return -1; - if(ch == '\n') lineno++; - if(ch != '*') goto s1; + if(ch < 0) + return -1; + if(ch == '\n') + lineno++; + if(ch != '*') + goto s1; s2: ch = getch(); - if(ch < 0) return -1; - if(ch == '\n') lineno++; - if(ch == '*') goto s2; - if(ch != '/') goto s1; + if(ch < 0) + return -1; + if(ch == '\n') + lineno++; + if(ch == '*') + goto s2; + if(ch != '/') + goto s1; goto again; } ungetch(); @@ -333,10 +340,14 @@ t = va_arg(f->args, Type *); switch(t->type){ - case TYPINT: return fmtprint(f, "%c%d", t->sign ? 's' : 'u', t->size * 8); - case TYPSTRING: return fmtprint(f, "string"); - case TYPPTR: return fmtprint(f, "%τ*", t->ref); - default: return fmtprint(f, "%t", t->type); + case TYPINT: + return fmtprint(f, "%c%d", t->sign ? 's' : 'u', t->size * 8); + case TYPSTRING: + return fmtprint(f, "string"); + case TYPPTR: + return fmtprint(f, "%τ*", t->ref); + default: + return fmtprint(f, "%t", t->type); } } @@ -385,10 +396,15 @@ case 0x41: return &typs32; case 0x80: return &typu64; case 0x81: return &typs64; - default: sysfatal("type: invalid (size,sign) = (%d,%d)\n", size, sign); return nil; + default: + sysfatal("type: invalid (size,sign) = (%d,%d)\n", size, sign); + return nil; } - case TYPSTRING: return &typstr; - case TYPPTR: return mkptr(va_arg(va, Type *)); - default: sysfatal("type: unknown %t", typ); return nil; + case TYPSTRING: + return &typstr; + case TYPPTR: + return mkptr(va_arg(va, Type *)); + default: + sysfatal("type: unknown %t", typ); return nil; } } --- a//sys/src/cmd/dtracy/parse.y +++ b//sys/src/cmd/dtracy/parse.y @@ -8,22 +8,22 @@ %} %union{ - Node *n; - Symbol *sym; - DTExpr *e; - s64int num; - char *str; - Type *t; + Node *n; + Symbol *sym; + DTExpr *e; + char *str; + Type *t; + s64int num; } -%type expr optexpr -%type optsym -%type type -%type probe +%type expr optexpr +%type optsym +%type type +%type probe -%token TSYM -%token TNUM -%token TSTR +%token TSYM +%token TNUM +%token TSTR %token TPRINT TPRINTF %token TIF %token TU8 TU16 TU32 TU64 @@ -46,41 +46,54 @@ %% -program: | program clause +program : /* empty */ + | program clause + ; -clause: { clausebegin(); } probes optpredicate optaction { clauseend(); } +clause : { clausebegin(); } probes optpredicate optaction { clauseend(); } + ; +optpredicate + : /* empty */ + | /* TIF expr { addpred(codegen(exprcheck($2, 1))); } + ; -optpredicate: | TIF expr { addpred(codegen(exprcheck($2, 1))); } - -optaction: - { +optaction + : /* empty */{ addstat(STATPRINT); addarg(node(OSYM, getsym("probe"))); } | action -action: '{' stats '}' -stats: | stats0 | stats0 ';' -stats0: stat | stats0 ';' stat + ; +action : '{' stats '}' + ; +stats : | stats0 | stats0 ';' + ; +stats0 : stat | stats0 ';' stat + ; +stat : expr { addstat(STATEXPR, exprcheck($1, 0)); } + | TPRINT { addstat(STATPRINT); } pelist + | TPRINTF { addstat(STATPRINTF); } pelist + | '@' optsym '[' expr ']' '=' TSYM '(' optexpr ')' { addstat(STATAGG, $2, $4, $7, $9); } + ; +optsym : TSYM | { $$ = nil; } + ; +optexpr : expr | { $$ = nil; } + ; -stat: expr { addstat(STATEXPR, exprcheck($1, 0)); } -| TPRINT { addstat(STATPRINT); } pelist -| TPRINTF { addstat(STATPRINTF); } pelist -| '@' optsym '[' expr ']' '=' TSYM '(' optexpr ')' { addstat(STATAGG, $2, $4, $7, $9); } -optsym: TSYM | { $$ = nil; } -optexpr: expr | { $$ = nil; } - -pelist: - '(' ')' +pelist : '(' ')' | '(' arg ',' ')' | '(' elist2 optcomma ')' | arg optcomma | elist2 optcomma -elist2: arg ',' arg | elist2 ',' arg -arg: expr { addarg(exprcheck($1, 0)); } -optcomma: | ',' - -expr: - TSYM { $$ = node(OSYM, $1); } + ; +elist2 : arg ',' arg | elist2 ',' arg + ; +arg : expr { addarg(exprcheck($1, 0)); } + ; +optcomma: /* empty */ + | ',' + ; +expr : TSYM { $$ = node(OSYM, $1); } | TNUM { $$ = node(ONUM, $1); } | TSTR { $$ = node(OSTR, $1); } | expr '+' expr { $$ = node(OBIN, OPADD, $1, $3); } @@ -107,9 +120,8 @@ | '(' expr ')' { $$ = $2; } | expr '?' expr ':' expr %prec '?' { $$ = node(OTERN, $1, $3, $5); } | '(' type ')' expr %prec castprec { $$ = node(OCAST, $2, $4); } - -type: - TU8 { $$ = type(TYPINT, 1, 0); } + ; +type : TU8 { $$ = type(TYPINT, 1, 0); } | TS8 { $$ = type(TYPINT, 1, 1); } | TU16 { $$ = type(TYPINT, 2, 0); } | TS16 { $$ = type(TYPINT, 2, 1); } @@ -118,13 +130,12 @@ | TU64 { $$ = type(TYPINT, 8, 0); } | TS64 { $$ = type(TYPINT, 8, 1); } | TSTRING { $$ = type(TYPSTRING); } - -probes: - probe { addprobe($1); } + ; +probes : probe { addprobe($1); } | probes ',' probe { addprobe($3); } - -probe: - TSYM { $$ = $1->name; } + ; +probe : TSYM { $$ = $1->name; } | TSTR { $$ = $1; } + ; %% --- a//sys/src/cmd/dtracy/type.c +++ b//sys/src/cmd/dtracy/type.c @@ -16,12 +16,12 @@ } /* - the type checker checks types. - the result is an expression that is correct if evaluated with 64-bit operands all the way. - to maintain c-like semantics, this means adding casts all over the place, which will get optimised later. - - note we use kencc, NOT ansi c, semantics for unsigned. -*/ + * the type checker checks types. + * the result is an expression that is correct if evaluated with 64-bit operands all the way. + * to maintain c-like semantics, this means adding casts all over the place, which will get optimised later. + * + * note we use kencc, NOT ansi c, semantics for unsigned. + */ Node * typecheck(Node *n) @@ -28,12 +28,18 @@ { int s1, s2, sign; - switch(/*nodetype*/n->type){ + switch(n->type){ case OSYM: switch(n->sym->type){ - case SYMNONE: error("undeclared '%s'", n->sym->name); break; - case SYMVAR: n->typ = n->sym->typ; break; - default: sysfatal("typecheck: unknown symbol type %d", n->sym->type); + case SYMNONE: + error("undeclared '%s'", n->sym->name); + break; + case SYMVAR: + n->typ = n->sym->typ; + break; + default: + sysfatal("typecheck: unknown symbol type %d", n->sym->type); + break; } break; case ONUM: @@ -160,7 +166,9 @@ error("don't know how to do ternary with %τ and %τ", n->n2->typ, n->n3->typ); break; case ORECORD: - default: sysfatal("typecheck: unknown node type %α", n->type); + default: + sysfatal("typecheck: unknown node type %α", n->type); + break; } return n; } @@ -168,16 +176,28 @@ vlong evalop(int op, int sign, vlong v1, vlong v2) { - switch(/*oper*/op){ - case OPADD: return v1 + v2; break; - case OPSUB: return v1 - v2; break; - case OPMUL: return v1 * v2; break; - case OPDIV: if(v2 == 0) sysfatal("division by zero"); return sign ? v1 / v2 : (uvlong)v1 / (uvlong)v2; break; - case OPMOD: if(v2 == 0) sysfatal("division by zero"); return sign ? v1 % v2 : (uvlong)v1 % (uvlong)v2; break; - case OPAND: return v1 & v2; break; - case OPOR: return v1 | v2; break; - case OPXOR: return v1 ^ v2; break; - case OPXNOR: return ~(v1 ^ v2); break; + switch(op){ + case OPADD: return v1 + v2; break; + case OPSUB: return v1 - v2; break; + case OPMUL: return v1 * v2; break; + case OPDIV: + if(v2 == 0) + sysfatal("division by zero"); + if(sign) + return v1 / v2; + else + return (uvlong)v1 / (uvlong)v2; + case OPMOD: + if(v2 == 0) + sysfatal("division by zero"); + if(sign) + return v1 % v2; + else + return (uvlong)v1 % (uvlong)v2; + case OPAND: return v1 & v2; break; + case OPOR: return v1 | v2; break; + case OPXOR: return v1 ^ v2; break; + case OPXNOR: return ~(v1 ^ v2); break; case OPLSH: if((u64int)v2 >= 64) return 0; @@ -197,12 +217,12 @@ return (u64int)v1 >> v2; } break; - case OPEQ: return v1 == v2; break; - case OPNE: return v1 != v2; break; - case OPLT: return v1 < v2; break; - case OPLE: return v1 <= v2; break; - case OPLAND: return v1 && v2; break; - case OPLOR: return v1 || v2; break; + case OPEQ: return v1 == v2; break; + case OPNE: return v1 != v2; break; + case OPLT: return v1 < v2; break; + case OPLE: return v1 <= v2; break; + case OPLAND: return v1 && v2; break; + case OPLOR: return v1 || v2; break; default: sysfatal("cfold: unknown op %.2x", op); return 0; @@ -218,7 +238,6 @@ } /* fold constants */ - static Node * cfold(Node *n) { @@ -282,6 +301,7 @@ switch(n->sym->idx){ case DTV_TIME: case DTV_PROBE: + case DTV_PTAG: n->recsize = 0; break; default: @@ -289,7 +309,8 @@ break; } break; - default: sysfatal("calcrecsize: unknown symbol type %d", n->sym->type); return nil; + default: + sysfatal("calcrecsize: unknown symbol type %d", n->sym->type); return nil; } break; case OBIN: @@ -315,7 +336,8 @@ n->recsize = min(n->typ->size, n->n1->recsize + n->n2->recsize + n->n3->recsize); break; case ORECORD: - default: sysfatal("calcrecsize: unknown type %α", n->type); return nil; + default: + sysfatal("calcrecsize: unknown type %α", n->type); return nil; } return n; } @@ -347,21 +369,22 @@ n->n3 = insrecord(n->n3); break; case ORECORD: - default: sysfatal("insrecord: unknown type %α", n->type); return nil; + default: + sysfatal("insrecord: unknown type %α", n->type); return nil; } return n; } /* - delete useless casts. - going down we determine the number of bits (m) needed to be correct at each stage. - going back up we determine the number of bits (n->databits) which can be either 0 or 1. - all other bits are either zero (n->upper == UPZX) or sign-extended (n->upper == UPSX). - note that by number of bits we always mean a consecutive block starting from the LSB. - - we can delete a cast if it either affects only bits not needed (according to m) or - if it's a no-op (according to databits, upper). -*/ + * delete useless casts. + * going down we determine the number of bits (m) needed to be correct at each stage. + * going back up we determine the number of bits (n->databits) which can be either 0 or 1. + * all other bits are either zero (n->upper == UPZX) or sign-extended (n->upper == UPSX). + * note that by number of bits we always mean a consecutive block starting from the LSB. + * + * we can delete a cast if it either affects only bits not needed (according to m) or + * if it's a no-op (according to databits, upper). + */ static Node * elidecasts(Node *n, int m) { @@ -377,7 +400,7 @@ n->databits = 64; break; case OBIN: - switch(/*oper*/n->op){ + switch(n->op){ case OPADD: case OPSUB: n->n1 = elidecasts(n->n1, m); @@ -467,9 +490,12 @@ n->databits = n->typ->size * 8; n->upper = n->typ->sign ? UPSX : UPZX; } - if(n->typ->size * 8 >= m) return n->n1; - if(n->typ->size * 8 >= n->n1->databits && n->typ->sign == n->n1->upper) return n->n1; - if(n->typ->size * 8 > n->n1->databits && n->typ->sign && !n->n1->upper) return n->n1; + if(n->typ->size * 8 >= m) + return n->n1; + if(n->typ->size * 8 >= n->n1->databits && n->typ->sign == n->n1->upper) + return n->n1; + if(n->typ->size * 8 > n->n1->databits && n->typ->sign && !n->n1->upper) + return n->n1; break; case TYPSTRING: n->n1 = elidecasts(n->n1, 64); @@ -503,7 +529,8 @@ n->upper = UPSX; } break; - default: sysfatal("elidecasts: unknown type %α", n->type); + default: + sysfatal("elidecasts: unknown type %α", n->type); } // print("need %d got %d%c %ε\n", n->needbits, n->databits, "ZS"[n->upper], n); return n; @@ -513,17 +540,23 @@ Node * exprcheck(Node *n, int pred) { - if(dflag) print("start %ε\n", n); + if(dflag) + print("start %ε\n", n); n = typecheck(n); - if(errors) return n; - if(dflag) print("typecheck %ε\n", n); + if(errors) + return n; + if(dflag) + print("typecheck %ε\n", n); n = cfold(n); - if(dflag) print("cfold %ε\n", n); + if(dflag) + print("cfold %ε\n", n); if(!pred){ n = insrecord(calcrecsize(n)); - if(dflag) print("insrecord %ε\n", n); + if(dflag) + print("insrecord %ε\n", n); } n = elidecasts(n, 64); - if(dflag) print("elidecasts %ε\n", n); + if(dflag) + print("elidecasts %ε\n", n); return n; } --- a//sys/src/libdtracy/dtefmt.c +++ b//sys/src/libdtracy/dtefmt.c @@ -14,6 +14,7 @@ [DTV_ARG8] "arg8", [DTV_ARG9] "arg9", [DTV_PID] "pid", + [DTV_PTAG] "ptag", [DTV_TIME] "time", [DTV_PROBE] "probe", [DTV_MACHNO] "machno", --- a//sys/src/libdtracy/pack.c +++ b//sys/src/libdtracy/pack.c @@ -106,31 +106,40 @@ *rp = nil; g = dtmalloc(sizeof(DTActGr)); - g->reclen = 12; + g->reclen = 16; g->ref = 1; - if(*s++ != 'g') goto fail; + if(*s++ != 'g') + goto fail; s = u32unpack(s, &g->id); - if(s == nil) goto fail; - for(;;) + if(s == nil) + goto fail; + for(;;){ switch(*s++){ case 'p': s = dteunpack(s, &g->pred); - if(s == nil) goto fail; + if(s == nil) + goto fail; break; case 'a': s = u32unpack(s, &n); - if(s == nil) goto fail; + if(s == nil) + goto fail; g->acts = dtmalloc(n * sizeof(DTAct)); g->nact = n; for(i = 0; i < n; i++){ - if(*s++ != 't') goto fail; + if(*s++ != 't') + goto fail; s = u32unpack(s, (u32int *) &g->acts[i].type); - if(s == nil) goto fail; - if(*s++ != 's') goto fail; + if(s == nil) + goto fail; + if(*s++ != 's') + goto fail; s = u32unpack(s, (u32int *) &g->acts[i].size); - if(s == nil) goto fail; + if(s == nil) + goto fail; s = dteunpack(s, &g->acts[i].p); - if(s == nil) goto fail; + if(s == nil) + goto fail; switch(g->acts[i].type){ case ACTTRACE: g->reclen += g->acts[i].size; @@ -139,14 +148,18 @@ g->reclen += g->acts[i].size; break; case ACTAGGKEY: - if(*s++ != 'A') goto fail; + if(*s++ != 'A') + goto fail; s = u32unpack(s, (u32int *) &g->acts[i].agg.id); - if(s == nil) goto fail; + if(s == nil) + goto fail; break; case ACTAGGVAL: - if(*s++ != 'A') goto fail; + if(*s++ != 'A') + goto fail; s = u32unpack(s, (u32int *) &g->acts[i].agg.id); - if(s == nil) goto fail; + if(s == nil) + goto fail; break; case ACTCANCEL: break; @@ -158,8 +171,10 @@ case 'G': *rp = g; return s; - default: goto fail; + default: + goto fail; } + } fail: dtgfree(g); return nil; @@ -174,19 +189,23 @@ *rp = nil; c = dtmalloc(sizeof(DTClause)); - if(*s++ != 'c') goto fail; + if(*s++ != 'c') + goto fail; s = u32unpack(s, (u32int*) &c->nprob); - if(s == nil) goto fail; + if(s == nil) + goto fail; c->probs = dtmalloc(sizeof(char *) * c->nprob); for(i = 0; i < c->nprob; i++){ e = strchr(s, '\n'); - if(e == nil) goto fail; + if(e == nil) + goto fail; c->probs[i] = dtmalloc(e - s + 1); memmove(c->probs[i], s, e - s); s = e + 1; } s = dtgunpack(s, &c->gr); - if(s == nil) goto fail; + if(s == nil) + goto fail; *rp = c; return s; fail: --- a//sys/src/libdtracy/prog.c +++ b//sys/src/libdtracy/prog.c @@ -137,19 +137,49 @@ b = ins >> 8; c = ins; switch(ins >> 24){ - case DTE_ADD: R[c] = R[a] + R[b]; break; - case DTE_SUB: R[c] = R[a] - R[b]; break; - case DTE_MUL: R[c] = R[a] * R[b]; break; - case DTE_SDIV: if(R[b] == 0) goto div0; R[c] = R[a] / R[b]; break; - case DTE_SMOD: if(R[b] == 0) goto div0; R[c] = R[a] % R[b]; break; - case DTE_UDIV: if(R[b] == 0) goto div0; R[c] = (uvlong)R[a] / (uvlong)R[b]; break; - case DTE_UMOD: if(R[b] == 0) goto div0; R[c] = (uvlong)R[a] % (uvlong)R[b]; break; - case DTE_AND: R[c] = R[a] & R[b]; break; - case DTE_OR: R[c] = R[a] | R[b]; break; - case DTE_XOR: R[c] = R[a] ^ R[b]; break; - case DTE_XNOR: R[c] = ~(R[a] ^ R[b]); break; - case DTE_LDI: R[c] = (s64int)ins << 40 >> 54 << (ins >> 8 & 63); break; - case DTE_XORI: R[c] ^= (s64int)ins << 40 >> 54 << (ins >> 8 & 63); break; + case DTE_ADD: R[c] = R[a] + R[b]; break; + case DTE_SUB: R[c] = R[a] - R[b]; break; + case DTE_MUL: R[c] = R[a] * R[b]; break; + case DTE_AND: R[c] = R[a] & R[b]; break; + case DTE_OR: R[c] = R[a] | R[b]; break; + case DTE_XOR: R[c] = R[a] ^ R[b]; break; + case DTE_XNOR: R[c] = ~(R[a] ^ R[b]); break; + case DTE_SEQ: R[c] = R[a] == R[b]; break; + case DTE_SNE: R[c] = R[a] != R[b]; break; + case DTE_SLT: R[c] = R[a] < R[b]; break; + case DTE_SLE: R[c] = R[a] <= R[b]; break; + case DTE_LDI: + R[c] = (s64int)ins << 40 >> 54 << (ins >> 8 & 63); + break; + case DTE_XORI: + R[c] ^= (s64int)ins << 40 >> 54 << (ins >> 8 & 63); + break; + case DTE_ZXT: + R[c] = (uvlong)R[a] << 64 - b >> 64 - b; + break; + case DTE_SXT: + R[c] = (vlong)R[a] << 64 - b >> 64 - b; + break; + case DTE_SDIV: + if(R[b] == 0) + goto div0; + R[c] = R[a] / R[b]; + break; + case DTE_SMOD: + if(R[b] == 0) + goto div0; + R[c] = R[a] % R[b]; + break; + case DTE_UDIV: + if(R[b] == 0) + goto div0; + R[c] = (uvlong)R[a] / (uvlong)R[b]; + break; + case DTE_UMOD: + if(R[b] == 0) + goto div0; + R[c] = (uvlong)R[a] % (uvlong)R[b]; + break; case DTE_LSL: if((u64int)R[b] >= 64) R[c] = 0; @@ -168,14 +198,22 @@ else R[c] = R[a] >> R[b]; break; - case DTE_SEQ: R[c] = R[a] == R[b]; break; - case DTE_SNE: R[c] = R[a] != R[b]; break; - case DTE_SLT: R[c] = R[a] < R[b]; break; - case DTE_SLE: R[c] = R[a] <= R[b]; break; - case DTE_BEQ: if(R[a] == R[b]) i += c; break; - case DTE_BNE: if(R[a] != R[b]) i += c; break; - case DTE_BLT: if(R[a] < R[b]) i += c; break; - case DTE_BLE: if(R[a] <= R[b]) i += c; break; + case DTE_BEQ: + if(R[a] == R[b]) + i += c; + break; + case DTE_BNE: + if(R[a] != R[b]) + i += c; + break; + case DTE_BLT: + if(R[a] < R[b]) + i += c; + break; + case DTE_BLE: + if(R[a] <= R[b]) + i += c; + break; case DTE_LDV: switch(a){ case DTV_ARG0: @@ -190,15 +228,22 @@ case DTV_ARG9: R[b] = info->arg[a - DTV_ARG0]; break; - case DTV_TIME: R[b] = info->ts; break; - case DTV_MACHNO: R[b] = info->machno; break; + case DTV_TIME: + R[b] = info->ts; + break; + case DTV_MACHNO: + R[b] = info->machno; + break; default: R[b] = dtgetvar(a); break; } - case DTE_ZXT: R[c] = (uvlong)R[a] << 64 - b >> 64 - b; break; - case DTE_SXT: R[c] = (vlong)R[a] << 64 - b >> 64 - b; break; - case DTE_RET: *retv = R[a]; return 0; + break; + case DTE_RET: + *retv = R[a]; + return 0; + default: + abort(); } } @@ -300,6 +345,7 @@ bp = &b->data[b->wr]; PUT4(info->epid); PUT8(info->ts); + PUT4(info->ptag); for(i = 0; i < g->nact; i++){ if(g->acts[i].type == ACTCANCEL) return 0; @@ -330,7 +376,8 @@ break; } } - assert(bp - b->data - b->wr == g->reclen); + if(bp - b->data - b->wr != g->reclen) + return -1; b->wr = bp - b->data; return 0; } @@ -342,6 +389,7 @@ info->ts = dttime(); info->machno = dtmachlock(-1); + info->ptag = dtgetvar(DTV_PTAG); for(e = p->enablist.probnext; e != &p->enablist; e = e->probnext) if(e->gr->chan->state == DTCGO){ info->ch = e->gr->chan; --- a//sys/src/libdtracy/prov.c +++ b//sys/src/libdtracy/prov.c @@ -72,8 +72,10 @@ char *patp, *strp, *p; patp = partmatch(pat, str, provonly); - if(patp == nil) return 0; - if(patp == (void*)-1) return 1; + if(patp == nil) + return 0; + if(patp == (void*)-1) + return 1; /* reached a * */ strp = str + (patp - pat); patp++; @@ -81,7 +83,8 @@ /* try the rest of the pattern against each position */ p = partmatch(patp, strp, provonly); if(p == nil){ - if(*strp == 0 || *strp == ':') return 0; + if(*strp == 0 || *strp == ':') + return 0; strp++; continue; } @@ -120,10 +123,12 @@ l[nl] = p; } nl++; - if(unique) goto out; + if(unique) + goto out; } } - if(uniqueprov) goto out; + if(uniqueprov) + goto out; } out: if(ret != nil)