9 /* this contains the code to prepare the kernel data structures and to parse records */
15 /* we could just rely on the types in the expression tree but i'm paranoid */
16 typedef struct Val Val;
37 case VALINT: r.v = va_arg(va, uvlong); break;
38 case VALSTR: r.s = va_arg(va, char*); break;
63 return fmtstrflush(&f);
69 clause = emalloc(sizeof(Clause));
70 clause->id = nclauses;
76 clause->probs = erealloc(clause->probs, sizeof(char *) * (clause->nprob + 1));
77 clause->probs[clause->nprob++] = insertstars(s);
80 static char *aggtypes[] = {
94 for(i = 0; i < nelem(aggtypes); i++)
95 if(strcmp(s->name, aggtypes[i]) == 0)
97 error("%s unknown aggregation type", s->name);
102 addstat(int type, ...)
107 clause->stats = erealloc(clause->stats, sizeof(Stat) * (clause->nstats + 1));
108 s = &clause->stats[clause->nstats++];
109 memset(s, 0, sizeof(Stat));
114 s->n = va_arg(va, Node *);
120 s->agg.name = va_arg(va, Symbol *);
121 s->agg.key = va_arg(va, Node *);
122 s->agg.type = aggtype(va_arg(va, Symbol *));
123 s->agg.value = va_arg(va, Node *);
124 if(s->agg.type == AGGCNT){
125 if(s->agg.value != nil)
126 error("too many arguments for count()");
128 if(s->agg.value == nil)
129 error("need argument for %s()", aggtypes[s->agg.type]);
133 sysfatal("addstat: unknown type %d", type);
143 assert(clause->nstats > 0);
144 s = &clause->stats[clause->nstats - 1];
145 s->arg = erealloc(s->arg, sizeof(Node *) * (s->narg + 1));
146 s->arg[s->narg++] = n;
152 clauses = erealloc(clauses, sizeof(Clause) * (nclauses + 1));
153 clauses[nclauses++] = clause;
157 actgradd(DTActGr *a, DTAct b)
159 a->acts = erealloc(a->acts, sizeof(DTAct) * (a->nact + 1));
160 a->acts[a->nact++] = b;
170 prepprintf(Node **arg, int narg, DTActGr *g, int *recoff)
176 if(narg <= 0) sysfatal("printf() needs an argument");
177 if((*arg)->type != OSTR) sysfatal("printf() format string must be a literal");
181 for(; *fmt != 0; fmt++){
188 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
189 case 'u': case '+': case '-': case ',': case '#': case ' ': case '.':
193 case 'x': case 'X': case 'o': case 'b': case 'd':
194 if(n >= narg) sysfatal("printf() too few arguments");
195 if(arg[n]->typ->type != TYPINT)
196 sysfatal("%d: print() %%%c with non-integer", arg[n]->line, *fmt);
197 arg[n] = tracegen(arg[n], g, recoff);
204 if(n >= narg) sysfatal("printf() too few arguments");
205 if(arg[n]->typ->type != TYPSTRING)
206 sysfatal("%d: print() %%s with non-string", arg[n]->line);
207 arg[n] = tracegen(arg[n], g, recoff);
211 case 0: sysfatal("printf() missing verb");
212 default: sysfatal("printf() unknown verb %%%c", *fmt);
215 if(n < narg) sysfatal("printf() too many arguments");
216 (*arg)->str = fmtstrflush(&f);
226 for(s = c->stats; s < c->stats + c->nstats; s++)
227 if(s->type != STATAGG)
233 mkdtclause(Clause *c)
240 d = emalloc(sizeof(DTClause));
243 d->gr = emalloc(sizeof(DTActGr));
244 d->gr->pred = c->pred;
247 for(s = c->stats; s < c->stats + c->nstats; s++)
250 actgradd(d->gr, (DTAct){ACTTRACE, codegen(s->n), 0, noagg});
253 for(i = 0; i < s->narg; i++)
254 s->arg[i] = tracegen(s->arg[i], d->gr, &recoff);
257 prepprintf(s->arg, s->narg, d->gr, &recoff);
260 DTAgg agg = {.id = s->agg.type << 28 | 1 << 16 | aggid++};
261 assert(dtaunpackid(&agg) >= 0);
262 aggs = realloc(aggs, sizeof(Agg) * aggid);
263 memset(&aggs[aggid-1], 0, sizeof(Agg));
264 aggs[aggid-1].DTAgg = agg;
265 aggs[aggid-1].name = strdup(s->agg.name == nil ? "" : s->agg.name->name);
266 actgradd(d->gr, (DTAct){ACTAGGKEY, codegen(s->agg.key), 8, agg});
268 if(n == nil) n = node(ONUM, 0ULL);
269 actgradd(d->gr, (DTAct){ACTAGGVAL, codegen(n), 8, agg});
274 actgradd(d->gr, (DTAct){ACTCANCEL, codegen(node(ONUM, 0)), 0, noagg});
284 for(i = 0; i < nclauses; i++){
285 d = mkdtclause(clauses[i]);
290 /* epid lookup table, filled with info from the kernel */
294 addepid(u32int epid, u32int cid, int reclen, char *p)
298 assert(cid < nclauses);
299 assert((uint)reclen >= 12);
300 e = emalloc(sizeof(Enab));
302 e->cl = clauses[cid];
304 e->probe = strdup(p);
305 ep = &enabtab[epid % nelem(enabtab)];
311 epidlookup(u32int epid)
315 for(e = enabtab[epid % nelem(enabtab)]; e != nil; e = e->next)
322 unpack(uchar *p, uchar *e, char *fmt, ...)
331 if(p + 1 > e) return nil;
332 *va_arg(va, u8int *) = p[0];
336 if(p + 2 > e) return nil;
337 *va_arg(va, u16int *) = p[0] | p[1] << 8;
341 if(p + 4 > e) return nil;
342 *va_arg(va, u32int *) = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
346 if(p + 8 > e) return nil;
347 vl = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
348 vl |= (uvlong)p[4] << 32 | (uvlong)p[5] << 40 | (uvlong)p[6] << 48 | (uvlong)p[7] << 56;
349 *va_arg(va, u64int *) = vl;
360 receval(Node *n, uchar *p, uchar *e, Enab *en)
372 switch(n->sym->type){
376 q = unpack(p + 4, e, "v", &v);
378 return mkval(VALINT, v);
380 return mkval(VALSTR, en->probe);
381 default: sysfatal("receval: unknown variable %d", n->type); return mkval(VALINT, 0LL);
384 default: sysfatal("receval: unknown symbol type %d", n->type); return mkval(VALINT, 0LL);
386 case ONUM: return mkval(VALINT, n->num);
388 a = receval(n->n1, p, e, en);
389 b = receval(n->n2, p, e, en);
390 assert(a.type == VALINT);
391 assert(b.type == VALINT);
392 return mkval(VALINT, evalop(n->op, n->typ->sign, a.v, b.v));
394 a = receval(n->n1, p, e, en);
395 assert(a.type == VALINT);
396 return mkval(VALINT, (uvlong) !a.v);
398 a = receval(n->n1, p, e, en);
399 assert(a.type == VALINT);
400 return a.v ? receval(n->n2, p, e, en) : receval(n->n3, p, e, en);
402 switch(n->typ->type){
404 switch(n->typ->size){
405 case 1: q = unpack(p + n->num, e, "c", &c); v = n->typ->sign ? (s8int)c : (u8int)c; break;
406 case 2: q = unpack(p + n->num, e, "s", &s); v = n->typ->sign ? (s16int)s : (u16int)s; break;
407 case 4: q = unpack(p + n->num, e, "i", &i); v = n->typ->sign ? (s32int)i : (u32int)i; break;
408 case 8: q = unpack(p + n->num, e, "v", &v); break;
412 return mkval(VALINT, v);
414 assert(p + n->num + n->typ->size <= e);
415 sp = emalloc(n->typ->size + 1);
416 memcpy(sp, p + n->num, n->typ->size);
417 return mkval(VALSTR, sp); /* TODO: fix leak */
419 sysfatal("receval: don't know how to parse record for %τ", n->typ);
422 sysfatal("receval: unknown type %α", n->type);
423 return mkval(VALINT, 0LL);
428 execprintf(Node **arg, int narg, uchar *p, uchar *e, Enab *en)
434 x = emalloc(sizeof(uvlong) * (narg - 1));
436 for(i = 0; i < narg - 1; i++){
437 v = receval(arg[i + 1], p, e, en);
441 xp += sizeof(uvlong);
450 vfprint(1, (*arg)->str, (va_list) x);
455 parseclause(Clause *cl, uchar *p, uchar *e, Enab *en, Biobuf *bp)
461 for(s = cl->stats; s < cl->stats + cl->nstats; s++)
463 case STATEXPR: break;
465 for(i = 0; i < s->narg; i++){
466 v = receval(s->arg[i], p, e, en);
469 Bprint(bp, "%lld", v.v);
472 Bprint(bp, "%s", v.s);
474 default: sysfatal("parseclause: unknown val type %d", s->type);
476 Bprint(bp, "%c", i == s->narg - 1 ? '\n' : ' ');
480 execprintf(s->arg, s->narg, p, e, en);
484 sysfatal("parseclause: unknown type %d", s->type);
490 parsefault(uchar *p0, uchar *e)
498 p = unpack(p0, e, "csci", &type, &n, &dummy, &epid);
499 if(p == nil) return nil;
500 en = epidlookup(epid);
506 p = unpack(p, e, "iv", &pid, &addr);
507 if(p == nil) return nil;
508 fprint(2, "dtracy: illegal access: probe=%s, pid=%d, addr=%#llx\n", en != nil ? en->probe : nil, pid, addr);
512 fprint(2, "dtracy: unknown fault type %#.2ux\n", type);
518 parsebuf(uchar *p, int n, Biobuf *bp)
527 p = unpack(p, e, "iv", &epid, &ts);
528 if(p == nil) goto err;
529 if(epid == (u32int)-1){
530 p = parsefault(p, e);
531 if(p == nil) goto err;
534 en = epidlookup(epid);
535 if(en == nil) goto err;
536 if(parseclause(en->cl, p - 12, p + en->reclen - 12, en, bp) < 0) return -1;
537 p += en->reclen - 12;
541 werrstr("buffer invalid");
546 dumpexpr(DTExpr *e, char *prefix)
550 for(i = 0; i < e->n; i++)
551 print("%s%.8ux %I\n", prefix, e->b[i], e->b[i]);
554 #pragma varargck type "ε" Node*
557 fmtstring(Fmt *f, char *s)
562 case '\n': fmtprint(f, "\\n"); break;
563 case '\r': fmtprint(f, "\\r"); break;
564 case '\t': fmtprint(f, "\\t"); break;
565 case '\v': fmtprint(f, "\\v"); break;
566 case '\b': fmtprint(f, "\\b"); break;
567 case '\a': fmtprint(f, "\\a"); break;
568 case '"': fmtprint(f, "\""); break;
569 case '\\': fmtprint(f, "\\"); break;
571 if(*s < 0x20 || *s >= 0x7f)
572 fmtprint(f, "\\%.3o", (uchar)*s);
579 typedef struct Op Op;
583 enum { PRECRIGHT = 1 } flags;
585 static Op optab[] = {
586 [OPLOR] {"||", 3, 0},
587 [OPLAND] {"&&", 4, 0},
589 [OPXNOR] {"~^", 6, 0},
596 [OPLSH] {"<<", 10, 0},
597 [OPRSH] {">>", 10, 0},
598 [OPADD] {"+", 11, 0},
599 [OPSUB] {"-", 11, 0},
600 [OPDIV] {"/", 12, 0},
601 [OPMOD] {"%", 12, 0},
602 [OPMUL] {"*", 12, 0},
604 enum { PREDUNARY = 14 };
614 n = va_arg(f->args, Node *);
616 case OSYM: fmtprint(f, "%s", n->sym->name); break;
617 case ONUM: fmtprint(f, "%lld", n->num); break;
618 case OSTR: fmtstring(f, n->str); break;
620 if(n->op >= nelem(optab) || optab[n->op].name == nil)
621 fmtprint(f, "(%*ε ??op%d %*ε)", PREDUNARY, n->n1, n->op, PREDUNARY, n->n2);
624 if(op->pred < p) fmtrune(f, '(');
625 fmtprint(f, "%*ε %s %*ε", op->pred + (op->flags & PRECRIGHT), n->n1, op->name, op->pred + (~op->flags & PRECRIGHT), n->n2);
626 if(op->pred < p) fmtrune(f, ')');
629 case OLNOT: fmtprint(f, "!%*ε", PREDUNARY, n->n1); break;
630 case OTERN: fmtprint(f, "%2ε ? %1ε : %1ε", n->n1, n->n2, n->n3); break;
631 case ORECORD: fmtprint(f, "record(%ε, %τ, %d)", n->n1, n->typ, (int)n->num); break;
632 case OCAST: fmtprint(f, "(%τ) %*ε", n->typ, PREDUNARY, n->n1); break;
633 default: fmtprint(f, "??? %α", n->type);
647 for(i = 0; i < nclauses; i++){
650 print("clause %d:\n", c->id);
651 for(j = 0; j < c->nprob; j++)
652 print("\tprobe '%s'\n", c->probs[j]);
653 print("\tkernel code:\n");
655 print("\t\tno predicate\n");
657 print("\t\tpredicate\n");
658 dumpexpr(c->pred, "\t\t\t");
660 for(a = d->gr->acts; a < d->gr->acts + d->gr->nact; a++)
663 print("\t\ttrace (%d bytes)\n", a->size);
664 dumpexpr(a->p, "\t\t\t");
667 print("\t\ttrace string (%d bytes)\n", a->size);
668 dumpexpr(a->p, "\t\t\t");
671 print("\t\taggregation key (%s,%d,%d)\n", a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type], a->agg.keysize, (u16int)a->agg.id);
672 dumpexpr(a->p, "\t\t\t");
675 print("\t\taggregation value (%s,%d,%d)\n", a->agg.type >= nelem(aggtypes) ? "???" : aggtypes[a->agg.type], a->agg.keysize, (u16int)a->agg.id);
676 dumpexpr(a->p, "\t\t\t");
679 print("\t\tcancel record\n");
682 print("\t\t??? %d\n", a->type);
684 print("\trecord formatting:\n");
685 for(s = c->stats; s < c->stats + c->nstats; s++)
690 print("\t\tprint\n");
691 for(j = 0; j < s->narg; j++)
692 print("\t\t\targ %ε\n", s->arg[j]);
695 print("\t\tprintf\n");
696 for(j = 0; j < s->narg; j++)
697 print("\t\t\targ %ε\n", s->arg[j]);
702 print("\t\t??? %d\n", s->type);