Validate registers, no need to initialize to 0
[lttng-ust.git] / liblttng-ust / lttng-filter.c
CommitLineData
2d78951a
MD
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>
cd54f6d9
MD
27#include <stdint.h>
28#include <errno.h>
29#include <string.h>
30#include <inttypes.h>
31#include <limits.h>
b1caea50 32#include <usterr-signal-safe.h>
cd54f6d9
MD
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...) \
54do { \
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 */
62struct bytecode_runtime {
63 uint16_t len;
64 char data[0];
65};
66
9522a886
MD
67enum reg_type {
68 REG_S64,
69 REG_DOUBLE,
70 REG_STRING,
225b6640 71 REG_TYPE_UNKNOWN,
9522a886
MD
72};
73
74/* Validation registers */
75struct vreg {
76 enum reg_type type;
77 int literal; /* is string literal ? */
78};
79
80/* Execution registers */
cd54f6d9 81struct reg {
9522a886 82 enum reg_type type;
cd54f6d9 83 int64_t v;
da6eed25 84 double d;
cd54f6d9
MD
85
86 const char *str;
87 size_t seq_len;
88 int literal; /* is string literal ? */
89};
90
91static 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 [ FILTER_OP_EQ ] = "EQ",
108 [ FILTER_OP_NE ] = "NE",
109 [ FILTER_OP_GT ] = "GT",
110 [ FILTER_OP_LT ] = "LT",
111 [ FILTER_OP_GE ] = "GE",
112 [ FILTER_OP_LE ] = "LE",
113
114 /* unary */
115 [ FILTER_OP_UNARY_PLUS ] = "UNARY_PLUS",
116 [ FILTER_OP_UNARY_MINUS ] = "UNARY_MINUS",
117 [ FILTER_OP_UNARY_NOT ] = "UNARY_NOT",
118
119 /* logical */
120 [ FILTER_OP_AND ] = "AND",
121 [ FILTER_OP_OR ] = "OR",
122
123 /* load */
124 [ FILTER_OP_LOAD_FIELD_REF ] = "LOAD_FIELD_REF",
2f0145d1
MD
125 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = "LOAD_FIELD_REF_STRING",
126 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = "LOAD_FIELD_REF_SEQUENCE",
127 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = "LOAD_FIELD_REF_S64",
128 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = "LOAD_FIELD_REF_DOUBLE",
129
cd54f6d9
MD
130 [ FILTER_OP_LOAD_STRING ] = "LOAD_STRING",
131 [ FILTER_OP_LOAD_S64 ] = "LOAD_S64",
da6eed25 132 [ FILTER_OP_LOAD_DOUBLE ] = "LOAD_DOUBLE",
cd54f6d9
MD
133};
134
135static
136const char *print_op(enum filter_op op)
137{
138 if (op >= NR_FILTER_OPS)
139 return "UNKNOWN";
140 else
141 return opnames[op];
142}
143
144/*
145 * -1: wildcard found.
146 * -2: unknown escape char.
147 * 0: normal char.
148 */
149
150static
151int parse_char(const char **p)
152{
153 switch (**p) {
154 case '\\':
155 (*p)++;
156 switch (**p) {
157 case '\\':
158 case '*':
159 return 0;
160 default:
161 return -2;
162 }
163 case '*':
164 return -1;
165 default:
166 return 0;
167 }
168}
169
170static
171int reg_strcmp(struct reg reg[NR_REG], const char *cmp_type)
172{
173 const char *p = reg[REG_R0].str, *q = reg[REG_R1].str;
174 int ret;
175 int diff;
176
177 for (;;) {
178 int escaped_r0 = 0;
179
180 if (unlikely(p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')) {
181 if (q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')
182 diff = 0;
183 else
184 diff = -1;
185 break;
186 }
187 if (unlikely(q - reg[REG_R1].str > reg[REG_R1].seq_len || *q == '\0')) {
188 if (p - reg[REG_R0].str > reg[REG_R0].seq_len || *p == '\0')
189 diff = 0;
190 else
191 diff = 1;
192 break;
193 }
194 if (reg[REG_R0].literal) {
195 ret = parse_char(&p);
196 if (ret == -1) {
197 return 0;
198 } else if (ret == -2) {
199 escaped_r0 = 1;
200 }
201 /* else compare both char */
202 }
203 if (reg[REG_R1].literal) {
204 ret = parse_char(&q);
205 if (ret == -1) {
206 return 0;
207 } else if (ret == -2) {
208 if (!escaped_r0)
209 return -1;
210 } else {
211 if (escaped_r0)
212 return 1;
213 }
214 } else {
215 if (escaped_r0)
216 return 1;
217 }
218 diff = *p - *q;
219 if (diff != 0)
220 break;
221 p++;
222 q++;
223 }
224 return diff;
225}
226
227static
228int lttng_filter_false(void *filter_data,
229 const char *filter_stack_data)
230{
231 return 0;
232}
2d78951a
MD
233
234static
235int lttng_filter_interpret_bytecode(void *filter_data,
236 const char *filter_stack_data)
237{
cd54f6d9
MD
238 struct bytecode_runtime *bytecode = filter_data;
239 void *pc, *next_pc, *start_pc;
240 int ret = -EINVAL;
241 int retval = 0;
242 struct reg reg[NR_REG];
cd54f6d9
MD
243
244 start_pc = &bytecode->data[0];
245 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
246 pc = next_pc) {
cd54f6d9
MD
247 dbg_printf("Executing op %s (%u)\n",
248 print_op((unsigned int) *(filter_opcode_t *) pc),
249 (unsigned int) *(filter_opcode_t *) pc);
250 switch (*(filter_opcode_t *) pc) {
251 case FILTER_OP_UNKNOWN:
2f0145d1 252 case FILTER_OP_LOAD_FIELD_REF:
cd54f6d9 253 default:
b1caea50 254 ERR("unknown bytecode op %u\n",
cd54f6d9
MD
255 (unsigned int) *(filter_opcode_t *) pc);
256 ret = -EINVAL;
257 goto end;
258
259 case FILTER_OP_RETURN:
260 retval = !!reg[0].v;
261 ret = 0;
262 goto end;
263
264 /* binary */
265 case FILTER_OP_MUL:
266 case FILTER_OP_DIV:
267 case FILTER_OP_MOD:
268 case FILTER_OP_PLUS:
269 case FILTER_OP_MINUS:
270 case FILTER_OP_RSHIFT:
271 case FILTER_OP_LSHIFT:
272 case FILTER_OP_BIN_AND:
273 case FILTER_OP_BIN_OR:
274 case FILTER_OP_BIN_XOR:
b1caea50 275 ERR("unsupported bytecode op %u\n",
cd54f6d9
MD
276 (unsigned int) *(filter_opcode_t *) pc);
277 ret = -EINVAL;
278 goto end;
279
280 case FILTER_OP_EQ:
281 {
cd54f6d9
MD
282 switch (reg[REG_R0].type) {
283 default:
b1caea50 284 ERR("unknown register type\n");
cd54f6d9
MD
285 ret = -EINVAL;
286 goto end;
287
288 case REG_STRING:
cd54f6d9
MD
289 reg[REG_R0].v = (reg_strcmp(reg, "==") == 0);
290 break;
291 case REG_S64:
da6eed25
MD
292 switch (reg[REG_R1].type) {
293 default:
b1caea50 294 ERR("unknown register type\n");
da6eed25
MD
295 ret = -EINVAL;
296 goto end;
297
298 case REG_S64:
299 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].v);
300 break;
301 case REG_DOUBLE:
302 reg[REG_R0].v = (reg[REG_R0].v == reg[REG_R1].d);
303 break;
304 }
305 break;
306 case REG_DOUBLE:
307 switch (reg[REG_R1].type) {
308 default:
b1caea50 309 ERR("unknown register type\n");
da6eed25
MD
310 ret = -EINVAL;
311 goto end;
312
313 case REG_S64:
314 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].v);
315 break;
316 case REG_DOUBLE:
317 reg[REG_R0].v = (reg[REG_R0].d == reg[REG_R1].d);
318 break;
319 }
cd54f6d9
MD
320 break;
321 }
322 reg[REG_R0].type = REG_S64;
323 next_pc += sizeof(struct binary_op);
324 break;
325 }
326 case FILTER_OP_NE:
327 {
cd54f6d9
MD
328 switch (reg[REG_R0].type) {
329 default:
b1caea50 330 ERR("unknown register type\n");
cd54f6d9
MD
331 ret = -EINVAL;
332 goto end;
333
334 case REG_STRING:
cd54f6d9
MD
335 reg[REG_R0].v = (reg_strcmp(reg, "!=") != 0);
336 break;
337 case REG_S64:
da6eed25
MD
338 switch (reg[REG_R1].type) {
339 default:
b1caea50 340 ERR("unknown register type\n");
da6eed25
MD
341 ret = -EINVAL;
342 goto end;
343
344 case REG_S64:
345 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].v);
346 break;
347 case REG_DOUBLE:
348 reg[REG_R0].v = (reg[REG_R0].v != reg[REG_R1].d);
349 break;
350 }
351 break;
352 case REG_DOUBLE:
353 switch (reg[REG_R1].type) {
354 default:
b1caea50 355 ERR("unknown register type\n");
da6eed25
MD
356 ret = -EINVAL;
357 goto end;
358
359 case REG_S64:
360 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].v);
361 break;
362 case REG_DOUBLE:
363 reg[REG_R0].v = (reg[REG_R0].d != reg[REG_R1].d);
364 break;
365 }
cd54f6d9
MD
366 break;
367 }
368 reg[REG_R0].type = REG_S64;
369 next_pc += sizeof(struct binary_op);
370 break;
371 }
372 case FILTER_OP_GT:
373 {
cd54f6d9
MD
374 switch (reg[REG_R0].type) {
375 default:
b1caea50 376 ERR("unknown register type\n");
cd54f6d9
MD
377 ret = -EINVAL;
378 goto end;
379
380 case REG_STRING:
cd54f6d9
MD
381 reg[REG_R0].v = (reg_strcmp(reg, ">") > 0);
382 break;
383 case REG_S64:
da6eed25
MD
384 switch (reg[REG_R1].type) {
385 default:
b1caea50 386 ERR("unknown register type\n");
da6eed25
MD
387 ret = -EINVAL;
388 goto end;
389
390 case REG_S64:
391 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].v);
392 break;
393 case REG_DOUBLE:
394 reg[REG_R0].v = (reg[REG_R0].v > reg[REG_R1].d);
395 break;
396 }
397 break;
398 case REG_DOUBLE:
399 switch (reg[REG_R1].type) {
400 default:
b1caea50 401 ERR("unknown register type\n");
da6eed25
MD
402 ret = -EINVAL;
403 goto end;
404
405 case REG_S64:
406 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].v);
407 break;
408 case REG_DOUBLE:
409 reg[REG_R0].v = (reg[REG_R0].d > reg[REG_R1].d);
410 break;
411 }
cd54f6d9
MD
412 break;
413 }
414 reg[REG_R0].type = REG_S64;
415 next_pc += sizeof(struct binary_op);
416 break;
417 }
418 case FILTER_OP_LT:
419 {
cd54f6d9
MD
420 switch (reg[REG_R0].type) {
421 default:
b1caea50 422 ERR("unknown register type\n");
cd54f6d9
MD
423 ret = -EINVAL;
424 goto end;
425
426 case REG_STRING:
cd54f6d9
MD
427 reg[REG_R0].v = (reg_strcmp(reg, "<") < 0);
428 break;
429 case REG_S64:
da6eed25
MD
430 switch (reg[REG_R1].type) {
431 default:
b1caea50 432 ERR("unknown register type\n");
da6eed25
MD
433 ret = -EINVAL;
434 goto end;
435
436 case REG_S64:
437 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].v);
438 break;
439 case REG_DOUBLE:
440 reg[REG_R0].v = (reg[REG_R0].v < reg[REG_R1].d);
441 break;
442 }
443 break;
444 case REG_DOUBLE:
445 switch (reg[REG_R1].type) {
446 default:
b1caea50 447 ERR("unknown register type\n");
da6eed25
MD
448 ret = -EINVAL;
449 goto end;
450
451 case REG_S64:
452 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].v);
453 break;
454 case REG_DOUBLE:
455 reg[REG_R0].v = (reg[REG_R0].d < reg[REG_R1].d);
456 break;
457 }
cd54f6d9
MD
458 break;
459 }
460 reg[REG_R0].type = REG_S64;
461 next_pc += sizeof(struct binary_op);
462 break;
463 }
464 case FILTER_OP_GE:
465 {
cd54f6d9
MD
466 switch (reg[REG_R0].type) {
467 default:
b1caea50 468 ERR("unknown register type\n");
cd54f6d9
MD
469 ret = -EINVAL;
470 goto end;
471
472 case REG_STRING:
cd54f6d9
MD
473 reg[REG_R0].v = (reg_strcmp(reg, ">=") >= 0);
474 break;
475 case REG_S64:
da6eed25
MD
476 switch (reg[REG_R1].type) {
477 default:
b1caea50 478 ERR("unknown register type\n");
da6eed25
MD
479 ret = -EINVAL;
480 goto end;
481
482 case REG_S64:
483 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].v);
484 break;
485 case REG_DOUBLE:
486 reg[REG_R0].v = (reg[REG_R0].v >= reg[REG_R1].d);
487 break;
488 }
489 break;
490 case REG_DOUBLE:
491 switch (reg[REG_R1].type) {
492 default:
b1caea50 493 ERR("unknown register type\n");
da6eed25
MD
494 ret = -EINVAL;
495 goto end;
496
497 case REG_S64:
498 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].v);
499 break;
500 case REG_DOUBLE:
501 reg[REG_R0].v = (reg[REG_R0].d >= reg[REG_R1].d);
502 break;
503 }
cd54f6d9
MD
504 break;
505 }
506 reg[REG_R0].type = REG_S64;
507 next_pc += sizeof(struct binary_op);
508 break;
509 }
510 case FILTER_OP_LE:
511 {
cd54f6d9
MD
512 switch (reg[REG_R0].type) {
513 default:
b1caea50 514 ERR("unknown register type\n");
cd54f6d9
MD
515 ret = -EINVAL;
516 goto end;
517
518 case REG_STRING:
cd54f6d9
MD
519 reg[REG_R0].v = (reg_strcmp(reg, "<=") <= 0);
520 break;
521 case REG_S64:
da6eed25
MD
522 switch (reg[REG_R1].type) {
523 default:
b1caea50 524 ERR("unknown register type\n");
da6eed25
MD
525 ret = -EINVAL;
526 goto end;
527
528 case REG_S64:
529 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].v);
530 break;
531 case REG_DOUBLE:
532 reg[REG_R0].v = (reg[REG_R0].v <= reg[REG_R1].d);
533 break;
534 }
535 break;
536 case REG_DOUBLE:
537 switch (reg[REG_R1].type) {
538 default:
b1caea50 539 ERR("unknown register type\n");
da6eed25
MD
540 ret = -EINVAL;
541 goto end;
542
543 case REG_S64:
544 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].v);
545 break;
546 case REG_DOUBLE:
547 reg[REG_R0].v = (reg[REG_R0].d <= reg[REG_R1].d);
548 break;
549 }
cd54f6d9
MD
550 break;
551 }
552 reg[REG_R0].type = REG_S64;
553 next_pc += sizeof(struct binary_op);
554 break;
555 }
556
557 /* unary */
558 case FILTER_OP_UNARY_PLUS:
559 {
cd54f6d9
MD
560 next_pc += sizeof(struct unary_op);
561 break;
562 }
563 case FILTER_OP_UNARY_MINUS:
564 {
565 struct unary_op *insn = (struct unary_op *) pc;
566
da6eed25
MD
567 switch (reg[insn->reg].type) {
568 default:
b1caea50 569 ERR("unknown register type\n");
cd54f6d9
MD
570 ret = -EINVAL;
571 goto end;
da6eed25
MD
572
573 case REG_STRING:
b1caea50 574 ERR("Unary minus can only be applied to numeric or floating point registers\n");
da6eed25
MD
575 ret = -EINVAL;
576 goto end;
577 case REG_S64:
578 reg[insn->reg].v = -reg[insn->reg].v;
579 break;
580 case REG_DOUBLE:
581 reg[insn->reg].d = -reg[insn->reg].d;
582 break;
cd54f6d9 583 }
cd54f6d9
MD
584 next_pc += sizeof(struct unary_op);
585 break;
586 }
587 case FILTER_OP_UNARY_NOT:
588 {
589 struct unary_op *insn = (struct unary_op *) pc;
590
da6eed25
MD
591 switch (reg[insn->reg].type) {
592 default:
b1caea50 593 ERR("unknown register type\n");
da6eed25
MD
594 ret = -EINVAL;
595 goto end;
596
597 case REG_STRING:
b1caea50 598 ERR("Unary not can only be applied to numeric or floating point registers\n");
da6eed25
MD
599 ret = -EINVAL;
600 goto end;
601 case REG_S64:
602 reg[insn->reg].v = !reg[insn->reg].v;
603 break;
604 case REG_DOUBLE:
605 reg[insn->reg].d = !reg[insn->reg].d;
606 break;
607 }
cd54f6d9
MD
608 reg[insn->reg].v = !reg[insn->reg].v;
609 next_pc += sizeof(struct unary_op);
610 break;
611 }
612 /* logical */
613 case FILTER_OP_AND:
614 {
615 struct logical_op *insn = (struct logical_op *) pc;
616
cd54f6d9 617 /* If REG_R0 is 0, skip and evaluate to 0 */
da6eed25
MD
618 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v == 0)
619 || (reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d == 0.0)) {
cd54f6d9
MD
620 dbg_printf("Jumping to bytecode offset %u\n",
621 (unsigned int) insn->skip_offset);
622 next_pc = start_pc + insn->skip_offset;
cd54f6d9
MD
623 } else {
624 next_pc += sizeof(struct logical_op);
625 }
626 break;
627 }
628 case FILTER_OP_OR:
629 {
630 struct logical_op *insn = (struct logical_op *) pc;
631
cd54f6d9 632 /* If REG_R0 is nonzero, skip and evaluate to 1 */
da6eed25
MD
633
634 if ((reg[REG_R0].type == REG_S64 && reg[REG_R0].v != 0)
635 || (reg[REG_R0].type == REG_DOUBLE && reg[REG_R0].d != 0.0)) {
cd54f6d9
MD
636 reg[REG_R0].v = 1;
637 dbg_printf("Jumping to bytecode offset %u\n",
638 (unsigned int) insn->skip_offset);
639 next_pc = start_pc + insn->skip_offset;
cd54f6d9
MD
640 } else {
641 next_pc += sizeof(struct logical_op);
642 }
643 break;
644 }
645
646 /* load */
2f0145d1 647 case FILTER_OP_LOAD_FIELD_REF_STRING:
cd54f6d9
MD
648 {
649 struct load_op *insn = (struct load_op *) pc;
650 struct field_ref *ref = (struct field_ref *) insn->data;
651
2f0145d1
MD
652 dbg_printf("load field ref offset %u type string\n",
653 ref->offset);
654 reg[insn->reg].str =
655 *(const char * const *) &filter_stack_data[ref->offset];
656 reg[insn->reg].type = REG_STRING;
657 reg[insn->reg].seq_len = UINT_MAX;
658 reg[insn->reg].literal = 0;
659 dbg_printf("ref load string %s\n", reg[insn->reg].str);
660 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
661 break;
662 }
cd54f6d9 663
2f0145d1
MD
664 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
665 {
666 struct load_op *insn = (struct load_op *) pc;
667 struct field_ref *ref = (struct field_ref *) insn->data;
cd54f6d9 668
2f0145d1
MD
669 dbg_printf("load field ref offset %u type sequence\n",
670 ref->offset);
671 reg[insn->reg].seq_len =
672 *(unsigned long *) &filter_stack_data[ref->offset];
673 reg[insn->reg].str =
674 *(const char **) (&filter_stack_data[ref->offset
675 + sizeof(unsigned long)]);
676 reg[insn->reg].type = REG_STRING;
677 reg[insn->reg].literal = 0;
678 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
679 break;
680 }
681
682 case FILTER_OP_LOAD_FIELD_REF_S64:
683 {
684 struct load_op *insn = (struct load_op *) pc;
685 struct field_ref *ref = (struct field_ref *) insn->data;
686
687 dbg_printf("load field ref offset %u type s64\n",
688 ref->offset);
689 memcpy(&reg[insn->reg].v, &filter_stack_data[ref->offset],
690 sizeof(struct literal_numeric));
691 reg[insn->reg].type = REG_S64;
692 reg[insn->reg].literal = 0;
693 dbg_printf("ref load s64 %" PRIi64 "\n", reg[insn->reg].v);
694 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
695 break;
696 }
697
698 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
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 double\n",
704 ref->offset);
705 memcpy(&reg[insn->reg].d, &filter_stack_data[ref->offset],
706 sizeof(struct literal_double));
707 reg[insn->reg].type = REG_DOUBLE;
708 reg[insn->reg].literal = 0;
709 dbg_printf("ref load double %g\n", reg[insn->reg].d);
cd54f6d9
MD
710 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
711 break;
712 }
713
714 case FILTER_OP_LOAD_STRING:
715 {
716 struct load_op *insn = (struct load_op *) pc;
717
cd54f6d9
MD
718 dbg_printf("load string %s\n", insn->data);
719 reg[insn->reg].str = insn->data;
720 reg[insn->reg].type = REG_STRING;
721 reg[insn->reg].seq_len = UINT_MAX;
722 reg[insn->reg].literal = 1;
723 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
724 break;
725 }
726
727 case FILTER_OP_LOAD_S64:
728 {
729 struct load_op *insn = (struct load_op *) pc;
730
cd54f6d9
MD
731 memcpy(&reg[insn->reg].v, insn->data,
732 sizeof(struct literal_numeric));
733 dbg_printf("load s64 %" PRIi64 "\n", reg[insn->reg].v);
734 reg[insn->reg].type = REG_S64;
735 next_pc += sizeof(struct load_op)
736 + sizeof(struct literal_numeric);
737 break;
738 }
da6eed25
MD
739
740 case FILTER_OP_LOAD_DOUBLE:
741 {
742 struct load_op *insn = (struct load_op *) pc;
743
da6eed25
MD
744 memcpy(&reg[insn->reg].d, insn->data,
745 sizeof(struct literal_double));
746 dbg_printf("load s64 %g\n", reg[insn->reg].d);
747 reg[insn->reg].type = REG_DOUBLE;
748 next_pc += sizeof(struct load_op)
749 + sizeof(struct literal_double);
750 break;
751 }
cd54f6d9
MD
752 }
753 }
754end:
755 /* return 0 (discard) on error */
756 if (ret)
757 return 0;
758 return retval;
759}
760
9522a886
MD
761static
762int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
763{
764 switch (reg[REG_R0].type) {
765 default:
766 goto error_unknown;
767
768 case REG_STRING:
769 switch (reg[REG_R1].type) {
770 default:
771 goto error_unknown;
772
773 case REG_STRING:
774 break;
775 case REG_S64:
776 case REG_DOUBLE:
777 goto error_mismatch;
778 }
779 break;
780 case REG_S64:
781 case REG_DOUBLE:
782 switch (reg[REG_R1].type) {
783 default:
784 goto error_unknown;
785
786 case REG_STRING:
787 goto error_mismatch;
788
789 case REG_S64:
790 case REG_DOUBLE:
791 break;
792 }
793 break;
794 }
795 return 0;
796
797error_unknown:
798
799 return -EINVAL;
800error_mismatch:
801 ERR("type mismatch for '%s' binary operator\n", str);
802 return -EINVAL;
803}
804
805static
806int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
807{
808 void *pc, *next_pc, *start_pc;
809 int ret = -EINVAL;
810 struct vreg reg[NR_REG];
811 int i;
812
813 for (i = 0; i < NR_REG; i++) {
225b6640 814 reg[i].type = REG_TYPE_UNKNOWN;
9522a886
MD
815 reg[i].literal = 0;
816 }
817
818 start_pc = &bytecode->data[0];
819 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
820 pc = next_pc) {
821 if (unlikely(pc >= start_pc + bytecode->len)) {
822 ERR("filter bytecode overflow\n");
823 ret = -EINVAL;
824 goto end;
825 }
826 dbg_printf("Validating op %s (%u)\n",
827 print_op((unsigned int) *(filter_opcode_t *) pc),
828 (unsigned int) *(filter_opcode_t *) pc);
829 switch (*(filter_opcode_t *) pc) {
830 case FILTER_OP_UNKNOWN:
831 default:
832 ERR("unknown bytecode op %u\n",
833 (unsigned int) *(filter_opcode_t *) pc);
834 ret = -EINVAL;
835 goto end;
836
837 case FILTER_OP_RETURN:
838 ret = 0;
839 goto end;
840
841 /* binary */
842 case FILTER_OP_MUL:
843 case FILTER_OP_DIV:
844 case FILTER_OP_MOD:
845 case FILTER_OP_PLUS:
846 case FILTER_OP_MINUS:
847 case FILTER_OP_RSHIFT:
848 case FILTER_OP_LSHIFT:
849 case FILTER_OP_BIN_AND:
850 case FILTER_OP_BIN_OR:
851 case FILTER_OP_BIN_XOR:
852 ERR("unsupported bytecode op %u\n",
853 (unsigned int) *(filter_opcode_t *) pc);
854 ret = -EINVAL;
855 goto end;
856
857 case FILTER_OP_EQ:
858 {
859 ret = bin_op_compare_check(reg, "==");
860 if (ret)
861 goto end;
862 reg[REG_R0].type = REG_S64;
863 next_pc += sizeof(struct binary_op);
864 break;
865 }
866 case FILTER_OP_NE:
867 {
868 ret = bin_op_compare_check(reg, "!=");
869 if (ret)
870 goto end;
871 reg[REG_R0].type = REG_S64;
872 next_pc += sizeof(struct binary_op);
873 break;
874 }
875 case FILTER_OP_GT:
876 {
877 ret = bin_op_compare_check(reg, ">");
878 if (ret)
879 goto end;
880 reg[REG_R0].type = REG_S64;
881 next_pc += sizeof(struct binary_op);
882 break;
883 }
884 case FILTER_OP_LT:
885 {
886 ret = bin_op_compare_check(reg, "<");
887 if (ret)
888 goto end;
889 reg[REG_R0].type = REG_S64;
890 next_pc += sizeof(struct binary_op);
891 break;
892 }
893 case FILTER_OP_GE:
894 {
895 ret = bin_op_compare_check(reg, ">=");
896 if (ret)
897 goto end;
898 reg[REG_R0].type = REG_S64;
899 next_pc += sizeof(struct binary_op);
900 break;
901 }
902 case FILTER_OP_LE:
903 {
904 ret = bin_op_compare_check(reg, "<=");
905 if (ret)
906 goto end;
907 reg[REG_R0].type = REG_S64;
908 next_pc += sizeof(struct binary_op);
909 break;
910 }
911
912 /* unary */
913 case FILTER_OP_UNARY_PLUS:
914 case FILTER_OP_UNARY_MINUS:
915 case FILTER_OP_UNARY_NOT:
916 {
917 struct unary_op *insn = (struct unary_op *) pc;
918
919 if (unlikely(insn->reg >= REG_ERROR)) {
920 ERR("invalid register %u\n",
921 (unsigned int) insn->reg);
922 ret = -EINVAL;
923 goto end;
924 }
925 switch (reg[insn->reg].type) {
926 default:
927 ERR("unknown register type\n");
928 ret = -EINVAL;
929 goto end;
930
931 case REG_STRING:
932 ERR("Unary op can only be applied to numeric or floating point registers\n");
933 ret = -EINVAL;
934 goto end;
935 case REG_S64:
936 break;
937 case REG_DOUBLE:
938 break;
939 }
940 next_pc += sizeof(struct unary_op);
941 break;
942 }
943 /* logical */
944 case FILTER_OP_AND:
945 case FILTER_OP_OR:
946 {
947 struct logical_op *insn = (struct logical_op *) pc;
948
225b6640
MD
949 if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
950 || reg[REG_R0].type == REG_TYPE_UNKNOWN
951 || reg[REG_R0].type == REG_STRING
952 || reg[REG_R1].type == REG_STRING)) {
953 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
9522a886
MD
954 ret = -EINVAL;
955 goto end;
956 }
957
958 dbg_printf("Validate jumping to bytecode offset %u\n",
959 (unsigned int) insn->skip_offset);
960 if (unlikely(start_pc + insn->skip_offset <= pc)) {
961 ERR("Loops are not allowed in bytecode\n");
962 ret = -EINVAL;
963 goto end;
964 }
965 next_pc += sizeof(struct logical_op);
966 break;
967 }
968
969 /* load */
970 case FILTER_OP_LOAD_FIELD_REF:
2f0145d1
MD
971 {
972 ERR("Unknown field ref type\n");
973 ret = -EINVAL;
974 goto end;
975 }
976 case FILTER_OP_LOAD_FIELD_REF_STRING:
977 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
9522a886
MD
978 {
979 struct load_op *insn = (struct load_op *) pc;
980 struct field_ref *ref = (struct field_ref *) insn->data;
981
982 if (unlikely(insn->reg >= REG_ERROR)) {
983 ERR("invalid register %u\n",
984 (unsigned int) insn->reg);
985 ret = -EINVAL;
986 goto end;
987 }
2f0145d1
MD
988 dbg_printf("Validate load field ref offset %u type string\n",
989 ref->offset);
990 reg[insn->reg].type = REG_STRING;
991 reg[insn->reg].literal = 0;
992 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
993 break;
994 }
995 case FILTER_OP_LOAD_FIELD_REF_S64:
996 {
997 struct load_op *insn = (struct load_op *) pc;
998 struct field_ref *ref = (struct field_ref *) insn->data;
999
1000 if (unlikely(insn->reg >= REG_ERROR)) {
1001 ERR("invalid register %u\n",
1002 (unsigned int) insn->reg);
9522a886
MD
1003 ret = -EINVAL;
1004 goto end;
9522a886 1005 }
2f0145d1
MD
1006 dbg_printf("Validate load field ref offset %u type s64\n",
1007 ref->offset);
1008 reg[insn->reg].type = REG_S64;
1009 reg[insn->reg].literal = 0;
1010 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1011 break;
1012 }
1013 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1014 {
1015 struct load_op *insn = (struct load_op *) pc;
1016 struct field_ref *ref = (struct field_ref *) insn->data;
9522a886 1017
2f0145d1
MD
1018 if (unlikely(insn->reg >= REG_ERROR)) {
1019 ERR("invalid register %u\n",
1020 (unsigned int) insn->reg);
1021 ret = -EINVAL;
1022 goto end;
1023 }
1024 dbg_printf("Validate load field ref offset %u type double\n",
1025 ref->offset);
1026 reg[insn->reg].type = REG_DOUBLE;
1027 reg[insn->reg].literal = 0;
9522a886
MD
1028 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1029 break;
1030 }
1031
1032 case FILTER_OP_LOAD_STRING:
1033 {
1034 struct load_op *insn = (struct load_op *) pc;
1035
1036 if (unlikely(insn->reg >= REG_ERROR)) {
1037 ERR("invalid register %u\n",
1038 (unsigned int) insn->reg);
1039 ret = -EINVAL;
1040 goto end;
1041 }
1042 reg[insn->reg].type = REG_STRING;
1043 reg[insn->reg].literal = 1;
1044 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1045 break;
1046 }
1047
1048 case FILTER_OP_LOAD_S64:
1049 {
1050 struct load_op *insn = (struct load_op *) pc;
1051
1052 if (unlikely(insn->reg >= REG_ERROR)) {
1053 ERR("invalid register %u\n",
1054 (unsigned int) insn->reg);
1055 ret = -EINVAL;
1056 goto end;
1057 }
1058 reg[insn->reg].type = REG_S64;
1059 next_pc += sizeof(struct load_op)
1060 + sizeof(struct literal_numeric);
1061 break;
1062 }
1063
1064 case FILTER_OP_LOAD_DOUBLE:
1065 {
1066 struct load_op *insn = (struct load_op *) pc;
1067
1068 if (unlikely(insn->reg >= REG_ERROR)) {
1069 ERR("invalid register %u\n",
1070 (unsigned int) insn->reg);
1071 ret = -EINVAL;
1072 goto end;
1073 }
1074 reg[insn->reg].type = REG_DOUBLE;
1075 next_pc += sizeof(struct load_op)
1076 + sizeof(struct literal_double);
1077 break;
1078 }
1079 }
1080 }
1081end:
1082 return ret;
1083}
1084
cd54f6d9
MD
1085static
1086int apply_field_reloc(struct ltt_event *event,
1087 struct bytecode_runtime *runtime,
1088 uint32_t runtime_len,
1089 uint32_t reloc_offset,
1090 const char *field_name)
1091{
1092 const struct lttng_event_desc *desc;
1093 const struct lttng_event_field *fields, *field = NULL;
1094 unsigned int nr_fields, i;
1095 struct field_ref *field_ref;
2f0145d1 1096 struct load_op *op;
cd54f6d9
MD
1097 uint32_t field_offset = 0;
1098
a8c27c7c 1099 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
cd54f6d9
MD
1100
1101 /* Ensure that the reloc is within the code */
1102 if (runtime_len - reloc_offset < sizeof(uint16_t))
1103 return -EINVAL;
1104
1105 /* Lookup event by name */
1106 desc = event->desc;
1107 if (!desc)
1108 return -EINVAL;
1109 fields = desc->fields;
1110 if (!fields)
1111 return -EINVAL;
1112 nr_fields = desc->nr_fields;
1113 for (i = 0; i < nr_fields; i++) {
1114 if (!strcmp(fields[i].name, field_name)) {
1115 field = &fields[i];
1116 break;
1117 }
1118 /* compute field offset */
1119 switch (fields[i].type.atype) {
1120 case atype_integer:
1121 case atype_enum:
1122 field_offset += sizeof(int64_t);
1123 break;
1124 case atype_array:
1125 case atype_sequence:
1126 field_offset += sizeof(unsigned long);
1127 field_offset += sizeof(void *);
1128 break;
1129 case atype_string:
1130 field_offset += sizeof(void *);
1131 break;
1132 case atype_float:
1133 field_offset += sizeof(double);
da6eed25 1134 break;
cd54f6d9
MD
1135 default:
1136 return -EINVAL;
1137 }
1138 }
1139 if (!field)
1140 return -EINVAL;
1141
1142 /* Check if field offset is too large for 16-bit offset */
1143 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1144 return -EINVAL;
1145
1146 /* set type */
2f0145d1
MD
1147 op = (struct load_op *) &runtime->data[reloc_offset];
1148 field_ref = (struct field_ref *) op->data;
cd54f6d9
MD
1149 switch (field->type.atype) {
1150 case atype_integer:
1151 case atype_enum:
2f0145d1 1152 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
cd54f6d9
MD
1153 break;
1154 case atype_array:
1155 case atype_sequence:
2f0145d1 1156 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
cd54f6d9
MD
1157 break;
1158 case atype_string:
2f0145d1 1159 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
cd54f6d9
MD
1160 break;
1161 case atype_float:
2f0145d1 1162 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
da6eed25 1163 break;
cd54f6d9
MD
1164 default:
1165 return -EINVAL;
1166 }
1167 /* set offset */
1168 field_ref->offset = (uint16_t) field_offset;
2d78951a
MD
1169 return 0;
1170}
1171
cd54f6d9
MD
1172/*
1173 * Take a bytecode with reloc table and link it to an event to create a
1174 * bytecode runtime.
1175 */
2d78951a
MD
1176static
1177int _lttng_filter_event_link_bytecode(struct ltt_event *event,
1178 struct lttng_ust_filter_bytecode *filter_bytecode)
1179{
cd54f6d9
MD
1180 int ret, offset, next_offset;
1181 struct bytecode_runtime *runtime = NULL;
1182 size_t runtime_alloc_len;
1183
2d78951a
MD
1184 if (!filter_bytecode)
1185 return 0;
cd54f6d9
MD
1186 /* Even is not connected to any description */
1187 if (!event->desc)
1188 return 0;
1189 /* Bytecode already linked */
1190 if (event->filter || event->filter_data)
1191 return 0;
2d78951a 1192
a8c27c7c 1193 dbg_printf("Linking\n");
cd54f6d9
MD
1194
1195 /* We don't need the reloc table in the runtime */
1196 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
1197 runtime = zmalloc(runtime_alloc_len);
1198 if (!runtime) {
1199 ret = -ENOMEM;
1200 goto link_error;
1201 }
1202 runtime->len = filter_bytecode->reloc_offset;
1203 /* copy original bytecode */
1204 memcpy(runtime->data, filter_bytecode->data, runtime->len);
1205 /*
1206 * apply relocs. Those are a uint16_t (offset in bytecode)
1207 * followed by a string (field name).
1208 */
cd54f6d9
MD
1209 for (offset = filter_bytecode->reloc_offset;
1210 offset < filter_bytecode->len;
1211 offset = next_offset) {
1212 uint16_t reloc_offset =
1213 *(uint16_t *) &filter_bytecode->data[offset];
1214 const char *field_name =
1215 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
1216
1217 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
1218 if (ret) {
1219 goto link_error;
1220 }
1221 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
1222 }
9522a886
MD
1223 /* Validate bytecode */
1224 ret = lttng_filter_validate_bytecode(runtime);
1225 if (ret) {
1226 goto link_error;
1227 }
cd54f6d9 1228 event->filter_data = runtime;
2d78951a 1229 event->filter = lttng_filter_interpret_bytecode;
2d78951a 1230 return 0;
cd54f6d9
MD
1231
1232link_error:
1233 event->filter = lttng_filter_false;
1234 free(runtime);
1235 return ret;
2d78951a
MD
1236}
1237
1238void lttng_filter_event_link_bytecode(struct ltt_event *event,
1239 struct lttng_ust_filter_bytecode *filter_bytecode)
1240{
1241 int ret;
1242
cd54f6d9 1243 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
2d78951a
MD
1244 if (ret) {
1245 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
1246 }
1247}
1248
1249/*
1250 * Link bytecode to all events for a wildcard. Skips events that already
1251 * have a bytecode linked.
1252 * We do not set each event's filter_bytecode field, because they do not
1253 * own the filter_bytecode: the wildcard owns it.
1254 */
1255void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
1256{
1257 struct ltt_event *event;
1258 int ret;
1259
1260 if (!wildcard->filter_bytecode)
1261 return;
1262
1263 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
1264 if (event->filter)
1265 continue;
1266 ret = _lttng_filter_event_link_bytecode(event,
1267 wildcard->filter_bytecode);
1268 if (ret) {
1269 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
1270 }
1271
1272 }
1273 return;
1274}
1275
1276/*
1277 * Need to attach filter to an event before starting tracing for the
cd54f6d9 1278 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1279 */
1280int lttng_filter_event_attach_bytecode(struct ltt_event *event,
1281 struct lttng_ust_filter_bytecode *filter_bytecode)
1282{
2d78951a
MD
1283 if (event->chan->session->been_active)
1284 return -EPERM;
1285 if (event->filter_bytecode)
1286 return -EEXIST;
cd54f6d9 1287 event->filter_bytecode = filter_bytecode;
2d78951a
MD
1288 return 0;
1289}
1290
1291/*
1292 * Need to attach filter to a wildcard before starting tracing for the
cd54f6d9 1293 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1294 */
1295int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
1296 struct lttng_ust_filter_bytecode *filter_bytecode)
1297{
2d78951a
MD
1298 if (wildcard->chan->session->been_active)
1299 return -EPERM;
1300 if (wildcard->filter_bytecode)
1301 return -EEXIST;
cd54f6d9 1302 wildcard->filter_bytecode = filter_bytecode;
2d78951a
MD
1303 return 0;
1304}
This page took 0.076916 seconds and 4 git commands to generate.