]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/prog.c
forgotten files
[plan9front.git] / sys / src / libdtracy / prog.c
1 #include <u.h>
2 #include <libc.h>
3 #include <dtracy.h>
4
5 int
6 dteverify(DTExpr *p)
7 {
8         int i, nregs;
9         u32int ins;
10         u8int a, b, c;
11         
12         nregs = 16;
13         for(i = 0; i < p->n; i++){
14                 ins = p->b[i];
15                 
16                 a = ins >> 16;
17                 b = ins >> 8;
18                 c = ins;
19                 switch(ins>>24){
20                 case DTE_ADD:
21                         if(ins == 0) continue;
22                         /* wet floor */
23                 case DTE_SUB:
24                 case DTE_MUL:
25                 case DTE_UDIV:
26                 case DTE_UMOD:
27                 case DTE_SDIV:
28                 case DTE_SMOD:
29                 case DTE_AND:
30                 case DTE_OR:
31                 case DTE_XOR:
32                 case DTE_XNOR:
33                 case DTE_LSL:
34                 case DTE_LSR:
35                 case DTE_ASR:
36                 case DTE_SEQ:
37                 case DTE_SNE:
38                 case DTE_SLT:
39                 case DTE_SLE:
40                         if(a >= nregs || b >= nregs || c >= nregs || c == 0)
41                                 goto invalid;
42                         break;
43                 case DTE_LDI:
44                 case DTE_XORI:
45                         if(c >= nregs || c == 0)
46                                 goto invalid;
47                         break;
48                 case DTE_BEQ:
49                 case DTE_BNE:
50                 case DTE_BLT:
51                 case DTE_BLE:
52                         if(a >= nregs || b >= nregs || i + 1 + c >= p->n)
53                                 goto invalid;
54                         break;
55                 case DTE_RET:
56                         if(a >= nregs || b != 0 || c != 0)
57                                 goto invalid;
58                         break;
59                 case DTE_LDV:
60                         if(a >= DTNVARS || b >= nregs)
61                                 goto invalid;
62                         break;
63                 case DTE_ZXT:
64                 case DTE_SXT:
65                         if(a >= nregs || b == 0 || b > 64 || c >= nregs)
66                                 goto invalid;
67                         break;
68                 default: goto invalid;
69                 }
70         }
71         if(p->n == 0 || p->b[p->n - 1] >> 24 != DTE_RET){
72                 werrstr("must end with RET");
73                 return -1;
74         }
75         return 0;
76
77 invalid:
78         werrstr("invalid instruction %#.8ux @ %#.4ux", ins, i);
79         return -1;
80 }
81
82 int
83 dtgverify(DTChan *, DTActGr *g)
84 {
85         int i;
86
87         if(g->pred != nil && dteverify(g->pred) < 0)
88                 return -1;
89         for(i = 0; i < g->nact; i++)
90                 switch(g->acts[i].type){
91                 case ACTTRACE:
92                         if(g->acts[i].p == nil || dteverify(g->acts[i].p) < 0 || (uint)g->acts[i].size > 8)
93                                 return -1;
94                         break;
95                 case ACTTRACESTR:
96                         if(g->acts[i].p == nil || dteverify(g->acts[i].p) < 0 || (uint)g->acts[i].size > DTRECMAX)
97                                 return -1;
98                         break;
99                 case ACTAGGKEY:
100                         if(g->acts[i].p == nil || dteverify(g->acts[i].p) < 0 || (uint)g->acts[i].size > 8)
101                                 return -1;
102                         if(i == g->nact - 1 || g->acts[i+1].type != ACTAGGVAL || g->acts[i+1].agg.id != g->acts[i].agg.id)
103                                 return -1;
104                         break;
105                 case ACTAGGVAL:
106                         if(g->acts[i].p == nil || dteverify(g->acts[i].p) < 0 || (uint)g->acts[i].size > 8)
107                                 return -1;
108                         if(i == 0 || g->acts[i-1].type != ACTAGGKEY)
109                                 return -1;
110                         if(dtaunpackid(&g->acts[i].agg) < 0)
111                                 return -1;
112                         break;
113                 case ACTCANCEL:
114                         if(g->acts[i].p == nil || dteverify(g->acts[i].p) < 0)
115                                 return -1;
116                         if(i != g->nact - 1)
117                                 return -1;
118                         break;
119                 default:
120                         return -1;
121                 }
122         return 0;
123 }
124
125 int
126 dteexec(DTExpr *p, DTTrigInfo *info, s64int *retv)
127 {
128         s64int R[16];
129         u32int ins;
130         u8int a, b, c;
131         int i;
132         
133         R[0] = 0;
134         for(i = 0;; i++){
135                 ins = p->b[i];
136                 a = ins >> 16;
137                 b = ins >> 8;
138                 c = ins;
139                 switch(ins >> 24){
140                 case DTE_ADD: R[c] = R[a] + R[b]; break;
141                 case DTE_SUB: R[c] = R[a] - R[b]; break;
142                 case DTE_MUL: R[c] = R[a] * R[b]; break;
143                 case DTE_SDIV: if(R[b] == 0) goto div0; R[c] = R[a] / R[b]; break;
144                 case DTE_SMOD: if(R[b] == 0) goto div0; R[c] = R[a] % R[b]; break;
145                 case DTE_UDIV: if(R[b] == 0) goto div0; R[c] = (uvlong)R[a] / (uvlong)R[b]; break;
146                 case DTE_UMOD: if(R[b] == 0) goto div0; R[c] = (uvlong)R[a] % (uvlong)R[b]; break;
147                 case DTE_AND: R[c] = R[a] & R[b]; break;
148                 case DTE_OR: R[c] = R[a] | R[b]; break;
149                 case DTE_XOR: R[c] = R[a] ^ R[b]; break;
150                 case DTE_XNOR: R[c] = ~(R[a] ^ R[b]); break;
151                 case DTE_LDI: R[c] = (s64int)ins << 40 >> 54 << (ins >> 8 & 63); break;
152                 case DTE_XORI: R[c] ^= (s64int)ins << 40 >> 54 << (ins >> 8 & 63); break;
153                 case DTE_LSL:
154                         if((u64int)R[b] >= 64)
155                                 R[c] = 0;
156                         else
157                                 R[c] = R[a] << R[b];
158                         break;
159                 case DTE_LSR:
160                         if((u64int)R[b] >= 64)
161                                 R[c] = 0;
162                         else
163                                 R[c] = (u64int)R[a] >> R[b];
164                         break;
165                 case DTE_ASR:
166                         if((u64int)R[b] >= 64)
167                                 R[c] = R[a] >> 63;
168                         else
169                                 R[c] = R[a] >> R[b];
170                         break;
171                 case DTE_SEQ: R[c] = R[a] == R[b]; break;
172                 case DTE_SNE: R[c] = R[a] != R[b]; break;
173                 case DTE_SLT: R[c] = R[a] < R[b]; break;
174                 case DTE_SLE: R[c] = R[a] <= R[b]; break;
175                 case DTE_BEQ: if(R[a] == R[b]) i += c; break;
176                 case DTE_BNE: if(R[a] != R[b]) i += c; break;
177                 case DTE_BLT: if(R[a] < R[b]) i += c; break;
178                 case DTE_BLE: if(R[a] <= R[b]) i += c; break;
179                 case DTE_LDV:
180                         switch(a){
181                         case DTV_ARG0:
182                         case DTV_ARG1:
183                         case DTV_ARG2:
184                         case DTV_ARG3:
185                         case DTV_ARG4:
186                         case DTV_ARG5:
187                         case DTV_ARG6:
188                         case DTV_ARG7:
189                         case DTV_ARG8:
190                         case DTV_ARG9:
191                                 R[b] = info->arg[a - DTV_ARG0];
192                                 break;
193                         case DTV_TIME: R[b] = info->ts; break;
194                         case DTV_MACHNO: R[b] = info->machno; break;
195                         default:
196                                 R[b] = dtgetvar(a);
197                                 break;
198                         }
199                 case DTE_ZXT: R[c] = (uvlong)R[a] << 64 - b >> 64 - b; break;
200                 case DTE_SXT: R[c] = (vlong)R[a] << 64 - b >> 64 - b; break;
201                 case DTE_RET: *retv = R[a]; return 0;
202                 }
203         }
204
205 div0:
206         snprint(info->ch->errstr, sizeof(info->ch->errstr), "division by zero");
207         return -1;
208 }
209
210 int
211 dtpeekstr(uvlong addr, u8int *v, int len)
212 {
213         int i;
214         
215         for(i = 0; i < len; i++){
216                 if(addr + i < addr || dtpeek(addr + i, &v[i], 1) < 0){
217                         memset(v, 0, len);
218                         return -1;
219                 }
220                 if(v[i] == 0)
221                         break;
222         }
223         if(i < len)
224                 memset(&v[i], 0, len - i);
225         return 0;
226 }
227
228 #define PUT1(c) *bp++ = c;
229 #define PUT2(c) *bp++ = c; *bp++ = c >> 8;
230 #define PUT4(c) *bp++ = c; *bp++ = c >> 8; *bp++ = c >> 16; *bp++ = c >> 24;
231 #define PUT8(c) PUT4(c); PUT4(c>>32);
232
233 int
234 dtcfault(DTTrigInfo *info, int type, char *fmt, ...)
235 {
236         DTBuf *b;
237         va_list va;
238         int n;
239         char *s;
240         u8int *bp;
241         u32int l;
242         uvlong q;
243         
244         b = info->ch->wrbufs[info->machno];
245         n = 20;
246         va_start(va, fmt);
247         for(s = fmt; *s != 0; s++)
248                 switch(*s){
249                 case 'i': n += 4; break;
250                 case 'p': n += 8; break;
251                 default:
252                         assert(0);
253                 }
254         va_end(va);
255         if(b->wr + n > DTBUFSZ)
256                 return -1;
257         bp = &b->data[b->wr];
258         PUT4(-1);
259         PUT8(info->ts);
260         PUT1(type);
261         PUT2(n);
262         PUT1(0);
263         PUT4(info->epid);
264         va_start(va, fmt);
265         for(s = fmt; *s != 0; s++)
266                 switch(*s){
267                 case 'i':
268                         l = va_arg(va, int);
269                         PUT4(l);
270                         break;
271                 case 'p':
272                         q = (uintptr) va_arg(va, void *);
273                         PUT8(q);
274                         break;
275                 }
276         va_end(va);
277         assert(bp - b->data - b->wr == n);
278         b->wr = bp - b->data;
279         return 0;
280 }
281
282 static int
283 dtgexec(DTActGr *g, DTTrigInfo *info)
284 {
285         DTBuf *b;
286         u8int *bp;
287         s64int v;
288         uchar aggkey[8];
289         int i, j;
290         
291         b = g->chan->wrbufs[info->machno];
292         if(b->wr + g->reclen > DTBUFSZ)
293                 return 0;
294         if(g->pred != nil){
295                 if(dteexec(g->pred, info, &v) < 0)
296                         return -1;
297                 if(v == 0)
298                         return 0;
299         }
300         bp = &b->data[b->wr];
301         PUT4(info->epid);
302         PUT8(info->ts);
303         for(i = 0; i < g->nact; i++){
304                 if(g->acts[i].type == ACTCANCEL)
305                         return 0;
306                 if(dteexec(g->acts[i].p, info, &v) < 0)
307                         return -1;
308                 switch(g->acts[i].type){
309                 case ACTTRACE:
310                         for(j = 0; j < g->acts[i].size; j++){
311                                 *bp++ = v;
312                                 v >>= 8;
313                         }
314                         break;
315                 case ACTTRACESTR:
316                         if(dtpeekstr(v, bp, g->acts[i].size) < 0){
317                                 dtcfault(info, DTFILL, "ip", dtgetvar(DTV_PID), v);
318                                 return 0;
319                         }
320                         bp += g->acts[i].size;
321                         break;
322                 case ACTAGGKEY:
323                         for(j = 0; j < g->acts[i].size; j++){
324                                 aggkey[j] = v;
325                                 v >>= 8;
326                         }
327                         break;
328                 case ACTAGGVAL:
329                         dtarecord(g->chan, info->machno, &g->acts[i].agg, aggkey, g->acts[i-1].size, v);
330                         break;
331                 }
332         }
333         assert(bp - b->data - b->wr == g->reclen);
334         b->wr = bp - b->data;
335         return 0;
336 }
337
338 void
339 dtptrigger(DTProbe *p, int machno, DTTrigInfo *info)
340 {
341         DTEnab *e;
342         
343         info->ts = dttime();
344         dtmachlock(machno);
345         info->machno = machno;
346         for(e = p->enablist.probnext; e != &p->enablist; e = e->probnext)
347                 if(e->gr->chan->state == DTCGO){
348                         info->ch = e->gr->chan;
349                         info->epid = e->epid;
350                         if(dtgexec(e->gr, info) < 0)
351                                 e->gr->chan->state = DTCFAULT;
352                 }
353         dtmachunlock(machno);
354 }