2 * lttng-filter-interpreter.c
4 * LTTng UST filter interpreter.
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include <urcu-pointer.h>
29 #include "lttng-filter.h"
33 * -2: unknown escape char.
38 int parse_char(const char **p
)
58 int stack_strcmp(struct estack
*stack
, int top
, const char *cmp_type
)
60 const char *p
= estack_bx(stack
, top
)->u
.s
.str
, *q
= estack_ax(stack
, top
)->u
.s
.str
;
67 if (unlikely(p
- estack_bx(stack
, top
)->u
.s
.str
>= estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0')) {
68 if (q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0') {
71 if (estack_ax(stack
, top
)->u
.s
.literal
) {
79 if (unlikely(q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0')) {
80 if (estack_bx(stack
, top
)->u
.s
.literal
) {
87 if (estack_bx(stack
, top
)->u
.s
.literal
) {
91 } else if (ret
== -2) {
94 /* else compare both char */
96 if (estack_ax(stack
, top
)->u
.s
.literal
) {
100 } else if (ret
== -2) {
120 uint64_t lttng_filter_false(void *filter_data
,
121 const char *filter_stack_data
)
126 #ifdef INTERPRETER_USE_SWITCH
129 * Fallback for compilers that do not support taking address of labels.
133 start_pc = &bytecode->data[0]; \
134 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
136 dbg_printf("Executing op %s (%u)\n", \
137 print_op((unsigned int) *(filter_opcode_t *) pc), \
138 (unsigned int) *(filter_opcode_t *) pc); \
139 switch (*(filter_opcode_t *) pc) {
141 #define OP(name) jump_target_##name: __attribute__((unused)); \
149 #define JUMP_TO(name) \
150 goto jump_target_##name
155 * Dispatch-table based interpreter.
159 start_pc = &bytecode->data[0]; \
160 pc = next_pc = start_pc; \
161 if (unlikely(pc - start_pc >= bytecode->len)) \
163 goto *dispatch[*(filter_opcode_t *) pc];
170 goto *dispatch[*(filter_opcode_t *) pc];
174 #define JUMP_TO(name) \
180 * Return 0 (discard), or raise the 0x1 flag (log event).
181 * Currently, other flags are kept for future extensions and have no
184 uint64_t lttng_filter_interpret_bytecode(void *filter_data
,
185 const char *filter_stack_data
)
187 struct bytecode_runtime
*bytecode
= filter_data
;
188 struct lttng_session
*session
= bytecode
->p
.session
;
189 void *pc
, *next_pc
, *start_pc
;
192 struct estack _stack
;
193 struct estack
*stack
= &_stack
;
194 register int64_t ax
= 0, bx
= 0;
195 register enum entry_type ax_t
= REG_UNKNOWN
, bx_t
= REG_UNKNOWN
;
196 register int top
= FILTER_STACK_EMPTY
;
197 #ifndef INTERPRETER_USE_SWITCH
198 static void *dispatch
[NR_FILTER_OPS
] = {
199 [ FILTER_OP_UNKNOWN
] = &&LABEL_FILTER_OP_UNKNOWN
,
201 [ FILTER_OP_RETURN
] = &&LABEL_FILTER_OP_RETURN
,
204 [ FILTER_OP_MUL
] = &&LABEL_FILTER_OP_MUL
,
205 [ FILTER_OP_DIV
] = &&LABEL_FILTER_OP_DIV
,
206 [ FILTER_OP_MOD
] = &&LABEL_FILTER_OP_MOD
,
207 [ FILTER_OP_PLUS
] = &&LABEL_FILTER_OP_PLUS
,
208 [ FILTER_OP_MINUS
] = &&LABEL_FILTER_OP_MINUS
,
209 [ FILTER_OP_RSHIFT
] = &&LABEL_FILTER_OP_RSHIFT
,
210 [ FILTER_OP_LSHIFT
] = &&LABEL_FILTER_OP_LSHIFT
,
211 [ FILTER_OP_BIN_AND
] = &&LABEL_FILTER_OP_BIN_AND
,
212 [ FILTER_OP_BIN_OR
] = &&LABEL_FILTER_OP_BIN_OR
,
213 [ FILTER_OP_BIN_XOR
] = &&LABEL_FILTER_OP_BIN_XOR
,
215 /* binary comparators */
216 [ FILTER_OP_EQ
] = &&LABEL_FILTER_OP_EQ
,
217 [ FILTER_OP_NE
] = &&LABEL_FILTER_OP_NE
,
218 [ FILTER_OP_GT
] = &&LABEL_FILTER_OP_GT
,
219 [ FILTER_OP_LT
] = &&LABEL_FILTER_OP_LT
,
220 [ FILTER_OP_GE
] = &&LABEL_FILTER_OP_GE
,
221 [ FILTER_OP_LE
] = &&LABEL_FILTER_OP_LE
,
223 /* string binary comparator */
224 [ FILTER_OP_EQ_STRING
] = &&LABEL_FILTER_OP_EQ_STRING
,
225 [ FILTER_OP_NE_STRING
] = &&LABEL_FILTER_OP_NE_STRING
,
226 [ FILTER_OP_GT_STRING
] = &&LABEL_FILTER_OP_GT_STRING
,
227 [ FILTER_OP_LT_STRING
] = &&LABEL_FILTER_OP_LT_STRING
,
228 [ FILTER_OP_GE_STRING
] = &&LABEL_FILTER_OP_GE_STRING
,
229 [ FILTER_OP_LE_STRING
] = &&LABEL_FILTER_OP_LE_STRING
,
231 /* s64 binary comparator */
232 [ FILTER_OP_EQ_S64
] = &&LABEL_FILTER_OP_EQ_S64
,
233 [ FILTER_OP_NE_S64
] = &&LABEL_FILTER_OP_NE_S64
,
234 [ FILTER_OP_GT_S64
] = &&LABEL_FILTER_OP_GT_S64
,
235 [ FILTER_OP_LT_S64
] = &&LABEL_FILTER_OP_LT_S64
,
236 [ FILTER_OP_GE_S64
] = &&LABEL_FILTER_OP_GE_S64
,
237 [ FILTER_OP_LE_S64
] = &&LABEL_FILTER_OP_LE_S64
,
239 /* double binary comparator */
240 [ FILTER_OP_EQ_DOUBLE
] = &&LABEL_FILTER_OP_EQ_DOUBLE
,
241 [ FILTER_OP_NE_DOUBLE
] = &&LABEL_FILTER_OP_NE_DOUBLE
,
242 [ FILTER_OP_GT_DOUBLE
] = &&LABEL_FILTER_OP_GT_DOUBLE
,
243 [ FILTER_OP_LT_DOUBLE
] = &&LABEL_FILTER_OP_LT_DOUBLE
,
244 [ FILTER_OP_GE_DOUBLE
] = &&LABEL_FILTER_OP_GE_DOUBLE
,
245 [ FILTER_OP_LE_DOUBLE
] = &&LABEL_FILTER_OP_LE_DOUBLE
,
247 /* Mixed S64-double binary comparators */
248 [ FILTER_OP_EQ_DOUBLE_S64
] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64
,
249 [ FILTER_OP_NE_DOUBLE_S64
] = &&LABEL_FILTER_OP_NE_DOUBLE_S64
,
250 [ FILTER_OP_GT_DOUBLE_S64
] = &&LABEL_FILTER_OP_GT_DOUBLE_S64
,
251 [ FILTER_OP_LT_DOUBLE_S64
] = &&LABEL_FILTER_OP_LT_DOUBLE_S64
,
252 [ FILTER_OP_GE_DOUBLE_S64
] = &&LABEL_FILTER_OP_GE_DOUBLE_S64
,
253 [ FILTER_OP_LE_DOUBLE_S64
] = &&LABEL_FILTER_OP_LE_DOUBLE_S64
,
255 [ FILTER_OP_EQ_S64_DOUBLE
] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE
,
256 [ FILTER_OP_NE_S64_DOUBLE
] = &&LABEL_FILTER_OP_NE_S64_DOUBLE
,
257 [ FILTER_OP_GT_S64_DOUBLE
] = &&LABEL_FILTER_OP_GT_S64_DOUBLE
,
258 [ FILTER_OP_LT_S64_DOUBLE
] = &&LABEL_FILTER_OP_LT_S64_DOUBLE
,
259 [ FILTER_OP_GE_S64_DOUBLE
] = &&LABEL_FILTER_OP_GE_S64_DOUBLE
,
260 [ FILTER_OP_LE_S64_DOUBLE
] = &&LABEL_FILTER_OP_LE_S64_DOUBLE
,
263 [ FILTER_OP_UNARY_PLUS
] = &&LABEL_FILTER_OP_UNARY_PLUS
,
264 [ FILTER_OP_UNARY_MINUS
] = &&LABEL_FILTER_OP_UNARY_MINUS
,
265 [ FILTER_OP_UNARY_NOT
] = &&LABEL_FILTER_OP_UNARY_NOT
,
266 [ FILTER_OP_UNARY_PLUS_S64
] = &&LABEL_FILTER_OP_UNARY_PLUS_S64
,
267 [ FILTER_OP_UNARY_MINUS_S64
] = &&LABEL_FILTER_OP_UNARY_MINUS_S64
,
268 [ FILTER_OP_UNARY_NOT_S64
] = &&LABEL_FILTER_OP_UNARY_NOT_S64
,
269 [ FILTER_OP_UNARY_PLUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE
,
270 [ FILTER_OP_UNARY_MINUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE
,
271 [ FILTER_OP_UNARY_NOT_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE
,
274 [ FILTER_OP_AND
] = &&LABEL_FILTER_OP_AND
,
275 [ FILTER_OP_OR
] = &&LABEL_FILTER_OP_OR
,
278 [ FILTER_OP_LOAD_FIELD_REF
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF
,
279 [ FILTER_OP_LOAD_FIELD_REF_STRING
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING
,
280 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE
,
281 [ FILTER_OP_LOAD_FIELD_REF_S64
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64
,
282 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE
,
284 /* load from immediate operand */
285 [ FILTER_OP_LOAD_STRING
] = &&LABEL_FILTER_OP_LOAD_STRING
,
286 [ FILTER_OP_LOAD_S64
] = &&LABEL_FILTER_OP_LOAD_S64
,
287 [ FILTER_OP_LOAD_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_DOUBLE
,
290 [ FILTER_OP_CAST_TO_S64
] = &&LABEL_FILTER_OP_CAST_TO_S64
,
291 [ FILTER_OP_CAST_DOUBLE_TO_S64
] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64
,
292 [ FILTER_OP_CAST_NOP
] = &&LABEL_FILTER_OP_CAST_NOP
,
294 /* get context ref */
295 [ FILTER_OP_GET_CONTEXT_REF
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF
,
296 [ FILTER_OP_GET_CONTEXT_REF_STRING
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING
,
297 [ FILTER_OP_GET_CONTEXT_REF_S64
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64
,
298 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE
,
300 #endif /* #ifndef INTERPRETER_USE_SWITCH */
304 OP(FILTER_OP_UNKNOWN
):
305 OP(FILTER_OP_LOAD_FIELD_REF
):
306 #ifdef INTERPRETER_USE_SWITCH
308 #endif /* INTERPRETER_USE_SWITCH */
309 ERR("unknown bytecode op %u\n",
310 (unsigned int) *(filter_opcode_t
*) pc
);
314 OP(FILTER_OP_RETURN
):
315 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
316 retval
= !!estack_ax_v
;
326 OP(FILTER_OP_RSHIFT
):
327 OP(FILTER_OP_LSHIFT
):
328 OP(FILTER_OP_BIN_AND
):
329 OP(FILTER_OP_BIN_OR
):
330 OP(FILTER_OP_BIN_XOR
):
331 ERR("unsupported bytecode op %u\n",
332 (unsigned int) *(filter_opcode_t
*) pc
);
338 /* Dynamic typing. */
339 switch (estack_ax_t
) {
341 switch (estack_bx_t
) {
343 JUMP_TO(FILTER_OP_EQ_S64
);
345 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64
);
350 ERR("Unknown filter register type (%d)",
357 switch (estack_bx_t
) {
359 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE
);
361 JUMP_TO(FILTER_OP_EQ_DOUBLE
);
366 ERR("Unknown filter register type (%d)",
373 switch (estack_bx_t
) {
374 case REG_S64
: /* Fall-through */
379 JUMP_TO(FILTER_OP_EQ_STRING
);
381 ERR("Unknown filter register type (%d)",
388 ERR("Unknown filter register type (%d)",
396 /* Dynamic typing. */
397 switch (estack_ax_t
) {
399 switch (estack_bx_t
) {
401 JUMP_TO(FILTER_OP_NE_S64
);
403 JUMP_TO(FILTER_OP_NE_DOUBLE_S64
);
408 ERR("Unknown filter register type (%d)",
415 switch (estack_bx_t
) {
417 JUMP_TO(FILTER_OP_NE_S64_DOUBLE
);
419 JUMP_TO(FILTER_OP_NE_DOUBLE
);
424 ERR("Unknown filter register type (%d)",
431 switch (estack_bx_t
) {
432 case REG_S64
: /* Fall-through */
437 JUMP_TO(FILTER_OP_NE_STRING
);
439 ERR("Unknown filter register type (%d)",
446 ERR("Unknown filter register type (%d)",
454 /* Dynamic typing. */
455 switch (estack_ax_t
) {
457 switch (estack_bx_t
) {
459 JUMP_TO(FILTER_OP_GT_S64
);
461 JUMP_TO(FILTER_OP_GT_DOUBLE_S64
);
466 ERR("Unknown filter register type (%d)",
473 switch (estack_bx_t
) {
475 JUMP_TO(FILTER_OP_GT_S64_DOUBLE
);
477 JUMP_TO(FILTER_OP_GT_DOUBLE
);
482 ERR("Unknown filter register type (%d)",
489 switch (estack_bx_t
) {
490 case REG_S64
: /* Fall-through */
495 JUMP_TO(FILTER_OP_GT_STRING
);
497 ERR("Unknown filter register type (%d)",
504 ERR("Unknown filter register type (%d)",
512 /* Dynamic typing. */
513 switch (estack_ax_t
) {
515 switch (estack_bx_t
) {
517 JUMP_TO(FILTER_OP_LT_S64
);
519 JUMP_TO(FILTER_OP_LT_DOUBLE_S64
);
524 ERR("Unknown filter register type (%d)",
531 switch (estack_bx_t
) {
533 JUMP_TO(FILTER_OP_LT_S64_DOUBLE
);
535 JUMP_TO(FILTER_OP_LT_DOUBLE
);
540 ERR("Unknown filter register type (%d)",
547 switch (estack_bx_t
) {
548 case REG_S64
: /* Fall-through */
553 JUMP_TO(FILTER_OP_LT_STRING
);
555 ERR("Unknown filter register type (%d)",
562 ERR("Unknown filter register type (%d)",
570 /* Dynamic typing. */
571 switch (estack_ax_t
) {
573 switch (estack_bx_t
) {
575 JUMP_TO(FILTER_OP_GE_S64
);
577 JUMP_TO(FILTER_OP_GE_DOUBLE_S64
);
582 ERR("Unknown filter register type (%d)",
589 switch (estack_bx_t
) {
591 JUMP_TO(FILTER_OP_GE_S64_DOUBLE
);
593 JUMP_TO(FILTER_OP_GE_DOUBLE
);
598 ERR("Unknown filter register type (%d)",
605 switch (estack_bx_t
) {
606 case REG_S64
: /* Fall-through */
611 JUMP_TO(FILTER_OP_GE_STRING
);
613 ERR("Unknown filter register type (%d)",
620 ERR("Unknown filter register type (%d)",
628 /* Dynamic typing. */
629 switch (estack_ax_t
) {
631 switch (estack_bx_t
) {
633 JUMP_TO(FILTER_OP_LE_S64
);
635 JUMP_TO(FILTER_OP_LE_DOUBLE_S64
);
640 ERR("Unknown filter register type (%d)",
647 switch (estack_bx_t
) {
649 JUMP_TO(FILTER_OP_LE_S64_DOUBLE
);
651 JUMP_TO(FILTER_OP_LE_DOUBLE
);
656 ERR("Unknown filter register type (%d)",
663 switch (estack_bx_t
) {
664 case REG_S64
: /* Fall-through */
669 JUMP_TO(FILTER_OP_LE_STRING
);
671 ERR("Unknown filter register type (%d)",
678 ERR("Unknown filter register type (%d)",
685 OP(FILTER_OP_EQ_STRING
):
689 res
= (stack_strcmp(stack
, top
, "==") == 0);
690 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
692 estack_ax_t
= REG_S64
;
693 next_pc
+= sizeof(struct binary_op
);
696 OP(FILTER_OP_NE_STRING
):
700 res
= (stack_strcmp(stack
, top
, "!=") != 0);
701 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
703 estack_ax_t
= REG_S64
;
704 next_pc
+= sizeof(struct binary_op
);
707 OP(FILTER_OP_GT_STRING
):
711 res
= (stack_strcmp(stack
, top
, ">") > 0);
712 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
714 estack_ax_t
= REG_S64
;
715 next_pc
+= sizeof(struct binary_op
);
718 OP(FILTER_OP_LT_STRING
):
722 res
= (stack_strcmp(stack
, top
, "<") < 0);
723 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
725 estack_ax_t
= REG_S64
;
726 next_pc
+= sizeof(struct binary_op
);
729 OP(FILTER_OP_GE_STRING
):
733 res
= (stack_strcmp(stack
, top
, ">=") >= 0);
734 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
736 estack_ax_t
= REG_S64
;
737 next_pc
+= sizeof(struct binary_op
);
740 OP(FILTER_OP_LE_STRING
):
744 res
= (stack_strcmp(stack
, top
, "<=") <= 0);
745 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
747 estack_ax_t
= REG_S64
;
748 next_pc
+= sizeof(struct binary_op
);
752 OP(FILTER_OP_EQ_S64
):
756 res
= (estack_bx_v
== estack_ax_v
);
757 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
759 estack_ax_t
= REG_S64
;
760 next_pc
+= sizeof(struct binary_op
);
763 OP(FILTER_OP_NE_S64
):
767 res
= (estack_bx_v
!= estack_ax_v
);
768 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
770 estack_ax_t
= REG_S64
;
771 next_pc
+= sizeof(struct binary_op
);
774 OP(FILTER_OP_GT_S64
):
778 res
= (estack_bx_v
> estack_ax_v
);
779 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
781 estack_ax_t
= REG_S64
;
782 next_pc
+= sizeof(struct binary_op
);
785 OP(FILTER_OP_LT_S64
):
789 res
= (estack_bx_v
< estack_ax_v
);
790 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
792 estack_ax_t
= REG_S64
;
793 next_pc
+= sizeof(struct binary_op
);
796 OP(FILTER_OP_GE_S64
):
800 res
= (estack_bx_v
>= estack_ax_v
);
801 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
803 estack_ax_t
= REG_S64
;
804 next_pc
+= sizeof(struct binary_op
);
807 OP(FILTER_OP_LE_S64
):
811 res
= (estack_bx_v
<= estack_ax_v
);
812 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
814 estack_ax_t
= REG_S64
;
815 next_pc
+= sizeof(struct binary_op
);
819 OP(FILTER_OP_EQ_DOUBLE
):
823 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax(stack
, top
)->u
.d
);
824 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
826 estack_ax_t
= REG_S64
;
827 next_pc
+= sizeof(struct binary_op
);
830 OP(FILTER_OP_NE_DOUBLE
):
834 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax(stack
, top
)->u
.d
);
835 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
837 estack_ax_t
= REG_S64
;
838 next_pc
+= sizeof(struct binary_op
);
841 OP(FILTER_OP_GT_DOUBLE
):
845 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax(stack
, top
)->u
.d
);
846 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
848 estack_ax_t
= REG_S64
;
849 next_pc
+= sizeof(struct binary_op
);
852 OP(FILTER_OP_LT_DOUBLE
):
856 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax(stack
, top
)->u
.d
);
857 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
859 estack_ax_t
= REG_S64
;
860 next_pc
+= sizeof(struct binary_op
);
863 OP(FILTER_OP_GE_DOUBLE
):
867 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax(stack
, top
)->u
.d
);
868 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
870 estack_ax_t
= REG_S64
;
871 next_pc
+= sizeof(struct binary_op
);
874 OP(FILTER_OP_LE_DOUBLE
):
878 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax(stack
, top
)->u
.d
);
879 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
881 estack_ax_t
= REG_S64
;
882 next_pc
+= sizeof(struct binary_op
);
886 /* Mixed S64-double binary comparators */
887 OP(FILTER_OP_EQ_DOUBLE_S64
):
891 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax_v
);
892 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
894 estack_ax_t
= REG_S64
;
895 next_pc
+= sizeof(struct binary_op
);
898 OP(FILTER_OP_NE_DOUBLE_S64
):
902 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax_v
);
903 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
905 estack_ax_t
= REG_S64
;
906 next_pc
+= sizeof(struct binary_op
);
909 OP(FILTER_OP_GT_DOUBLE_S64
):
913 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax_v
);
914 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
916 estack_ax_t
= REG_S64
;
917 next_pc
+= sizeof(struct binary_op
);
920 OP(FILTER_OP_LT_DOUBLE_S64
):
924 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax_v
);
925 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
927 estack_ax_t
= REG_S64
;
928 next_pc
+= sizeof(struct binary_op
);
931 OP(FILTER_OP_GE_DOUBLE_S64
):
935 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax_v
);
936 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
938 estack_ax_t
= REG_S64
;
939 next_pc
+= sizeof(struct binary_op
);
942 OP(FILTER_OP_LE_DOUBLE_S64
):
946 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax_v
);
947 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
949 estack_ax_t
= REG_S64
;
950 next_pc
+= sizeof(struct binary_op
);
954 OP(FILTER_OP_EQ_S64_DOUBLE
):
958 res
= (estack_bx_v
== estack_ax(stack
, top
)->u
.d
);
959 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
961 estack_ax_t
= REG_S64
;
962 next_pc
+= sizeof(struct binary_op
);
965 OP(FILTER_OP_NE_S64_DOUBLE
):
969 res
= (estack_bx_v
!= estack_ax(stack
, top
)->u
.d
);
970 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
972 estack_ax_t
= REG_S64
;
973 next_pc
+= sizeof(struct binary_op
);
976 OP(FILTER_OP_GT_S64_DOUBLE
):
980 res
= (estack_bx_v
> estack_ax(stack
, top
)->u
.d
);
981 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
983 estack_ax_t
= REG_S64
;
984 next_pc
+= sizeof(struct binary_op
);
987 OP(FILTER_OP_LT_S64_DOUBLE
):
991 res
= (estack_bx_v
< estack_ax(stack
, top
)->u
.d
);
992 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
994 estack_ax_t
= REG_S64
;
995 next_pc
+= sizeof(struct binary_op
);
998 OP(FILTER_OP_GE_S64_DOUBLE
):
1002 res
= (estack_bx_v
>= estack_ax(stack
, top
)->u
.d
);
1003 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1005 estack_ax_t
= REG_S64
;
1006 next_pc
+= sizeof(struct binary_op
);
1009 OP(FILTER_OP_LE_S64_DOUBLE
):
1013 res
= (estack_bx_v
<= estack_ax(stack
, top
)->u
.d
);
1014 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1016 estack_ax_t
= REG_S64
;
1017 next_pc
+= sizeof(struct binary_op
);
1022 OP(FILTER_OP_UNARY_PLUS
):
1024 /* Dynamic typing. */
1025 switch (estack_ax_t
) {
1026 case REG_S64
: /* Fall-through. */
1027 JUMP_TO(FILTER_OP_UNARY_PLUS_S64
);
1029 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE
);
1034 ERR("Unknown filter register type (%d)",
1040 OP(FILTER_OP_UNARY_MINUS
):
1042 /* Dynamic typing. */
1043 switch (estack_ax_t
) {
1045 JUMP_TO(FILTER_OP_UNARY_MINUS_S64
);
1047 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE
);
1052 ERR("Unknown filter register type (%d)",
1058 OP(FILTER_OP_UNARY_NOT
):
1060 /* Dynamic typing. */
1061 switch (estack_ax_t
) {
1063 JUMP_TO(FILTER_OP_UNARY_NOT_S64
);
1065 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE
);
1070 ERR("Unknown filter register type (%d)",
1075 next_pc
+= sizeof(struct unary_op
);
1079 OP(FILTER_OP_UNARY_PLUS_S64
):
1080 OP(FILTER_OP_UNARY_PLUS_DOUBLE
):
1082 next_pc
+= sizeof(struct unary_op
);
1085 OP(FILTER_OP_UNARY_MINUS_S64
):
1087 estack_ax_v
= -estack_ax_v
;
1088 next_pc
+= sizeof(struct unary_op
);
1091 OP(FILTER_OP_UNARY_MINUS_DOUBLE
):
1093 estack_ax(stack
, top
)->u
.d
= -estack_ax(stack
, top
)->u
.d
;
1094 next_pc
+= sizeof(struct unary_op
);
1097 OP(FILTER_OP_UNARY_NOT_S64
):
1099 estack_ax_v
= !estack_ax_v
;
1100 next_pc
+= sizeof(struct unary_op
);
1103 OP(FILTER_OP_UNARY_NOT_DOUBLE
):
1105 estack_ax_v
= !estack_ax(stack
, top
)->u
.d
;
1106 estack_ax_t
= REG_S64
;
1107 next_pc
+= sizeof(struct unary_op
);
1114 struct logical_op
*insn
= (struct logical_op
*) pc
;
1116 if (estack_ax_t
!= REG_S64
) {
1120 /* If AX is 0, skip and evaluate to 0 */
1121 if (unlikely(estack_ax_v
== 0)) {
1122 dbg_printf("Jumping to bytecode offset %u\n",
1123 (unsigned int) insn
->skip_offset
);
1124 next_pc
= start_pc
+ insn
->skip_offset
;
1126 /* Pop 1 when jump not taken */
1127 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1128 next_pc
+= sizeof(struct logical_op
);
1134 struct logical_op
*insn
= (struct logical_op
*) pc
;
1136 if (estack_ax_t
!= REG_S64
) {
1140 /* If AX is nonzero, skip and evaluate to 1 */
1141 if (unlikely(estack_ax_v
!= 0)) {
1143 dbg_printf("Jumping to bytecode offset %u\n",
1144 (unsigned int) insn
->skip_offset
);
1145 next_pc
= start_pc
+ insn
->skip_offset
;
1147 /* Pop 1 when jump not taken */
1148 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1149 next_pc
+= sizeof(struct logical_op
);
1155 /* load field ref */
1156 OP(FILTER_OP_LOAD_FIELD_REF_STRING
):
1158 struct load_op
*insn
= (struct load_op
*) pc
;
1159 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1161 dbg_printf("load field ref offset %u type string\n",
1163 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1164 estack_ax(stack
, top
)->u
.s
.str
=
1165 *(const char * const *) &filter_stack_data
[ref
->offset
];
1166 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1167 dbg_printf("Filter warning: loading a NULL string.\n");
1171 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1172 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1173 estack_ax_t
= REG_STRING
;
1174 dbg_printf("ref load string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1175 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1179 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE
):
1181 struct load_op
*insn
= (struct load_op
*) pc
;
1182 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1184 dbg_printf("load field ref offset %u type sequence\n",
1186 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1187 estack_ax(stack
, top
)->u
.s
.seq_len
=
1188 *(unsigned long *) &filter_stack_data
[ref
->offset
];
1189 estack_ax(stack
, top
)->u
.s
.str
=
1190 *(const char **) (&filter_stack_data
[ref
->offset
1191 + sizeof(unsigned long)]);
1192 estack_ax_t
= REG_STRING
;
1193 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1194 dbg_printf("Filter warning: loading a NULL sequence.\n");
1198 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1199 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1203 OP(FILTER_OP_LOAD_FIELD_REF_S64
):
1205 struct load_op
*insn
= (struct load_op
*) pc
;
1206 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1208 dbg_printf("load field ref offset %u type s64\n",
1210 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1212 ((struct literal_numeric
*) &filter_stack_data
[ref
->offset
])->v
;
1213 estack_ax_t
= REG_S64
;
1214 dbg_printf("ref load s64 %" PRIi64
"\n", estack_ax_v
);
1215 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1219 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE
):
1221 struct load_op
*insn
= (struct load_op
*) pc
;
1222 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1224 dbg_printf("load field ref offset %u type double\n",
1226 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1227 memcpy(&estack_ax(stack
, top
)->u
.d
, &filter_stack_data
[ref
->offset
],
1228 sizeof(struct literal_double
));
1229 estack_ax_t
= REG_DOUBLE
;
1230 dbg_printf("ref load double %g\n", estack_ax(stack
, top
)->u
.d
);
1231 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1235 /* load from immediate operand */
1236 OP(FILTER_OP_LOAD_STRING
):
1238 struct load_op
*insn
= (struct load_op
*) pc
;
1240 dbg_printf("load string %s\n", insn
->data
);
1241 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1242 estack_ax(stack
, top
)->u
.s
.str
= insn
->data
;
1243 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1244 estack_ax(stack
, top
)->u
.s
.literal
= 1;
1245 estack_ax_t
= REG_STRING
;
1246 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1250 OP(FILTER_OP_LOAD_S64
):
1252 struct load_op
*insn
= (struct load_op
*) pc
;
1254 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1255 estack_ax_v
= ((struct literal_numeric
*) insn
->data
)->v
;
1256 estack_ax_t
= REG_S64
;
1257 dbg_printf("load s64 %" PRIi64
"\n", estack_ax_v
);
1258 next_pc
+= sizeof(struct load_op
)
1259 + sizeof(struct literal_numeric
);
1263 OP(FILTER_OP_LOAD_DOUBLE
):
1265 struct load_op
*insn
= (struct load_op
*) pc
;
1267 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1268 memcpy(&estack_ax(stack
, top
)->u
.d
, insn
->data
,
1269 sizeof(struct literal_double
));
1270 estack_ax_t
= REG_DOUBLE
;
1271 dbg_printf("load double %g\n", estack_ax(stack
, top
)->u
.d
);
1272 next_pc
+= sizeof(struct load_op
)
1273 + sizeof(struct literal_double
);
1278 OP(FILTER_OP_CAST_TO_S64
):
1280 /* Dynamic typing. */
1281 switch (estack_ax_t
) {
1283 JUMP_TO(FILTER_OP_CAST_NOP
);
1285 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64
);
1290 ERR("Unknown filter register type (%d)",
1297 OP(FILTER_OP_CAST_DOUBLE_TO_S64
):
1299 estack_ax_v
= (int64_t) estack_ax(stack
, top
)->u
.d
;
1300 estack_ax_t
= REG_S64
;
1301 next_pc
+= sizeof(struct cast_op
);
1305 OP(FILTER_OP_CAST_NOP
):
1307 next_pc
+= sizeof(struct cast_op
);
1311 /* get context ref */
1312 OP(FILTER_OP_GET_CONTEXT_REF
):
1314 struct load_op
*insn
= (struct load_op
*) pc
;
1315 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1316 struct lttng_ctx
*ctx
;
1317 struct lttng_ctx_field
*ctx_field
;
1318 struct lttng_ctx_value v
;
1320 dbg_printf("get context ref offset %u type dynamic\n",
1322 ctx
= rcu_dereference(session
->ctx
);
1323 ctx_field
= &ctx
->fields
[ref
->offset
];
1324 ctx_field
->get_value(ctx_field
, &v
);
1325 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1327 case LTTNG_UST_DYNAMIC_TYPE_NONE
:
1330 case LTTNG_UST_DYNAMIC_TYPE_S64
:
1331 estack_ax_v
= v
.u
.s64
;
1332 estack_ax_t
= REG_S64
;
1333 dbg_printf("ref get context dynamic s64 %" PRIi64
"\n", estack_ax_v
);
1335 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE
:
1336 estack_ax(stack
, top
)->u
.d
= v
.u
.d
;
1337 estack_ax_t
= REG_DOUBLE
;
1338 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack
, top
)->u
.d
);
1340 case LTTNG_UST_DYNAMIC_TYPE_STRING
:
1341 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1342 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1343 dbg_printf("Filter warning: loading a NULL string.\n");
1347 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1348 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1349 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1350 estack_ax_t
= REG_STRING
;
1353 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v
.sel
);
1357 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1361 OP(FILTER_OP_GET_CONTEXT_REF_STRING
):
1363 struct load_op
*insn
= (struct load_op
*) pc
;
1364 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1365 struct lttng_ctx
*ctx
;
1366 struct lttng_ctx_field
*ctx_field
;
1367 struct lttng_ctx_value v
;
1369 dbg_printf("get context ref offset %u type string\n",
1371 ctx
= rcu_dereference(session
->ctx
);
1372 ctx_field
= &ctx
->fields
[ref
->offset
];
1373 ctx_field
->get_value(ctx_field
, &v
);
1374 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1375 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1376 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1377 dbg_printf("Filter warning: loading a NULL string.\n");
1381 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1382 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1383 estack_ax_t
= REG_STRING
;
1384 dbg_printf("ref get context string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1385 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1389 OP(FILTER_OP_GET_CONTEXT_REF_S64
):
1391 struct load_op
*insn
= (struct load_op
*) pc
;
1392 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1393 struct lttng_ctx
*ctx
;
1394 struct lttng_ctx_field
*ctx_field
;
1395 struct lttng_ctx_value v
;
1397 dbg_printf("get context ref offset %u type s64\n",
1399 ctx
= rcu_dereference(session
->ctx
);
1400 ctx_field
= &ctx
->fields
[ref
->offset
];
1401 ctx_field
->get_value(ctx_field
, &v
);
1402 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1403 estack_ax_v
= v
.u
.s64
;
1404 estack_ax_t
= REG_S64
;
1405 dbg_printf("ref get context s64 %" PRIi64
"\n", estack_ax_v
);
1406 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1410 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE
):
1412 struct load_op
*insn
= (struct load_op
*) pc
;
1413 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1414 struct lttng_ctx
*ctx
;
1415 struct lttng_ctx_field
*ctx_field
;
1416 struct lttng_ctx_value v
;
1418 dbg_printf("get context ref offset %u type double\n",
1420 ctx
= rcu_dereference(session
->ctx
);
1421 ctx_field
= &ctx
->fields
[ref
->offset
];
1422 ctx_field
->get_value(ctx_field
, &v
);
1423 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1424 memcpy(&estack_ax(stack
, top
)->u
.d
, &v
.u
.d
, sizeof(struct literal_double
));
1425 estack_ax_t
= REG_DOUBLE
;
1426 dbg_printf("ref get context double %g\n", estack_ax(stack
, top
)->u
.d
);
1427 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1433 /* return 0 (discard) on error */