2 * lttng-filter-interpreter.c
4 * LTTng UST filter interpreter.
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
23 #include <urcu-pointer.h>
24 #include "lttng-filter.h"
28 * -2: unknown escape char.
33 int parse_char(const char **p
)
53 int stack_strcmp(struct estack
*stack
, int top
, const char *cmp_type
)
55 const char *p
= estack_bx(stack
, top
)->u
.s
.str
, *q
= estack_ax(stack
, top
)->u
.s
.str
;
62 if (unlikely(p
- estack_bx(stack
, top
)->u
.s
.str
>= estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0')) {
63 if (q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0') {
66 if (estack_ax(stack
, top
)->u
.s
.literal
) {
74 if (unlikely(q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0')) {
75 if (estack_bx(stack
, top
)->u
.s
.literal
) {
82 if (estack_bx(stack
, top
)->u
.s
.literal
) {
86 } else if (ret
== -2) {
89 /* else compare both char */
91 if (estack_ax(stack
, top
)->u
.s
.literal
) {
95 } else if (ret
== -2) {
115 uint64_t lttng_filter_false(void *filter_data
,
116 const char *filter_stack_data
)
121 #ifdef INTERPRETER_USE_SWITCH
124 * Fallback for compilers that do not support taking address of labels.
128 start_pc = &bytecode->data[0]; \
129 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
131 dbg_printf("Executing op %s (%u)\n", \
132 print_op((unsigned int) *(filter_opcode_t *) pc), \
133 (unsigned int) *(filter_opcode_t *) pc); \
134 switch (*(filter_opcode_t *) pc) {
136 #define OP(name) jump_target_##name: __attribute__((unused)); \
144 #define JUMP_TO(name) \
145 goto jump_target_##name
150 * Dispatch-table based interpreter.
154 start_pc = &bytecode->data[0]; \
155 pc = next_pc = start_pc; \
156 if (unlikely(pc - start_pc >= bytecode->len)) \
158 goto *dispatch[*(filter_opcode_t *) pc];
165 goto *dispatch[*(filter_opcode_t *) pc];
169 #define JUMP_TO(name) \
175 * Return 0 (discard), or raise the 0x1 flag (log event).
176 * Currently, other flags are kept for future extensions and have no
179 uint64_t lttng_filter_interpret_bytecode(void *filter_data
,
180 const char *filter_stack_data
)
182 struct bytecode_runtime
*bytecode
= filter_data
;
183 struct lttng_session
*session
= bytecode
->p
.session
;
184 void *pc
, *next_pc
, *start_pc
;
187 struct estack _stack
;
188 struct estack
*stack
= &_stack
;
189 register int64_t ax
= 0, bx
= 0;
190 register enum entry_type ax_t
= REG_UNKNOWN
, bx_t
= REG_UNKNOWN
;
191 register int top
= FILTER_STACK_EMPTY
;
192 #ifndef INTERPRETER_USE_SWITCH
193 static void *dispatch
[NR_FILTER_OPS
] = {
194 [ FILTER_OP_UNKNOWN
] = &&LABEL_FILTER_OP_UNKNOWN
,
196 [ FILTER_OP_RETURN
] = &&LABEL_FILTER_OP_RETURN
,
199 [ FILTER_OP_MUL
] = &&LABEL_FILTER_OP_MUL
,
200 [ FILTER_OP_DIV
] = &&LABEL_FILTER_OP_DIV
,
201 [ FILTER_OP_MOD
] = &&LABEL_FILTER_OP_MOD
,
202 [ FILTER_OP_PLUS
] = &&LABEL_FILTER_OP_PLUS
,
203 [ FILTER_OP_MINUS
] = &&LABEL_FILTER_OP_MINUS
,
204 [ FILTER_OP_RSHIFT
] = &&LABEL_FILTER_OP_RSHIFT
,
205 [ FILTER_OP_LSHIFT
] = &&LABEL_FILTER_OP_LSHIFT
,
206 [ FILTER_OP_BIN_AND
] = &&LABEL_FILTER_OP_BIN_AND
,
207 [ FILTER_OP_BIN_OR
] = &&LABEL_FILTER_OP_BIN_OR
,
208 [ FILTER_OP_BIN_XOR
] = &&LABEL_FILTER_OP_BIN_XOR
,
210 /* binary comparators */
211 [ FILTER_OP_EQ
] = &&LABEL_FILTER_OP_EQ
,
212 [ FILTER_OP_NE
] = &&LABEL_FILTER_OP_NE
,
213 [ FILTER_OP_GT
] = &&LABEL_FILTER_OP_GT
,
214 [ FILTER_OP_LT
] = &&LABEL_FILTER_OP_LT
,
215 [ FILTER_OP_GE
] = &&LABEL_FILTER_OP_GE
,
216 [ FILTER_OP_LE
] = &&LABEL_FILTER_OP_LE
,
218 /* string binary comparator */
219 [ FILTER_OP_EQ_STRING
] = &&LABEL_FILTER_OP_EQ_STRING
,
220 [ FILTER_OP_NE_STRING
] = &&LABEL_FILTER_OP_NE_STRING
,
221 [ FILTER_OP_GT_STRING
] = &&LABEL_FILTER_OP_GT_STRING
,
222 [ FILTER_OP_LT_STRING
] = &&LABEL_FILTER_OP_LT_STRING
,
223 [ FILTER_OP_GE_STRING
] = &&LABEL_FILTER_OP_GE_STRING
,
224 [ FILTER_OP_LE_STRING
] = &&LABEL_FILTER_OP_LE_STRING
,
226 /* s64 binary comparator */
227 [ FILTER_OP_EQ_S64
] = &&LABEL_FILTER_OP_EQ_S64
,
228 [ FILTER_OP_NE_S64
] = &&LABEL_FILTER_OP_NE_S64
,
229 [ FILTER_OP_GT_S64
] = &&LABEL_FILTER_OP_GT_S64
,
230 [ FILTER_OP_LT_S64
] = &&LABEL_FILTER_OP_LT_S64
,
231 [ FILTER_OP_GE_S64
] = &&LABEL_FILTER_OP_GE_S64
,
232 [ FILTER_OP_LE_S64
] = &&LABEL_FILTER_OP_LE_S64
,
234 /* double binary comparator */
235 [ FILTER_OP_EQ_DOUBLE
] = &&LABEL_FILTER_OP_EQ_DOUBLE
,
236 [ FILTER_OP_NE_DOUBLE
] = &&LABEL_FILTER_OP_NE_DOUBLE
,
237 [ FILTER_OP_GT_DOUBLE
] = &&LABEL_FILTER_OP_GT_DOUBLE
,
238 [ FILTER_OP_LT_DOUBLE
] = &&LABEL_FILTER_OP_LT_DOUBLE
,
239 [ FILTER_OP_GE_DOUBLE
] = &&LABEL_FILTER_OP_GE_DOUBLE
,
240 [ FILTER_OP_LE_DOUBLE
] = &&LABEL_FILTER_OP_LE_DOUBLE
,
242 /* Mixed S64-double binary comparators */
243 [ FILTER_OP_EQ_DOUBLE_S64
] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64
,
244 [ FILTER_OP_NE_DOUBLE_S64
] = &&LABEL_FILTER_OP_NE_DOUBLE_S64
,
245 [ FILTER_OP_GT_DOUBLE_S64
] = &&LABEL_FILTER_OP_GT_DOUBLE_S64
,
246 [ FILTER_OP_LT_DOUBLE_S64
] = &&LABEL_FILTER_OP_LT_DOUBLE_S64
,
247 [ FILTER_OP_GE_DOUBLE_S64
] = &&LABEL_FILTER_OP_GE_DOUBLE_S64
,
248 [ FILTER_OP_LE_DOUBLE_S64
] = &&LABEL_FILTER_OP_LE_DOUBLE_S64
,
250 [ FILTER_OP_EQ_S64_DOUBLE
] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE
,
251 [ FILTER_OP_NE_S64_DOUBLE
] = &&LABEL_FILTER_OP_NE_S64_DOUBLE
,
252 [ FILTER_OP_GT_S64_DOUBLE
] = &&LABEL_FILTER_OP_GT_S64_DOUBLE
,
253 [ FILTER_OP_LT_S64_DOUBLE
] = &&LABEL_FILTER_OP_LT_S64_DOUBLE
,
254 [ FILTER_OP_GE_S64_DOUBLE
] = &&LABEL_FILTER_OP_GE_S64_DOUBLE
,
255 [ FILTER_OP_LE_S64_DOUBLE
] = &&LABEL_FILTER_OP_LE_S64_DOUBLE
,
258 [ FILTER_OP_UNARY_PLUS
] = &&LABEL_FILTER_OP_UNARY_PLUS
,
259 [ FILTER_OP_UNARY_MINUS
] = &&LABEL_FILTER_OP_UNARY_MINUS
,
260 [ FILTER_OP_UNARY_NOT
] = &&LABEL_FILTER_OP_UNARY_NOT
,
261 [ FILTER_OP_UNARY_PLUS_S64
] = &&LABEL_FILTER_OP_UNARY_PLUS_S64
,
262 [ FILTER_OP_UNARY_MINUS_S64
] = &&LABEL_FILTER_OP_UNARY_MINUS_S64
,
263 [ FILTER_OP_UNARY_NOT_S64
] = &&LABEL_FILTER_OP_UNARY_NOT_S64
,
264 [ FILTER_OP_UNARY_PLUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE
,
265 [ FILTER_OP_UNARY_MINUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE
,
266 [ FILTER_OP_UNARY_NOT_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE
,
269 [ FILTER_OP_AND
] = &&LABEL_FILTER_OP_AND
,
270 [ FILTER_OP_OR
] = &&LABEL_FILTER_OP_OR
,
273 [ FILTER_OP_LOAD_FIELD_REF
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF
,
274 [ FILTER_OP_LOAD_FIELD_REF_STRING
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING
,
275 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE
,
276 [ FILTER_OP_LOAD_FIELD_REF_S64
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64
,
277 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE
,
279 /* load from immediate operand */
280 [ FILTER_OP_LOAD_STRING
] = &&LABEL_FILTER_OP_LOAD_STRING
,
281 [ FILTER_OP_LOAD_S64
] = &&LABEL_FILTER_OP_LOAD_S64
,
282 [ FILTER_OP_LOAD_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_DOUBLE
,
285 [ FILTER_OP_CAST_TO_S64
] = &&LABEL_FILTER_OP_CAST_TO_S64
,
286 [ FILTER_OP_CAST_DOUBLE_TO_S64
] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64
,
287 [ FILTER_OP_CAST_NOP
] = &&LABEL_FILTER_OP_CAST_NOP
,
289 /* get context ref */
290 [ FILTER_OP_GET_CONTEXT_REF
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF
,
291 [ FILTER_OP_GET_CONTEXT_REF_STRING
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING
,
292 [ FILTER_OP_GET_CONTEXT_REF_S64
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64
,
293 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE
,
295 #endif /* #ifndef INTERPRETER_USE_SWITCH */
299 OP(FILTER_OP_UNKNOWN
):
300 OP(FILTER_OP_LOAD_FIELD_REF
):
301 #ifdef INTERPRETER_USE_SWITCH
303 #endif /* INTERPRETER_USE_SWITCH */
304 ERR("unknown bytecode op %u\n",
305 (unsigned int) *(filter_opcode_t
*) pc
);
309 OP(FILTER_OP_RETURN
):
310 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
311 retval
= !!estack_ax_v
;
321 OP(FILTER_OP_RSHIFT
):
322 OP(FILTER_OP_LSHIFT
):
323 OP(FILTER_OP_BIN_AND
):
324 OP(FILTER_OP_BIN_OR
):
325 OP(FILTER_OP_BIN_XOR
):
326 ERR("unsupported bytecode op %u\n",
327 (unsigned int) *(filter_opcode_t
*) pc
);
333 /* Dynamic typing. */
334 switch (estack_ax_t
) {
336 switch (estack_bx_t
) {
338 JUMP_TO(FILTER_OP_EQ_S64
);
340 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64
);
345 ERR("Unknown filter register type (%d)",
352 switch (estack_bx_t
) {
354 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE
);
356 JUMP_TO(FILTER_OP_EQ_DOUBLE
);
361 ERR("Unknown filter register type (%d)",
368 switch (estack_bx_t
) {
369 case REG_S64
: /* Fall-through */
374 JUMP_TO(FILTER_OP_EQ_STRING
);
376 ERR("Unknown filter register type (%d)",
383 ERR("Unknown filter register type (%d)",
391 /* Dynamic typing. */
392 switch (estack_ax_t
) {
394 switch (estack_bx_t
) {
396 JUMP_TO(FILTER_OP_NE_S64
);
398 JUMP_TO(FILTER_OP_NE_DOUBLE_S64
);
403 ERR("Unknown filter register type (%d)",
410 switch (estack_bx_t
) {
412 JUMP_TO(FILTER_OP_NE_S64_DOUBLE
);
414 JUMP_TO(FILTER_OP_NE_DOUBLE
);
419 ERR("Unknown filter register type (%d)",
426 switch (estack_bx_t
) {
427 case REG_S64
: /* Fall-through */
432 JUMP_TO(FILTER_OP_NE_STRING
);
434 ERR("Unknown filter register type (%d)",
441 ERR("Unknown filter register type (%d)",
449 /* Dynamic typing. */
450 switch (estack_ax_t
) {
452 switch (estack_bx_t
) {
454 JUMP_TO(FILTER_OP_GT_S64
);
456 JUMP_TO(FILTER_OP_GT_DOUBLE_S64
);
461 ERR("Unknown filter register type (%d)",
468 switch (estack_bx_t
) {
470 JUMP_TO(FILTER_OP_GT_S64_DOUBLE
);
472 JUMP_TO(FILTER_OP_GT_DOUBLE
);
477 ERR("Unknown filter register type (%d)",
484 switch (estack_bx_t
) {
485 case REG_S64
: /* Fall-through */
490 JUMP_TO(FILTER_OP_GT_STRING
);
492 ERR("Unknown filter register type (%d)",
499 ERR("Unknown filter register type (%d)",
507 /* Dynamic typing. */
508 switch (estack_ax_t
) {
510 switch (estack_bx_t
) {
512 JUMP_TO(FILTER_OP_LT_S64
);
514 JUMP_TO(FILTER_OP_LT_DOUBLE_S64
);
519 ERR("Unknown filter register type (%d)",
526 switch (estack_bx_t
) {
528 JUMP_TO(FILTER_OP_LT_S64_DOUBLE
);
530 JUMP_TO(FILTER_OP_LT_DOUBLE
);
535 ERR("Unknown filter register type (%d)",
542 switch (estack_bx_t
) {
543 case REG_S64
: /* Fall-through */
548 JUMP_TO(FILTER_OP_LT_STRING
);
550 ERR("Unknown filter register type (%d)",
557 ERR("Unknown filter register type (%d)",
565 /* Dynamic typing. */
566 switch (estack_ax_t
) {
568 switch (estack_bx_t
) {
570 JUMP_TO(FILTER_OP_GE_S64
);
572 JUMP_TO(FILTER_OP_GE_DOUBLE_S64
);
577 ERR("Unknown filter register type (%d)",
584 switch (estack_bx_t
) {
586 JUMP_TO(FILTER_OP_GE_S64_DOUBLE
);
588 JUMP_TO(FILTER_OP_GE_DOUBLE
);
593 ERR("Unknown filter register type (%d)",
600 switch (estack_bx_t
) {
601 case REG_S64
: /* Fall-through */
606 JUMP_TO(FILTER_OP_GE_STRING
);
608 ERR("Unknown filter register type (%d)",
615 ERR("Unknown filter register type (%d)",
623 /* Dynamic typing. */
624 switch (estack_ax_t
) {
626 switch (estack_bx_t
) {
628 JUMP_TO(FILTER_OP_LE_S64
);
630 JUMP_TO(FILTER_OP_LE_DOUBLE_S64
);
635 ERR("Unknown filter register type (%d)",
642 switch (estack_bx_t
) {
644 JUMP_TO(FILTER_OP_LE_S64_DOUBLE
);
646 JUMP_TO(FILTER_OP_LE_DOUBLE
);
651 ERR("Unknown filter register type (%d)",
658 switch (estack_bx_t
) {
659 case REG_S64
: /* Fall-through */
664 JUMP_TO(FILTER_OP_LE_STRING
);
666 ERR("Unknown filter register type (%d)",
673 ERR("Unknown filter register type (%d)",
680 OP(FILTER_OP_EQ_STRING
):
684 res
= (stack_strcmp(stack
, top
, "==") == 0);
685 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
687 estack_ax_t
= REG_S64
;
688 next_pc
+= sizeof(struct binary_op
);
691 OP(FILTER_OP_NE_STRING
):
695 res
= (stack_strcmp(stack
, top
, "!=") != 0);
696 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
698 estack_ax_t
= REG_S64
;
699 next_pc
+= sizeof(struct binary_op
);
702 OP(FILTER_OP_GT_STRING
):
706 res
= (stack_strcmp(stack
, top
, ">") > 0);
707 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
709 estack_ax_t
= REG_S64
;
710 next_pc
+= sizeof(struct binary_op
);
713 OP(FILTER_OP_LT_STRING
):
717 res
= (stack_strcmp(stack
, top
, "<") < 0);
718 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
720 estack_ax_t
= REG_S64
;
721 next_pc
+= sizeof(struct binary_op
);
724 OP(FILTER_OP_GE_STRING
):
728 res
= (stack_strcmp(stack
, top
, ">=") >= 0);
729 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
731 estack_ax_t
= REG_S64
;
732 next_pc
+= sizeof(struct binary_op
);
735 OP(FILTER_OP_LE_STRING
):
739 res
= (stack_strcmp(stack
, top
, "<=") <= 0);
740 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
742 estack_ax_t
= REG_S64
;
743 next_pc
+= sizeof(struct binary_op
);
747 OP(FILTER_OP_EQ_S64
):
751 res
= (estack_bx_v
== estack_ax_v
);
752 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
754 estack_ax_t
= REG_S64
;
755 next_pc
+= sizeof(struct binary_op
);
758 OP(FILTER_OP_NE_S64
):
762 res
= (estack_bx_v
!= estack_ax_v
);
763 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
765 estack_ax_t
= REG_S64
;
766 next_pc
+= sizeof(struct binary_op
);
769 OP(FILTER_OP_GT_S64
):
773 res
= (estack_bx_v
> estack_ax_v
);
774 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
776 estack_ax_t
= REG_S64
;
777 next_pc
+= sizeof(struct binary_op
);
780 OP(FILTER_OP_LT_S64
):
784 res
= (estack_bx_v
< estack_ax_v
);
785 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
787 estack_ax_t
= REG_S64
;
788 next_pc
+= sizeof(struct binary_op
);
791 OP(FILTER_OP_GE_S64
):
795 res
= (estack_bx_v
>= estack_ax_v
);
796 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
798 estack_ax_t
= REG_S64
;
799 next_pc
+= sizeof(struct binary_op
);
802 OP(FILTER_OP_LE_S64
):
806 res
= (estack_bx_v
<= estack_ax_v
);
807 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
809 estack_ax_t
= REG_S64
;
810 next_pc
+= sizeof(struct binary_op
);
814 OP(FILTER_OP_EQ_DOUBLE
):
818 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax(stack
, top
)->u
.d
);
819 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
821 estack_ax_t
= REG_S64
;
822 next_pc
+= sizeof(struct binary_op
);
825 OP(FILTER_OP_NE_DOUBLE
):
829 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax(stack
, top
)->u
.d
);
830 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
832 estack_ax_t
= REG_S64
;
833 next_pc
+= sizeof(struct binary_op
);
836 OP(FILTER_OP_GT_DOUBLE
):
840 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax(stack
, top
)->u
.d
);
841 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
843 estack_ax_t
= REG_S64
;
844 next_pc
+= sizeof(struct binary_op
);
847 OP(FILTER_OP_LT_DOUBLE
):
851 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax(stack
, top
)->u
.d
);
852 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
854 estack_ax_t
= REG_S64
;
855 next_pc
+= sizeof(struct binary_op
);
858 OP(FILTER_OP_GE_DOUBLE
):
862 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax(stack
, top
)->u
.d
);
863 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
865 estack_ax_t
= REG_S64
;
866 next_pc
+= sizeof(struct binary_op
);
869 OP(FILTER_OP_LE_DOUBLE
):
873 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax(stack
, top
)->u
.d
);
874 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
876 estack_ax_t
= REG_S64
;
877 next_pc
+= sizeof(struct binary_op
);
881 /* Mixed S64-double binary comparators */
882 OP(FILTER_OP_EQ_DOUBLE_S64
):
886 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax_v
);
887 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
889 estack_ax_t
= REG_S64
;
890 next_pc
+= sizeof(struct binary_op
);
893 OP(FILTER_OP_NE_DOUBLE_S64
):
897 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax_v
);
898 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
900 estack_ax_t
= REG_S64
;
901 next_pc
+= sizeof(struct binary_op
);
904 OP(FILTER_OP_GT_DOUBLE_S64
):
908 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax_v
);
909 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
911 estack_ax_t
= REG_S64
;
912 next_pc
+= sizeof(struct binary_op
);
915 OP(FILTER_OP_LT_DOUBLE_S64
):
919 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax_v
);
920 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
922 estack_ax_t
= REG_S64
;
923 next_pc
+= sizeof(struct binary_op
);
926 OP(FILTER_OP_GE_DOUBLE_S64
):
930 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax_v
);
931 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
933 estack_ax_t
= REG_S64
;
934 next_pc
+= sizeof(struct binary_op
);
937 OP(FILTER_OP_LE_DOUBLE_S64
):
941 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax_v
);
942 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
944 estack_ax_t
= REG_S64
;
945 next_pc
+= sizeof(struct binary_op
);
949 OP(FILTER_OP_EQ_S64_DOUBLE
):
953 res
= (estack_bx_v
== estack_ax(stack
, top
)->u
.d
);
954 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
956 estack_ax_t
= REG_S64
;
957 next_pc
+= sizeof(struct binary_op
);
960 OP(FILTER_OP_NE_S64_DOUBLE
):
964 res
= (estack_bx_v
!= estack_ax(stack
, top
)->u
.d
);
965 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
967 estack_ax_t
= REG_S64
;
968 next_pc
+= sizeof(struct binary_op
);
971 OP(FILTER_OP_GT_S64_DOUBLE
):
975 res
= (estack_bx_v
> estack_ax(stack
, top
)->u
.d
);
976 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
978 estack_ax_t
= REG_S64
;
979 next_pc
+= sizeof(struct binary_op
);
982 OP(FILTER_OP_LT_S64_DOUBLE
):
986 res
= (estack_bx_v
< estack_ax(stack
, top
)->u
.d
);
987 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
989 estack_ax_t
= REG_S64
;
990 next_pc
+= sizeof(struct binary_op
);
993 OP(FILTER_OP_GE_S64_DOUBLE
):
997 res
= (estack_bx_v
>= estack_ax(stack
, top
)->u
.d
);
998 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1000 estack_ax_t
= REG_S64
;
1001 next_pc
+= sizeof(struct binary_op
);
1004 OP(FILTER_OP_LE_S64_DOUBLE
):
1008 res
= (estack_bx_v
<= estack_ax(stack
, top
)->u
.d
);
1009 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1011 estack_ax_t
= REG_S64
;
1012 next_pc
+= sizeof(struct binary_op
);
1017 OP(FILTER_OP_UNARY_PLUS
):
1019 /* Dynamic typing. */
1020 switch (estack_ax_t
) {
1021 case REG_S64
: /* Fall-through. */
1022 JUMP_TO(FILTER_OP_UNARY_PLUS_S64
);
1024 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE
);
1029 ERR("Unknown filter register type (%d)",
1035 OP(FILTER_OP_UNARY_MINUS
):
1037 /* Dynamic typing. */
1038 switch (estack_ax_t
) {
1040 JUMP_TO(FILTER_OP_UNARY_MINUS_S64
);
1042 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE
);
1047 ERR("Unknown filter register type (%d)",
1053 OP(FILTER_OP_UNARY_NOT
):
1055 /* Dynamic typing. */
1056 switch (estack_ax_t
) {
1058 JUMP_TO(FILTER_OP_UNARY_NOT_S64
);
1060 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE
);
1065 ERR("Unknown filter register type (%d)",
1070 next_pc
+= sizeof(struct unary_op
);
1074 OP(FILTER_OP_UNARY_PLUS_S64
):
1075 OP(FILTER_OP_UNARY_PLUS_DOUBLE
):
1077 next_pc
+= sizeof(struct unary_op
);
1080 OP(FILTER_OP_UNARY_MINUS_S64
):
1082 estack_ax_v
= -estack_ax_v
;
1083 next_pc
+= sizeof(struct unary_op
);
1086 OP(FILTER_OP_UNARY_MINUS_DOUBLE
):
1088 estack_ax(stack
, top
)->u
.d
= -estack_ax(stack
, top
)->u
.d
;
1089 next_pc
+= sizeof(struct unary_op
);
1092 OP(FILTER_OP_UNARY_NOT_S64
):
1094 estack_ax_v
= !estack_ax_v
;
1095 next_pc
+= sizeof(struct unary_op
);
1098 OP(FILTER_OP_UNARY_NOT_DOUBLE
):
1100 estack_ax_v
= !estack_ax(stack
, top
)->u
.d
;
1101 estack_ax_t
= REG_S64
;
1102 next_pc
+= sizeof(struct unary_op
);
1109 struct logical_op
*insn
= (struct logical_op
*) pc
;
1111 if (estack_ax_t
!= REG_S64
) {
1115 /* If AX is 0, skip and evaluate to 0 */
1116 if (unlikely(estack_ax_v
== 0)) {
1117 dbg_printf("Jumping to bytecode offset %u\n",
1118 (unsigned int) insn
->skip_offset
);
1119 next_pc
= start_pc
+ insn
->skip_offset
;
1121 /* Pop 1 when jump not taken */
1122 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1123 next_pc
+= sizeof(struct logical_op
);
1129 struct logical_op
*insn
= (struct logical_op
*) pc
;
1131 if (estack_ax_t
!= REG_S64
) {
1135 /* If AX is nonzero, skip and evaluate to 1 */
1136 if (unlikely(estack_ax_v
!= 0)) {
1138 dbg_printf("Jumping to bytecode offset %u\n",
1139 (unsigned int) insn
->skip_offset
);
1140 next_pc
= start_pc
+ insn
->skip_offset
;
1142 /* Pop 1 when jump not taken */
1143 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1144 next_pc
+= sizeof(struct logical_op
);
1150 /* load field ref */
1151 OP(FILTER_OP_LOAD_FIELD_REF_STRING
):
1153 struct load_op
*insn
= (struct load_op
*) pc
;
1154 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1156 dbg_printf("load field ref offset %u type string\n",
1158 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1159 estack_ax(stack
, top
)->u
.s
.str
=
1160 *(const char * const *) &filter_stack_data
[ref
->offset
];
1161 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1162 dbg_printf("Filter warning: loading a NULL string.\n");
1166 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1167 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1168 estack_ax_t
= REG_STRING
;
1169 dbg_printf("ref load string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1170 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1174 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE
):
1176 struct load_op
*insn
= (struct load_op
*) pc
;
1177 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1179 dbg_printf("load field ref offset %u type sequence\n",
1181 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1182 estack_ax(stack
, top
)->u
.s
.seq_len
=
1183 *(unsigned long *) &filter_stack_data
[ref
->offset
];
1184 estack_ax(stack
, top
)->u
.s
.str
=
1185 *(const char **) (&filter_stack_data
[ref
->offset
1186 + sizeof(unsigned long)]);
1187 estack_ax_t
= REG_STRING
;
1188 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1189 dbg_printf("Filter warning: loading a NULL sequence.\n");
1193 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1194 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1198 OP(FILTER_OP_LOAD_FIELD_REF_S64
):
1200 struct load_op
*insn
= (struct load_op
*) pc
;
1201 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1203 dbg_printf("load field ref offset %u type s64\n",
1205 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1207 ((struct literal_numeric
*) &filter_stack_data
[ref
->offset
])->v
;
1208 estack_ax_t
= REG_S64
;
1209 dbg_printf("ref load s64 %" PRIi64
"\n", estack_ax_v
);
1210 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1214 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE
):
1216 struct load_op
*insn
= (struct load_op
*) pc
;
1217 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1219 dbg_printf("load field ref offset %u type double\n",
1221 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1222 memcpy(&estack_ax(stack
, top
)->u
.d
, &filter_stack_data
[ref
->offset
],
1223 sizeof(struct literal_double
));
1224 estack_ax_t
= REG_DOUBLE
;
1225 dbg_printf("ref load double %g\n", estack_ax(stack
, top
)->u
.d
);
1226 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1230 /* load from immediate operand */
1231 OP(FILTER_OP_LOAD_STRING
):
1233 struct load_op
*insn
= (struct load_op
*) pc
;
1235 dbg_printf("load string %s\n", insn
->data
);
1236 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1237 estack_ax(stack
, top
)->u
.s
.str
= insn
->data
;
1238 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1239 estack_ax(stack
, top
)->u
.s
.literal
= 1;
1240 estack_ax_t
= REG_STRING
;
1241 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1245 OP(FILTER_OP_LOAD_S64
):
1247 struct load_op
*insn
= (struct load_op
*) pc
;
1249 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1250 estack_ax_v
= ((struct literal_numeric
*) insn
->data
)->v
;
1251 estack_ax_t
= REG_S64
;
1252 dbg_printf("load s64 %" PRIi64
"\n", estack_ax_v
);
1253 next_pc
+= sizeof(struct load_op
)
1254 + sizeof(struct literal_numeric
);
1258 OP(FILTER_OP_LOAD_DOUBLE
):
1260 struct load_op
*insn
= (struct load_op
*) pc
;
1262 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1263 memcpy(&estack_ax(stack
, top
)->u
.d
, insn
->data
,
1264 sizeof(struct literal_double
));
1265 estack_ax_t
= REG_DOUBLE
;
1266 dbg_printf("load double %g\n", estack_ax(stack
, top
)->u
.d
);
1267 next_pc
+= sizeof(struct load_op
)
1268 + sizeof(struct literal_double
);
1273 OP(FILTER_OP_CAST_TO_S64
):
1275 /* Dynamic typing. */
1276 switch (estack_ax_t
) {
1278 JUMP_TO(FILTER_OP_CAST_NOP
);
1280 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64
);
1285 ERR("Unknown filter register type (%d)",
1292 OP(FILTER_OP_CAST_DOUBLE_TO_S64
):
1294 estack_ax_v
= (int64_t) estack_ax(stack
, top
)->u
.d
;
1295 estack_ax_t
= REG_S64
;
1296 next_pc
+= sizeof(struct cast_op
);
1300 OP(FILTER_OP_CAST_NOP
):
1302 next_pc
+= sizeof(struct cast_op
);
1306 /* get context ref */
1307 OP(FILTER_OP_GET_CONTEXT_REF
):
1309 struct load_op
*insn
= (struct load_op
*) pc
;
1310 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1311 struct lttng_ctx
*ctx
;
1312 struct lttng_ctx_field
*ctx_field
;
1313 struct lttng_ctx_value v
;
1315 dbg_printf("get context ref offset %u type dynamic\n",
1317 ctx
= rcu_dereference(session
->ctx
);
1318 ctx_field
= &ctx
->fields
[ref
->offset
];
1319 ctx_field
->get_value(ctx_field
, &v
);
1320 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1322 case LTTNG_UST_DYNAMIC_TYPE_NONE
:
1325 case LTTNG_UST_DYNAMIC_TYPE_S64
:
1326 estack_ax_v
= v
.u
.s64
;
1327 estack_ax_t
= REG_S64
;
1328 dbg_printf("ref get context dynamic s64 %" PRIi64
"\n", estack_ax_v
);
1330 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE
:
1331 estack_ax(stack
, top
)->u
.d
= v
.u
.d
;
1332 estack_ax_t
= REG_DOUBLE
;
1333 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack
, top
)->u
.d
);
1335 case LTTNG_UST_DYNAMIC_TYPE_STRING
:
1336 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1337 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1338 dbg_printf("Filter warning: loading a NULL string.\n");
1342 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1343 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1344 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1345 estack_ax_t
= REG_STRING
;
1348 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v
.sel
);
1352 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1356 OP(FILTER_OP_GET_CONTEXT_REF_STRING
):
1358 struct load_op
*insn
= (struct load_op
*) pc
;
1359 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1360 struct lttng_ctx
*ctx
;
1361 struct lttng_ctx_field
*ctx_field
;
1362 struct lttng_ctx_value v
;
1364 dbg_printf("get context ref offset %u type string\n",
1366 ctx
= rcu_dereference(session
->ctx
);
1367 ctx_field
= &ctx
->fields
[ref
->offset
];
1368 ctx_field
->get_value(ctx_field
, &v
);
1369 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1370 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1371 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1372 dbg_printf("Filter warning: loading a NULL string.\n");
1376 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1377 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1378 estack_ax_t
= REG_STRING
;
1379 dbg_printf("ref get context string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1380 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1384 OP(FILTER_OP_GET_CONTEXT_REF_S64
):
1386 struct load_op
*insn
= (struct load_op
*) pc
;
1387 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1388 struct lttng_ctx
*ctx
;
1389 struct lttng_ctx_field
*ctx_field
;
1390 struct lttng_ctx_value v
;
1392 dbg_printf("get context ref offset %u type s64\n",
1394 ctx
= rcu_dereference(session
->ctx
);
1395 ctx_field
= &ctx
->fields
[ref
->offset
];
1396 ctx_field
->get_value(ctx_field
, &v
);
1397 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1398 estack_ax_v
= v
.u
.s64
;
1399 estack_ax_t
= REG_S64
;
1400 dbg_printf("ref get context s64 %" PRIi64
"\n", estack_ax_v
);
1401 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1405 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE
):
1407 struct load_op
*insn
= (struct load_op
*) pc
;
1408 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1409 struct lttng_ctx
*ctx
;
1410 struct lttng_ctx_field
*ctx_field
;
1411 struct lttng_ctx_value v
;
1413 dbg_printf("get context ref offset %u type double\n",
1415 ctx
= rcu_dereference(session
->ctx
);
1416 ctx_field
= &ctx
->fields
[ref
->offset
];
1417 ctx_field
->get_value(ctx_field
, &v
);
1418 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1419 memcpy(&estack_ax(stack
, top
)->u
.d
, &v
.u
.d
, sizeof(struct literal_double
));
1420 estack_ax_t
= REG_DOUBLE
;
1421 dbg_printf("ref get context double %g\n", estack_ax(stack
, top
)->u
.d
);
1422 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1428 /* return 0 (discard) on error */