Implement dispatch-table based interpretor
[lttng-ust.git] / liblttng-ust / lttng-filter.c
1 /*
2 * lttng-filter.c
3 *
4 * LTTng UST filter code.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <errno.h>
24 #include <stdio.h>
25 #include <helper.h>
26 #include <lttng/ust-events.h>
27 #include <stdint.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <inttypes.h>
31 #include <limits.h>
32 #include <usterr-signal-safe.h>
33 #include "filter-bytecode.h"
34
35 #define NR_REG 2
36
37 #ifndef min_t
38 #define min_t(type, a, b) \
39 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
40 #endif
41
42 #ifndef likely
43 #define likely(x) __builtin_expect(!!(x), 1)
44 #endif
45
46 #ifndef unlikely
47 #define unlikely(x) __builtin_expect(!!(x), 0)
48 #endif
49
50 #ifdef DEBUG
51 #define dbg_printf(fmt, args...) printf("[debug bytecode] " fmt, ## args)
52 #else
53 #define dbg_printf(fmt, args...) \
54 do { \
55 /* do nothing but check printf format */ \
56 if (0) \
57 printf("[debug bytecode] " fmt, ## args); \
58 } while (0)
59 #endif
60
61 /* Linked bytecode */
62 struct bytecode_runtime {
63 uint16_t len;
64 char data[0];
65 };
66
67 enum reg_type {
68 REG_S64,
69 REG_DOUBLE,
70 REG_STRING,
71 REG_TYPE_UNKNOWN,
72 };
73
74 /* Validation registers */
75 struct vreg {
76 enum reg_type type;
77 int literal; /* is string literal ? */
78 };
79
80 /* Execution registers */
81 struct reg {
82 enum reg_type type;
83 int64_t v;
84 double d;
85
86 const char *str;
87 size_t seq_len;
88 int literal; /* is string literal ? */
89 };
90
91 static const char *opnames[] = {
92 [ FILTER_OP_UNKNOWN ] = "UNKNOWN",
93
94 [ FILTER_OP_RETURN ] = "RETURN",
95
96 /* binary */
97 [ FILTER_OP_MUL ] = "MUL",
98 [ FILTER_OP_DIV ] = "DIV",
99 [ FILTER_OP_MOD ] = "MOD",
100 [ FILTER_OP_PLUS ] = "PLUS",
101 [ FILTER_OP_MINUS ] = "MINUS",
102 [ FILTER_OP_RSHIFT ] = "RSHIFT",
103 [ FILTER_OP_LSHIFT ] = "LSHIFT",
104 [ FILTER_OP_BIN_AND ] = "BIN_AND",
105 [ FILTER_OP_BIN_OR ] = "BIN_OR",
106 [ FILTER_OP_BIN_XOR ] = "BIN_XOR",
107
108 /* binary comparators */
109 [ FILTER_OP_EQ ] = "EQ",
110 [ FILTER_OP_NE ] = "NE",
111 [ FILTER_OP_GT ] = "GT",
112 [ FILTER_OP_LT ] = "LT",
113 [ FILTER_OP_GE ] = "GE",
114 [ FILTER_OP_LE ] = "LE",
115
116 /* string binary comparators */
117 [ FILTER_OP_EQ_STRING ] = "EQ_STRING",
118 [ FILTER_OP_NE_STRING ] = "NE_STRING",
119 [ FILTER_OP_GT_STRING ] = "GT_STRING",
120 [ FILTER_OP_LT_STRING ] = "LT_STRING",
121 [ FILTER_OP_GE_STRING ] = "GE_STRING",
122 [ FILTER_OP_LE_STRING ] = "LE_STRING",
123
124 /* s64 binary comparators */
125 [ FILTER_OP_EQ_S64 ] = "EQ_S64",
126 [ FILTER_OP_NE_S64 ] = "NE_S64",
127 [ FILTER_OP_GT_S64 ] = "GT_S64",
128 [ FILTER_OP_LT_S64 ] = "LT_S64",
129 [ FILTER_OP_GE_S64 ] = "GE_S64",
130 [ FILTER_OP_LE_S64 ] = "LE_S64",
131
132 /* double binary comparators */
133 [ FILTER_OP_EQ_DOUBLE ] = "EQ_DOUBLE",
134 [ FILTER_OP_NE_DOUBLE ] = "NE_DOUBLE",
135 [ FILTER_OP_GT_DOUBLE ] = "GT_DOUBLE",
136 [ FILTER_OP_LT_DOUBLE ] = "LT_DOUBLE",
137 [ FILTER_OP_GE_DOUBLE ] = "GE_DOUBLE",
138 [ FILTER_OP_LE_DOUBLE ] = "LE_DOUBLE",
139
140
141 /* unary */
142 [ FILTER_OP_UNARY_PLUS ] = "UNARY_PLUS",
143 [ FILTER_OP_UNARY_MINUS ] = "UNARY_MINUS",
144 [ FILTER_OP_UNARY_NOT ] = "UNARY_NOT",
145 [ FILTER_OP_UNARY_PLUS_S64 ] = "UNARY_PLUS_S64",
146 [ FILTER_OP_UNARY_MINUS_S64 ] = "UNARY_MINUS_S64",
147 [ FILTER_OP_UNARY_NOT_S64 ] = "UNARY_NOT_S64",
148 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = "UNARY_PLUS_DOUBLE",
149 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = "UNARY_MINUS_DOUBLE",
150 [ FILTER_OP_UNARY_NOT_DOUBLE ] = "UNARY_NOT_DOUBLE",
151
152 /* logical */
153 [ FILTER_OP_AND ] = "AND",
154 [ FILTER_OP_OR ] = "OR",
155
156 /* load */
157 [ FILTER_OP_LOAD_FIELD_REF ] = "LOAD_FIELD_REF",
158 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = "LOAD_FIELD_REF_STRING",
159 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = "LOAD_FIELD_REF_SEQUENCE",
160 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = "LOAD_FIELD_REF_S64",
161 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = "LOAD_FIELD_REF_DOUBLE",
162
163 [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
164 [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
165 [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
166 };
167
168 static
169 const char *print_op(enum filter_op op)
170 {
171 if (op >= NR_FILTER_OPS)
172 return "UNKNOWN";
173 else
174 return opnames[op];
175 }
176
177 /*
178 * -1: wildcard found.
179 * -2: unknown escape char.
180 * 0: normal char.
181 */
182
183 static
184 int parse_char(const char **p)
185 {
186 switch (**p) {
187 case '\\':
188 (*p)++;
189 switch (**p) {
190 case '\\':
191 case '*':
192 return 0;
193 default:
194 return -2;
195 }
196 case '*':
197 return -1;
198 default:
199 return 0;
200 }
201 }
202
203 static
204 int reg_strcmp(struct reg reg[NR_REG], const char *cmp_type)
205 {
206 const char *p = reg[REG_R0].str, *q = reg[REG_R1].str;
207 int ret;
208 int diff;
209
210 for (;;) {
211 int escaped_r0 = 0;
212
213 if (unlikely(p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')) {
214 if (q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')
215 diff = 0;
216 else
217 diff = -1;
218 break;
219 }
220 if (unlikely(q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')) {
221 if (p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')
222 diff = 0;
223 else
224 diff = 1;
225 break;
226 }
227 if (reg[REG_R0].literal) {
228 ret = parse_char(&p);
229 if (ret == -1) {
230 return 0;
231 } else if (ret == -2) {
232 escaped_r0 = 1;
233 }
234 /* else compare both char */
235 }
236 if (reg[REG_R1].literal) {
237 ret = parse_char(&q);
238 if (ret == -1) {
239 return 0;
240 } else if (ret == -2) {
241 if (!escaped_r0)
242 return -1;
243 } else {
244 if (escaped_r0)
245 return 1;
246 }
247 } else {
248 if (escaped_r0)
249 return 1;
250 }
251 diff = *p - *q;
252 if (diff != 0)
253 break;
254 p++;
255 q++;
256 }
257 return diff;
258 }
259
260 static
261 int lttng_filter_false(void *filter_data,
262 const char *filter_stack_data)
263 {
264 return 0;
265 }
266
267 #ifdef INTERPRETER_USE_SWITCH
268
269 /*
270 * Fallback for compilers that do not support taking address of labels.
271 */
272
273 #define START_OP \
274 start_pc = &bytecode->data[0]; \
275 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
276 pc = next_pc) { \
277 dbg_printf("Executing op %s (%u)\n", \
278 print_op((unsigned int) *(filter_opcode_t *) pc), \
279 (unsigned int) *(filter_opcode_t *) pc); \
280 switch (*(filter_opcode_t *) pc) {
281
282 #define OP(name) case name
283
284 #define PO break
285
286 #define END_OP } \
287 }
288
289 #else
290
291 /*
292 * Dispatch-table based interpreter.
293 */
294
295 #define START_OP \
296 start_pc = &bytecode->data[0]; \
297 pc = next_pc = start_pc; \
298 if (unlikely(pc - start_pc >= bytecode->len)) \
299 goto end; \
300 goto *dispatch[*(filter_opcode_t *) pc];
301
302 #define OP(name) \
303 LABEL_##name
304
305 #define PO \
306 pc = next_pc; \
307 goto *dispatch[*(filter_opcode_t *) pc];
308
309 #define END_OP
310
311 #endif
312
313 static
314 int lttng_filter_interpret_bytecode(void *filter_data,
315 const char *filter_stack_data)
316 {
317 struct bytecode_runtime *bytecode = filter_data;
318 void *pc, *next_pc, *start_pc;
319 int ret = -EINVAL;
320 int retval = 0;
321 struct reg reg[NR_REG];
322 #ifndef INTERPRETER_USE_SWITCH
323 static void *dispatch[NR_FILTER_OPS] = {
324 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
325
326 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
327
328 /* binary */
329 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
330 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
331 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
332 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
333 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
334 [ FILTER_OP_RSHIFT ] = &&LABEL_FILTER_OP_RSHIFT,
335 [ FILTER_OP_LSHIFT ] = &&LABEL_FILTER_OP_LSHIFT,
336 [ FILTER_OP_BIN_AND ] = &&LABEL_FILTER_OP_BIN_AND,
337 [ FILTER_OP_BIN_OR ] = &&LABEL_FILTER_OP_BIN_OR,
338 [ FILTER_OP_BIN_XOR ] = &&LABEL_FILTER_OP_BIN_XOR,
339
340 /* binary comparators */
341 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
342 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
343 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
344 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
345 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
346 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
347
348 /* string binary comparator */
349 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
350 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
351 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
352 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
353 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
354 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
355
356 /* s64 binary comparator */
357 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
358 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
359 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
360 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
361 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
362 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
363
364 /* double binary comparator */
365 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
366 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
367 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
368 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
369 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
370 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
371
372 /* unary */
373 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
374 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
375 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
376 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
377 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
378 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
379 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
380 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
381 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
382
383 /* logical */
384 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
385 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
386
387 /* load */
388 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
389 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
390 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
391 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
392 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
393
394 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
395 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
396 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
397 };
398 #endif /* #ifndef INTERPRETER_USE_SWITCH */
399
400 START_OP
401
402 OP(FILTER_OP_UNKNOWN):
403 OP(FILTER_OP_LOAD_FIELD_REF):
404 #ifdef INTERPRETER_USE_SWITCH
405 default:
406 #endif /* INTERPRETER_USE_SWITCH */
407 ERR("unknown bytecode op %u\n",
408 (unsigned int) *(filter_opcode_t *) pc);
409 ret = -EINVAL;
410 goto end;
411
412 OP(FILTER_OP_RETURN):
413 retval = !!reg[0].v;
414 ret = 0;
415 goto end;
416
417 /* binary */
418 OP(FILTER_OP_MUL):
419 OP(FILTER_OP_DIV):
420 OP(FILTER_OP_MOD):
421 OP(FILTER_OP_PLUS):
422 OP(FILTER_OP_MINUS):
423 OP(FILTER_OP_RSHIFT):
424 OP(FILTER_OP_LSHIFT):
425 OP(FILTER_OP_BIN_AND):
426 OP(FILTER_OP_BIN_OR):
427 OP(FILTER_OP_BIN_XOR):
428 ERR("unsupported bytecode op %u\n",
429 (unsigned int) *(filter_opcode_t *) pc);
430 ret = -EINVAL;
431 goto end;
432
433 OP(FILTER_OP_EQ):
434 OP(FILTER_OP_NE):
435 OP(FILTER_OP_GT):
436 OP(FILTER_OP_LT):
437 OP(FILTER_OP_GE):
438 OP(FILTER_OP_LE):
439 ERR("unsupported non-specialized bytecode op %u\n",
440 (unsigned int) *(filter_opcode_t *) pc);
441 ret = -EINVAL;
442 goto end;
443
444 OP(FILTER_OP_EQ_STRING):
445 {
446 reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
447 reg[REG_R0].type = REG_S64;
448 next_pc += sizeof(struct binary_op);
449 PO;
450 }
451 OP(FILTER_OP_NE_STRING):
452 {
453 reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
454 reg[REG_R0].type = REG_S64;
455 next_pc += sizeof(struct binary_op);
456 PO;
457 }
458 OP(FILTER_OP_GT_STRING):
459 {
460 reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
461 reg[REG_R0].type = REG_S64;
462 next_pc += sizeof(struct binary_op);
463 PO;
464 }
465 OP(FILTER_OP_LT_STRING):
466 {
467 reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
468 reg[REG_R0].type = REG_S64;
469 next_pc += sizeof(struct binary_op);
470 PO;
471 }
472 OP(FILTER_OP_GE_STRING):
473 {
474 reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
475 reg[REG_R0].type = REG_S64;
476 next_pc += sizeof(struct binary_op);
477 PO;
478 }
479 OP(FILTER_OP_LE_STRING):
480 {
481 reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
482 reg[REG_R0].type = REG_S64;
483 next_pc += sizeof(struct binary_op);
484 PO;
485 }
486
487 OP(FILTER_OP_EQ_S64):
488 {
489 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
490 reg[REG_R0].type = REG_S64;
491 next_pc += sizeof(struct binary_op);
492 PO;
493 }
494 OP(FILTER_OP_NE_S64):
495 {
496 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
497 reg[REG_R0].type = REG_S64;
498 next_pc += sizeof(struct binary_op);
499 PO;
500 }
501 OP(FILTER_OP_GT_S64):
502 {
503 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
504 reg[REG_R0].type = REG_S64;
505 next_pc += sizeof(struct binary_op);
506 PO;
507 }
508 OP(FILTER_OP_LT_S64):
509 {
510 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
511 reg[REG_R0].type = REG_S64;
512 next_pc += sizeof(struct binary_op);
513 PO;
514 }
515 OP(FILTER_OP_GE_S64):
516 {
517 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
518 reg[REG_R0].type = REG_S64;
519 next_pc += sizeof(struct binary_op);
520 PO;
521 }
522 OP(FILTER_OP_LE_S64):
523 {
524 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
525 reg[REG_R0].type = REG_S64;
526 next_pc += sizeof(struct binary_op);
527 PO;
528 }
529
530 OP(FILTER_OP_EQ_DOUBLE):
531 {
532 if (unlikely(reg[REG_R0].type == REG_S64))
533 reg[REG_R0].d = (double) reg[REG_R0].v;
534 else if (unlikely(reg[REG_R1].type == REG_S64))
535 reg[REG_R1].d = (double) reg[REG_R1].v;
536 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
537 reg[REG_R0].type = REG_S64;
538 next_pc += sizeof(struct binary_op);
539 PO;
540 }
541 OP(FILTER_OP_NE_DOUBLE):
542 {
543 if (unlikely(reg[REG_R0].type == REG_S64))
544 reg[REG_R0].d = (double) reg[REG_R0].v;
545 else if (unlikely(reg[REG_R1].type == REG_S64))
546 reg[REG_R1].d = (double) reg[REG_R1].v;
547 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
548 reg[REG_R0].type = REG_S64;
549 next_pc += sizeof(struct binary_op);
550 PO;
551 }
552 OP(FILTER_OP_GT_DOUBLE):
553 {
554 if (unlikely(reg[REG_R0].type == REG_S64))
555 reg[REG_R0].d = (double) reg[REG_R0].v;
556 else if (unlikely(reg[REG_R1].type == REG_S64))
557 reg[REG_R1].d = (double) reg[REG_R1].v;
558 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
559 reg[REG_R0].type = REG_S64;
560 next_pc += sizeof(struct binary_op);
561 PO;
562 }
563 OP(FILTER_OP_LT_DOUBLE):
564 {
565 if (unlikely(reg[REG_R0].type == REG_S64))
566 reg[REG_R0].d = (double) reg[REG_R0].v;
567 else if (unlikely(reg[REG_R1].type == REG_S64))
568 reg[REG_R1].d = (double) reg[REG_R1].v;
569 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
570 reg[REG_R0].type = REG_S64;
571 next_pc += sizeof(struct binary_op);
572 PO;
573 }
574 OP(FILTER_OP_GE_DOUBLE):
575 {
576 if (unlikely(reg[REG_R0].type == REG_S64))
577 reg[REG_R0].d = (double) reg[REG_R0].v;
578 else if (unlikely(reg[REG_R1].type == REG_S64))
579 reg[REG_R1].d = (double) reg[REG_R1].v;
580 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
581 reg[REG_R0].type = REG_S64;
582 next_pc += sizeof(struct binary_op);
583 PO;
584 }
585 OP(FILTER_OP_LE_DOUBLE):
586 {
587 if (unlikely(reg[REG_R0].type == REG_S64))
588 reg[REG_R0].d = (double) reg[REG_R0].v;
589 else if (unlikely(reg[REG_R1].type == REG_S64))
590 reg[REG_R1].d = (double) reg[REG_R1].v;
591 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].d);
592 reg[REG_R0].type = REG_S64;
593 next_pc += sizeof(struct binary_op);
594 PO;
595 }
596
597 /* unary */
598 OP(FILTER_OP_UNARY_PLUS):
599 OP(FILTER_OP_UNARY_MINUS):
600 OP(FILTER_OP_UNARY_NOT):
601 ERR("unsupported non-specialized bytecode op %u\n",
602 (unsigned int) *(filter_opcode_t *) pc);
603 ret = -EINVAL;
604 goto end;
605
606
607 OP(FILTER_OP_UNARY_PLUS_S64):
608 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
609 {
610 next_pc += sizeof(struct unary_op);
611 PO;
612 }
613 OP(FILTER_OP_UNARY_MINUS_S64):
614 {
615 struct unary_op *insn = (struct unary_op *) pc;
616
617 reg[insn->reg].v = -reg[insn->reg].v;
618 next_pc += sizeof(struct unary_op);
619 PO;
620 }
621 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
622 {
623 struct unary_op *insn = (struct unary_op *) pc;
624
625 reg[insn->reg].d = -reg[insn->reg].d;
626 next_pc += sizeof(struct unary_op);
627 PO;
628 }
629 OP(FILTER_OP_UNARY_NOT_S64):
630 {
631 struct unary_op *insn = (struct unary_op *) pc;
632
633 reg[insn->reg].v = !reg[insn->reg].v;
634 next_pc += sizeof(struct unary_op);
635 PO;
636 }
637 OP(FILTER_OP_UNARY_NOT_DOUBLE):
638 {
639 struct unary_op *insn = (struct unary_op *) pc;
640
641 reg[insn->reg].d = !reg[insn->reg].d;
642 next_pc += sizeof(struct unary_op);
643 PO;
644 }
645
646 /* logical */
647 OP(FILTER_OP_AND):
648 {
649 struct logical_op *insn = (struct logical_op *) pc;
650
651 /* If REG_R0 is 0, skip and evaluate to 0 */
652 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v == 0)
653 || unlikely(reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d == 0.0)) {
654 dbg_printf("Jumping to bytecode offset %u\n",
655 (unsigned int) insn->skip_offset);
656 next_pc = start_pc + insn->skip_offset;
657 } else {
658 next_pc += sizeof(struct logical_op);
659 }
660 PO;
661 }
662 OP(FILTER_OP_OR):
663 {
664 struct logical_op *insn = (struct logical_op *) pc;
665
666 /* If REG_R0 is nonzero, skip and evaluate to 1 */
667
668 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v != 0)
669 || unlikely(reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d != 0.0)) {
670 reg[REG_R0].v = 1;
671 dbg_printf("Jumping to bytecode offset %u\n",
672 (unsigned int) insn->skip_offset);
673 next_pc = start_pc + insn->skip_offset;
674 } else {
675 next_pc += sizeof(struct logical_op);
676 }
677 PO;
678 }
679
680 /* load */
681 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
682 {
683 struct load_op *insn = (struct load_op *) pc;
684 struct field_ref *ref = (struct field_ref *) insn->data;
685
686 dbg_printf("load field ref offset %u type string\n",
687 ref->offset);
688 reg[insn->reg].str =
689 *(const char * const *) &filter_stack_data[ref->offset];
690 reg[insn->reg].type = REG_STRING;
691 reg[insn->reg].seq_len = UINT_MAX;
692 reg[insn->reg].literal = 0;
693 dbg_printf("ref load string %s\n", reg[insn->reg].str);
694 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
695 PO;
696 }
697
698 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
699 {
700 struct load_op *insn = (struct load_op *) pc;
701 struct field_ref *ref = (struct field_ref *) insn->data;
702
703 dbg_printf("load field ref offset %u type sequence\n",
704 ref->offset);
705 reg[insn->reg].seq_len =
706 *(unsigned long *) &filter_stack_data[ref->offset];
707 reg[insn->reg].str =
708 *(const char **) (&filter_stack_data[ref->offset
709 + sizeof(unsigned long)]);
710 reg[insn->reg].type = REG_STRING;
711 reg[insn->reg].literal = 0;
712 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
713 PO;
714 }
715
716 OP(FILTER_OP_LOAD_FIELD_REF_S64):
717 {
718 struct load_op *insn = (struct load_op *) pc;
719 struct field_ref *ref = (struct field_ref *) insn->data;
720
721 dbg_printf("load field ref offset %u type s64\n",
722 ref->offset);
723 memcpy(&reg[insn->reg].v, &filter_stack_data[ref->offset],
724 sizeof(struct literal_numeric));
725 reg[insn->reg].type = REG_S64;
726 reg[insn->reg].literal = 0;
727 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
728 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
729 PO;
730 }
731
732 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
733 {
734 struct load_op *insn = (struct load_op *) pc;
735 struct field_ref *ref = (struct field_ref *) insn->data;
736
737 dbg_printf("load field ref offset %u type double\n",
738 ref->offset);
739 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
740 sizeof(struct literal_double));
741 reg[insn->reg].type = REG_DOUBLE;
742 reg[insn->reg].literal = 0;
743 dbg_printf("ref load double %g\n", reg[insn->reg].d);
744 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
745 PO;
746 }
747
748 OP(FILTER_OP_LOAD_STRING):
749 {
750 struct load_op *insn = (struct load_op *) pc;
751
752 dbg_printf("load string %s\n", insn->data);
753 reg[insn->reg].str = insn->data;
754 reg[insn->reg].type = REG_STRING;
755 reg[insn->reg].seq_len = UINT_MAX;
756 reg[insn->reg].literal = 1;
757 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
758 PO;
759 }
760
761 OP(FILTER_OP_LOAD_S64):
762 {
763 struct load_op *insn = (struct load_op *) pc;
764
765 memcpy(&reg[insn->reg].v, insn->data,
766 sizeof(struct literal_numeric));
767 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
768 reg[insn->reg].type = REG_S64;
769 reg[insn->reg].literal = 1;
770 next_pc += sizeof(struct load_op)
771 + sizeof(struct literal_numeric);
772 PO;
773 }
774
775 OP(FILTER_OP_LOAD_DOUBLE):
776 {
777 struct load_op *insn = (struct load_op *) pc;
778
779 memcpy(&reg[insn->reg].d, insn->data,
780 sizeof(struct literal_double));
781 dbg_printf("load s64 %g\n", reg[insn->reg].d);
782 reg[insn->reg].type = REG_DOUBLE;
783 reg[insn->reg].literal = 1;
784 next_pc += sizeof(struct load_op)
785 + sizeof(struct literal_double);
786 PO;
787 }
788
789 END_OP
790 end:
791 /* return 0 (discard) on error */
792 if (ret)
793 return 0;
794 return retval;
795 }
796
797 #undef START_OP
798 #undef OP
799 #undef PO
800 #undef END_OP
801
802 static
803 int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
804 {
805 switch (reg[REG_R0].type) {
806 default:
807 goto error_unknown;
808
809 case REG_STRING:
810 switch (reg[REG_R1].type) {
811 default:
812 goto error_unknown;
813
814 case REG_STRING:
815 break;
816 case REG_S64:
817 case REG_DOUBLE:
818 goto error_mismatch;
819 }
820 break;
821 case REG_S64:
822 case REG_DOUBLE:
823 switch (reg[REG_R1].type) {
824 default:
825 goto error_unknown;
826
827 case REG_STRING:
828 goto error_mismatch;
829
830 case REG_S64:
831 case REG_DOUBLE:
832 break;
833 }
834 break;
835 }
836 return 0;
837
838 error_unknown:
839
840 return -EINVAL;
841 error_mismatch:
842 ERR("type mismatch for '%s' binary operator\n", str);
843 return -EINVAL;
844 }
845
846 static
847 int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
848 {
849 void *pc, *next_pc, *start_pc;
850 int ret = -EINVAL;
851 struct vreg reg[NR_REG];
852 int i;
853
854 for (i = 0; i < NR_REG; i++) {
855 reg[i].type = REG_TYPE_UNKNOWN;
856 reg[i].literal = 0;
857 }
858
859 start_pc = &bytecode->data[0];
860 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
861 pc = next_pc) {
862 if (unlikely(pc >= start_pc + bytecode->len)) {
863 ERR("filter bytecode overflow\n");
864 ret = -EINVAL;
865 goto end;
866 }
867 dbg_printf("Validating op %s (%u)\n",
868 print_op((unsigned int) *(filter_opcode_t *) pc),
869 (unsigned int) *(filter_opcode_t *) pc);
870 switch (*(filter_opcode_t *) pc) {
871 case FILTER_OP_UNKNOWN:
872 default:
873 ERR("unknown bytecode op %u\n",
874 (unsigned int) *(filter_opcode_t *) pc);
875 ret = -EINVAL;
876 goto end;
877
878 case FILTER_OP_RETURN:
879 ret = 0;
880 goto end;
881
882 /* binary */
883 case FILTER_OP_MUL:
884 case FILTER_OP_DIV:
885 case FILTER_OP_MOD:
886 case FILTER_OP_PLUS:
887 case FILTER_OP_MINUS:
888 case FILTER_OP_RSHIFT:
889 case FILTER_OP_LSHIFT:
890 case FILTER_OP_BIN_AND:
891 case FILTER_OP_BIN_OR:
892 case FILTER_OP_BIN_XOR:
893 ERR("unsupported bytecode op %u\n",
894 (unsigned int) *(filter_opcode_t *) pc);
895 ret = -EINVAL;
896 goto end;
897
898 case FILTER_OP_EQ:
899 {
900 ret = bin_op_compare_check(reg, "==");
901 if (ret)
902 goto end;
903 reg[REG_R0].type = REG_S64;
904 next_pc += sizeof(struct binary_op);
905 break;
906 }
907 case FILTER_OP_NE:
908 {
909 ret = bin_op_compare_check(reg, "!=");
910 if (ret)
911 goto end;
912 reg[REG_R0].type = REG_S64;
913 next_pc += sizeof(struct binary_op);
914 break;
915 }
916 case FILTER_OP_GT:
917 {
918 ret = bin_op_compare_check(reg, ">");
919 if (ret)
920 goto end;
921 reg[REG_R0].type = REG_S64;
922 next_pc += sizeof(struct binary_op);
923 break;
924 }
925 case FILTER_OP_LT:
926 {
927 ret = bin_op_compare_check(reg, "<");
928 if (ret)
929 goto end;
930 reg[REG_R0].type = REG_S64;
931 next_pc += sizeof(struct binary_op);
932 break;
933 }
934 case FILTER_OP_GE:
935 {
936 ret = bin_op_compare_check(reg, ">=");
937 if (ret)
938 goto end;
939 reg[REG_R0].type = REG_S64;
940 next_pc += sizeof(struct binary_op);
941 break;
942 }
943 case FILTER_OP_LE:
944 {
945 ret = bin_op_compare_check(reg, "<=");
946 if (ret)
947 goto end;
948 reg[REG_R0].type = REG_S64;
949 next_pc += sizeof(struct binary_op);
950 break;
951 }
952
953 case FILTER_OP_EQ_STRING:
954 case FILTER_OP_NE_STRING:
955 case FILTER_OP_GT_STRING:
956 case FILTER_OP_LT_STRING:
957 case FILTER_OP_GE_STRING:
958 case FILTER_OP_LE_STRING:
959 {
960 if (reg[REG_R0].type != REG_STRING
961 || reg[REG_R1].type != REG_STRING) {
962 ERR("Unexpected register type for string comparator\n");
963 ret = -EINVAL;
964 goto end;
965 }
966 reg[REG_R0].type = REG_S64;
967 next_pc += sizeof(struct binary_op);
968 break;
969 }
970
971 case FILTER_OP_EQ_S64:
972 case FILTER_OP_NE_S64:
973 case FILTER_OP_GT_S64:
974 case FILTER_OP_LT_S64:
975 case FILTER_OP_GE_S64:
976 case FILTER_OP_LE_S64:
977 {
978 if (reg[REG_R0].type != REG_S64
979 || reg[REG_R1].type != REG_S64) {
980 ERR("Unexpected register type for s64 comparator\n");
981 ret = -EINVAL;
982 goto end;
983 }
984 reg[REG_R0].type = REG_S64;
985 next_pc += sizeof(struct binary_op);
986 break;
987 }
988
989 case FILTER_OP_EQ_DOUBLE:
990 case FILTER_OP_NE_DOUBLE:
991 case FILTER_OP_GT_DOUBLE:
992 case FILTER_OP_LT_DOUBLE:
993 case FILTER_OP_GE_DOUBLE:
994 case FILTER_OP_LE_DOUBLE:
995 {
996 if ((reg[REG_R0].type != REG_DOUBLE && reg[REG_R0].type != REG_S64)
997 || (reg[REG_R1].type != REG_DOUBLE && reg[REG_R1].type != REG_S64)) {
998 ERR("Unexpected register type for double comparator\n");
999 ret = -EINVAL;
1000 goto end;
1001 }
1002 reg[REG_R0].type = REG_DOUBLE;
1003 next_pc += sizeof(struct binary_op);
1004 break;
1005 }
1006
1007 /* unary */
1008 case FILTER_OP_UNARY_PLUS:
1009 case FILTER_OP_UNARY_MINUS:
1010 case FILTER_OP_UNARY_NOT:
1011 {
1012 struct unary_op *insn = (struct unary_op *) pc;
1013
1014 if (unlikely(insn->reg >= REG_ERROR)) {
1015 ERR("invalid register %u\n",
1016 (unsigned int) insn->reg);
1017 ret = -EINVAL;
1018 goto end;
1019 }
1020 switch (reg[insn->reg].type) {
1021 default:
1022 ERR("unknown register type\n");
1023 ret = -EINVAL;
1024 goto end;
1025
1026 case REG_STRING:
1027 ERR("Unary op can only be applied to numeric or floating point registers\n");
1028 ret = -EINVAL;
1029 goto end;
1030 case REG_S64:
1031 break;
1032 case REG_DOUBLE:
1033 break;
1034 }
1035 next_pc += sizeof(struct unary_op);
1036 break;
1037 }
1038
1039 case FILTER_OP_UNARY_PLUS_S64:
1040 case FILTER_OP_UNARY_MINUS_S64:
1041 case FILTER_OP_UNARY_NOT_S64:
1042 {
1043 struct unary_op *insn = (struct unary_op *) pc;
1044
1045 if (unlikely(insn->reg >= REG_ERROR)) {
1046 ERR("invalid register %u\n",
1047 (unsigned int) insn->reg);
1048 ret = -EINVAL;
1049 goto end;
1050 }
1051 if (reg[insn->reg].type != REG_S64) {
1052 ERR("Invalid register type\n");
1053 ret = -EINVAL;
1054 goto end;
1055 }
1056 next_pc += sizeof(struct unary_op);
1057 break;
1058 }
1059
1060 case FILTER_OP_UNARY_PLUS_DOUBLE:
1061 case FILTER_OP_UNARY_MINUS_DOUBLE:
1062 case FILTER_OP_UNARY_NOT_DOUBLE:
1063 {
1064 struct unary_op *insn = (struct unary_op *) pc;
1065
1066 if (unlikely(insn->reg >= REG_ERROR)) {
1067 ERR("invalid register %u\n",
1068 (unsigned int) insn->reg);
1069 ret = -EINVAL;
1070 goto end;
1071 }
1072 if (reg[insn->reg].type != REG_DOUBLE) {
1073 ERR("Invalid register type\n");
1074 ret = -EINVAL;
1075 goto end;
1076 }
1077 next_pc += sizeof(struct unary_op);
1078 break;
1079 }
1080
1081 /* logical */
1082 case FILTER_OP_AND:
1083 case FILTER_OP_OR:
1084 {
1085 struct logical_op *insn = (struct logical_op *) pc;
1086
1087 if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
1088 || reg[REG_R1].type == REG_TYPE_UNKNOWN
1089 || reg[REG_R0].type == REG_STRING
1090 || reg[REG_R1].type == REG_STRING)) {
1091 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
1092 ret = -EINVAL;
1093 goto end;
1094 }
1095
1096 dbg_printf("Validate jumping to bytecode offset %u\n",
1097 (unsigned int) insn->skip_offset);
1098 if (unlikely(start_pc + insn->skip_offset <= pc)) {
1099 ERR("Loops are not allowed in bytecode\n");
1100 ret = -EINVAL;
1101 goto end;
1102 }
1103 next_pc += sizeof(struct logical_op);
1104 break;
1105 }
1106
1107 /* load */
1108 case FILTER_OP_LOAD_FIELD_REF:
1109 {
1110 ERR("Unknown field ref type\n");
1111 ret = -EINVAL;
1112 goto end;
1113 }
1114 case FILTER_OP_LOAD_FIELD_REF_STRING:
1115 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1116 {
1117 struct load_op *insn = (struct load_op *) pc;
1118 struct field_ref *ref = (struct field_ref *) insn->data;
1119
1120 if (unlikely(insn->reg >= REG_ERROR)) {
1121 ERR("invalid register %u\n",
1122 (unsigned int) insn->reg);
1123 ret = -EINVAL;
1124 goto end;
1125 }
1126 dbg_printf("Validate load field ref offset %u type string\n",
1127 ref->offset);
1128 reg[insn->reg].type = REG_STRING;
1129 reg[insn->reg].literal = 0;
1130 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1131 break;
1132 }
1133 case FILTER_OP_LOAD_FIELD_REF_S64:
1134 {
1135 struct load_op *insn = (struct load_op *) pc;
1136 struct field_ref *ref = (struct field_ref *) insn->data;
1137
1138 if (unlikely(insn->reg >= REG_ERROR)) {
1139 ERR("invalid register %u\n",
1140 (unsigned int) insn->reg);
1141 ret = -EINVAL;
1142 goto end;
1143 }
1144 dbg_printf("Validate load field ref offset %u type s64\n",
1145 ref->offset);
1146 reg[insn->reg].type = REG_S64;
1147 reg[insn->reg].literal = 0;
1148 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1149 break;
1150 }
1151 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1152 {
1153 struct load_op *insn = (struct load_op *) pc;
1154 struct field_ref *ref = (struct field_ref *) insn->data;
1155
1156 if (unlikely(insn->reg >= REG_ERROR)) {
1157 ERR("invalid register %u\n",
1158 (unsigned int) insn->reg);
1159 ret = -EINVAL;
1160 goto end;
1161 }
1162 dbg_printf("Validate load field ref offset %u type double\n",
1163 ref->offset);
1164 reg[insn->reg].type = REG_DOUBLE;
1165 reg[insn->reg].literal = 0;
1166 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1167 break;
1168 }
1169
1170 case FILTER_OP_LOAD_STRING:
1171 {
1172 struct load_op *insn = (struct load_op *) pc;
1173
1174 if (unlikely(insn->reg >= REG_ERROR)) {
1175 ERR("invalid register %u\n",
1176 (unsigned int) insn->reg);
1177 ret = -EINVAL;
1178 goto end;
1179 }
1180 reg[insn->reg].type = REG_STRING;
1181 reg[insn->reg].literal = 1;
1182 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1183 break;
1184 }
1185
1186 case FILTER_OP_LOAD_S64:
1187 {
1188 struct load_op *insn = (struct load_op *) pc;
1189
1190 if (unlikely(insn->reg >= REG_ERROR)) {
1191 ERR("invalid register %u\n",
1192 (unsigned int) insn->reg);
1193 ret = -EINVAL;
1194 goto end;
1195 }
1196 reg[insn->reg].type = REG_S64;
1197 reg[insn->reg].literal = 1;
1198 next_pc += sizeof(struct load_op)
1199 + sizeof(struct literal_numeric);
1200 break;
1201 }
1202
1203 case FILTER_OP_LOAD_DOUBLE:
1204 {
1205 struct load_op *insn = (struct load_op *) pc;
1206
1207 if (unlikely(insn->reg >= REG_ERROR)) {
1208 ERR("invalid register %u\n",
1209 (unsigned int) insn->reg);
1210 ret = -EINVAL;
1211 goto end;
1212 }
1213 reg[insn->reg].type = REG_DOUBLE;
1214 reg[insn->reg].literal = 1;
1215 next_pc += sizeof(struct load_op)
1216 + sizeof(struct literal_double);
1217 break;
1218 }
1219 }
1220 }
1221 end:
1222 return ret;
1223 }
1224
1225 static
1226 int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
1227 {
1228 void *pc, *next_pc, *start_pc;
1229 int ret = -EINVAL;
1230 struct vreg reg[NR_REG];
1231 int i;
1232
1233 for (i = 0; i < NR_REG; i++) {
1234 reg[i].type = REG_TYPE_UNKNOWN;
1235 reg[i].literal = 0;
1236 }
1237
1238 start_pc = &bytecode->data[0];
1239 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1240 pc = next_pc) {
1241 switch (*(filter_opcode_t *) pc) {
1242 case FILTER_OP_UNKNOWN:
1243 default:
1244 ERR("unknown bytecode op %u\n",
1245 (unsigned int) *(filter_opcode_t *) pc);
1246 ret = -EINVAL;
1247 goto end;
1248
1249 case FILTER_OP_RETURN:
1250 ret = 0;
1251 goto end;
1252
1253 /* binary */
1254 case FILTER_OP_MUL:
1255 case FILTER_OP_DIV:
1256 case FILTER_OP_MOD:
1257 case FILTER_OP_PLUS:
1258 case FILTER_OP_MINUS:
1259 case FILTER_OP_RSHIFT:
1260 case FILTER_OP_LSHIFT:
1261 case FILTER_OP_BIN_AND:
1262 case FILTER_OP_BIN_OR:
1263 case FILTER_OP_BIN_XOR:
1264 ERR("unsupported bytecode op %u\n",
1265 (unsigned int) *(filter_opcode_t *) pc);
1266 ret = -EINVAL;
1267 goto end;
1268
1269 case FILTER_OP_EQ:
1270 {
1271 struct binary_op *insn = (struct binary_op *) pc;
1272
1273 switch(reg[REG_R0].type) {
1274 default:
1275 ERR("unknown register type\n");
1276 ret = -EINVAL;
1277 goto end;
1278
1279 case REG_STRING:
1280 insn->op = FILTER_OP_EQ_STRING;
1281 break;
1282 case REG_S64:
1283 if (reg[REG_R1].type == REG_S64)
1284 insn->op = FILTER_OP_EQ_S64;
1285 else
1286 insn->op = FILTER_OP_EQ_DOUBLE;
1287 break;
1288 case REG_DOUBLE:
1289 insn->op = FILTER_OP_EQ_DOUBLE;
1290 break;
1291 }
1292 reg[REG_R0].type = REG_S64;
1293 next_pc += sizeof(struct binary_op);
1294 break;
1295 }
1296
1297 case FILTER_OP_NE:
1298 {
1299 struct binary_op *insn = (struct binary_op *) pc;
1300
1301 switch(reg[REG_R0].type) {
1302 default:
1303 ERR("unknown register type\n");
1304 ret = -EINVAL;
1305 goto end;
1306
1307 case REG_STRING:
1308 insn->op = FILTER_OP_NE_STRING;
1309 break;
1310 case REG_S64:
1311 if (reg[REG_R1].type == REG_S64)
1312 insn->op = FILTER_OP_NE_S64;
1313 else
1314 insn->op = FILTER_OP_NE_DOUBLE;
1315 break;
1316 case REG_DOUBLE:
1317 insn->op = FILTER_OP_NE_DOUBLE;
1318 break;
1319 }
1320 reg[REG_R0].type = REG_S64;
1321 next_pc += sizeof(struct binary_op);
1322 break;
1323 }
1324
1325 case FILTER_OP_GT:
1326 {
1327 struct binary_op *insn = (struct binary_op *) pc;
1328
1329 switch(reg[REG_R0].type) {
1330 default:
1331 ERR("unknown register type\n");
1332 ret = -EINVAL;
1333 goto end;
1334
1335 case REG_STRING:
1336 insn->op = FILTER_OP_GT_STRING;
1337 break;
1338 case REG_S64:
1339 if (reg[REG_R1].type == REG_S64)
1340 insn->op = FILTER_OP_GT_S64;
1341 else
1342 insn->op = FILTER_OP_GT_DOUBLE;
1343 break;
1344 case REG_DOUBLE:
1345 insn->op = FILTER_OP_GT_DOUBLE;
1346 break;
1347 }
1348 reg[REG_R0].type = REG_S64;
1349 next_pc += sizeof(struct binary_op);
1350 break;
1351 }
1352
1353 case FILTER_OP_LT:
1354 {
1355 struct binary_op *insn = (struct binary_op *) pc;
1356
1357 switch(reg[REG_R0].type) {
1358 default:
1359 ERR("unknown register type\n");
1360 ret = -EINVAL;
1361 goto end;
1362
1363 case REG_STRING:
1364 insn->op = FILTER_OP_LT_STRING;
1365 break;
1366 case REG_S64:
1367 if (reg[REG_R1].type == REG_S64)
1368 insn->op = FILTER_OP_LT_S64;
1369 else
1370 insn->op = FILTER_OP_LT_DOUBLE;
1371 break;
1372 case REG_DOUBLE:
1373 insn->op = FILTER_OP_LT_DOUBLE;
1374 break;
1375 }
1376 reg[REG_R0].type = REG_S64;
1377 next_pc += sizeof(struct binary_op);
1378 break;
1379 }
1380
1381 case FILTER_OP_GE:
1382 {
1383 struct binary_op *insn = (struct binary_op *) pc;
1384
1385 switch(reg[REG_R0].type) {
1386 default:
1387 ERR("unknown register type\n");
1388 ret = -EINVAL;
1389 goto end;
1390
1391 case REG_STRING:
1392 insn->op = FILTER_OP_GE_STRING;
1393 break;
1394 case REG_S64:
1395 if (reg[REG_R1].type == REG_S64)
1396 insn->op = FILTER_OP_GE_S64;
1397 else
1398 insn->op = FILTER_OP_GE_DOUBLE;
1399 break;
1400 case REG_DOUBLE:
1401 insn->op = FILTER_OP_GE_DOUBLE;
1402 break;
1403 }
1404 reg[REG_R0].type = REG_S64;
1405 next_pc += sizeof(struct binary_op);
1406 break;
1407 }
1408 case FILTER_OP_LE:
1409 {
1410 struct binary_op *insn = (struct binary_op *) pc;
1411
1412 switch(reg[REG_R0].type) {
1413 default:
1414 ERR("unknown register type\n");
1415 ret = -EINVAL;
1416 goto end;
1417
1418 case REG_STRING:
1419 insn->op = FILTER_OP_LE_STRING;
1420 break;
1421 case REG_S64:
1422 if (reg[REG_R1].type == REG_S64)
1423 insn->op = FILTER_OP_LE_S64;
1424 else
1425 insn->op = FILTER_OP_LE_DOUBLE;
1426 break;
1427 case REG_DOUBLE:
1428 insn->op = FILTER_OP_LE_DOUBLE;
1429 break;
1430 }
1431 reg[REG_R0].type = REG_S64;
1432 next_pc += sizeof(struct binary_op);
1433 break;
1434 }
1435
1436 case FILTER_OP_EQ_STRING:
1437 case FILTER_OP_NE_STRING:
1438 case FILTER_OP_GT_STRING:
1439 case FILTER_OP_LT_STRING:
1440 case FILTER_OP_GE_STRING:
1441 case FILTER_OP_LE_STRING:
1442 case FILTER_OP_EQ_S64:
1443 case FILTER_OP_NE_S64:
1444 case FILTER_OP_GT_S64:
1445 case FILTER_OP_LT_S64:
1446 case FILTER_OP_GE_S64:
1447 case FILTER_OP_LE_S64:
1448 case FILTER_OP_EQ_DOUBLE:
1449 case FILTER_OP_NE_DOUBLE:
1450 case FILTER_OP_GT_DOUBLE:
1451 case FILTER_OP_LT_DOUBLE:
1452 case FILTER_OP_GE_DOUBLE:
1453 case FILTER_OP_LE_DOUBLE:
1454 {
1455 reg[REG_R0].type = REG_S64;
1456 next_pc += sizeof(struct binary_op);
1457 break;
1458 }
1459
1460 /* unary */
1461 case FILTER_OP_UNARY_PLUS:
1462 {
1463 struct unary_op *insn = (struct unary_op *) pc;
1464
1465 switch(reg[insn->reg].type) {
1466 default:
1467 ERR("unknown register type\n");
1468 ret = -EINVAL;
1469 goto end;
1470
1471 case REG_S64:
1472 insn->op = FILTER_OP_UNARY_PLUS_S64;
1473 break;
1474 case REG_DOUBLE:
1475 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1476 break;
1477 }
1478 break;
1479 }
1480
1481 case FILTER_OP_UNARY_MINUS:
1482 {
1483 struct unary_op *insn = (struct unary_op *) pc;
1484
1485 switch(reg[insn->reg].type) {
1486 default:
1487 ERR("unknown register type\n");
1488 ret = -EINVAL;
1489 goto end;
1490
1491 case REG_S64:
1492 insn->op = FILTER_OP_UNARY_MINUS_S64;
1493 break;
1494 case REG_DOUBLE:
1495 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1496 break;
1497 }
1498 break;
1499 }
1500
1501 case FILTER_OP_UNARY_NOT:
1502 {
1503 struct unary_op *insn = (struct unary_op *) pc;
1504
1505 switch(reg[insn->reg].type) {
1506 default:
1507 ERR("unknown register type\n");
1508 ret = -EINVAL;
1509 goto end;
1510
1511 case REG_S64:
1512 insn->op = FILTER_OP_UNARY_NOT_S64;
1513 break;
1514 case REG_DOUBLE:
1515 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1516 break;
1517 }
1518 break;
1519 }
1520
1521 case FILTER_OP_UNARY_PLUS_S64:
1522 case FILTER_OP_UNARY_MINUS_S64:
1523 case FILTER_OP_UNARY_NOT_S64:
1524 case FILTER_OP_UNARY_PLUS_DOUBLE:
1525 case FILTER_OP_UNARY_MINUS_DOUBLE:
1526 case FILTER_OP_UNARY_NOT_DOUBLE:
1527 {
1528 next_pc += sizeof(struct unary_op);
1529 break;
1530 }
1531
1532 /* logical */
1533 case FILTER_OP_AND:
1534 case FILTER_OP_OR:
1535 {
1536 next_pc += sizeof(struct logical_op);
1537 break;
1538 }
1539
1540 /* load */
1541 case FILTER_OP_LOAD_FIELD_REF:
1542 {
1543 ERR("Unknown field ref type\n");
1544 ret = -EINVAL;
1545 goto end;
1546 }
1547 case FILTER_OP_LOAD_FIELD_REF_STRING:
1548 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1549 {
1550 struct load_op *insn = (struct load_op *) pc;
1551
1552 reg[insn->reg].type = REG_STRING;
1553 reg[insn->reg].literal = 0;
1554 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1555 break;
1556 }
1557 case FILTER_OP_LOAD_FIELD_REF_S64:
1558 {
1559 struct load_op *insn = (struct load_op *) pc;
1560
1561 reg[insn->reg].type = REG_S64;
1562 reg[insn->reg].literal = 0;
1563 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1564 break;
1565 }
1566 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1567 {
1568 struct load_op *insn = (struct load_op *) pc;
1569
1570 reg[insn->reg].type = REG_DOUBLE;
1571 reg[insn->reg].literal = 0;
1572 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1573 break;
1574 }
1575
1576 case FILTER_OP_LOAD_STRING:
1577 {
1578 struct load_op *insn = (struct load_op *) pc;
1579
1580 reg[insn->reg].type = REG_STRING;
1581 reg[insn->reg].literal = 1;
1582 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1583 break;
1584 }
1585
1586 case FILTER_OP_LOAD_S64:
1587 {
1588 struct load_op *insn = (struct load_op *) pc;
1589
1590 reg[insn->reg].type = REG_S64;
1591 reg[insn->reg].literal = 1;
1592 next_pc += sizeof(struct load_op)
1593 + sizeof(struct literal_numeric);
1594 break;
1595 }
1596
1597 case FILTER_OP_LOAD_DOUBLE:
1598 {
1599 struct load_op *insn = (struct load_op *) pc;
1600
1601 reg[insn->reg].type = REG_DOUBLE;
1602 reg[insn->reg].literal = 1;
1603 next_pc += sizeof(struct load_op)
1604 + sizeof(struct literal_double);
1605 break;
1606 }
1607 }
1608 }
1609 end:
1610 return ret;
1611 }
1612
1613
1614
1615 static
1616 int apply_field_reloc(struct ltt_event *event,
1617 struct bytecode_runtime *runtime,
1618 uint32_t runtime_len,
1619 uint32_t reloc_offset,
1620 const char *field_name)
1621 {
1622 const struct lttng_event_desc *desc;
1623 const struct lttng_event_field *fields, *field = NULL;
1624 unsigned int nr_fields, i;
1625 struct field_ref *field_ref;
1626 struct load_op *op;
1627 uint32_t field_offset = 0;
1628
1629 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
1630
1631 /* Ensure that the reloc is within the code */
1632 if (runtime_len - reloc_offset < sizeof(uint16_t))
1633 return -EINVAL;
1634
1635 /* Lookup event by name */
1636 desc = event->desc;
1637 if (!desc)
1638 return -EINVAL;
1639 fields = desc->fields;
1640 if (!fields)
1641 return -EINVAL;
1642 nr_fields = desc->nr_fields;
1643 for (i = 0; i < nr_fields; i++) {
1644 if (!strcmp(fields[i].name, field_name)) {
1645 field = &fields[i];
1646 break;
1647 }
1648 /* compute field offset */
1649 switch (fields[i].type.atype) {
1650 case atype_integer:
1651 case atype_enum:
1652 field_offset += sizeof(int64_t);
1653 break;
1654 case atype_array:
1655 case atype_sequence:
1656 field_offset += sizeof(unsigned long);
1657 field_offset += sizeof(void *);
1658 break;
1659 case atype_string:
1660 field_offset += sizeof(void *);
1661 break;
1662 case atype_float:
1663 field_offset += sizeof(double);
1664 break;
1665 default:
1666 return -EINVAL;
1667 }
1668 }
1669 if (!field)
1670 return -EINVAL;
1671
1672 /* Check if field offset is too large for 16-bit offset */
1673 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1674 return -EINVAL;
1675
1676 /* set type */
1677 op = (struct load_op *) &runtime->data[reloc_offset];
1678 field_ref = (struct field_ref *) op->data;
1679 switch (field->type.atype) {
1680 case atype_integer:
1681 case atype_enum:
1682 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
1683 break;
1684 case atype_array:
1685 case atype_sequence:
1686 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
1687 break;
1688 case atype_string:
1689 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
1690 break;
1691 case atype_float:
1692 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
1693 break;
1694 default:
1695 return -EINVAL;
1696 }
1697 /* set offset */
1698 field_ref->offset = (uint16_t) field_offset;
1699 return 0;
1700 }
1701
1702 /*
1703 * Take a bytecode with reloc table and link it to an event to create a
1704 * bytecode runtime.
1705 */
1706 static
1707 int _lttng_filter_event_link_bytecode(struct ltt_event *event,
1708 struct lttng_ust_filter_bytecode *filter_bytecode)
1709 {
1710 int ret, offset, next_offset;
1711 struct bytecode_runtime *runtime = NULL;
1712 size_t runtime_alloc_len;
1713
1714 if (!filter_bytecode)
1715 return 0;
1716 /* Even is not connected to any description */
1717 if (!event->desc)
1718 return 0;
1719 /* Bytecode already linked */
1720 if (event->filter || event->filter_data)
1721 return 0;
1722
1723 dbg_printf("Linking\n");
1724
1725 /* We don't need the reloc table in the runtime */
1726 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
1727 runtime = zmalloc(runtime_alloc_len);
1728 if (!runtime) {
1729 ret = -ENOMEM;
1730 goto link_error;
1731 }
1732 runtime->len = filter_bytecode->reloc_offset;
1733 /* copy original bytecode */
1734 memcpy(runtime->data, filter_bytecode->data, runtime->len);
1735 /*
1736 * apply relocs. Those are a uint16_t (offset in bytecode)
1737 * followed by a string (field name).
1738 */
1739 for (offset = filter_bytecode->reloc_offset;
1740 offset < filter_bytecode->len;
1741 offset = next_offset) {
1742 uint16_t reloc_offset =
1743 *(uint16_t *) &filter_bytecode->data[offset];
1744 const char *field_name =
1745 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
1746
1747 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
1748 if (ret) {
1749 goto link_error;
1750 }
1751 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
1752 }
1753 /* Validate bytecode */
1754 ret = lttng_filter_validate_bytecode(runtime);
1755 if (ret) {
1756 goto link_error;
1757 }
1758 /* Specialize bytecode */
1759 ret = lttng_filter_specialize_bytecode(runtime);
1760 if (ret) {
1761 goto link_error;
1762 }
1763 event->filter_data = runtime;
1764 event->filter = lttng_filter_interpret_bytecode;
1765 return 0;
1766
1767 link_error:
1768 event->filter = lttng_filter_false;
1769 free(runtime);
1770 return ret;
1771 }
1772
1773 void lttng_filter_event_link_bytecode(struct ltt_event *event,
1774 struct lttng_ust_filter_bytecode *filter_bytecode)
1775 {
1776 int ret;
1777
1778 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
1779 if (ret) {
1780 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
1781 }
1782 }
1783
1784 /*
1785 * Link bytecode to all events for a wildcard. Skips events that already
1786 * have a bytecode linked.
1787 * We do not set each event's filter_bytecode field, because they do not
1788 * own the filter_bytecode: the wildcard owns it.
1789 */
1790 void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
1791 {
1792 struct ltt_event *event;
1793 int ret;
1794
1795 if (!wildcard->filter_bytecode)
1796 return;
1797
1798 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
1799 if (event->filter)
1800 continue;
1801 ret = _lttng_filter_event_link_bytecode(event,
1802 wildcard->filter_bytecode);
1803 if (ret) {
1804 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
1805 }
1806
1807 }
1808 return;
1809 }
1810
1811 /*
1812 * Need to attach filter to an event before starting tracing for the
1813 * session. We own the filter_bytecode if we return success.
1814 */
1815 int lttng_filter_event_attach_bytecode(struct ltt_event *event,
1816 struct lttng_ust_filter_bytecode *filter_bytecode)
1817 {
1818 if (event->chan->session->been_active)
1819 return -EPERM;
1820 if (event->filter_bytecode)
1821 return -EEXIST;
1822 event->filter_bytecode = filter_bytecode;
1823 return 0;
1824 }
1825
1826 /*
1827 * Need to attach filter to a wildcard before starting tracing for the
1828 * session. We own the filter_bytecode if we return success.
1829 */
1830 int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
1831 struct lttng_ust_filter_bytecode *filter_bytecode)
1832 {
1833 if (wildcard->chan->session->been_active)
1834 return -EPERM;
1835 if (wildcard->filter_bytecode)
1836 return -EEXIST;
1837 wildcard->filter_bytecode = filter_bytecode;
1838 return 0;
1839 }
This page took 0.064237 seconds and 5 git commands to generate.