4 * LTTng UST filter code.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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.
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.
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
26 #include <lttng/ust-events.h>
32 #include <usterr-signal-safe.h>
33 #include "filter-bytecode.h"
38 #define min_t(type, a, b) \
39 ((type) (a) < (type) (b) ? (type) (a) : (type) (b))
43 #define likely(x) __builtin_expect(!!(x), 1)
47 #define unlikely(x) __builtin_expect(!!(x), 0)
51 #define dbg_printf(fmt, args...) printf("[debug bytecode] " fmt, ## args)
53 #define dbg_printf(fmt, args...) \
55 /* do nothing but check printf format */ \
57 printf("[debug bytecode] " fmt, ## args); \
62 struct bytecode_runtime
{
74 /* Validation registers */
77 int literal
; /* is string literal ? */
80 /* Execution registers */
88 int literal
; /* is string literal ? */
91 static const char *opnames
[] = {
92 [ FILTER_OP_UNKNOWN
] = "UNKNOWN",
94 [ FILTER_OP_RETURN
] = "RETURN",
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",
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",
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",
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",
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",
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",
153 [ FILTER_OP_AND
] = "AND",
154 [ FILTER_OP_OR
] = "OR",
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",
163 [ FILTER_OP_LOAD_STRING
] = "LOAD_STRING",
164 [ FILTER_OP_LOAD_S64
] = "LOAD_S64",
165 [ FILTER_OP_LOAD_DOUBLE
] = "LOAD_DOUBLE",
169 const char *print_op(enum filter_op op
)
171 if (op
>= NR_FILTER_OPS
)
178 * -1: wildcard found.
179 * -2: unknown escape char.
184 int parse_char(const char **p
)
204 int reg_strcmp(struct reg reg
[NR_REG
], const char *cmp_type
)
206 const char *p
= reg
[REG_R0
].str
, *q
= reg
[REG_R1
].str
;
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')
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')
227 if (reg
[REG_R0
].literal
) {
228 ret
= parse_char(&p
);
231 } else if (ret
== -2) {
234 /* else compare both char */
236 if (reg
[REG_R1
].literal
) {
237 ret
= parse_char(&q
);
240 } else if (ret
== -2) {
261 int lttng_filter_false(void *filter_data
,
262 const char *filter_stack_data
)
268 int lttng_filter_interpret_bytecode(void *filter_data
,
269 const char *filter_stack_data
)
271 struct bytecode_runtime
*bytecode
= filter_data
;
272 void *pc
, *next_pc
, *start_pc
;
275 struct reg reg
[NR_REG
];
277 start_pc
= &bytecode
->data
[0];
278 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
280 dbg_printf("Executing op %s (%u)\n",
281 print_op((unsigned int) *(filter_opcode_t
*) pc
),
282 (unsigned int) *(filter_opcode_t
*) pc
);
283 switch (*(filter_opcode_t
*) pc
) {
284 case FILTER_OP_UNKNOWN
:
285 case FILTER_OP_LOAD_FIELD_REF
:
287 ERR("unknown bytecode op %u\n",
288 (unsigned int) *(filter_opcode_t
*) pc
);
292 case FILTER_OP_RETURN
:
302 case FILTER_OP_MINUS
:
303 case FILTER_OP_RSHIFT
:
304 case FILTER_OP_LSHIFT
:
305 case FILTER_OP_BIN_AND
:
306 case FILTER_OP_BIN_OR
:
307 case FILTER_OP_BIN_XOR
:
308 ERR("unsupported bytecode op %u\n",
309 (unsigned int) *(filter_opcode_t
*) pc
);
319 ERR("unsupported non-specialized bytecode op %u\n",
320 (unsigned int) *(filter_opcode_t
*) pc
);
324 case FILTER_OP_EQ_STRING
:
326 reg
[REG_R0
].v
= (reg_strcmp(reg
, "==") == 0);
327 reg
[REG_R0
].type
= REG_S64
;
328 next_pc
+= sizeof(struct binary_op
);
331 case FILTER_OP_NE_STRING
:
333 reg
[REG_R0
].v
= (reg_strcmp(reg
, "!=") != 0);
334 reg
[REG_R0
].type
= REG_S64
;
335 next_pc
+= sizeof(struct binary_op
);
338 case FILTER_OP_GT_STRING
:
340 reg
[REG_R0
].v
= (reg_strcmp(reg
, ">") > 0);
341 reg
[REG_R0
].type
= REG_S64
;
342 next_pc
+= sizeof(struct binary_op
);
345 case FILTER_OP_LT_STRING
:
347 reg
[REG_R0
].v
= (reg_strcmp(reg
, "<") < 0);
348 reg
[REG_R0
].type
= REG_S64
;
349 next_pc
+= sizeof(struct binary_op
);
352 case FILTER_OP_GE_STRING
:
354 reg
[REG_R0
].v
= (reg_strcmp(reg
, ">=") >= 0);
355 reg
[REG_R0
].type
= REG_S64
;
356 next_pc
+= sizeof(struct binary_op
);
359 case FILTER_OP_LE_STRING
:
361 reg
[REG_R0
].v
= (reg_strcmp(reg
, "<=") <= 0);
362 reg
[REG_R0
].type
= REG_S64
;
363 next_pc
+= sizeof(struct binary_op
);
367 case FILTER_OP_EQ_S64
:
369 reg
[REG_R0
].v
= (reg
[REG_R0
].v
== reg
[REG_R1
].v
);
370 reg
[REG_R0
].type
= REG_S64
;
371 next_pc
+= sizeof(struct binary_op
);
374 case FILTER_OP_NE_S64
:
376 reg
[REG_R0
].v
= (reg
[REG_R0
].v
!= reg
[REG_R1
].v
);
377 reg
[REG_R0
].type
= REG_S64
;
378 next_pc
+= sizeof(struct binary_op
);
381 case FILTER_OP_GT_S64
:
383 reg
[REG_R0
].v
= (reg
[REG_R0
].v
> reg
[REG_R1
].v
);
384 reg
[REG_R0
].type
= REG_S64
;
385 next_pc
+= sizeof(struct binary_op
);
388 case FILTER_OP_LT_S64
:
390 reg
[REG_R0
].v
= (reg
[REG_R0
].v
< reg
[REG_R1
].v
);
391 reg
[REG_R0
].type
= REG_S64
;
392 next_pc
+= sizeof(struct binary_op
);
395 case FILTER_OP_GE_S64
:
397 reg
[REG_R0
].v
= (reg
[REG_R0
].v
>= reg
[REG_R1
].v
);
398 reg
[REG_R0
].type
= REG_S64
;
399 next_pc
+= sizeof(struct binary_op
);
402 case FILTER_OP_LE_S64
:
404 reg
[REG_R0
].v
= (reg
[REG_R0
].v
<= reg
[REG_R1
].v
);
405 reg
[REG_R0
].type
= REG_S64
;
406 next_pc
+= sizeof(struct binary_op
);
410 case FILTER_OP_EQ_DOUBLE
:
412 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
413 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
414 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
415 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
416 reg
[REG_R0
].v
= (reg
[REG_R0
].d
== reg
[REG_R1
].d
);
417 reg
[REG_R0
].type
= REG_S64
;
418 next_pc
+= sizeof(struct binary_op
);
421 case FILTER_OP_NE_DOUBLE
:
423 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
424 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
425 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
426 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
427 reg
[REG_R0
].v
= (reg
[REG_R0
].d
!= reg
[REG_R1
].d
);
428 reg
[REG_R0
].type
= REG_S64
;
429 next_pc
+= sizeof(struct binary_op
);
432 case FILTER_OP_GT_DOUBLE
:
434 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
435 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
436 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
437 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
438 reg
[REG_R0
].v
= (reg
[REG_R0
].d
> reg
[REG_R1
].d
);
439 reg
[REG_R0
].type
= REG_S64
;
440 next_pc
+= sizeof(struct binary_op
);
443 case FILTER_OP_LT_DOUBLE
:
445 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
446 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
447 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
448 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
449 reg
[REG_R0
].v
= (reg
[REG_R0
].d
< reg
[REG_R1
].d
);
450 reg
[REG_R0
].type
= REG_S64
;
451 next_pc
+= sizeof(struct binary_op
);
454 case FILTER_OP_GE_DOUBLE
:
456 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
457 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
458 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
459 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
460 reg
[REG_R0
].v
= (reg
[REG_R0
].d
>= reg
[REG_R1
].d
);
461 reg
[REG_R0
].type
= REG_S64
;
462 next_pc
+= sizeof(struct binary_op
);
465 case FILTER_OP_LE_DOUBLE
:
467 if (unlikely(reg
[REG_R0
].type
== REG_S64
))
468 reg
[REG_R0
].d
= (double) reg
[REG_R0
].v
;
469 else if (unlikely(reg
[REG_R1
].type
== REG_S64
))
470 reg
[REG_R1
].d
= (double) reg
[REG_R1
].v
;
471 reg
[REG_R0
].v
= (reg
[REG_R0
].d
<= reg
[REG_R1
].d
);
472 reg
[REG_R0
].type
= REG_S64
;
473 next_pc
+= sizeof(struct binary_op
);
478 case FILTER_OP_UNARY_PLUS
:
480 next_pc
+= sizeof(struct unary_op
);
483 case FILTER_OP_UNARY_MINUS
:
485 struct unary_op
*insn
= (struct unary_op
*) pc
;
487 switch (reg
[insn
->reg
].type
) {
489 ERR("unknown register type\n");
494 ERR("Unary minus can only be applied to numeric or floating point registers\n");
498 reg
[insn
->reg
].v
= -reg
[insn
->reg
].v
;
501 reg
[insn
->reg
].d
= -reg
[insn
->reg
].d
;
504 next_pc
+= sizeof(struct unary_op
);
507 case FILTER_OP_UNARY_NOT
:
509 struct unary_op
*insn
= (struct unary_op
*) pc
;
511 switch (reg
[insn
->reg
].type
) {
513 ERR("unknown register type\n");
518 ERR("Unary not can only be applied to numeric or floating point registers\n");
522 reg
[insn
->reg
].v
= !reg
[insn
->reg
].v
;
525 reg
[insn
->reg
].d
= !reg
[insn
->reg
].d
;
528 reg
[insn
->reg
].v
= !reg
[insn
->reg
].v
;
529 next_pc
+= sizeof(struct unary_op
);
535 struct logical_op
*insn
= (struct logical_op
*) pc
;
537 /* If REG_R0 is 0, skip and evaluate to 0 */
538 if ((reg
[REG_R0
].type
== REG_S64
&& reg
[REG_R0
].v
== 0)
539 || (reg
[REG_R0
].type
== REG_DOUBLE
&& reg
[REG_R0
].d
== 0.0)) {
540 dbg_printf("Jumping to bytecode offset %u\n",
541 (unsigned int) insn
->skip_offset
);
542 next_pc
= start_pc
+ insn
->skip_offset
;
544 next_pc
+= sizeof(struct logical_op
);
550 struct logical_op
*insn
= (struct logical_op
*) pc
;
552 /* If REG_R0 is nonzero, skip and evaluate to 1 */
554 if ((reg
[REG_R0
].type
== REG_S64
&& reg
[REG_R0
].v
!= 0)
555 || (reg
[REG_R0
].type
== REG_DOUBLE
&& reg
[REG_R0
].d
!= 0.0)) {
557 dbg_printf("Jumping to bytecode offset %u\n",
558 (unsigned int) insn
->skip_offset
);
559 next_pc
= start_pc
+ insn
->skip_offset
;
561 next_pc
+= sizeof(struct logical_op
);
567 case FILTER_OP_LOAD_FIELD_REF_STRING
:
569 struct load_op
*insn
= (struct load_op
*) pc
;
570 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
572 dbg_printf("load field ref offset %u type string\n",
575 *(const char * const *) &filter_stack_data
[ref
->offset
];
576 reg
[insn
->reg
].type
= REG_STRING
;
577 reg
[insn
->reg
].seq_len
= UINT_MAX
;
578 reg
[insn
->reg
].literal
= 0;
579 dbg_printf("ref load string %s\n", reg
[insn
->reg
].str
);
580 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
584 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
586 struct load_op
*insn
= (struct load_op
*) pc
;
587 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
589 dbg_printf("load field ref offset %u type sequence\n",
591 reg
[insn
->reg
].seq_len
=
592 *(unsigned long *) &filter_stack_data
[ref
->offset
];
594 *(const char **) (&filter_stack_data
[ref
->offset
595 + sizeof(unsigned long)]);
596 reg
[insn
->reg
].type
= REG_STRING
;
597 reg
[insn
->reg
].literal
= 0;
598 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
602 case FILTER_OP_LOAD_FIELD_REF_S64
:
604 struct load_op
*insn
= (struct load_op
*) pc
;
605 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
607 dbg_printf("load field ref offset %u type s64\n",
609 memcpy(®
[insn
->reg
].v
, &filter_stack_data
[ref
->offset
],
610 sizeof(struct literal_numeric
));
611 reg
[insn
->reg
].type
= REG_S64
;
612 reg
[insn
->reg
].literal
= 0;
613 dbg_printf("ref load s64 %" PRIi64
"\n", reg
[insn
->reg
].v
);
614 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
618 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
620 struct load_op
*insn
= (struct load_op
*) pc
;
621 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
623 dbg_printf("load field ref offset %u type double\n",
625 memcpy(®
[insn
->reg
].d
, &filter_stack_data
[ref
->offset
],
626 sizeof(struct literal_double
));
627 reg
[insn
->reg
].type
= REG_DOUBLE
;
628 reg
[insn
->reg
].literal
= 0;
629 dbg_printf("ref load double %g\n", reg
[insn
->reg
].d
);
630 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
634 case FILTER_OP_LOAD_STRING
:
636 struct load_op
*insn
= (struct load_op
*) pc
;
638 dbg_printf("load string %s\n", insn
->data
);
639 reg
[insn
->reg
].str
= insn
->data
;
640 reg
[insn
->reg
].type
= REG_STRING
;
641 reg
[insn
->reg
].seq_len
= UINT_MAX
;
642 reg
[insn
->reg
].literal
= 1;
643 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
647 case FILTER_OP_LOAD_S64
:
649 struct load_op
*insn
= (struct load_op
*) pc
;
651 memcpy(®
[insn
->reg
].v
, insn
->data
,
652 sizeof(struct literal_numeric
));
653 dbg_printf("load s64 %" PRIi64
"\n", reg
[insn
->reg
].v
);
654 reg
[insn
->reg
].type
= REG_S64
;
655 reg
[insn
->reg
].literal
= 1;
656 next_pc
+= sizeof(struct load_op
)
657 + sizeof(struct literal_numeric
);
661 case FILTER_OP_LOAD_DOUBLE
:
663 struct load_op
*insn
= (struct load_op
*) pc
;
665 memcpy(®
[insn
->reg
].d
, insn
->data
,
666 sizeof(struct literal_double
));
667 dbg_printf("load s64 %g\n", reg
[insn
->reg
].d
);
668 reg
[insn
->reg
].type
= REG_DOUBLE
;
669 reg
[insn
->reg
].literal
= 1;
670 next_pc
+= sizeof(struct load_op
)
671 + sizeof(struct literal_double
);
677 /* return 0 (discard) on error */
684 int bin_op_compare_check(struct vreg reg
[NR_REG
], const char *str
)
686 switch (reg
[REG_R0
].type
) {
691 switch (reg
[REG_R1
].type
) {
704 switch (reg
[REG_R1
].type
) {
723 ERR("type mismatch for '%s' binary operator\n", str
);
728 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
730 void *pc
, *next_pc
, *start_pc
;
732 struct vreg reg
[NR_REG
];
735 for (i
= 0; i
< NR_REG
; i
++) {
736 reg
[i
].type
= REG_TYPE_UNKNOWN
;
740 start_pc
= &bytecode
->data
[0];
741 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
743 if (unlikely(pc
>= start_pc
+ bytecode
->len
)) {
744 ERR("filter bytecode overflow\n");
748 dbg_printf("Validating op %s (%u)\n",
749 print_op((unsigned int) *(filter_opcode_t
*) pc
),
750 (unsigned int) *(filter_opcode_t
*) pc
);
751 switch (*(filter_opcode_t
*) pc
) {
752 case FILTER_OP_UNKNOWN
:
754 ERR("unknown bytecode op %u\n",
755 (unsigned int) *(filter_opcode_t
*) pc
);
759 case FILTER_OP_RETURN
:
768 case FILTER_OP_MINUS
:
769 case FILTER_OP_RSHIFT
:
770 case FILTER_OP_LSHIFT
:
771 case FILTER_OP_BIN_AND
:
772 case FILTER_OP_BIN_OR
:
773 case FILTER_OP_BIN_XOR
:
774 ERR("unsupported bytecode op %u\n",
775 (unsigned int) *(filter_opcode_t
*) pc
);
781 ret
= bin_op_compare_check(reg
, "==");
784 reg
[REG_R0
].type
= REG_S64
;
785 next_pc
+= sizeof(struct binary_op
);
790 ret
= bin_op_compare_check(reg
, "!=");
793 reg
[REG_R0
].type
= REG_S64
;
794 next_pc
+= sizeof(struct binary_op
);
799 ret
= bin_op_compare_check(reg
, ">");
802 reg
[REG_R0
].type
= REG_S64
;
803 next_pc
+= sizeof(struct binary_op
);
808 ret
= bin_op_compare_check(reg
, "<");
811 reg
[REG_R0
].type
= REG_S64
;
812 next_pc
+= sizeof(struct binary_op
);
817 ret
= bin_op_compare_check(reg
, ">=");
820 reg
[REG_R0
].type
= REG_S64
;
821 next_pc
+= sizeof(struct binary_op
);
826 ret
= bin_op_compare_check(reg
, "<=");
829 reg
[REG_R0
].type
= REG_S64
;
830 next_pc
+= sizeof(struct binary_op
);
834 case FILTER_OP_EQ_STRING
:
835 case FILTER_OP_NE_STRING
:
836 case FILTER_OP_GT_STRING
:
837 case FILTER_OP_LT_STRING
:
838 case FILTER_OP_GE_STRING
:
839 case FILTER_OP_LE_STRING
:
841 if (reg
[REG_R0
].type
!= REG_STRING
842 || reg
[REG_R1
].type
!= REG_STRING
) {
843 ERR("Unexpected register type for string comparator\n");
847 reg
[REG_R0
].type
= REG_S64
;
848 next_pc
+= sizeof(struct binary_op
);
852 case FILTER_OP_EQ_S64
:
853 case FILTER_OP_NE_S64
:
854 case FILTER_OP_GT_S64
:
855 case FILTER_OP_LT_S64
:
856 case FILTER_OP_GE_S64
:
857 case FILTER_OP_LE_S64
:
859 if (reg
[REG_R0
].type
!= REG_S64
860 || reg
[REG_R1
].type
!= REG_S64
) {
861 ERR("Unexpected register type for s64 comparator\n");
865 reg
[REG_R0
].type
= REG_S64
;
866 next_pc
+= sizeof(struct binary_op
);
870 case FILTER_OP_EQ_DOUBLE
:
871 case FILTER_OP_NE_DOUBLE
:
872 case FILTER_OP_GT_DOUBLE
:
873 case FILTER_OP_LT_DOUBLE
:
874 case FILTER_OP_GE_DOUBLE
:
875 case FILTER_OP_LE_DOUBLE
:
877 if ((reg
[REG_R0
].type
!= REG_DOUBLE
&& reg
[REG_R0
].type
!= REG_S64
)
878 || (reg
[REG_R1
].type
!= REG_DOUBLE
&& reg
[REG_R1
].type
!= REG_S64
)) {
879 ERR("Unexpected register type for double comparator\n");
883 reg
[REG_R0
].type
= REG_DOUBLE
;
884 next_pc
+= sizeof(struct binary_op
);
889 case FILTER_OP_UNARY_PLUS
:
890 case FILTER_OP_UNARY_MINUS
:
891 case FILTER_OP_UNARY_NOT
:
893 struct unary_op
*insn
= (struct unary_op
*) pc
;
895 if (unlikely(insn
->reg
>= REG_ERROR
)) {
896 ERR("invalid register %u\n",
897 (unsigned int) insn
->reg
);
901 switch (reg
[insn
->reg
].type
) {
903 ERR("unknown register type\n");
908 ERR("Unary op can only be applied to numeric or floating point registers\n");
916 next_pc
+= sizeof(struct unary_op
);
920 case FILTER_OP_UNARY_PLUS_S64
:
921 case FILTER_OP_UNARY_MINUS_S64
:
922 case FILTER_OP_UNARY_NOT_S64
:
924 struct unary_op
*insn
= (struct unary_op
*) pc
;
926 if (unlikely(insn
->reg
>= REG_ERROR
)) {
927 ERR("invalid register %u\n",
928 (unsigned int) insn
->reg
);
932 if (reg
[insn
->reg
].type
!= REG_S64
) {
933 ERR("Invalid register type\n");
937 next_pc
+= sizeof(struct unary_op
);
941 case FILTER_OP_UNARY_PLUS_DOUBLE
:
942 case FILTER_OP_UNARY_MINUS_DOUBLE
:
943 case FILTER_OP_UNARY_NOT_DOUBLE
:
945 struct unary_op
*insn
= (struct unary_op
*) pc
;
947 if (unlikely(insn
->reg
>= REG_ERROR
)) {
948 ERR("invalid register %u\n",
949 (unsigned int) insn
->reg
);
953 if (reg
[insn
->reg
].type
!= REG_DOUBLE
) {
954 ERR("Invalid register type\n");
958 next_pc
+= sizeof(struct unary_op
);
966 struct logical_op
*insn
= (struct logical_op
*) pc
;
968 if (unlikely(reg
[REG_R0
].type
== REG_TYPE_UNKNOWN
969 || reg
[REG_R0
].type
== REG_TYPE_UNKNOWN
970 || reg
[REG_R0
].type
== REG_STRING
971 || reg
[REG_R1
].type
== REG_STRING
)) {
972 ERR("Logical comparator can only be applied to numeric and floating point registers\n");
977 dbg_printf("Validate jumping to bytecode offset %u\n",
978 (unsigned int) insn
->skip_offset
);
979 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
980 ERR("Loops are not allowed in bytecode\n");
984 next_pc
+= sizeof(struct logical_op
);
989 case FILTER_OP_LOAD_FIELD_REF
:
991 ERR("Unknown field ref type\n");
995 case FILTER_OP_LOAD_FIELD_REF_STRING
:
996 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
998 struct load_op
*insn
= (struct load_op
*) pc
;
999 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1001 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1002 ERR("invalid register %u\n",
1003 (unsigned int) insn
->reg
);
1007 dbg_printf("Validate load field ref offset %u type string\n",
1009 reg
[insn
->reg
].type
= REG_STRING
;
1010 reg
[insn
->reg
].literal
= 0;
1011 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1014 case FILTER_OP_LOAD_FIELD_REF_S64
:
1016 struct load_op
*insn
= (struct load_op
*) pc
;
1017 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1019 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1020 ERR("invalid register %u\n",
1021 (unsigned int) insn
->reg
);
1025 dbg_printf("Validate load field ref offset %u type s64\n",
1027 reg
[insn
->reg
].type
= REG_S64
;
1028 reg
[insn
->reg
].literal
= 0;
1029 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1032 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
1034 struct load_op
*insn
= (struct load_op
*) pc
;
1035 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1037 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1038 ERR("invalid register %u\n",
1039 (unsigned int) insn
->reg
);
1043 dbg_printf("Validate load field ref offset %u type double\n",
1045 reg
[insn
->reg
].type
= REG_DOUBLE
;
1046 reg
[insn
->reg
].literal
= 0;
1047 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1051 case FILTER_OP_LOAD_STRING
:
1053 struct load_op
*insn
= (struct load_op
*) pc
;
1055 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1056 ERR("invalid register %u\n",
1057 (unsigned int) insn
->reg
);
1061 reg
[insn
->reg
].type
= REG_STRING
;
1062 reg
[insn
->reg
].literal
= 1;
1063 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1067 case FILTER_OP_LOAD_S64
:
1069 struct load_op
*insn
= (struct load_op
*) pc
;
1071 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1072 ERR("invalid register %u\n",
1073 (unsigned int) insn
->reg
);
1077 reg
[insn
->reg
].type
= REG_S64
;
1078 reg
[insn
->reg
].literal
= 1;
1079 next_pc
+= sizeof(struct load_op
)
1080 + sizeof(struct literal_numeric
);
1084 case FILTER_OP_LOAD_DOUBLE
:
1086 struct load_op
*insn
= (struct load_op
*) pc
;
1088 if (unlikely(insn
->reg
>= REG_ERROR
)) {
1089 ERR("invalid register %u\n",
1090 (unsigned int) insn
->reg
);
1094 reg
[insn
->reg
].type
= REG_DOUBLE
;
1095 reg
[insn
->reg
].literal
= 1;
1096 next_pc
+= sizeof(struct load_op
)
1097 + sizeof(struct literal_double
);
1107 int lttng_filter_specialize_bytecode(struct bytecode_runtime
*bytecode
)
1109 void *pc
, *next_pc
, *start_pc
;
1111 struct vreg reg
[NR_REG
];
1114 for (i
= 0; i
< NR_REG
; i
++) {
1115 reg
[i
].type
= REG_TYPE_UNKNOWN
;
1119 start_pc
= &bytecode
->data
[0];
1120 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
1122 switch (*(filter_opcode_t
*) pc
) {
1123 case FILTER_OP_UNKNOWN
:
1125 ERR("unknown bytecode op %u\n",
1126 (unsigned int) *(filter_opcode_t
*) pc
);
1130 case FILTER_OP_RETURN
:
1138 case FILTER_OP_PLUS
:
1139 case FILTER_OP_MINUS
:
1140 case FILTER_OP_RSHIFT
:
1141 case FILTER_OP_LSHIFT
:
1142 case FILTER_OP_BIN_AND
:
1143 case FILTER_OP_BIN_OR
:
1144 case FILTER_OP_BIN_XOR
:
1145 ERR("unsupported bytecode op %u\n",
1146 (unsigned int) *(filter_opcode_t
*) pc
);
1152 struct binary_op
*insn
= (struct binary_op
*) pc
;
1154 switch(reg
[REG_R0
].type
) {
1156 ERR("unknown register type\n");
1161 insn
->op
= FILTER_OP_EQ_STRING
;
1164 if (reg
[REG_R1
].type
== REG_S64
)
1165 insn
->op
= FILTER_OP_EQ_S64
;
1167 insn
->op
= FILTER_OP_EQ_DOUBLE
;
1170 insn
->op
= FILTER_OP_EQ_DOUBLE
;
1173 reg
[REG_R0
].type
= REG_S64
;
1174 next_pc
+= sizeof(struct binary_op
);
1180 struct binary_op
*insn
= (struct binary_op
*) pc
;
1182 switch(reg
[REG_R0
].type
) {
1184 ERR("unknown register type\n");
1189 insn
->op
= FILTER_OP_NE_STRING
;
1192 if (reg
[REG_R1
].type
== REG_S64
)
1193 insn
->op
= FILTER_OP_NE_S64
;
1195 insn
->op
= FILTER_OP_NE_DOUBLE
;
1198 insn
->op
= FILTER_OP_NE_DOUBLE
;
1201 reg
[REG_R0
].type
= REG_S64
;
1202 next_pc
+= sizeof(struct binary_op
);
1208 struct binary_op
*insn
= (struct binary_op
*) pc
;
1210 switch(reg
[REG_R0
].type
) {
1212 ERR("unknown register type\n");
1217 insn
->op
= FILTER_OP_GT_STRING
;
1220 if (reg
[REG_R1
].type
== REG_S64
)
1221 insn
->op
= FILTER_OP_GT_S64
;
1223 insn
->op
= FILTER_OP_GT_DOUBLE
;
1226 insn
->op
= FILTER_OP_GT_DOUBLE
;
1229 reg
[REG_R0
].type
= REG_S64
;
1230 next_pc
+= sizeof(struct binary_op
);
1236 struct binary_op
*insn
= (struct binary_op
*) pc
;
1238 switch(reg
[REG_R0
].type
) {
1240 ERR("unknown register type\n");
1245 insn
->op
= FILTER_OP_LT_STRING
;
1248 if (reg
[REG_R1
].type
== REG_S64
)
1249 insn
->op
= FILTER_OP_LT_S64
;
1251 insn
->op
= FILTER_OP_LT_DOUBLE
;
1254 insn
->op
= FILTER_OP_LT_DOUBLE
;
1257 reg
[REG_R0
].type
= REG_S64
;
1258 next_pc
+= sizeof(struct binary_op
);
1264 struct binary_op
*insn
= (struct binary_op
*) pc
;
1266 switch(reg
[REG_R0
].type
) {
1268 ERR("unknown register type\n");
1273 insn
->op
= FILTER_OP_GE_STRING
;
1276 if (reg
[REG_R1
].type
== REG_S64
)
1277 insn
->op
= FILTER_OP_GE_S64
;
1279 insn
->op
= FILTER_OP_GE_DOUBLE
;
1282 insn
->op
= FILTER_OP_GE_DOUBLE
;
1285 reg
[REG_R0
].type
= REG_S64
;
1286 next_pc
+= sizeof(struct binary_op
);
1291 struct binary_op
*insn
= (struct binary_op
*) pc
;
1293 switch(reg
[REG_R0
].type
) {
1295 ERR("unknown register type\n");
1300 insn
->op
= FILTER_OP_LE_STRING
;
1303 if (reg
[REG_R1
].type
== REG_S64
)
1304 insn
->op
= FILTER_OP_LE_S64
;
1306 insn
->op
= FILTER_OP_LE_DOUBLE
;
1309 insn
->op
= FILTER_OP_LE_DOUBLE
;
1312 reg
[REG_R0
].type
= REG_S64
;
1313 next_pc
+= sizeof(struct binary_op
);
1317 case FILTER_OP_EQ_STRING
:
1318 case FILTER_OP_NE_STRING
:
1319 case FILTER_OP_GT_STRING
:
1320 case FILTER_OP_LT_STRING
:
1321 case FILTER_OP_GE_STRING
:
1322 case FILTER_OP_LE_STRING
:
1323 case FILTER_OP_EQ_S64
:
1324 case FILTER_OP_NE_S64
:
1325 case FILTER_OP_GT_S64
:
1326 case FILTER_OP_LT_S64
:
1327 case FILTER_OP_GE_S64
:
1328 case FILTER_OP_LE_S64
:
1329 case FILTER_OP_EQ_DOUBLE
:
1330 case FILTER_OP_NE_DOUBLE
:
1331 case FILTER_OP_GT_DOUBLE
:
1332 case FILTER_OP_LT_DOUBLE
:
1333 case FILTER_OP_GE_DOUBLE
:
1334 case FILTER_OP_LE_DOUBLE
:
1336 reg
[REG_R0
].type
= REG_S64
;
1337 next_pc
+= sizeof(struct binary_op
);
1343 case FILTER_OP_UNARY_PLUS
:
1345 struct unary_op
*insn
= (struct unary_op
*) pc
;
1347 switch(reg
[insn
->reg
].type
) {
1349 ERR("unknown register type\n");
1354 insn
->op
= FILTER_OP_UNARY_PLUS_S64
;
1357 insn
->op
= FILTER_OP_UNARY_PLUS_DOUBLE
;
1363 case FILTER_OP_UNARY_MINUS
:
1365 struct unary_op
*insn
= (struct unary_op
*) pc
;
1367 switch(reg
[insn
->reg
].type
) {
1369 ERR("unknown register type\n");
1374 insn
->op
= FILTER_OP_UNARY_MINUS_S64
;
1377 insn
->op
= FILTER_OP_UNARY_MINUS_DOUBLE
;
1383 case FILTER_OP_UNARY_NOT
:
1385 struct unary_op
*insn
= (struct unary_op
*) pc
;
1387 switch(reg
[insn
->reg
].type
) {
1389 ERR("unknown register type\n");
1394 insn
->op
= FILTER_OP_UNARY_NOT_S64
;
1397 insn
->op
= FILTER_OP_UNARY_NOT_DOUBLE
;
1403 case FILTER_OP_UNARY_PLUS_S64
:
1404 case FILTER_OP_UNARY_MINUS_S64
:
1405 case FILTER_OP_UNARY_NOT_S64
:
1406 case FILTER_OP_UNARY_PLUS_DOUBLE
:
1407 case FILTER_OP_UNARY_MINUS_DOUBLE
:
1408 case FILTER_OP_UNARY_NOT_DOUBLE
:
1410 next_pc
+= sizeof(struct unary_op
);
1418 next_pc
+= sizeof(struct logical_op
);
1423 case FILTER_OP_LOAD_FIELD_REF
:
1425 ERR("Unknown field ref type\n");
1429 case FILTER_OP_LOAD_FIELD_REF_STRING
:
1430 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
1432 struct load_op
*insn
= (struct load_op
*) pc
;
1434 reg
[insn
->reg
].type
= REG_STRING
;
1435 reg
[insn
->reg
].literal
= 0;
1436 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1439 case FILTER_OP_LOAD_FIELD_REF_S64
:
1441 struct load_op
*insn
= (struct load_op
*) pc
;
1443 reg
[insn
->reg
].type
= REG_S64
;
1444 reg
[insn
->reg
].literal
= 0;
1445 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1448 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
1450 struct load_op
*insn
= (struct load_op
*) pc
;
1452 reg
[insn
->reg
].type
= REG_DOUBLE
;
1453 reg
[insn
->reg
].literal
= 0;
1454 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1458 case FILTER_OP_LOAD_STRING
:
1460 struct load_op
*insn
= (struct load_op
*) pc
;
1462 reg
[insn
->reg
].type
= REG_STRING
;
1463 reg
[insn
->reg
].literal
= 1;
1464 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1468 case FILTER_OP_LOAD_S64
:
1470 struct load_op
*insn
= (struct load_op
*) pc
;
1472 reg
[insn
->reg
].type
= REG_S64
;
1473 reg
[insn
->reg
].literal
= 1;
1474 next_pc
+= sizeof(struct load_op
)
1475 + sizeof(struct literal_numeric
);
1479 case FILTER_OP_LOAD_DOUBLE
:
1481 struct load_op
*insn
= (struct load_op
*) pc
;
1483 reg
[insn
->reg
].type
= REG_DOUBLE
;
1484 reg
[insn
->reg
].literal
= 1;
1485 next_pc
+= sizeof(struct load_op
)
1486 + sizeof(struct literal_double
);
1498 int apply_field_reloc(struct ltt_event
*event
,
1499 struct bytecode_runtime
*runtime
,
1500 uint32_t runtime_len
,
1501 uint32_t reloc_offset
,
1502 const char *field_name
)
1504 const struct lttng_event_desc
*desc
;
1505 const struct lttng_event_field
*fields
, *field
= NULL
;
1506 unsigned int nr_fields
, i
;
1507 struct field_ref
*field_ref
;
1509 uint32_t field_offset
= 0;
1511 dbg_printf("Apply reloc: %u %s\n", reloc_offset
, field_name
);
1513 /* Ensure that the reloc is within the code */
1514 if (runtime_len
- reloc_offset
< sizeof(uint16_t))
1517 /* Lookup event by name */
1521 fields
= desc
->fields
;
1524 nr_fields
= desc
->nr_fields
;
1525 for (i
= 0; i
< nr_fields
; i
++) {
1526 if (!strcmp(fields
[i
].name
, field_name
)) {
1530 /* compute field offset */
1531 switch (fields
[i
].type
.atype
) {
1534 field_offset
+= sizeof(int64_t);
1537 case atype_sequence
:
1538 field_offset
+= sizeof(unsigned long);
1539 field_offset
+= sizeof(void *);
1542 field_offset
+= sizeof(void *);
1545 field_offset
+= sizeof(double);
1554 /* Check if field offset is too large for 16-bit offset */
1555 if (field_offset
> FILTER_BYTECODE_MAX_LEN
)
1559 op
= (struct load_op
*) &runtime
->data
[reloc_offset
];
1560 field_ref
= (struct field_ref
*) op
->data
;
1561 switch (field
->type
.atype
) {
1564 op
->op
= FILTER_OP_LOAD_FIELD_REF_S64
;
1567 case atype_sequence
:
1568 op
->op
= FILTER_OP_LOAD_FIELD_REF_SEQUENCE
;
1571 op
->op
= FILTER_OP_LOAD_FIELD_REF_STRING
;
1574 op
->op
= FILTER_OP_LOAD_FIELD_REF_DOUBLE
;
1580 field_ref
->offset
= (uint16_t) field_offset
;
1585 * Take a bytecode with reloc table and link it to an event to create a
1589 int _lttng_filter_event_link_bytecode(struct ltt_event
*event
,
1590 struct lttng_ust_filter_bytecode
*filter_bytecode
)
1592 int ret
, offset
, next_offset
;
1593 struct bytecode_runtime
*runtime
= NULL
;
1594 size_t runtime_alloc_len
;
1596 if (!filter_bytecode
)
1598 /* Even is not connected to any description */
1601 /* Bytecode already linked */
1602 if (event
->filter
|| event
->filter_data
)
1605 dbg_printf("Linking\n");
1607 /* We don't need the reloc table in the runtime */
1608 runtime_alloc_len
= sizeof(*runtime
) + filter_bytecode
->reloc_offset
;
1609 runtime
= zmalloc(runtime_alloc_len
);
1614 runtime
->len
= filter_bytecode
->reloc_offset
;
1615 /* copy original bytecode */
1616 memcpy(runtime
->data
, filter_bytecode
->data
, runtime
->len
);
1618 * apply relocs. Those are a uint16_t (offset in bytecode)
1619 * followed by a string (field name).
1621 for (offset
= filter_bytecode
->reloc_offset
;
1622 offset
< filter_bytecode
->len
;
1623 offset
= next_offset
) {
1624 uint16_t reloc_offset
=
1625 *(uint16_t *) &filter_bytecode
->data
[offset
];
1626 const char *field_name
=
1627 (const char *) &filter_bytecode
->data
[offset
+ sizeof(uint16_t)];
1629 ret
= apply_field_reloc(event
, runtime
, runtime
->len
, reloc_offset
, field_name
);
1633 next_offset
= offset
+ sizeof(uint16_t) + strlen(field_name
) + 1;
1635 /* Validate bytecode */
1636 ret
= lttng_filter_validate_bytecode(runtime
);
1640 /* Specialize bytecode */
1641 ret
= lttng_filter_specialize_bytecode(runtime
);
1645 event
->filter_data
= runtime
;
1646 event
->filter
= lttng_filter_interpret_bytecode
;
1650 event
->filter
= lttng_filter_false
;
1655 void lttng_filter_event_link_bytecode(struct ltt_event
*event
,
1656 struct lttng_ust_filter_bytecode
*filter_bytecode
)
1660 ret
= _lttng_filter_event_link_bytecode(event
, filter_bytecode
);
1662 fprintf(stderr
, "[lttng filter] error linking event bytecode\n");
1667 * Link bytecode to all events for a wildcard. Skips events that already
1668 * have a bytecode linked.
1669 * We do not set each event's filter_bytecode field, because they do not
1670 * own the filter_bytecode: the wildcard owns it.
1672 void lttng_filter_wildcard_link_bytecode(struct session_wildcard
*wildcard
)
1674 struct ltt_event
*event
;
1677 if (!wildcard
->filter_bytecode
)
1680 cds_list_for_each_entry(event
, &wildcard
->events
, wildcard_list
) {
1683 ret
= _lttng_filter_event_link_bytecode(event
,
1684 wildcard
->filter_bytecode
);
1686 fprintf(stderr
, "[lttng filter] error linking wildcard bytecode\n");
1694 * Need to attach filter to an event before starting tracing for the
1695 * session. We own the filter_bytecode if we return success.
1697 int lttng_filter_event_attach_bytecode(struct ltt_event
*event
,
1698 struct lttng_ust_filter_bytecode
*filter_bytecode
)
1700 if (event
->chan
->session
->been_active
)
1702 if (event
->filter_bytecode
)
1704 event
->filter_bytecode
= filter_bytecode
;
1709 * Need to attach filter to a wildcard before starting tracing for the
1710 * session. We own the filter_bytecode if we return success.
1712 int lttng_filter_wildcard_attach_bytecode(struct session_wildcard
*wildcard
,
1713 struct lttng_ust_filter_bytecode
*filter_bytecode
)
1715 if (wildcard
->chan
->session
->been_active
)
1717 if (wildcard
->filter_bytecode
)
1719 wildcard
->filter_bytecode
= filter_bytecode
;