Specialize load and unary ops
[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;
08c84b15 735 reg[insn->reg].literal = 1;
cd54f6d9
MD
736 next_pc += sizeof(struct load_op)
737 + sizeof(struct literal_numeric);
738 break;
739 }
da6eed25
MD
740
741 case FILTER_OP_LOAD_DOUBLE:
742 {
743 struct load_op *insn = (struct load_op *) pc;
744
da6eed25
MD
745 memcpy(&reg[insn->reg].d, insn->data,
746 sizeof(struct literal_double));
747 dbg_printf("load s64 %g\n", reg[insn->reg].d);
748 reg[insn->reg].type = REG_DOUBLE;
08c84b15 749 reg[insn->reg].literal = 1;
da6eed25
MD
750 next_pc += sizeof(struct load_op)
751 + sizeof(struct literal_double);
752 break;
753 }
cd54f6d9
MD
754 }
755 }
756end:
757 /* return 0 (discard) on error */
758 if (ret)
759 return 0;
760 return retval;
761}
762
9522a886
MD
763static
764int bin_op_compare_check(struct vreg reg[NR_REG], const char *str)
765{
766 switch (reg[REG_R0].type) {
767 default:
768 goto error_unknown;
769
770 case REG_STRING:
771 switch (reg[REG_R1].type) {
772 default:
773 goto error_unknown;
774
775 case REG_STRING:
776 break;
777 case REG_S64:
778 case REG_DOUBLE:
779 goto error_mismatch;
780 }
781 break;
782 case REG_S64:
783 case REG_DOUBLE:
784 switch (reg[REG_R1].type) {
785 default:
786 goto error_unknown;
787
788 case REG_STRING:
789 goto error_mismatch;
790
791 case REG_S64:
792 case REG_DOUBLE:
793 break;
794 }
795 break;
796 }
797 return 0;
798
799error_unknown:
800
801 return -EINVAL;
802error_mismatch:
803 ERR("type mismatch for '%s' binary operator\n", str);
804 return -EINVAL;
805}
806
807static
808int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
809{
810 void *pc, *next_pc, *start_pc;
811 int ret = -EINVAL;
812 struct vreg reg[NR_REG];
813 int i;
814
815 for (i = 0; i < NR_REG; i++) {
225b6640 816 reg[i].type = REG_TYPE_UNKNOWN;
9522a886
MD
817 reg[i].literal = 0;
818 }
819
820 start_pc = &bytecode->data[0];
821 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
822 pc = next_pc) {
823 if (unlikely(pc >= start_pc + bytecode->len)) {
824 ERR("filter bytecode overflow\n");
825 ret = -EINVAL;
826 goto end;
827 }
828 dbg_printf("Validating op %s (%u)\n",
829 print_op((unsigned int) *(filter_opcode_t *) pc),
830 (unsigned int) *(filter_opcode_t *) pc);
831 switch (*(filter_opcode_t *) pc) {
832 case FILTER_OP_UNKNOWN:
833 default:
834 ERR("unknown bytecode op %u\n",
835 (unsigned int) *(filter_opcode_t *) pc);
836 ret = -EINVAL;
837 goto end;
838
839 case FILTER_OP_RETURN:
840 ret = 0;
841 goto end;
842
843 /* binary */
844 case FILTER_OP_MUL:
845 case FILTER_OP_DIV:
846 case FILTER_OP_MOD:
847 case FILTER_OP_PLUS:
848 case FILTER_OP_MINUS:
849 case FILTER_OP_RSHIFT:
850 case FILTER_OP_LSHIFT:
851 case FILTER_OP_BIN_AND:
852 case FILTER_OP_BIN_OR:
853 case FILTER_OP_BIN_XOR:
854 ERR("unsupported bytecode op %u\n",
855 (unsigned int) *(filter_opcode_t *) pc);
856 ret = -EINVAL;
857 goto end;
858
859 case FILTER_OP_EQ:
860 {
861 ret = bin_op_compare_check(reg, "==");
862 if (ret)
863 goto end;
864 reg[REG_R0].type = REG_S64;
865 next_pc += sizeof(struct binary_op);
866 break;
867 }
868 case FILTER_OP_NE:
869 {
870 ret = bin_op_compare_check(reg, "!=");
871 if (ret)
872 goto end;
873 reg[REG_R0].type = REG_S64;
874 next_pc += sizeof(struct binary_op);
875 break;
876 }
877 case FILTER_OP_GT:
878 {
879 ret = bin_op_compare_check(reg, ">");
880 if (ret)
881 goto end;
882 reg[REG_R0].type = REG_S64;
883 next_pc += sizeof(struct binary_op);
884 break;
885 }
886 case FILTER_OP_LT:
887 {
888 ret = bin_op_compare_check(reg, "<");
889 if (ret)
890 goto end;
891 reg[REG_R0].type = REG_S64;
892 next_pc += sizeof(struct binary_op);
893 break;
894 }
895 case FILTER_OP_GE:
896 {
897 ret = bin_op_compare_check(reg, ">=");
898 if (ret)
899 goto end;
900 reg[REG_R0].type = REG_S64;
901 next_pc += sizeof(struct binary_op);
902 break;
903 }
904 case FILTER_OP_LE:
905 {
906 ret = bin_op_compare_check(reg, "<=");
907 if (ret)
908 goto end;
909 reg[REG_R0].type = REG_S64;
910 next_pc += sizeof(struct binary_op);
911 break;
912 }
913
914 /* unary */
915 case FILTER_OP_UNARY_PLUS:
916 case FILTER_OP_UNARY_MINUS:
917 case FILTER_OP_UNARY_NOT:
918 {
919 struct unary_op *insn = (struct unary_op *) pc;
920
921 if (unlikely(insn->reg >= REG_ERROR)) {
922 ERR("invalid register %u\n",
923 (unsigned int) insn->reg);
924 ret = -EINVAL;
925 goto end;
926 }
927 switch (reg[insn->reg].type) {
928 default:
929 ERR("unknown register type\n");
930 ret = -EINVAL;
931 goto end;
932
933 case REG_STRING:
934 ERR("Unary op can only be applied to numeric or floating point registers\n");
935 ret = -EINVAL;
936 goto end;
937 case REG_S64:
938 break;
939 case REG_DOUBLE:
940 break;
941 }
942 next_pc += sizeof(struct unary_op);
943 break;
944 }
08c84b15
MD
945
946 case FILTER_OP_UNARY_PLUS_S64:
947 case FILTER_OP_UNARY_MINUS_S64:
948 case FILTER_OP_UNARY_NOT_S64:
949 {
950 struct unary_op *insn = (struct unary_op *) pc;
951
952 if (unlikely(insn->reg >= REG_ERROR)) {
953 ERR("invalid register %u\n",
954 (unsigned int) insn->reg);
955 ret = -EINVAL;
956 goto end;
957 }
958 if (reg[insn->reg].type != REG_S64) {
959 ERR("Invalid register type\n");
960 ret = -EINVAL;
961 goto end;
962 }
963 next_pc += sizeof(struct unary_op);
964 break;
965 }
966
967 case FILTER_OP_UNARY_PLUS_DOUBLE:
968 case FILTER_OP_UNARY_MINUS_DOUBLE:
969 case FILTER_OP_UNARY_NOT_DOUBLE:
970 {
971 struct unary_op *insn = (struct unary_op *) pc;
972
973 if (unlikely(insn->reg >= REG_ERROR)) {
974 ERR("invalid register %u\n",
975 (unsigned int) insn->reg);
976 ret = -EINVAL;
977 goto end;
978 }
979 if (reg[insn->reg].type != REG_DOUBLE) {
980 ERR("Invalid register type\n");
981 ret = -EINVAL;
982 goto end;
983 }
984 next_pc += sizeof(struct unary_op);
985 break;
986 }
987
9522a886
MD
988 /* logical */
989 case FILTER_OP_AND:
990 case FILTER_OP_OR:
991 {
992 struct logical_op *insn = (struct logical_op *) pc;
993
225b6640
MD
994 if (unlikely(reg[REG_R0].type == REG_TYPE_UNKNOWN
995 || reg[REG_R0].type == REG_TYPE_UNKNOWN
996 || reg[REG_R0].type == REG_STRING
997 || reg[REG_R1].type == REG_STRING)) {
998 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
9522a886
MD
999 ret = -EINVAL;
1000 goto end;
1001 }
1002
1003 dbg_printf("Validate jumping to bytecode offset %u\n",
1004 (unsigned int) insn->skip_offset);
1005 if (unlikely(start_pc + insn->skip_offset <= pc)) {
1006 ERR("Loops are not allowed in bytecode\n");
1007 ret = -EINVAL;
1008 goto end;
1009 }
1010 next_pc += sizeof(struct logical_op);
1011 break;
1012 }
1013
1014 /* load */
1015 case FILTER_OP_LOAD_FIELD_REF:
2f0145d1
MD
1016 {
1017 ERR("Unknown field ref type\n");
1018 ret = -EINVAL;
1019 goto end;
1020 }
1021 case FILTER_OP_LOAD_FIELD_REF_STRING:
1022 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
9522a886
MD
1023 {
1024 struct load_op *insn = (struct load_op *) pc;
1025 struct field_ref *ref = (struct field_ref *) insn->data;
1026
1027 if (unlikely(insn->reg >= REG_ERROR)) {
1028 ERR("invalid register %u\n",
1029 (unsigned int) insn->reg);
1030 ret = -EINVAL;
1031 goto end;
1032 }
2f0145d1
MD
1033 dbg_printf("Validate load field ref offset %u type string\n",
1034 ref->offset);
1035 reg[insn->reg].type = REG_STRING;
1036 reg[insn->reg].literal = 0;
1037 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1038 break;
1039 }
1040 case FILTER_OP_LOAD_FIELD_REF_S64:
1041 {
1042 struct load_op *insn = (struct load_op *) pc;
1043 struct field_ref *ref = (struct field_ref *) insn->data;
1044
1045 if (unlikely(insn->reg >= REG_ERROR)) {
1046 ERR("invalid register %u\n",
1047 (unsigned int) insn->reg);
9522a886
MD
1048 ret = -EINVAL;
1049 goto end;
9522a886 1050 }
2f0145d1
MD
1051 dbg_printf("Validate load field ref offset %u type s64\n",
1052 ref->offset);
1053 reg[insn->reg].type = REG_S64;
1054 reg[insn->reg].literal = 0;
1055 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1056 break;
1057 }
1058 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1059 {
1060 struct load_op *insn = (struct load_op *) pc;
1061 struct field_ref *ref = (struct field_ref *) insn->data;
9522a886 1062
2f0145d1
MD
1063 if (unlikely(insn->reg >= REG_ERROR)) {
1064 ERR("invalid register %u\n",
1065 (unsigned int) insn->reg);
1066 ret = -EINVAL;
1067 goto end;
1068 }
1069 dbg_printf("Validate load field ref offset %u type double\n",
1070 ref->offset);
1071 reg[insn->reg].type = REG_DOUBLE;
1072 reg[insn->reg].literal = 0;
9522a886
MD
1073 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1074 break;
1075 }
1076
1077 case FILTER_OP_LOAD_STRING:
1078 {
1079 struct load_op *insn = (struct load_op *) pc;
1080
1081 if (unlikely(insn->reg >= REG_ERROR)) {
1082 ERR("invalid register %u\n",
1083 (unsigned int) insn->reg);
1084 ret = -EINVAL;
1085 goto end;
1086 }
1087 reg[insn->reg].type = REG_STRING;
1088 reg[insn->reg].literal = 1;
1089 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1090 break;
1091 }
1092
1093 case FILTER_OP_LOAD_S64:
1094 {
1095 struct load_op *insn = (struct load_op *) pc;
1096
1097 if (unlikely(insn->reg >= REG_ERROR)) {
1098 ERR("invalid register %u\n",
1099 (unsigned int) insn->reg);
1100 ret = -EINVAL;
1101 goto end;
1102 }
1103 reg[insn->reg].type = REG_S64;
08c84b15 1104 reg[insn->reg].literal = 1;
9522a886
MD
1105 next_pc += sizeof(struct load_op)
1106 + sizeof(struct literal_numeric);
1107 break;
1108 }
1109
1110 case FILTER_OP_LOAD_DOUBLE:
1111 {
1112 struct load_op *insn = (struct load_op *) pc;
1113
1114 if (unlikely(insn->reg >= REG_ERROR)) {
1115 ERR("invalid register %u\n",
1116 (unsigned int) insn->reg);
1117 ret = -EINVAL;
1118 goto end;
1119 }
1120 reg[insn->reg].type = REG_DOUBLE;
08c84b15 1121 reg[insn->reg].literal = 1;
9522a886
MD
1122 next_pc += sizeof(struct load_op)
1123 + sizeof(struct literal_double);
1124 break;
1125 }
1126 }
1127 }
1128end:
1129 return ret;
1130}
1131
08c84b15
MD
1132static
1133int lttng_filter_specialize_bytecode(struct bytecode_runtime *bytecode)
1134{
1135 void *pc, *next_pc, *start_pc;
1136 int ret = -EINVAL;
1137 struct vreg reg[NR_REG];
1138 int i;
1139
1140 for (i = 0; i < NR_REG; i++) {
1141 reg[i].type = REG_TYPE_UNKNOWN;
1142 reg[i].literal = 0;
1143 }
1144
1145 start_pc = &bytecode->data[0];
1146 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1147 pc = next_pc) {
1148 switch (*(filter_opcode_t *) pc) {
1149 case FILTER_OP_UNKNOWN:
1150 default:
1151 ERR("unknown bytecode op %u\n",
1152 (unsigned int) *(filter_opcode_t *) pc);
1153 ret = -EINVAL;
1154 goto end;
1155
1156 case FILTER_OP_RETURN:
1157 ret = 0;
1158 goto end;
1159
1160 /* binary */
1161 case FILTER_OP_MUL:
1162 case FILTER_OP_DIV:
1163 case FILTER_OP_MOD:
1164 case FILTER_OP_PLUS:
1165 case FILTER_OP_MINUS:
1166 case FILTER_OP_RSHIFT:
1167 case FILTER_OP_LSHIFT:
1168 case FILTER_OP_BIN_AND:
1169 case FILTER_OP_BIN_OR:
1170 case FILTER_OP_BIN_XOR:
1171 ERR("unsupported bytecode op %u\n",
1172 (unsigned int) *(filter_opcode_t *) pc);
1173 ret = -EINVAL;
1174 goto end;
1175
1176 case FILTER_OP_EQ:
1177 case FILTER_OP_NE:
1178 case FILTER_OP_GT:
1179 case FILTER_OP_LT:
1180 case FILTER_OP_GE:
1181 case FILTER_OP_LE:
1182 {
1183 reg[REG_R0].type = REG_S64;
1184 next_pc += sizeof(struct binary_op);
1185 break;
1186 }
1187
1188 /* unary */
1189 case FILTER_OP_UNARY_PLUS:
1190 {
1191 struct unary_op *insn = (struct unary_op *) pc;
1192
1193 switch(reg[insn->reg].type) {
1194 default:
1195 ERR("unknown register type\n");
1196 ret = -EINVAL;
1197 goto end;
1198
1199 case REG_S64:
1200 insn->op = FILTER_OP_UNARY_PLUS_S64;
1201 break;
1202 case REG_DOUBLE:
1203 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1204 break;
1205 }
1206 break;
1207 }
1208
1209 case FILTER_OP_UNARY_MINUS:
1210 {
1211 struct unary_op *insn = (struct unary_op *) pc;
1212
1213 switch(reg[insn->reg].type) {
1214 default:
1215 ERR("unknown register type\n");
1216 ret = -EINVAL;
1217 goto end;
1218
1219 case REG_S64:
1220 insn->op = FILTER_OP_UNARY_MINUS_S64;
1221 break;
1222 case REG_DOUBLE:
1223 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1224 break;
1225 }
1226 break;
1227 }
1228
1229 case FILTER_OP_UNARY_NOT:
1230 {
1231 struct unary_op *insn = (struct unary_op *) pc;
1232
1233 switch(reg[insn->reg].type) {
1234 default:
1235 ERR("unknown register type\n");
1236 ret = -EINVAL;
1237 goto end;
1238
1239 case REG_S64:
1240 insn->op = FILTER_OP_UNARY_NOT_S64;
1241 break;
1242 case REG_DOUBLE:
1243 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1244 break;
1245 }
1246 break;
1247 }
1248
1249 case FILTER_OP_UNARY_PLUS_S64:
1250 case FILTER_OP_UNARY_MINUS_S64:
1251 case FILTER_OP_UNARY_NOT_S64:
1252 case FILTER_OP_UNARY_PLUS_DOUBLE:
1253 case FILTER_OP_UNARY_MINUS_DOUBLE:
1254 case FILTER_OP_UNARY_NOT_DOUBLE:
1255 {
1256 next_pc += sizeof(struct unary_op);
1257 break;
1258 }
1259
1260 /* logical */
1261 case FILTER_OP_AND:
1262 case FILTER_OP_OR:
1263 {
1264 next_pc += sizeof(struct logical_op);
1265 break;
1266 }
1267
1268 /* load */
1269 case FILTER_OP_LOAD_FIELD_REF:
1270 {
1271 ERR("Unknown field ref type\n");
1272 ret = -EINVAL;
1273 goto end;
1274 }
1275 case FILTER_OP_LOAD_FIELD_REF_STRING:
1276 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
1277 {
1278 struct load_op *insn = (struct load_op *) pc;
1279
1280 reg[insn->reg].type = REG_STRING;
1281 reg[insn->reg].literal = 0;
1282 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1283 break;
1284 }
1285 case FILTER_OP_LOAD_FIELD_REF_S64:
1286 {
1287 struct load_op *insn = (struct load_op *) pc;
1288
1289 reg[insn->reg].type = REG_S64;
1290 reg[insn->reg].literal = 0;
1291 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1292 break;
1293 }
1294 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
1295 {
1296 struct load_op *insn = (struct load_op *) pc;
1297
1298 reg[insn->reg].type = REG_DOUBLE;
1299 reg[insn->reg].literal = 0;
1300 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1301 break;
1302 }
1303
1304 case FILTER_OP_LOAD_STRING:
1305 {
1306 struct load_op *insn = (struct load_op *) pc;
1307
1308 reg[insn->reg].type = REG_STRING;
1309 reg[insn->reg].literal = 1;
1310 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1311 break;
1312 }
1313
1314 case FILTER_OP_LOAD_S64:
1315 {
1316 struct load_op *insn = (struct load_op *) pc;
1317
1318 reg[insn->reg].type = REG_S64;
1319 reg[insn->reg].literal = 1;
1320 next_pc += sizeof(struct load_op)
1321 + sizeof(struct literal_numeric);
1322 break;
1323 }
1324
1325 case FILTER_OP_LOAD_DOUBLE:
1326 {
1327 struct load_op *insn = (struct load_op *) pc;
1328
1329 reg[insn->reg].type = REG_DOUBLE;
1330 reg[insn->reg].literal = 1;
1331 next_pc += sizeof(struct load_op)
1332 + sizeof(struct literal_double);
1333 break;
1334 }
1335 }
1336 }
1337end:
1338 return ret;
1339}
1340
1341
1342
cd54f6d9
MD
1343static
1344int apply_field_reloc(struct ltt_event *event,
1345 struct bytecode_runtime *runtime,
1346 uint32_t runtime_len,
1347 uint32_t reloc_offset,
1348 const char *field_name)
1349{
1350 const struct lttng_event_desc *desc;
1351 const struct lttng_event_field *fields, *field = NULL;
1352 unsigned int nr_fields, i;
1353 struct field_ref *field_ref;
2f0145d1 1354 struct load_op *op;
cd54f6d9
MD
1355 uint32_t field_offset = 0;
1356
a8c27c7c 1357 dbg_printf("Apply reloc: %u %s\n", reloc_offset, field_name);
cd54f6d9
MD
1358
1359 /* Ensure that the reloc is within the code */
1360 if (runtime_len - reloc_offset < sizeof(uint16_t))
1361 return -EINVAL;
1362
1363 /* Lookup event by name */
1364 desc = event->desc;
1365 if (!desc)
1366 return -EINVAL;
1367 fields = desc->fields;
1368 if (!fields)
1369 return -EINVAL;
1370 nr_fields = desc->nr_fields;
1371 for (i = 0; i < nr_fields; i++) {
1372 if (!strcmp(fields[i].name, field_name)) {
1373 field = &fields[i];
1374 break;
1375 }
1376 /* compute field offset */
1377 switch (fields[i].type.atype) {
1378 case atype_integer:
1379 case atype_enum:
1380 field_offset += sizeof(int64_t);
1381 break;
1382 case atype_array:
1383 case atype_sequence:
1384 field_offset += sizeof(unsigned long);
1385 field_offset += sizeof(void *);
1386 break;
1387 case atype_string:
1388 field_offset += sizeof(void *);
1389 break;
1390 case atype_float:
1391 field_offset += sizeof(double);
da6eed25 1392 break;
cd54f6d9
MD
1393 default:
1394 return -EINVAL;
1395 }
1396 }
1397 if (!field)
1398 return -EINVAL;
1399
1400 /* Check if field offset is too large for 16-bit offset */
1401 if (field_offset > FILTER_BYTECODE_MAX_LEN)
1402 return -EINVAL;
1403
1404 /* set type */
2f0145d1
MD
1405 op = (struct load_op *) &runtime->data[reloc_offset];
1406 field_ref = (struct field_ref *) op->data;
cd54f6d9
MD
1407 switch (field->type.atype) {
1408 case atype_integer:
1409 case atype_enum:
2f0145d1 1410 op->op = FILTER_OP_LOAD_FIELD_REF_S64;
cd54f6d9
MD
1411 break;
1412 case atype_array:
1413 case atype_sequence:
2f0145d1 1414 op->op = FILTER_OP_LOAD_FIELD_REF_SEQUENCE;
cd54f6d9
MD
1415 break;
1416 case atype_string:
2f0145d1 1417 op->op = FILTER_OP_LOAD_FIELD_REF_STRING;
cd54f6d9
MD
1418 break;
1419 case atype_float:
2f0145d1 1420 op->op = FILTER_OP_LOAD_FIELD_REF_DOUBLE;
da6eed25 1421 break;
cd54f6d9
MD
1422 default:
1423 return -EINVAL;
1424 }
1425 /* set offset */
1426 field_ref->offset = (uint16_t) field_offset;
2d78951a
MD
1427 return 0;
1428}
1429
cd54f6d9
MD
1430/*
1431 * Take a bytecode with reloc table and link it to an event to create a
1432 * bytecode runtime.
1433 */
2d78951a
MD
1434static
1435int _lttng_filter_event_link_bytecode(struct ltt_event *event,
1436 struct lttng_ust_filter_bytecode *filter_bytecode)
1437{
cd54f6d9
MD
1438 int ret, offset, next_offset;
1439 struct bytecode_runtime *runtime = NULL;
1440 size_t runtime_alloc_len;
1441
2d78951a
MD
1442 if (!filter_bytecode)
1443 return 0;
cd54f6d9
MD
1444 /* Even is not connected to any description */
1445 if (!event->desc)
1446 return 0;
1447 /* Bytecode already linked */
1448 if (event->filter || event->filter_data)
1449 return 0;
2d78951a 1450
a8c27c7c 1451 dbg_printf("Linking\n");
cd54f6d9
MD
1452
1453 /* We don't need the reloc table in the runtime */
1454 runtime_alloc_len = sizeof(*runtime) + filter_bytecode->reloc_offset;
1455 runtime = zmalloc(runtime_alloc_len);
1456 if (!runtime) {
1457 ret = -ENOMEM;
1458 goto link_error;
1459 }
1460 runtime->len = filter_bytecode->reloc_offset;
1461 /* copy original bytecode */
1462 memcpy(runtime->data, filter_bytecode->data, runtime->len);
1463 /*
1464 * apply relocs. Those are a uint16_t (offset in bytecode)
1465 * followed by a string (field name).
1466 */
cd54f6d9
MD
1467 for (offset = filter_bytecode->reloc_offset;
1468 offset < filter_bytecode->len;
1469 offset = next_offset) {
1470 uint16_t reloc_offset =
1471 *(uint16_t *) &filter_bytecode->data[offset];
1472 const char *field_name =
1473 (const char *) &filter_bytecode->data[offset + sizeof(uint16_t)];
1474
1475 ret = apply_field_reloc(event, runtime, runtime->len, reloc_offset, field_name);
1476 if (ret) {
1477 goto link_error;
1478 }
1479 next_offset = offset + sizeof(uint16_t) + strlen(field_name) + 1;
1480 }
9522a886
MD
1481 /* Validate bytecode */
1482 ret = lttng_filter_validate_bytecode(runtime);
1483 if (ret) {
1484 goto link_error;
1485 }
08c84b15
MD
1486 /* Specialize bytecode */
1487 ret = lttng_filter_specialize_bytecode(runtime);
1488 if (ret) {
1489 goto link_error;
1490 }
cd54f6d9 1491 event->filter_data = runtime;
2d78951a 1492 event->filter = lttng_filter_interpret_bytecode;
2d78951a 1493 return 0;
cd54f6d9
MD
1494
1495link_error:
1496 event->filter = lttng_filter_false;
1497 free(runtime);
1498 return ret;
2d78951a
MD
1499}
1500
1501void lttng_filter_event_link_bytecode(struct ltt_event *event,
1502 struct lttng_ust_filter_bytecode *filter_bytecode)
1503{
1504 int ret;
1505
cd54f6d9 1506 ret = _lttng_filter_event_link_bytecode(event, filter_bytecode);
2d78951a
MD
1507 if (ret) {
1508 fprintf(stderr, "[lttng filter] error linking event bytecode\n");
1509 }
1510}
1511
1512/*
1513 * Link bytecode to all events for a wildcard. Skips events that already
1514 * have a bytecode linked.
1515 * We do not set each event's filter_bytecode field, because they do not
1516 * own the filter_bytecode: the wildcard owns it.
1517 */
1518void lttng_filter_wildcard_link_bytecode(struct session_wildcard *wildcard)
1519{
1520 struct ltt_event *event;
1521 int ret;
1522
1523 if (!wildcard->filter_bytecode)
1524 return;
1525
1526 cds_list_for_each_entry(event, &wildcard->events, wildcard_list) {
1527 if (event->filter)
1528 continue;
1529 ret = _lttng_filter_event_link_bytecode(event,
1530 wildcard->filter_bytecode);
1531 if (ret) {
1532 fprintf(stderr, "[lttng filter] error linking wildcard bytecode\n");
1533 }
1534
1535 }
1536 return;
1537}
1538
1539/*
1540 * Need to attach filter to an event before starting tracing for the
cd54f6d9 1541 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1542 */
1543int lttng_filter_event_attach_bytecode(struct ltt_event *event,
1544 struct lttng_ust_filter_bytecode *filter_bytecode)
1545{
2d78951a
MD
1546 if (event->chan->session->been_active)
1547 return -EPERM;
1548 if (event->filter_bytecode)
1549 return -EEXIST;
cd54f6d9 1550 event->filter_bytecode = filter_bytecode;
2d78951a
MD
1551 return 0;
1552}
1553
1554/*
1555 * Need to attach filter to a wildcard before starting tracing for the
cd54f6d9 1556 * session. We own the filter_bytecode if we return success.
2d78951a
MD
1557 */
1558int lttng_filter_wildcard_attach_bytecode(struct session_wildcard *wildcard,
1559 struct lttng_ust_filter_bytecode *filter_bytecode)
1560{
2d78951a
MD
1561 if (wildcard->chan->session->been_active)
1562 return -EPERM;
1563 if (wildcard->filter_bytecode)
1564 return -EEXIST;
cd54f6d9 1565 wildcard->filter_bytecode = filter_bytecode;
2d78951a
MD
1566 return 0;
1567}
This page took 0.097207 seconds and 4 git commands to generate.