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
24 #include <urcu-pointer.h>
25 #include "lttng-filter.h"
29 * -2: unknown escape char.
34 int parse_char(const char **p
)
54 int stack_strcmp(struct estack
*stack
, int top
, const char *cmp_type
)
56 const char *p
= estack_bx(stack
, top
)->u
.s
.str
, *q
= estack_ax(stack
, top
)->u
.s
.str
;
63 if (unlikely(p
- estack_bx(stack
, top
)->u
.s
.str
>= estack_bx(stack
, top
)->u
.s
.seq_len
|| *p
== '\0')) {
64 if (q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0') {
67 if (estack_ax(stack
, top
)->u
.s
.literal
) {
75 if (unlikely(q
- estack_ax(stack
, top
)->u
.s
.str
>= estack_ax(stack
, top
)->u
.s
.seq_len
|| *q
== '\0')) {
76 if (estack_bx(stack
, top
)->u
.s
.literal
) {
83 if (estack_bx(stack
, top
)->u
.s
.literal
) {
87 } else if (ret
== -2) {
90 /* else compare both char */
92 if (estack_ax(stack
, top
)->u
.s
.literal
) {
96 } else if (ret
== -2) {
116 uint64_t lttng_filter_false(void *filter_data
,
117 const char *filter_stack_data
)
122 #ifdef INTERPRETER_USE_SWITCH
125 * Fallback for compilers that do not support taking address of labels.
129 start_pc = &bytecode->data[0]; \
130 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
132 dbg_printf("Executing op %s (%u)\n", \
133 print_op((unsigned int) *(filter_opcode_t *) pc), \
134 (unsigned int) *(filter_opcode_t *) pc); \
135 switch (*(filter_opcode_t *) pc) {
137 #define OP(name) jump_target_##name: __attribute__((unused)); \
145 #define JUMP_TO(name) \
146 goto jump_target_##name
151 * Dispatch-table based interpreter.
155 start_pc = &bytecode->data[0]; \
156 pc = next_pc = start_pc; \
157 if (unlikely(pc - start_pc >= bytecode->len)) \
159 goto *dispatch[*(filter_opcode_t *) pc];
166 goto *dispatch[*(filter_opcode_t *) pc];
170 #define JUMP_TO(name) \
176 * Return 0 (discard), or raise the 0x1 flag (log event).
177 * Currently, other flags are kept for future extensions and have no
180 uint64_t lttng_filter_interpret_bytecode(void *filter_data
,
181 const char *filter_stack_data
)
183 struct bytecode_runtime
*bytecode
= filter_data
;
184 struct lttng_session
*session
= bytecode
->p
.session
;
185 void *pc
, *next_pc
, *start_pc
;
188 struct estack _stack
;
189 struct estack
*stack
= &_stack
;
190 register int64_t ax
= 0, bx
= 0;
191 register enum entry_type ax_t
= REG_UNKNOWN
, bx_t
= REG_UNKNOWN
;
192 register int top
= FILTER_STACK_EMPTY
;
193 #ifndef INTERPRETER_USE_SWITCH
194 static void *dispatch
[NR_FILTER_OPS
] = {
195 [ FILTER_OP_UNKNOWN
] = &&LABEL_FILTER_OP_UNKNOWN
,
197 [ FILTER_OP_RETURN
] = &&LABEL_FILTER_OP_RETURN
,
200 [ FILTER_OP_MUL
] = &&LABEL_FILTER_OP_MUL
,
201 [ FILTER_OP_DIV
] = &&LABEL_FILTER_OP_DIV
,
202 [ FILTER_OP_MOD
] = &&LABEL_FILTER_OP_MOD
,
203 [ FILTER_OP_PLUS
] = &&LABEL_FILTER_OP_PLUS
,
204 [ FILTER_OP_MINUS
] = &&LABEL_FILTER_OP_MINUS
,
205 [ FILTER_OP_RSHIFT
] = &&LABEL_FILTER_OP_RSHIFT
,
206 [ FILTER_OP_LSHIFT
] = &&LABEL_FILTER_OP_LSHIFT
,
207 [ FILTER_OP_BIN_AND
] = &&LABEL_FILTER_OP_BIN_AND
,
208 [ FILTER_OP_BIN_OR
] = &&LABEL_FILTER_OP_BIN_OR
,
209 [ FILTER_OP_BIN_XOR
] = &&LABEL_FILTER_OP_BIN_XOR
,
211 /* binary comparators */
212 [ FILTER_OP_EQ
] = &&LABEL_FILTER_OP_EQ
,
213 [ FILTER_OP_NE
] = &&LABEL_FILTER_OP_NE
,
214 [ FILTER_OP_GT
] = &&LABEL_FILTER_OP_GT
,
215 [ FILTER_OP_LT
] = &&LABEL_FILTER_OP_LT
,
216 [ FILTER_OP_GE
] = &&LABEL_FILTER_OP_GE
,
217 [ FILTER_OP_LE
] = &&LABEL_FILTER_OP_LE
,
219 /* string binary comparator */
220 [ FILTER_OP_EQ_STRING
] = &&LABEL_FILTER_OP_EQ_STRING
,
221 [ FILTER_OP_NE_STRING
] = &&LABEL_FILTER_OP_NE_STRING
,
222 [ FILTER_OP_GT_STRING
] = &&LABEL_FILTER_OP_GT_STRING
,
223 [ FILTER_OP_LT_STRING
] = &&LABEL_FILTER_OP_LT_STRING
,
224 [ FILTER_OP_GE_STRING
] = &&LABEL_FILTER_OP_GE_STRING
,
225 [ FILTER_OP_LE_STRING
] = &&LABEL_FILTER_OP_LE_STRING
,
227 /* s64 binary comparator */
228 [ FILTER_OP_EQ_S64
] = &&LABEL_FILTER_OP_EQ_S64
,
229 [ FILTER_OP_NE_S64
] = &&LABEL_FILTER_OP_NE_S64
,
230 [ FILTER_OP_GT_S64
] = &&LABEL_FILTER_OP_GT_S64
,
231 [ FILTER_OP_LT_S64
] = &&LABEL_FILTER_OP_LT_S64
,
232 [ FILTER_OP_GE_S64
] = &&LABEL_FILTER_OP_GE_S64
,
233 [ FILTER_OP_LE_S64
] = &&LABEL_FILTER_OP_LE_S64
,
235 /* double binary comparator */
236 [ FILTER_OP_EQ_DOUBLE
] = &&LABEL_FILTER_OP_EQ_DOUBLE
,
237 [ FILTER_OP_NE_DOUBLE
] = &&LABEL_FILTER_OP_NE_DOUBLE
,
238 [ FILTER_OP_GT_DOUBLE
] = &&LABEL_FILTER_OP_GT_DOUBLE
,
239 [ FILTER_OP_LT_DOUBLE
] = &&LABEL_FILTER_OP_LT_DOUBLE
,
240 [ FILTER_OP_GE_DOUBLE
] = &&LABEL_FILTER_OP_GE_DOUBLE
,
241 [ FILTER_OP_LE_DOUBLE
] = &&LABEL_FILTER_OP_LE_DOUBLE
,
243 /* Mixed S64-double binary comparators */
244 [ FILTER_OP_EQ_DOUBLE_S64
] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64
,
245 [ FILTER_OP_NE_DOUBLE_S64
] = &&LABEL_FILTER_OP_NE_DOUBLE_S64
,
246 [ FILTER_OP_GT_DOUBLE_S64
] = &&LABEL_FILTER_OP_GT_DOUBLE_S64
,
247 [ FILTER_OP_LT_DOUBLE_S64
] = &&LABEL_FILTER_OP_LT_DOUBLE_S64
,
248 [ FILTER_OP_GE_DOUBLE_S64
] = &&LABEL_FILTER_OP_GE_DOUBLE_S64
,
249 [ FILTER_OP_LE_DOUBLE_S64
] = &&LABEL_FILTER_OP_LE_DOUBLE_S64
,
251 [ FILTER_OP_EQ_S64_DOUBLE
] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE
,
252 [ FILTER_OP_NE_S64_DOUBLE
] = &&LABEL_FILTER_OP_NE_S64_DOUBLE
,
253 [ FILTER_OP_GT_S64_DOUBLE
] = &&LABEL_FILTER_OP_GT_S64_DOUBLE
,
254 [ FILTER_OP_LT_S64_DOUBLE
] = &&LABEL_FILTER_OP_LT_S64_DOUBLE
,
255 [ FILTER_OP_GE_S64_DOUBLE
] = &&LABEL_FILTER_OP_GE_S64_DOUBLE
,
256 [ FILTER_OP_LE_S64_DOUBLE
] = &&LABEL_FILTER_OP_LE_S64_DOUBLE
,
259 [ FILTER_OP_UNARY_PLUS
] = &&LABEL_FILTER_OP_UNARY_PLUS
,
260 [ FILTER_OP_UNARY_MINUS
] = &&LABEL_FILTER_OP_UNARY_MINUS
,
261 [ FILTER_OP_UNARY_NOT
] = &&LABEL_FILTER_OP_UNARY_NOT
,
262 [ FILTER_OP_UNARY_PLUS_S64
] = &&LABEL_FILTER_OP_UNARY_PLUS_S64
,
263 [ FILTER_OP_UNARY_MINUS_S64
] = &&LABEL_FILTER_OP_UNARY_MINUS_S64
,
264 [ FILTER_OP_UNARY_NOT_S64
] = &&LABEL_FILTER_OP_UNARY_NOT_S64
,
265 [ FILTER_OP_UNARY_PLUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE
,
266 [ FILTER_OP_UNARY_MINUS_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE
,
267 [ FILTER_OP_UNARY_NOT_DOUBLE
] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE
,
270 [ FILTER_OP_AND
] = &&LABEL_FILTER_OP_AND
,
271 [ FILTER_OP_OR
] = &&LABEL_FILTER_OP_OR
,
274 [ FILTER_OP_LOAD_FIELD_REF
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF
,
275 [ FILTER_OP_LOAD_FIELD_REF_STRING
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING
,
276 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE
,
277 [ FILTER_OP_LOAD_FIELD_REF_S64
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64
,
278 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE
,
280 /* load from immediate operand */
281 [ FILTER_OP_LOAD_STRING
] = &&LABEL_FILTER_OP_LOAD_STRING
,
282 [ FILTER_OP_LOAD_S64
] = &&LABEL_FILTER_OP_LOAD_S64
,
283 [ FILTER_OP_LOAD_DOUBLE
] = &&LABEL_FILTER_OP_LOAD_DOUBLE
,
286 [ FILTER_OP_CAST_TO_S64
] = &&LABEL_FILTER_OP_CAST_TO_S64
,
287 [ FILTER_OP_CAST_DOUBLE_TO_S64
] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64
,
288 [ FILTER_OP_CAST_NOP
] = &&LABEL_FILTER_OP_CAST_NOP
,
290 /* get context ref */
291 [ FILTER_OP_GET_CONTEXT_REF
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF
,
292 [ FILTER_OP_GET_CONTEXT_REF_STRING
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING
,
293 [ FILTER_OP_GET_CONTEXT_REF_S64
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64
,
294 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE
] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE
,
296 #endif /* #ifndef INTERPRETER_USE_SWITCH */
300 OP(FILTER_OP_UNKNOWN
):
301 OP(FILTER_OP_LOAD_FIELD_REF
):
302 #ifdef INTERPRETER_USE_SWITCH
304 #endif /* INTERPRETER_USE_SWITCH */
305 ERR("unknown bytecode op %u\n",
306 (unsigned int) *(filter_opcode_t
*) pc
);
310 OP(FILTER_OP_RETURN
):
311 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
312 retval
= !!estack_ax_v
;
322 OP(FILTER_OP_RSHIFT
):
323 OP(FILTER_OP_LSHIFT
):
324 OP(FILTER_OP_BIN_AND
):
325 OP(FILTER_OP_BIN_OR
):
326 OP(FILTER_OP_BIN_XOR
):
327 ERR("unsupported bytecode op %u\n",
328 (unsigned int) *(filter_opcode_t
*) pc
);
334 /* Dynamic typing. */
335 switch (estack_ax_t
) {
337 switch (estack_bx_t
) {
339 JUMP_TO(FILTER_OP_EQ_S64
);
341 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64
);
346 ERR("Unknown filter register type (%d)",
353 switch (estack_bx_t
) {
355 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE
);
357 JUMP_TO(FILTER_OP_EQ_DOUBLE
);
362 ERR("Unknown filter register type (%d)",
369 switch (estack_bx_t
) {
370 case REG_S64
: /* Fall-through */
375 JUMP_TO(FILTER_OP_EQ_STRING
);
377 ERR("Unknown filter register type (%d)",
384 ERR("Unknown filter register type (%d)",
392 /* Dynamic typing. */
393 switch (estack_ax_t
) {
395 switch (estack_bx_t
) {
397 JUMP_TO(FILTER_OP_NE_S64
);
399 JUMP_TO(FILTER_OP_NE_DOUBLE_S64
);
404 ERR("Unknown filter register type (%d)",
411 switch (estack_bx_t
) {
413 JUMP_TO(FILTER_OP_NE_S64_DOUBLE
);
415 JUMP_TO(FILTER_OP_NE_DOUBLE
);
420 ERR("Unknown filter register type (%d)",
427 switch (estack_bx_t
) {
428 case REG_S64
: /* Fall-through */
433 JUMP_TO(FILTER_OP_NE_STRING
);
435 ERR("Unknown filter register type (%d)",
442 ERR("Unknown filter register type (%d)",
450 /* Dynamic typing. */
451 switch (estack_ax_t
) {
453 switch (estack_bx_t
) {
455 JUMP_TO(FILTER_OP_GT_S64
);
457 JUMP_TO(FILTER_OP_GT_DOUBLE_S64
);
462 ERR("Unknown filter register type (%d)",
469 switch (estack_bx_t
) {
471 JUMP_TO(FILTER_OP_GT_S64_DOUBLE
);
473 JUMP_TO(FILTER_OP_GT_DOUBLE
);
478 ERR("Unknown filter register type (%d)",
485 switch (estack_bx_t
) {
486 case REG_S64
: /* Fall-through */
491 JUMP_TO(FILTER_OP_GT_STRING
);
493 ERR("Unknown filter register type (%d)",
500 ERR("Unknown filter register type (%d)",
508 /* Dynamic typing. */
509 switch (estack_ax_t
) {
511 switch (estack_bx_t
) {
513 JUMP_TO(FILTER_OP_LT_S64
);
515 JUMP_TO(FILTER_OP_LT_DOUBLE_S64
);
520 ERR("Unknown filter register type (%d)",
527 switch (estack_bx_t
) {
529 JUMP_TO(FILTER_OP_LT_S64_DOUBLE
);
531 JUMP_TO(FILTER_OP_LT_DOUBLE
);
536 ERR("Unknown filter register type (%d)",
543 switch (estack_bx_t
) {
544 case REG_S64
: /* Fall-through */
549 JUMP_TO(FILTER_OP_LT_STRING
);
551 ERR("Unknown filter register type (%d)",
558 ERR("Unknown filter register type (%d)",
566 /* Dynamic typing. */
567 switch (estack_ax_t
) {
569 switch (estack_bx_t
) {
571 JUMP_TO(FILTER_OP_GE_S64
);
573 JUMP_TO(FILTER_OP_GE_DOUBLE_S64
);
578 ERR("Unknown filter register type (%d)",
585 switch (estack_bx_t
) {
587 JUMP_TO(FILTER_OP_GE_S64_DOUBLE
);
589 JUMP_TO(FILTER_OP_GE_DOUBLE
);
594 ERR("Unknown filter register type (%d)",
601 switch (estack_bx_t
) {
602 case REG_S64
: /* Fall-through */
607 JUMP_TO(FILTER_OP_GE_STRING
);
609 ERR("Unknown filter register type (%d)",
616 ERR("Unknown filter register type (%d)",
624 /* Dynamic typing. */
625 switch (estack_ax_t
) {
627 switch (estack_bx_t
) {
629 JUMP_TO(FILTER_OP_LE_S64
);
631 JUMP_TO(FILTER_OP_LE_DOUBLE_S64
);
636 ERR("Unknown filter register type (%d)",
643 switch (estack_bx_t
) {
645 JUMP_TO(FILTER_OP_LE_S64_DOUBLE
);
647 JUMP_TO(FILTER_OP_LE_DOUBLE
);
652 ERR("Unknown filter register type (%d)",
659 switch (estack_bx_t
) {
660 case REG_S64
: /* Fall-through */
665 JUMP_TO(FILTER_OP_LE_STRING
);
667 ERR("Unknown filter register type (%d)",
674 ERR("Unknown filter register type (%d)",
681 OP(FILTER_OP_EQ_STRING
):
685 res
= (stack_strcmp(stack
, top
, "==") == 0);
686 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
688 estack_ax_t
= REG_S64
;
689 next_pc
+= sizeof(struct binary_op
);
692 OP(FILTER_OP_NE_STRING
):
696 res
= (stack_strcmp(stack
, top
, "!=") != 0);
697 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
699 estack_ax_t
= REG_S64
;
700 next_pc
+= sizeof(struct binary_op
);
703 OP(FILTER_OP_GT_STRING
):
707 res
= (stack_strcmp(stack
, top
, ">") > 0);
708 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
710 estack_ax_t
= REG_S64
;
711 next_pc
+= sizeof(struct binary_op
);
714 OP(FILTER_OP_LT_STRING
):
718 res
= (stack_strcmp(stack
, top
, "<") < 0);
719 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
721 estack_ax_t
= REG_S64
;
722 next_pc
+= sizeof(struct binary_op
);
725 OP(FILTER_OP_GE_STRING
):
729 res
= (stack_strcmp(stack
, top
, ">=") >= 0);
730 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
732 estack_ax_t
= REG_S64
;
733 next_pc
+= sizeof(struct binary_op
);
736 OP(FILTER_OP_LE_STRING
):
740 res
= (stack_strcmp(stack
, top
, "<=") <= 0);
741 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
743 estack_ax_t
= REG_S64
;
744 next_pc
+= sizeof(struct binary_op
);
748 OP(FILTER_OP_EQ_S64
):
752 res
= (estack_bx_v
== estack_ax_v
);
753 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
755 estack_ax_t
= REG_S64
;
756 next_pc
+= sizeof(struct binary_op
);
759 OP(FILTER_OP_NE_S64
):
763 res
= (estack_bx_v
!= estack_ax_v
);
764 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
766 estack_ax_t
= REG_S64
;
767 next_pc
+= sizeof(struct binary_op
);
770 OP(FILTER_OP_GT_S64
):
774 res
= (estack_bx_v
> estack_ax_v
);
775 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
777 estack_ax_t
= REG_S64
;
778 next_pc
+= sizeof(struct binary_op
);
781 OP(FILTER_OP_LT_S64
):
785 res
= (estack_bx_v
< estack_ax_v
);
786 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
788 estack_ax_t
= REG_S64
;
789 next_pc
+= sizeof(struct binary_op
);
792 OP(FILTER_OP_GE_S64
):
796 res
= (estack_bx_v
>= estack_ax_v
);
797 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
799 estack_ax_t
= REG_S64
;
800 next_pc
+= sizeof(struct binary_op
);
803 OP(FILTER_OP_LE_S64
):
807 res
= (estack_bx_v
<= estack_ax_v
);
808 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
810 estack_ax_t
= REG_S64
;
811 next_pc
+= sizeof(struct binary_op
);
815 OP(FILTER_OP_EQ_DOUBLE
):
819 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax(stack
, top
)->u
.d
);
820 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
822 estack_ax_t
= REG_S64
;
823 next_pc
+= sizeof(struct binary_op
);
826 OP(FILTER_OP_NE_DOUBLE
):
830 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax(stack
, top
)->u
.d
);
831 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
833 estack_ax_t
= REG_S64
;
834 next_pc
+= sizeof(struct binary_op
);
837 OP(FILTER_OP_GT_DOUBLE
):
841 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax(stack
, top
)->u
.d
);
842 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
844 estack_ax_t
= REG_S64
;
845 next_pc
+= sizeof(struct binary_op
);
848 OP(FILTER_OP_LT_DOUBLE
):
852 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax(stack
, top
)->u
.d
);
853 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
855 estack_ax_t
= REG_S64
;
856 next_pc
+= sizeof(struct binary_op
);
859 OP(FILTER_OP_GE_DOUBLE
):
863 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax(stack
, top
)->u
.d
);
864 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
866 estack_ax_t
= REG_S64
;
867 next_pc
+= sizeof(struct binary_op
);
870 OP(FILTER_OP_LE_DOUBLE
):
874 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax(stack
, top
)->u
.d
);
875 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
877 estack_ax_t
= REG_S64
;
878 next_pc
+= sizeof(struct binary_op
);
882 /* Mixed S64-double binary comparators */
883 OP(FILTER_OP_EQ_DOUBLE_S64
):
887 res
= (estack_bx(stack
, top
)->u
.d
== estack_ax_v
);
888 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
890 estack_ax_t
= REG_S64
;
891 next_pc
+= sizeof(struct binary_op
);
894 OP(FILTER_OP_NE_DOUBLE_S64
):
898 res
= (estack_bx(stack
, top
)->u
.d
!= estack_ax_v
);
899 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
901 estack_ax_t
= REG_S64
;
902 next_pc
+= sizeof(struct binary_op
);
905 OP(FILTER_OP_GT_DOUBLE_S64
):
909 res
= (estack_bx(stack
, top
)->u
.d
> estack_ax_v
);
910 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
912 estack_ax_t
= REG_S64
;
913 next_pc
+= sizeof(struct binary_op
);
916 OP(FILTER_OP_LT_DOUBLE_S64
):
920 res
= (estack_bx(stack
, top
)->u
.d
< estack_ax_v
);
921 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
923 estack_ax_t
= REG_S64
;
924 next_pc
+= sizeof(struct binary_op
);
927 OP(FILTER_OP_GE_DOUBLE_S64
):
931 res
= (estack_bx(stack
, top
)->u
.d
>= estack_ax_v
);
932 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
934 estack_ax_t
= REG_S64
;
935 next_pc
+= sizeof(struct binary_op
);
938 OP(FILTER_OP_LE_DOUBLE_S64
):
942 res
= (estack_bx(stack
, top
)->u
.d
<= estack_ax_v
);
943 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
945 estack_ax_t
= REG_S64
;
946 next_pc
+= sizeof(struct binary_op
);
950 OP(FILTER_OP_EQ_S64_DOUBLE
):
954 res
= (estack_bx_v
== estack_ax(stack
, top
)->u
.d
);
955 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
957 estack_ax_t
= REG_S64
;
958 next_pc
+= sizeof(struct binary_op
);
961 OP(FILTER_OP_NE_S64_DOUBLE
):
965 res
= (estack_bx_v
!= estack_ax(stack
, top
)->u
.d
);
966 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
968 estack_ax_t
= REG_S64
;
969 next_pc
+= sizeof(struct binary_op
);
972 OP(FILTER_OP_GT_S64_DOUBLE
):
976 res
= (estack_bx_v
> estack_ax(stack
, top
)->u
.d
);
977 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
979 estack_ax_t
= REG_S64
;
980 next_pc
+= sizeof(struct binary_op
);
983 OP(FILTER_OP_LT_S64_DOUBLE
):
987 res
= (estack_bx_v
< estack_ax(stack
, top
)->u
.d
);
988 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
990 estack_ax_t
= REG_S64
;
991 next_pc
+= sizeof(struct binary_op
);
994 OP(FILTER_OP_GE_S64_DOUBLE
):
998 res
= (estack_bx_v
>= estack_ax(stack
, top
)->u
.d
);
999 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1001 estack_ax_t
= REG_S64
;
1002 next_pc
+= sizeof(struct binary_op
);
1005 OP(FILTER_OP_LE_S64_DOUBLE
):
1009 res
= (estack_bx_v
<= estack_ax(stack
, top
)->u
.d
);
1010 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1012 estack_ax_t
= REG_S64
;
1013 next_pc
+= sizeof(struct binary_op
);
1018 OP(FILTER_OP_UNARY_PLUS
):
1020 /* Dynamic typing. */
1021 switch (estack_ax_t
) {
1022 case REG_S64
: /* Fall-through. */
1023 JUMP_TO(FILTER_OP_UNARY_PLUS_S64
);
1025 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE
);
1030 ERR("Unknown filter register type (%d)",
1036 OP(FILTER_OP_UNARY_MINUS
):
1038 /* Dynamic typing. */
1039 switch (estack_ax_t
) {
1041 JUMP_TO(FILTER_OP_UNARY_MINUS_S64
);
1043 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE
);
1048 ERR("Unknown filter register type (%d)",
1054 OP(FILTER_OP_UNARY_NOT
):
1056 /* Dynamic typing. */
1057 switch (estack_ax_t
) {
1059 JUMP_TO(FILTER_OP_UNARY_NOT_S64
);
1061 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE
);
1066 ERR("Unknown filter register type (%d)",
1071 next_pc
+= sizeof(struct unary_op
);
1075 OP(FILTER_OP_UNARY_PLUS_S64
):
1076 OP(FILTER_OP_UNARY_PLUS_DOUBLE
):
1078 next_pc
+= sizeof(struct unary_op
);
1081 OP(FILTER_OP_UNARY_MINUS_S64
):
1083 estack_ax_v
= -estack_ax_v
;
1084 next_pc
+= sizeof(struct unary_op
);
1087 OP(FILTER_OP_UNARY_MINUS_DOUBLE
):
1089 estack_ax(stack
, top
)->u
.d
= -estack_ax(stack
, top
)->u
.d
;
1090 next_pc
+= sizeof(struct unary_op
);
1093 OP(FILTER_OP_UNARY_NOT_S64
):
1095 estack_ax_v
= !estack_ax_v
;
1096 next_pc
+= sizeof(struct unary_op
);
1099 OP(FILTER_OP_UNARY_NOT_DOUBLE
):
1101 estack_ax_v
= !estack_ax(stack
, top
)->u
.d
;
1102 estack_ax_t
= REG_S64
;
1103 next_pc
+= sizeof(struct unary_op
);
1110 struct logical_op
*insn
= (struct logical_op
*) pc
;
1112 if (estack_ax_t
!= REG_S64
) {
1116 /* If AX is 0, skip and evaluate to 0 */
1117 if (unlikely(estack_ax_v
== 0)) {
1118 dbg_printf("Jumping to bytecode offset %u\n",
1119 (unsigned int) insn
->skip_offset
);
1120 next_pc
= start_pc
+ insn
->skip_offset
;
1122 /* Pop 1 when jump not taken */
1123 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1124 next_pc
+= sizeof(struct logical_op
);
1130 struct logical_op
*insn
= (struct logical_op
*) pc
;
1132 if (estack_ax_t
!= REG_S64
) {
1136 /* If AX is nonzero, skip and evaluate to 1 */
1137 if (unlikely(estack_ax_v
!= 0)) {
1139 dbg_printf("Jumping to bytecode offset %u\n",
1140 (unsigned int) insn
->skip_offset
);
1141 next_pc
= start_pc
+ insn
->skip_offset
;
1143 /* Pop 1 when jump not taken */
1144 estack_pop(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1145 next_pc
+= sizeof(struct logical_op
);
1151 /* load field ref */
1152 OP(FILTER_OP_LOAD_FIELD_REF_STRING
):
1154 struct load_op
*insn
= (struct load_op
*) pc
;
1155 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1157 dbg_printf("load field ref offset %u type string\n",
1159 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1160 estack_ax(stack
, top
)->u
.s
.str
=
1161 *(const char * const *) &filter_stack_data
[ref
->offset
];
1162 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1163 dbg_printf("Filter warning: loading a NULL string.\n");
1167 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1168 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1169 estack_ax_t
= REG_STRING
;
1170 dbg_printf("ref load string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1171 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1175 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE
):
1177 struct load_op
*insn
= (struct load_op
*) pc
;
1178 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1180 dbg_printf("load field ref offset %u type sequence\n",
1182 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1183 estack_ax(stack
, top
)->u
.s
.seq_len
=
1184 *(unsigned long *) &filter_stack_data
[ref
->offset
];
1185 estack_ax(stack
, top
)->u
.s
.str
=
1186 *(const char **) (&filter_stack_data
[ref
->offset
1187 + sizeof(unsigned long)]);
1188 estack_ax_t
= REG_STRING
;
1189 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1190 dbg_printf("Filter warning: loading a NULL sequence.\n");
1194 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1195 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1199 OP(FILTER_OP_LOAD_FIELD_REF_S64
):
1201 struct load_op
*insn
= (struct load_op
*) pc
;
1202 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1204 dbg_printf("load field ref offset %u type s64\n",
1206 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1208 ((struct literal_numeric
*) &filter_stack_data
[ref
->offset
])->v
;
1209 estack_ax_t
= REG_S64
;
1210 dbg_printf("ref load s64 %" PRIi64
"\n", estack_ax_v
);
1211 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1215 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE
):
1217 struct load_op
*insn
= (struct load_op
*) pc
;
1218 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1220 dbg_printf("load field ref offset %u type double\n",
1222 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1223 memcpy(&estack_ax(stack
, top
)->u
.d
, &filter_stack_data
[ref
->offset
],
1224 sizeof(struct literal_double
));
1225 estack_ax_t
= REG_DOUBLE
;
1226 dbg_printf("ref load double %g\n", estack_ax(stack
, top
)->u
.d
);
1227 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1231 /* load from immediate operand */
1232 OP(FILTER_OP_LOAD_STRING
):
1234 struct load_op
*insn
= (struct load_op
*) pc
;
1236 dbg_printf("load string %s\n", insn
->data
);
1237 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1238 estack_ax(stack
, top
)->u
.s
.str
= insn
->data
;
1239 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1240 estack_ax(stack
, top
)->u
.s
.literal
= 1;
1241 estack_ax_t
= REG_STRING
;
1242 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1246 OP(FILTER_OP_LOAD_S64
):
1248 struct load_op
*insn
= (struct load_op
*) pc
;
1250 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1251 estack_ax_v
= ((struct literal_numeric
*) insn
->data
)->v
;
1252 estack_ax_t
= REG_S64
;
1253 dbg_printf("load s64 %" PRIi64
"\n", estack_ax_v
);
1254 next_pc
+= sizeof(struct load_op
)
1255 + sizeof(struct literal_numeric
);
1259 OP(FILTER_OP_LOAD_DOUBLE
):
1261 struct load_op
*insn
= (struct load_op
*) pc
;
1263 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1264 memcpy(&estack_ax(stack
, top
)->u
.d
, insn
->data
,
1265 sizeof(struct literal_double
));
1266 estack_ax_t
= REG_DOUBLE
;
1267 dbg_printf("load double %g\n", estack_ax(stack
, top
)->u
.d
);
1268 next_pc
+= sizeof(struct load_op
)
1269 + sizeof(struct literal_double
);
1274 OP(FILTER_OP_CAST_TO_S64
):
1276 /* Dynamic typing. */
1277 switch (estack_ax_t
) {
1279 JUMP_TO(FILTER_OP_CAST_NOP
);
1281 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64
);
1286 ERR("Unknown filter register type (%d)",
1293 OP(FILTER_OP_CAST_DOUBLE_TO_S64
):
1295 estack_ax_v
= (int64_t) estack_ax(stack
, top
)->u
.d
;
1296 estack_ax_t
= REG_S64
;
1297 next_pc
+= sizeof(struct cast_op
);
1301 OP(FILTER_OP_CAST_NOP
):
1303 next_pc
+= sizeof(struct cast_op
);
1307 /* get context ref */
1308 OP(FILTER_OP_GET_CONTEXT_REF
):
1310 struct load_op
*insn
= (struct load_op
*) pc
;
1311 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1312 struct lttng_ctx
*ctx
;
1313 struct lttng_ctx_field
*ctx_field
;
1314 struct lttng_ctx_value v
;
1316 dbg_printf("get context ref offset %u type dynamic\n",
1318 ctx
= rcu_dereference(session
->ctx
);
1319 ctx_field
= &ctx
->fields
[ref
->offset
];
1320 ctx_field
->get_value(ctx_field
, &v
);
1321 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1323 case LTTNG_UST_DYNAMIC_TYPE_NONE
:
1326 case LTTNG_UST_DYNAMIC_TYPE_S64
:
1327 estack_ax_v
= v
.u
.s64
;
1328 estack_ax_t
= REG_S64
;
1329 dbg_printf("ref get context dynamic s64 %" PRIi64
"\n", estack_ax_v
);
1331 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE
:
1332 estack_ax(stack
, top
)->u
.d
= v
.u
.d
;
1333 estack_ax_t
= REG_DOUBLE
;
1334 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack
, top
)->u
.d
);
1336 case LTTNG_UST_DYNAMIC_TYPE_STRING
:
1337 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1338 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1339 dbg_printf("Filter warning: loading a NULL string.\n");
1343 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1344 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1345 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1346 estack_ax_t
= REG_STRING
;
1349 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v
.sel
);
1353 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1357 OP(FILTER_OP_GET_CONTEXT_REF_STRING
):
1359 struct load_op
*insn
= (struct load_op
*) pc
;
1360 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1361 struct lttng_ctx
*ctx
;
1362 struct lttng_ctx_field
*ctx_field
;
1363 struct lttng_ctx_value v
;
1365 dbg_printf("get context ref offset %u type string\n",
1367 ctx
= rcu_dereference(session
->ctx
);
1368 ctx_field
= &ctx
->fields
[ref
->offset
];
1369 ctx_field
->get_value(ctx_field
, &v
);
1370 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1371 estack_ax(stack
, top
)->u
.s
.str
= v
.u
.str
;
1372 if (unlikely(!estack_ax(stack
, top
)->u
.s
.str
)) {
1373 dbg_printf("Filter warning: loading a NULL string.\n");
1377 estack_ax(stack
, top
)->u
.s
.seq_len
= UINT_MAX
;
1378 estack_ax(stack
, top
)->u
.s
.literal
= 0;
1379 estack_ax_t
= REG_STRING
;
1380 dbg_printf("ref get context string %s\n", estack_ax(stack
, top
)->u
.s
.str
);
1381 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1385 OP(FILTER_OP_GET_CONTEXT_REF_S64
):
1387 struct load_op
*insn
= (struct load_op
*) pc
;
1388 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1389 struct lttng_ctx
*ctx
;
1390 struct lttng_ctx_field
*ctx_field
;
1391 struct lttng_ctx_value v
;
1393 dbg_printf("get context ref offset %u type s64\n",
1395 ctx
= rcu_dereference(session
->ctx
);
1396 ctx_field
= &ctx
->fields
[ref
->offset
];
1397 ctx_field
->get_value(ctx_field
, &v
);
1398 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1399 estack_ax_v
= v
.u
.s64
;
1400 estack_ax_t
= REG_S64
;
1401 dbg_printf("ref get context s64 %" PRIi64
"\n", estack_ax_v
);
1402 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1406 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE
):
1408 struct load_op
*insn
= (struct load_op
*) pc
;
1409 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
1410 struct lttng_ctx
*ctx
;
1411 struct lttng_ctx_field
*ctx_field
;
1412 struct lttng_ctx_value v
;
1414 dbg_printf("get context ref offset %u type double\n",
1416 ctx
= rcu_dereference(session
->ctx
);
1417 ctx_field
= &ctx
->fields
[ref
->offset
];
1418 ctx_field
->get_value(ctx_field
, &v
);
1419 estack_push(stack
, top
, ax
, bx
, ax_t
, bx_t
);
1420 memcpy(&estack_ax(stack
, top
)->u
.d
, &v
.u
.d
, sizeof(struct literal_double
));
1421 estack_ax_t
= REG_DOUBLE
;
1422 dbg_printf("ref get context double %g\n", estack_ax(stack
, top
)->u
.d
);
1423 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1429 /* return 0 (discard) on error */