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 (p
- estack_bx(stack
, top
)->u
.s
.str
>= estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0') {
78 if (estack_bx(stack
, top
)->u
.s
.literal
) {
86 if (estack_bx(stack
, top
)->u
.s
.literal
) {
90 } else if (ret
== -2) {
93 /* else compare both char */
95 if (estack_ax(stack
, top
)->u
.s
.literal
) {
99 } else if (ret
== -2) {
119 uint64_t lttng_filter_false(void *filter_data
,
120 const char *filter_stack_data
)
125 #ifdef INTERPRETER_USE_SWITCH
128 * Fallback for compilers that do not support taking address of labels.
132 start_pc = &bytecode->data[0]; \
133 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
135 dbg_printf("Executing op %s (%u)\n", \
136 print_op((unsigned int) *(filter_opcode_t *) pc), \
137 (unsigned int) *(filter_opcode_t *) pc); \
138 switch (*(filter_opcode_t *) pc) {
140 #define OP(name) jump_target_##name: __attribute__((unused)); \
148 #define JUMP_TO(name) \
149 goto jump_target_##name
154 * Dispatch-table based interpreter.
158 start_pc = &bytecode->data[0]; \
159 pc = next_pc = start_pc; \
160 if (unlikely(pc - start_pc >= bytecode->len)) \
162 goto *dispatch[*(filter_opcode_t *) pc];
169 goto *dispatch[*(filter_opcode_t *) pc];
173 #define JUMP_TO(name) \
179 * Return 0 (discard), or raise the 0x1 flag (log event).
180 * Currently, other flags are kept for future extensions and have no
183 uint64_t lttng_filter_interpret_bytecode(void *filter_data
,
184 const char *filter_stack_data
)
186 struct bytecode_runtime
*bytecode
= filter_data
;
187 struct lttng_session
*session
= bytecode
->p
.session
;
188 void *pc
, *next_pc
, *start_pc
;
191 struct estack _stack
;
192 struct estack
*stack
= &_stack
;
193 register int64_t ax
= 0, bx
= 0;
194 register enum entry_type ax_t
= REG_UNKNOWN
, bx_t
= REG_UNKNOWN
;
195 register int top
= FILTER_STACK_EMPTY
;
196 #ifndef INTERPRETER_USE_SWITCH
197 static void *dispatch
[NR_FILTER_OPS
] = {
198 [ FILTER_OP_UNKNOWN
] = &&LABEL_FILTER_OP_UNKNOWN
,
200 [ FILTER_OP_RETURN
] = &&LABEL_FILTER_OP_RETURN
,
203 [ FILTER_OP_MUL
] = &&LABEL_FILTER_OP_MUL
,
204 [ FILTER_OP_DIV
] = &&LABEL_FILTER_OP_DIV
,
205 [ FILTER_OP_MOD
] = &&LABEL_FILTER_OP_MOD
,
206 [ FILTER_OP_PLUS
] = &&LABEL_FILTER_OP_PLUS
,
207 [ FILTER_OP_MINUS
] = &&LABEL_FILTER_OP_MINUS
,
208 [ FILTER_OP_RSHIFT
] = &&LABEL_FILTER_OP_RSHIFT
,
209 [ FILTER_OP_LSHIFT
] = &&LABEL_FILTER_OP_LSHIFT
,
210 [ FILTER_OP_BIN_AND
] = &&LABEL_FILTER_OP_BIN_AND
,
211 [ FILTER_OP_BIN_OR
] = &&LABEL_FILTER_OP_BIN_OR
,
212 [ FILTER_OP_BIN_XOR
] = &&LABEL_FILTER_OP_BIN_XOR
,
214 /* binary comparators */
215 [ FILTER_OP_EQ
] = &&LABEL_FILTER_OP_EQ
,
216 [ FILTER_OP_NE
] = &&LABEL_FILTER_OP_NE
,
217 [ FILTER_OP_GT
] = &&LABEL_FILTER_OP_GT
,
218 [ FILTER_OP_LT
] = &&LABEL_FILTER_OP_LT
,
219 [ FILTER_OP_GE
] = &&LABEL_FILTER_OP_GE
,
220 [ FILTER_OP_LE
] = &&LABEL_FILTER_OP_LE
,
222 /* string binary comparator */
223 [ FILTER_OP_EQ_STRING
] = &&LABEL_FILTER_OP_EQ_STRING
,
224 [ FILTER_OP_NE_STRING
] = &&LABEL_FILTER_OP_NE_STRING
,
225 [ FILTER_OP_GT_STRING
] = &&LABEL_FILTER_OP_GT_STRING
,
226 [ FILTER_OP_LT_STRING
] = &&LABEL_FILTER_OP_LT_STRING
,
227 [ FILTER_OP_GE_STRING
] = &&LABEL_FILTER_OP_GE_STRING
,
228 [ FILTER_OP_LE_STRING
] = &&LABEL_FILTER_OP_LE_STRING
,
230 /* s64 binary comparator */
231 [ FILTER_OP_EQ_S64
] = &&LABEL_FILTER_OP_EQ_S64
,
232 [ FILTER_OP_NE_S64
] = &&LABEL_FILTER_OP_NE_S64
,
233 [ FILTER_OP_GT_S64
] = &&LABEL_FILTER_OP_GT_S64
,
234 [ FILTER_OP_LT_S64
] = &&LABEL_FILTER_OP_LT_S64
,
235 [ FILTER_OP_GE_S64
] = &&LABEL_FILTER_OP_GE_S64
,
236 [ FILTER_OP_LE_S64
] = &&LABEL_FILTER_OP_LE_S64
,
238 /* double binary comparator */
239 [ FILTER_OP_EQ_DOUBLE
] = &&LABEL_FILTER_OP_EQ_DOUBLE
,
240 [ FILTER_OP_NE_DOUBLE
] = &&LABEL_FILTER_OP_NE_DOUBLE
,
241 [ FILTER_OP_GT_DOUBLE
] = &&LABEL_FILTER_OP_GT_DOUBLE
,
242 [ FILTER_OP_LT_DOUBLE
] = &&LABEL_FILTER_OP_LT_DOUBLE
,
243 [ FILTER_OP_GE_DOUBLE
] = &&LABEL_FILTER_OP_GE_DOUBLE
,
244 [ FILTER_OP_LE_DOUBLE
] = &&LABEL_FILTER_OP_LE_DOUBLE
,
246 /* Mixed S64-double binary comparators */
247 [ FILTER_OP_EQ_DOUBLE_S64
] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64
,
248 [ FILTER_OP_NE_DOUBLE_S64
] = &&LABEL_FILTER_OP_NE_DOUBLE_S64
,
249 [ FILTER_OP_GT_DOUBLE_S64
] = &&LABEL_FILTER_OP_GT_DOUBLE_S64
,
250 [ FILTER_OP_LT_DOUBLE_S64
] = &&LABEL_FILTER_OP_LT_DOUBLE_S64
,
251 [ FILTER_OP_GE_DOUBLE_S64
] = &&LABEL_FILTER_OP_GE_DOUBLE_S64
,
252 [ FILTER_OP_LE_DOUBLE_S64
] = &&LABEL_FILTER_OP_LE_DOUBLE_S64
,
254 [ FILTER_OP_EQ_S64_DOUBLE
] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE
,
255 [ FILTER_OP_NE_S64_DOUBLE
] = &&LABEL_FILTER_OP_NE_S64_DOUBLE
,
256 [ FILTER_OP_GT_S64_DOUBLE
] = &&LABEL_FILTER_OP_GT_S64_DOUBLE
,
257 [ FILTER_OP_LT_S64_DOUBLE
] = &&LABEL_FILTER_OP_LT_S64_DOUBLE
,
258 [ FILTER_OP_GE_S64_DOUBLE
] = &&LABEL_FILTER_OP_GE_S64_DOUBLE
,
259 [ FILTER_OP_LE_S64_DOUBLE
] = &&LABEL_FILTER_OP_LE_S64_DOUBLE
,
262 [ FILTER_OP_UNARY_PLUS
] = &&LABEL_FILTER_OP_UNARY_PLUS
,
263 [ FILTER_OP_UNARY_MINUS
] = &&LABEL_FILTER_OP_UNARY_MINUS
,
264 [ FILTER_OP_UNARY_NOT
] = &&LABEL_FILTER_OP_UNARY_NOT
,
265 [ FILTER_OP_UNARY_PLUS_S64
] = &&LABEL_FILTER_OP_UNARY_PLUS_S64
,
266 [ FILTER_OP_UNARY_MINUS_S64
] = &&LABEL_FILTER_OP_UNARY_MINUS_S64
,
267 [ FILTER_OP_UNARY_NOT_S64
] = &&LABEL_FILTER_OP_UNARY_NOT_S64
,
268 [ FILTER_OP_UNARY_PLUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE
,
269 [ FILTER_OP_UNARY_MINUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE
,
270 [ FILTER_OP_UNARY_NOT_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE
,
273 [ FILTER_OP_AND
] = &&LABEL_FILTER_OP_AND
,
274 [ FILTER_OP_OR
] = &&LABEL_FILTER_OP_OR
,
277 [ FILTER_OP_LOAD_FIELD_REF
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF
,
278 [ FILTER_OP_LOAD_FIELD_REF_STRING
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING
,
279 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE
,
280 [ FILTER_OP_LOAD_FIELD_REF_S64
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64
,
281 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE
,
283 /* load from immediate operand */
284 [ FILTER_OP_LOAD_STRING
] = &&LABEL_FILTER_OP_LOAD_STRING
,
285 [ FILTER_OP_LOAD_S64
] = &&LABEL_FILTER_OP_LOAD_S64
,
286 [ FILTER_OP_LOAD_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_DOUBLE
,
289 [ FILTER_OP_CAST_TO_S64
] = &&LABEL_FILTER_OP_CAST_TO_S64
,
290 [ FILTER_OP_CAST_DOUBLE_TO_S64
] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64
,
291 [ FILTER_OP_CAST_NOP
] = &&LABEL_FILTER_OP_CAST_NOP
,
293 /* get context ref */
294 [ FILTER_OP_GET_CONTEXT_REF
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF
,
295 [ FILTER_OP_GET_CONTEXT_REF_STRING
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING
,
296 [ FILTER_OP_GET_CONTEXT_REF_S64
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64
,
297 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE
,
299 #endif /* #ifndef INTERPRETER_USE_SWITCH */
303 OP(FILTER_OP_UNKNOWN
):
304 OP(FILTER_OP_LOAD_FIELD_REF
):
305 #ifdef INTERPRETER_USE_SWITCH
307 #endif /* INTERPRETER_USE_SWITCH */
308 ERR("unknown bytecode op %u\n",
309 (unsigned int) *(filter_opcode_t
*) pc
);
313 OP(FILTER_OP_RETURN
):
314 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
315 retval
= !!estack_ax_v
;
325 OP(FILTER_OP_RSHIFT
):
326 OP(FILTER_OP_LSHIFT
):
327 OP(FILTER_OP_BIN_AND
):
328 OP(FILTER_OP_BIN_OR
):
329 OP(FILTER_OP_BIN_XOR
):
330 ERR("unsupported bytecode op %u\n",
331 (unsigned int) *(filter_opcode_t
*) pc
);
337 /* Dynamic typing. */
338 switch (estack_ax_t
) {
340 switch (estack_bx_t
) {
342 JUMP_TO(FILTER_OP_EQ_S64
);
344 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64
);
349 ERR("Unknown filter register type (%d)",
356 switch (estack_bx_t
) {
358 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE
);
360 JUMP_TO(FILTER_OP_EQ_DOUBLE
);
365 ERR("Unknown filter register type (%d)",
372 switch (estack_bx_t
) {
373 case REG_S64
: /* Fall-through */
378 JUMP_TO(FILTER_OP_EQ_STRING
);
380 ERR("Unknown filter register type (%d)",
387 ERR("Unknown filter register type (%d)",
395 /* Dynamic typing. */
396 switch (estack_ax_t
) {
398 switch (estack_bx_t
) {
400 JUMP_TO(FILTER_OP_NE_S64
);
402 JUMP_TO(FILTER_OP_NE_DOUBLE_S64
);
407 ERR("Unknown filter register type (%d)",
414 switch (estack_bx_t
) {
416 JUMP_TO(FILTER_OP_NE_S64_DOUBLE
);
418 JUMP_TO(FILTER_OP_NE_DOUBLE
);
423 ERR("Unknown filter register type (%d)",
430 switch (estack_bx_t
) {
431 case REG_S64
: /* Fall-through */
436 JUMP_TO(FILTER_OP_NE_STRING
);
438 ERR("Unknown filter register type (%d)",
445 ERR("Unknown filter register type (%d)",
453 /* Dynamic typing. */
454 switch (estack_ax_t
) {
456 switch (estack_bx_t
) {
458 JUMP_TO(FILTER_OP_GT_S64
);
460 JUMP_TO(FILTER_OP_GT_DOUBLE_S64
);
465 ERR("Unknown filter register type (%d)",
472 switch (estack_bx_t
) {
474 JUMP_TO(FILTER_OP_GT_S64_DOUBLE
);
476 JUMP_TO(FILTER_OP_GT_DOUBLE
);
481 ERR("Unknown filter register type (%d)",
488 switch (estack_bx_t
) {
489 case REG_S64
: /* Fall-through */
494 JUMP_TO(FILTER_OP_GT_STRING
);
496 ERR("Unknown filter register type (%d)",
503 ERR("Unknown filter register type (%d)",
511 /* Dynamic typing. */
512 switch (estack_ax_t
) {
514 switch (estack_bx_t
) {
516 JUMP_TO(FILTER_OP_LT_S64
);
518 JUMP_TO(FILTER_OP_LT_DOUBLE_S64
);
523 ERR("Unknown filter register type (%d)",
530 switch (estack_bx_t
) {
532 JUMP_TO(FILTER_OP_LT_S64_DOUBLE
);
534 JUMP_TO(FILTER_OP_LT_DOUBLE
);
539 ERR("Unknown filter register type (%d)",
546 switch (estack_bx_t
) {
547 case REG_S64
: /* Fall-through */
552 JUMP_TO(FILTER_OP_LT_STRING
);
554 ERR("Unknown filter register type (%d)",
561 ERR("Unknown filter register type (%d)",
569 /* Dynamic typing. */
570 switch (estack_ax_t
) {
572 switch (estack_bx_t
) {
574 JUMP_TO(FILTER_OP_GE_S64
);
576 JUMP_TO(FILTER_OP_GE_DOUBLE_S64
);
581 ERR("Unknown filter register type (%d)",
588 switch (estack_bx_t
) {
590 JUMP_TO(FILTER_OP_GE_S64_DOUBLE
);
592 JUMP_TO(FILTER_OP_GE_DOUBLE
);
597 ERR("Unknown filter register type (%d)",
604 switch (estack_bx_t
) {
605 case REG_S64
: /* Fall-through */
610 JUMP_TO(FILTER_OP_GE_STRING
);
612 ERR("Unknown filter register type (%d)",
619 ERR("Unknown filter register type (%d)",
627 /* Dynamic typing. */
628 switch (estack_ax_t
) {
630 switch (estack_bx_t
) {
632 JUMP_TO(FILTER_OP_LE_S64
);
634 JUMP_TO(FILTER_OP_LE_DOUBLE_S64
);
639 ERR("Unknown filter register type (%d)",
646 switch (estack_bx_t
) {
648 JUMP_TO(FILTER_OP_LE_S64_DOUBLE
);
650 JUMP_TO(FILTER_OP_LE_DOUBLE
);
655 ERR("Unknown filter register type (%d)",
662 switch (estack_bx_t
) {
663 case REG_S64
: /* Fall-through */
668 JUMP_TO(FILTER_OP_LE_STRING
);
670 ERR("Unknown filter register type (%d)",
677 ERR("Unknown filter register type (%d)",
684 OP(FILTER_OP_EQ_STRING
):
688 res
= (stack_strcmp(stack
, top
, "==") == 0);
689 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
691 estack_ax_t
= REG_S64
;
692 next_pc
+= sizeof(struct binary_op
);
695 OP(FILTER_OP_NE_STRING
):
699 res
= (stack_strcmp(stack
, top
, "!=") != 0);
700 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
702 estack_ax_t
= REG_S64
;
703 next_pc
+= sizeof(struct binary_op
);
706 OP(FILTER_OP_GT_STRING
):
710 res
= (stack_strcmp(stack
, top
, ">") > 0);
711 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
713 estack_ax_t
= REG_S64
;
714 next_pc
+= sizeof(struct binary_op
);
717 OP(FILTER_OP_LT_STRING
):
721 res
= (stack_strcmp(stack
, top
, "<") < 0);
722 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
724 estack_ax_t
= REG_S64
;
725 next_pc
+= sizeof(struct binary_op
);
728 OP(FILTER_OP_GE_STRING
):
732 res
= (stack_strcmp(stack
, top
, ">=") >= 0);
733 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
735 estack_ax_t
= REG_S64
;
736 next_pc
+= sizeof(struct binary_op
);
739 OP(FILTER_OP_LE_STRING
):
743 res
= (stack_strcmp(stack
, top
, "<=") <= 0);
744 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
746 estack_ax_t
= REG_S64
;
747 next_pc
+= sizeof(struct binary_op
);
751 OP(FILTER_OP_EQ_S64
):
755 res
= (estack_bx_v
== estack_ax_v
);
756 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
758 estack_ax_t
= REG_S64
;
759 next_pc
+= sizeof(struct binary_op
);
762 OP(FILTER_OP_NE_S64
):
766 res
= (estack_bx_v
!= estack_ax_v
);
767 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
769 estack_ax_t
= REG_S64
;
770 next_pc
+= sizeof(struct binary_op
);
773 OP(FILTER_OP_GT_S64
):
777 res
= (estack_bx_v
> estack_ax_v
);
778 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
780 estack_ax_t
= REG_S64
;
781 next_pc
+= sizeof(struct binary_op
);
784 OP(FILTER_OP_LT_S64
):
788 res
= (estack_bx_v
< estack_ax_v
);
789 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
791 estack_ax_t
= REG_S64
;
792 next_pc
+= sizeof(struct binary_op
);
795 OP(FILTER_OP_GE_S64
):
799 res
= (estack_bx_v
>= estack_ax_v
);
800 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
802 estack_ax_t
= REG_S64
;
803 next_pc
+= sizeof(struct binary_op
);
806 OP(FILTER_OP_LE_S64
):
810 res
= (estack_bx_v
<= estack_ax_v
);
811 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
813 estack_ax_t
= REG_S64
;
814 next_pc
+= sizeof(struct binary_op
);
818 OP(FILTER_OP_EQ_DOUBLE
):
822 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax(stack
, top
)->u
.d
);
823 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
825 estack_ax_t
= REG_S64
;
826 next_pc
+= sizeof(struct binary_op
);
829 OP(FILTER_OP_NE_DOUBLE
):
833 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax(stack
, top
)->u
.d
);
834 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
836 estack_ax_t
= REG_S64
;
837 next_pc
+= sizeof(struct binary_op
);
840 OP(FILTER_OP_GT_DOUBLE
):
844 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax(stack
, top
)->u
.d
);
845 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
847 estack_ax_t
= REG_S64
;
848 next_pc
+= sizeof(struct binary_op
);
851 OP(FILTER_OP_LT_DOUBLE
):
855 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax(stack
, top
)->u
.d
);
856 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
858 estack_ax_t
= REG_S64
;
859 next_pc
+= sizeof(struct binary_op
);
862 OP(FILTER_OP_GE_DOUBLE
):
866 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax(stack
, top
)->u
.d
);
867 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
869 estack_ax_t
= REG_S64
;
870 next_pc
+= sizeof(struct binary_op
);
873 OP(FILTER_OP_LE_DOUBLE
):
877 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax(stack
, top
)->u
.d
);
878 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
880 estack_ax_t
= REG_S64
;
881 next_pc
+= sizeof(struct binary_op
);
885 /* Mixed S64-double binary comparators */
886 OP(FILTER_OP_EQ_DOUBLE_S64
):
890 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax_v
);
891 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
893 estack_ax_t
= REG_S64
;
894 next_pc
+= sizeof(struct binary_op
);
897 OP(FILTER_OP_NE_DOUBLE_S64
):
901 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax_v
);
902 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
904 estack_ax_t
= REG_S64
;
905 next_pc
+= sizeof(struct binary_op
);
908 OP(FILTER_OP_GT_DOUBLE_S64
):
912 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax_v
);
913 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
915 estack_ax_t
= REG_S64
;
916 next_pc
+= sizeof(struct binary_op
);
919 OP(FILTER_OP_LT_DOUBLE_S64
):
923 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax_v
);
924 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
926 estack_ax_t
= REG_S64
;
927 next_pc
+= sizeof(struct binary_op
);
930 OP(FILTER_OP_GE_DOUBLE_S64
):
934 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax_v
);
935 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
937 estack_ax_t
= REG_S64
;
938 next_pc
+= sizeof(struct binary_op
);
941 OP(FILTER_OP_LE_DOUBLE_S64
):
945 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax_v
);
946 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
948 estack_ax_t
= REG_S64
;
949 next_pc
+= sizeof(struct binary_op
);
953 OP(FILTER_OP_EQ_S64_DOUBLE
):
957 res
= (estack_bx_v
== estack_ax(stack
, top
)->u
.d
);
958 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
960 estack_ax_t
= REG_S64
;
961 next_pc
+= sizeof(struct binary_op
);
964 OP(FILTER_OP_NE_S64_DOUBLE
):
968 res
= (estack_bx_v
!= estack_ax(stack
, top
)->u
.d
);
969 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
971 estack_ax_t
= REG_S64
;
972 next_pc
+= sizeof(struct binary_op
);
975 OP(FILTER_OP_GT_S64_DOUBLE
):
979 res
= (estack_bx_v
> estack_ax(stack
, top
)->u
.d
);
980 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
982 estack_ax_t
= REG_S64
;
983 next_pc
+= sizeof(struct binary_op
);
986 OP(FILTER_OP_LT_S64_DOUBLE
):
990 res
= (estack_bx_v
< estack_ax(stack
, top
)->u
.d
);
991 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
993 estack_ax_t
= REG_S64
;
994 next_pc
+= sizeof(struct binary_op
);
997 OP(FILTER_OP_GE_S64_DOUBLE
):
1001 res
= (estack_bx_v
>= estack_ax(stack
, top
)->u
.d
);
1002 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1004 estack_ax_t
= REG_S64
;
1005 next_pc
+= sizeof(struct binary_op
);
1008 OP(FILTER_OP_LE_S64_DOUBLE
):
1012 res
= (estack_bx_v
<= estack_ax(stack
, top
)->u
.d
);
1013 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1015 estack_ax_t
= REG_S64
;
1016 next_pc
+= sizeof(struct binary_op
);
1021 OP(FILTER_OP_UNARY_PLUS
):
1023 /* Dynamic typing. */
1024 switch (estack_ax_t
) {
1025 case REG_S64
: /* Fall-through. */
1026 JUMP_TO(FILTER_OP_UNARY_PLUS_S64
);
1028 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE
);
1033 ERR("Unknown filter register type (%d)",
1039 OP(FILTER_OP_UNARY_MINUS
):
1041 /* Dynamic typing. */
1042 switch (estack_ax_t
) {
1044 JUMP_TO(FILTER_OP_UNARY_MINUS_S64
);
1046 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE
);
1051 ERR("Unknown filter register type (%d)",
1057 OP(FILTER_OP_UNARY_NOT
):
1059 /* Dynamic typing. */
1060 switch (estack_ax_t
) {
1062 JUMP_TO(FILTER_OP_UNARY_NOT_S64
);
1064 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE
);
1069 ERR("Unknown filter register type (%d)",
1074 next_pc
+= sizeof(struct unary_op
);
1078 OP(FILTER_OP_UNARY_PLUS_S64
):
1079 OP(FILTER_OP_UNARY_PLUS_DOUBLE
):
1081 next_pc
+= sizeof(struct unary_op
);
1084 OP(FILTER_OP_UNARY_MINUS_S64
):
1086 estack_ax_v
= -estack_ax_v
;
1087 next_pc
+= sizeof(struct unary_op
);
1090 OP(FILTER_OP_UNARY_MINUS_DOUBLE
):
1092 estack_ax(stack
, top
)->u
.d
= -estack_ax(stack
, top
)->u
.d
;
1093 next_pc
+= sizeof(struct unary_op
);
1096 OP(FILTER_OP_UNARY_NOT_S64
):
1098 estack_ax_v
= !estack_ax_v
;
1099 next_pc
+= sizeof(struct unary_op
);
1102 OP(FILTER_OP_UNARY_NOT_DOUBLE
):
1104 estack_ax_v
= !estack_ax(stack
, top
)->u
.d
;
1105 estack_ax_t
= REG_S64
;
1106 next_pc
+= sizeof(struct unary_op
);
1113 struct logical_op
*insn
= (struct logical_op
*) pc
;
1115 if (estack_ax_t
!= REG_S64
) {
1119 /* If AX is 0, skip and evaluate to 0 */
1120 if (unlikely(estack_ax_v
== 0)) {
1121 dbg_printf("Jumping to bytecode offset %u\n",
1122 (unsigned int) insn
->skip_offset
);
1123 next_pc
= start_pc
+ insn
->skip_offset
;
1125 /* Pop 1 when jump not taken */
1126 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1127 next_pc
+= sizeof(struct logical_op
);
1133 struct logical_op
*insn
= (struct logical_op
*) pc
;
1135 if (estack_ax_t
!= REG_S64
) {
1139 /* If AX is nonzero, skip and evaluate to 1 */
1140 if (unlikely(estack_ax_v
!= 0)) {
1142 dbg_printf("Jumping to bytecode offset %u\n",
1143 (unsigned int) insn
->skip_offset
);
1144 next_pc
= start_pc
+ insn
->skip_offset
;
1146 /* Pop 1 when jump not taken */
1147 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1148 next_pc
+= sizeof(struct logical_op
);
1154 /* load field ref */
1155 OP(FILTER_OP_LOAD_FIELD_REF_STRING
):
1157 struct load_op
*insn
= (struct load_op
*) pc
;
1158 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1160 dbg_printf("load field ref offset %u type string\n",
1162 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1163 estack_ax(stack
, top
)->u
.s
.str
=
1164 *(const char * const *) &filter_stack_data
[ref
->offset
];
1165 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1166 dbg_printf("Filter warning: loading a NULL string.\n");
1170 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1171 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1172 estack_ax_t
= REG_STRING
;
1173 dbg_printf("ref load string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1174 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1178 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE
):
1180 struct load_op
*insn
= (struct load_op
*) pc
;
1181 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1183 dbg_printf("load field ref offset %u type sequence\n",
1185 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1186 estack_ax(stack
, top
)->u
.s
.seq_len
=
1187 *(unsigned long *) &filter_stack_data
[ref
->offset
];
1188 estack_ax(stack
, top
)->u
.s
.str
=
1189 *(const char **) (&filter_stack_data
[ref
->offset
1190 + sizeof(unsigned long)]);
1191 estack_ax_t
= REG_STRING
;
1192 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1193 dbg_printf("Filter warning: loading a NULL sequence.\n");
1197 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1198 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1202 OP(FILTER_OP_LOAD_FIELD_REF_S64
):
1204 struct load_op
*insn
= (struct load_op
*) pc
;
1205 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1207 dbg_printf("load field ref offset %u type s64\n",
1209 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1211 ((struct literal_numeric
*) &filter_stack_data
[ref
->offset
])->v
;
1212 estack_ax_t
= REG_S64
;
1213 dbg_printf("ref load s64 %" PRIi64
"\n", estack_ax_v
);
1214 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1218 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE
):
1220 struct load_op
*insn
= (struct load_op
*) pc
;
1221 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1223 dbg_printf("load field ref offset %u type double\n",
1225 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1226 memcpy(&estack_ax(stack
, top
)->u
.d
, &filter_stack_data
[ref
->offset
],
1227 sizeof(struct literal_double
));
1228 estack_ax_t
= REG_DOUBLE
;
1229 dbg_printf("ref load double %g\n", estack_ax(stack
, top
)->u
.d
);
1230 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1234 /* load from immediate operand */
1235 OP(FILTER_OP_LOAD_STRING
):
1237 struct load_op
*insn
= (struct load_op
*) pc
;
1239 dbg_printf("load string %s\n", insn
->data
);
1240 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1241 estack_ax(stack
, top
)->u
.s
.str
= insn
->data
;
1242 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1243 estack_ax(stack
, top
)->u
.s
.literal
= 1;
1244 estack_ax_t
= REG_STRING
;
1245 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1249 OP(FILTER_OP_LOAD_S64
):
1251 struct load_op
*insn
= (struct load_op
*) pc
;
1253 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1254 estack_ax_v
= ((struct literal_numeric
*) insn
->data
)->v
;
1255 estack_ax_t
= REG_S64
;
1256 dbg_printf("load s64 %" PRIi64
"\n", estack_ax_v
);
1257 next_pc
+= sizeof(struct load_op
)
1258 + sizeof(struct literal_numeric
);
1262 OP(FILTER_OP_LOAD_DOUBLE
):
1264 struct load_op
*insn
= (struct load_op
*) pc
;
1266 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1267 memcpy(&estack_ax(stack
, top
)->u
.d
, insn
->data
,
1268 sizeof(struct literal_double
));
1269 estack_ax_t
= REG_DOUBLE
;
1270 dbg_printf("load double %g\n", estack_ax(stack
, top
)->u
.d
);
1271 next_pc
+= sizeof(struct load_op
)
1272 + sizeof(struct literal_double
);
1277 OP(FILTER_OP_CAST_TO_S64
):
1279 /* Dynamic typing. */
1280 switch (estack_ax_t
) {
1282 JUMP_TO(FILTER_OP_CAST_NOP
);
1284 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64
);
1289 ERR("Unknown filter register type (%d)",
1296 OP(FILTER_OP_CAST_DOUBLE_TO_S64
):
1298 estack_ax_v
= (int64_t) estack_ax(stack
, top
)->u
.d
;
1299 estack_ax_t
= REG_S64
;
1300 next_pc
+= sizeof(struct cast_op
);
1304 OP(FILTER_OP_CAST_NOP
):
1306 next_pc
+= sizeof(struct cast_op
);
1310 /* get context ref */
1311 OP(FILTER_OP_GET_CONTEXT_REF
):
1313 struct load_op
*insn
= (struct load_op
*) pc
;
1314 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1315 struct lttng_ctx
*ctx
;
1316 struct lttng_ctx_field
*ctx_field
;
1317 struct lttng_ctx_value v
;
1319 dbg_printf("get context ref offset %u type dynamic\n",
1321 ctx
= rcu_dereference(session
->ctx
);
1322 ctx_field
= &ctx
->fields
[ref
->offset
];
1323 ctx_field
->get_value(ctx_field
, &v
);
1324 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1326 case LTTNG_UST_DYNAMIC_TYPE_NONE
:
1329 case LTTNG_UST_DYNAMIC_TYPE_S64
:
1330 estack_ax_v
= v
.u
.s64
;
1331 estack_ax_t
= REG_S64
;
1332 dbg_printf("ref get context dynamic s64 %" PRIi64
"\n", estack_ax_v
);
1334 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE
:
1335 estack_ax(stack
, top
)->u
.d
= v
.u
.d
;
1336 estack_ax_t
= REG_DOUBLE
;
1337 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack
, top
)->u
.d
);
1339 case LTTNG_UST_DYNAMIC_TYPE_STRING
:
1340 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1341 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1342 dbg_printf("Filter warning: loading a NULL string.\n");
1346 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1347 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1348 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1349 estack_ax_t
= REG_STRING
;
1352 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v
.sel
);
1356 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1360 OP(FILTER_OP_GET_CONTEXT_REF_STRING
):
1362 struct load_op
*insn
= (struct load_op
*) pc
;
1363 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1364 struct lttng_ctx
*ctx
;
1365 struct lttng_ctx_field
*ctx_field
;
1366 struct lttng_ctx_value v
;
1368 dbg_printf("get context ref offset %u type string\n",
1370 ctx
= rcu_dereference(session
->ctx
);
1371 ctx_field
= &ctx
->fields
[ref
->offset
];
1372 ctx_field
->get_value(ctx_field
, &v
);
1373 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1374 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1375 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1376 dbg_printf("Filter warning: loading a NULL string.\n");
1380 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1381 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1382 estack_ax_t
= REG_STRING
;
1383 dbg_printf("ref get context string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1384 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1388 OP(FILTER_OP_GET_CONTEXT_REF_S64
):
1390 struct load_op
*insn
= (struct load_op
*) pc
;
1391 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1392 struct lttng_ctx
*ctx
;
1393 struct lttng_ctx_field
*ctx_field
;
1394 struct lttng_ctx_value v
;
1396 dbg_printf("get context ref offset %u type s64\n",
1398 ctx
= rcu_dereference(session
->ctx
);
1399 ctx_field
= &ctx
->fields
[ref
->offset
];
1400 ctx_field
->get_value(ctx_field
, &v
);
1401 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1402 estack_ax_v
= v
.u
.s64
;
1403 estack_ax_t
= REG_S64
;
1404 dbg_printf("ref get context s64 %" PRIi64
"\n", estack_ax_v
);
1405 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1409 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE
):
1411 struct load_op
*insn
= (struct load_op
*) pc
;
1412 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1413 struct lttng_ctx
*ctx
;
1414 struct lttng_ctx_field
*ctx_field
;
1415 struct lttng_ctx_value v
;
1417 dbg_printf("get context ref offset %u type double\n",
1419 ctx
= rcu_dereference(session
->ctx
);
1420 ctx_field
= &ctx
->fields
[ref
->offset
];
1421 ctx_field
->get_value(ctx_field
, &v
);
1422 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1423 memcpy(&estack_ax(stack
, top
)->u
.d
, &v
.u
.d
, sizeof(struct literal_double
));
1424 estack_ax_t
= REG_DOUBLE
;
1425 dbg_printf("ref get context double %g\n", estack_ax(stack
, top
)->u
.d
);
1426 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1432 /* return 0 (discard) on error */