Decouple `struct lttng_session` from filter code
[lttng-ust.git] / liblttng-ust / lttng-filter-interpreter.c
1 /*
2 * lttng-filter-interpreter.c
3 *
4 * LTTng UST filter interpreter.
5 *
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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
24 * SOFTWARE.
25 */
26
27 #define _LGPL_SOURCE
28 #include <stddef.h>
29 #include <stdint.h>
30 #include <urcu-pointer.h>
31 #include <lttng/ust-endian.h>
32 #include "lttng-filter.h"
33 #include "string-utils.h"
34
35 /*
36 * -1: wildcard found.
37 * -2: unknown escape char.
38 * 0: normal char.
39 */
40
41 static
42 int parse_char(const char **p)
43 {
44 switch (**p) {
45 case '\\':
46 (*p)++;
47 switch (**p) {
48 case '\\':
49 case '*':
50 return 0;
51 default:
52 return -2;
53 }
54 case '*':
55 return -1;
56 default:
57 return 0;
58 }
59 }
60
61 /*
62 * Returns SIZE_MAX if the string is null-terminated, or the number of
63 * characters if not.
64 */
65 static
66 size_t get_str_or_seq_len(const struct estack_entry *entry)
67 {
68 return entry->u.s.seq_len;
69 }
70
71 static
72 int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
73 {
74 const char *pattern;
75 const char *candidate;
76 size_t pattern_len;
77 size_t candidate_len;
78
79 /* Find out which side is the pattern vs. the candidate. */
80 if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
81 pattern = estack_ax(stack, top)->u.s.str;
82 pattern_len = get_str_or_seq_len(estack_ax(stack, top));
83 candidate = estack_bx(stack, top)->u.s.str;
84 candidate_len = get_str_or_seq_len(estack_bx(stack, top));
85 } else {
86 pattern = estack_bx(stack, top)->u.s.str;
87 pattern_len = get_str_or_seq_len(estack_bx(stack, top));
88 candidate = estack_ax(stack, top)->u.s.str;
89 candidate_len = get_str_or_seq_len(estack_ax(stack, top));
90 }
91
92 /* Perform the match. Returns 0 when the result is true. */
93 return !strutils_star_glob_match(pattern, pattern_len, candidate,
94 candidate_len);
95 }
96
97 static
98 int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
99 {
100 const char *p = estack_bx(stack, top)->u.s.str, *q = estack_ax(stack, top)->u.s.str;
101 int ret;
102 int diff;
103
104 for (;;) {
105 int escaped_r0 = 0;
106
107 if (unlikely(p - estack_bx(stack, top)->u.s.str >= estack_bx(stack, top)->u.s.seq_len || *p == '\0')) {
108 if (q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0') {
109 return 0;
110 } else {
111 if (estack_ax(stack, top)->u.s.literal_type ==
112 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
113 ret = parse_char(&q);
114 if (ret == -1)
115 return 0;
116 }
117 return -1;
118 }
119 }
120 if (unlikely(q - estack_ax(stack, top)->u.s.str >= estack_ax(stack, top)->u.s.seq_len || *q == '\0')) {
121 if (estack_bx(stack, top)->u.s.literal_type ==
122 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
123 ret = parse_char(&p);
124 if (ret == -1)
125 return 0;
126 }
127 return 1;
128 }
129 if (estack_bx(stack, top)->u.s.literal_type ==
130 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
131 ret = parse_char(&p);
132 if (ret == -1) {
133 return 0;
134 } else if (ret == -2) {
135 escaped_r0 = 1;
136 }
137 /* else compare both char */
138 }
139 if (estack_ax(stack, top)->u.s.literal_type ==
140 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
141 ret = parse_char(&q);
142 if (ret == -1) {
143 return 0;
144 } else if (ret == -2) {
145 if (!escaped_r0)
146 return -1;
147 } else {
148 if (escaped_r0)
149 return 1;
150 }
151 } else {
152 if (escaped_r0)
153 return 1;
154 }
155 diff = *p - *q;
156 if (diff != 0)
157 break;
158 p++;
159 q++;
160 }
161 return diff;
162 }
163
164 uint64_t lttng_filter_false(void *filter_data,
165 const char *filter_stack_data)
166 {
167 return LTTNG_FILTER_DISCARD;
168 }
169
170 #ifdef INTERPRETER_USE_SWITCH
171
172 /*
173 * Fallback for compilers that do not support taking address of labels.
174 */
175
176 #define START_OP \
177 start_pc = &bytecode->data[0]; \
178 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
179 pc = next_pc) { \
180 dbg_printf("Executing op %s (%u)\n", \
181 print_op((unsigned int) *(filter_opcode_t *) pc), \
182 (unsigned int) *(filter_opcode_t *) pc); \
183 switch (*(filter_opcode_t *) pc) {
184
185 #define OP(name) jump_target_##name: __attribute__((unused)); \
186 case name
187
188 #define PO break
189
190 #define END_OP } \
191 }
192
193 #define JUMP_TO(name) \
194 goto jump_target_##name
195
196 #else
197
198 /*
199 * Dispatch-table based interpreter.
200 */
201
202 #define START_OP \
203 start_pc = &bytecode->code[0]; \
204 pc = next_pc = start_pc; \
205 if (unlikely(pc - start_pc >= bytecode->len)) \
206 goto end; \
207 goto *dispatch[*(filter_opcode_t *) pc];
208
209 #define OP(name) \
210 LABEL_##name
211
212 #define PO \
213 pc = next_pc; \
214 goto *dispatch[*(filter_opcode_t *) pc];
215
216 #define END_OP
217
218 #define JUMP_TO(name) \
219 goto LABEL_##name
220
221 #endif
222
223 static int context_get_index(struct lttng_ctx *ctx,
224 struct load_ptr *ptr,
225 uint32_t idx)
226 {
227
228 struct lttng_ctx_field *ctx_field;
229 struct lttng_event_field *field;
230 struct lttng_ctx_value v;
231
232 ctx_field = &ctx->fields[idx];
233 field = &ctx_field->event_field;
234 ptr->type = LOAD_OBJECT;
235 /* field is only used for types nested within variants. */
236 ptr->field = NULL;
237
238 switch (field->type.atype) {
239 case atype_integer:
240 ctx_field->get_value(ctx_field, &v);
241 if (field->type.u.integer.signedness) {
242 ptr->object_type = OBJECT_TYPE_S64;
243 ptr->u.s64 = v.u.s64;
244 ptr->ptr = &ptr->u.s64;
245 } else {
246 ptr->object_type = OBJECT_TYPE_U64;
247 ptr->u.u64 = v.u.s64; /* Cast. */
248 ptr->ptr = &ptr->u.u64;
249 }
250 break;
251 case atype_enum: /* Fall-through */
252 case atype_enum_nestable:
253 {
254 const struct lttng_integer_type *itype;
255
256 if (field->type.atype == atype_enum) {
257 itype = &field->type.u.legacy.basic.enumeration.container_type;
258 } else {
259 itype = &field->type.u.enum_nestable.container_type->u.integer;
260 }
261 ctx_field->get_value(ctx_field, &v);
262 if (itype->signedness) {
263 ptr->object_type = OBJECT_TYPE_S64;
264 ptr->u.s64 = v.u.s64;
265 ptr->ptr = &ptr->u.s64;
266 } else {
267 ptr->object_type = OBJECT_TYPE_U64;
268 ptr->u.u64 = v.u.s64; /* Cast. */
269 ptr->ptr = &ptr->u.u64;
270 }
271 break;
272 }
273 case atype_array:
274 if (field->type.u.legacy.array.elem_type.atype != atype_integer) {
275 ERR("Array nesting only supports integer types.");
276 return -EINVAL;
277 }
278 if (field->type.u.legacy.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
279 ERR("Only string arrays are supported for contexts.");
280 return -EINVAL;
281 }
282 ptr->object_type = OBJECT_TYPE_STRING;
283 ctx_field->get_value(ctx_field, &v);
284 ptr->ptr = v.u.str;
285 break;
286 case atype_array_nestable:
287 if (field->type.u.array_nestable.elem_type->atype != atype_integer) {
288 ERR("Array nesting only supports integer types.");
289 return -EINVAL;
290 }
291 if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
292 ERR("Only string arrays are supported for contexts.");
293 return -EINVAL;
294 }
295 ptr->object_type = OBJECT_TYPE_STRING;
296 ctx_field->get_value(ctx_field, &v);
297 ptr->ptr = v.u.str;
298 break;
299 case atype_sequence:
300 if (field->type.u.legacy.sequence.elem_type.atype != atype_integer) {
301 ERR("Sequence nesting only supports integer types.");
302 return -EINVAL;
303 }
304 if (field->type.u.legacy.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
305 ERR("Only string sequences are supported for contexts.");
306 return -EINVAL;
307 }
308 ptr->object_type = OBJECT_TYPE_STRING;
309 ctx_field->get_value(ctx_field, &v);
310 ptr->ptr = v.u.str;
311 break;
312 case atype_sequence_nestable:
313 if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) {
314 ERR("Sequence nesting only supports integer types.");
315 return -EINVAL;
316 }
317 if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
318 ERR("Only string sequences are supported for contexts.");
319 return -EINVAL;
320 }
321 ptr->object_type = OBJECT_TYPE_STRING;
322 ctx_field->get_value(ctx_field, &v);
323 ptr->ptr = v.u.str;
324 break;
325 case atype_string:
326 ptr->object_type = OBJECT_TYPE_STRING;
327 ctx_field->get_value(ctx_field, &v);
328 ptr->ptr = v.u.str;
329 break;
330 case atype_float:
331 ptr->object_type = OBJECT_TYPE_DOUBLE;
332 ctx_field->get_value(ctx_field, &v);
333 ptr->u.d = v.u.d;
334 ptr->ptr = &ptr->u.d;
335 break;
336 case atype_dynamic:
337 ctx_field->get_value(ctx_field, &v);
338 switch (v.sel) {
339 case LTTNG_UST_DYNAMIC_TYPE_NONE:
340 return -EINVAL;
341 case LTTNG_UST_DYNAMIC_TYPE_S64:
342 ptr->object_type = OBJECT_TYPE_S64;
343 ptr->u.s64 = v.u.s64;
344 ptr->ptr = &ptr->u.s64;
345 dbg_printf("context get index dynamic s64 %" PRIi64 "\n", ptr->u.s64);
346 break;
347 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE:
348 ptr->object_type = OBJECT_TYPE_DOUBLE;
349 ptr->u.d = v.u.d;
350 ptr->ptr = &ptr->u.d;
351 dbg_printf("context get index dynamic double %g\n", ptr->u.d);
352 break;
353 case LTTNG_UST_DYNAMIC_TYPE_STRING:
354 ptr->object_type = OBJECT_TYPE_STRING;
355 ptr->ptr = v.u.str;
356 dbg_printf("context get index dynamic string %s\n", (const char *) ptr->ptr);
357 break;
358 default:
359 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v.sel);
360 return -EINVAL;
361 }
362 break;
363 case atype_struct:
364 ERR("Structure type cannot be loaded.");
365 return -EINVAL;
366 default:
367 ERR("Unknown type: %d", (int) field->type.atype);
368 return -EINVAL;
369 }
370 return 0;
371 }
372
373 static int dynamic_get_index(struct lttng_ctx *ctx,
374 struct bytecode_runtime *runtime,
375 uint64_t index, struct estack_entry *stack_top)
376 {
377 int ret;
378 const struct filter_get_index_data *gid;
379
380 /*
381 * Types nested within variants need to perform dynamic lookup
382 * based on the field descriptions. LTTng-UST does not implement
383 * variants for now.
384 */
385 if (stack_top->u.ptr.field)
386 return -EINVAL;
387 gid = (const struct filter_get_index_data *) &runtime->data[index];
388 switch (stack_top->u.ptr.type) {
389 case LOAD_OBJECT:
390 switch (stack_top->u.ptr.object_type) {
391 case OBJECT_TYPE_ARRAY:
392 {
393 const char *ptr;
394
395 assert(gid->offset < gid->array_len);
396 /* Skip count (unsigned long) */
397 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
398 ptr = ptr + gid->offset;
399 stack_top->u.ptr.ptr = ptr;
400 stack_top->u.ptr.object_type = gid->elem.type;
401 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
402 /* field is only used for types nested within variants. */
403 stack_top->u.ptr.field = NULL;
404 break;
405 }
406 case OBJECT_TYPE_SEQUENCE:
407 {
408 const char *ptr;
409 size_t ptr_seq_len;
410
411 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
412 ptr_seq_len = *(unsigned long *) stack_top->u.ptr.ptr;
413 if (gid->offset >= gid->elem.len * ptr_seq_len) {
414 ret = -EINVAL;
415 goto end;
416 }
417 ptr = ptr + gid->offset;
418 stack_top->u.ptr.ptr = ptr;
419 stack_top->u.ptr.object_type = gid->elem.type;
420 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
421 /* field is only used for types nested within variants. */
422 stack_top->u.ptr.field = NULL;
423 break;
424 }
425 case OBJECT_TYPE_STRUCT:
426 ERR("Nested structures are not supported yet.");
427 ret = -EINVAL;
428 goto end;
429 case OBJECT_TYPE_VARIANT:
430 default:
431 ERR("Unexpected get index type %d",
432 (int) stack_top->u.ptr.object_type);
433 ret = -EINVAL;
434 goto end;
435 }
436 break;
437 case LOAD_ROOT_CONTEXT:
438 case LOAD_ROOT_APP_CONTEXT: /* Fall-through */
439 {
440 ret = context_get_index(ctx,
441 &stack_top->u.ptr,
442 gid->ctx_index);
443 if (ret) {
444 goto end;
445 }
446 break;
447 }
448 case LOAD_ROOT_PAYLOAD:
449 stack_top->u.ptr.ptr += gid->offset;
450 if (gid->elem.type == OBJECT_TYPE_STRING)
451 stack_top->u.ptr.ptr = *(const char * const *) stack_top->u.ptr.ptr;
452 stack_top->u.ptr.object_type = gid->elem.type;
453 stack_top->u.ptr.type = LOAD_OBJECT;
454 /* field is only used for types nested within variants. */
455 stack_top->u.ptr.field = NULL;
456 break;
457 }
458 return 0;
459
460 end:
461 return ret;
462 }
463
464 static int dynamic_load_field(struct estack_entry *stack_top)
465 {
466 int ret;
467
468 switch (stack_top->u.ptr.type) {
469 case LOAD_OBJECT:
470 break;
471 case LOAD_ROOT_CONTEXT:
472 case LOAD_ROOT_APP_CONTEXT:
473 case LOAD_ROOT_PAYLOAD:
474 default:
475 dbg_printf("Filter warning: cannot load root, missing field name.\n");
476 ret = -EINVAL;
477 goto end;
478 }
479 switch (stack_top->u.ptr.object_type) {
480 case OBJECT_TYPE_S8:
481 dbg_printf("op load field s8\n");
482 stack_top->u.v = *(int8_t *) stack_top->u.ptr.ptr;
483 stack_top->type = REG_S64;
484 break;
485 case OBJECT_TYPE_S16:
486 {
487 int16_t tmp;
488
489 dbg_printf("op load field s16\n");
490 tmp = *(int16_t *) stack_top->u.ptr.ptr;
491 if (stack_top->u.ptr.rev_bo)
492 tmp = bswap_16(tmp);
493 stack_top->u.v = tmp;
494 stack_top->type = REG_S64;
495 break;
496 }
497 case OBJECT_TYPE_S32:
498 {
499 int32_t tmp;
500
501 dbg_printf("op load field s32\n");
502 tmp = *(int32_t *) stack_top->u.ptr.ptr;
503 if (stack_top->u.ptr.rev_bo)
504 tmp = bswap_32(tmp);
505 stack_top->u.v = tmp;
506 stack_top->type = REG_S64;
507 break;
508 }
509 case OBJECT_TYPE_S64:
510 {
511 int64_t tmp;
512
513 dbg_printf("op load field s64\n");
514 tmp = *(int64_t *) stack_top->u.ptr.ptr;
515 if (stack_top->u.ptr.rev_bo)
516 tmp = bswap_64(tmp);
517 stack_top->u.v = tmp;
518 stack_top->type = REG_S64;
519 break;
520 }
521 case OBJECT_TYPE_U8:
522 dbg_printf("op load field u8\n");
523 stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr;
524 stack_top->type = REG_S64;
525 break;
526 case OBJECT_TYPE_U16:
527 {
528 uint16_t tmp;
529
530 dbg_printf("op load field u16\n");
531 tmp = *(uint16_t *) stack_top->u.ptr.ptr;
532 if (stack_top->u.ptr.rev_bo)
533 tmp = bswap_16(tmp);
534 stack_top->u.v = tmp;
535 stack_top->type = REG_S64;
536 break;
537 }
538 case OBJECT_TYPE_U32:
539 {
540 uint32_t tmp;
541
542 dbg_printf("op load field u32\n");
543 tmp = *(uint32_t *) stack_top->u.ptr.ptr;
544 if (stack_top->u.ptr.rev_bo)
545 tmp = bswap_32(tmp);
546 stack_top->u.v = tmp;
547 stack_top->type = REG_S64;
548 break;
549 }
550 case OBJECT_TYPE_U64:
551 {
552 uint64_t tmp;
553
554 dbg_printf("op load field u64\n");
555 tmp = *(uint64_t *) stack_top->u.ptr.ptr;
556 if (stack_top->u.ptr.rev_bo)
557 tmp = bswap_64(tmp);
558 stack_top->u.v = tmp;
559 stack_top->type = REG_S64;
560 break;
561 }
562 case OBJECT_TYPE_DOUBLE:
563 memcpy(&stack_top->u.d,
564 stack_top->u.ptr.ptr,
565 sizeof(struct literal_double));
566 stack_top->type = REG_DOUBLE;
567 break;
568 case OBJECT_TYPE_STRING:
569 {
570 const char *str;
571
572 dbg_printf("op load field string\n");
573 str = (const char *) stack_top->u.ptr.ptr;
574 stack_top->u.s.str = str;
575 if (unlikely(!stack_top->u.s.str)) {
576 dbg_printf("Filter warning: loading a NULL string.\n");
577 ret = -EINVAL;
578 goto end;
579 }
580 stack_top->u.s.seq_len = SIZE_MAX;
581 stack_top->u.s.literal_type =
582 ESTACK_STRING_LITERAL_TYPE_NONE;
583 stack_top->type = REG_STRING;
584 break;
585 }
586 case OBJECT_TYPE_STRING_SEQUENCE:
587 {
588 const char *ptr;
589
590 dbg_printf("op load field string sequence\n");
591 ptr = stack_top->u.ptr.ptr;
592 stack_top->u.s.seq_len = *(unsigned long *) ptr;
593 stack_top->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
594 stack_top->type = REG_STRING;
595 if (unlikely(!stack_top->u.s.str)) {
596 dbg_printf("Filter warning: loading a NULL sequence.\n");
597 ret = -EINVAL;
598 goto end;
599 }
600 stack_top->u.s.literal_type =
601 ESTACK_STRING_LITERAL_TYPE_NONE;
602 break;
603 }
604 case OBJECT_TYPE_DYNAMIC:
605 /*
606 * Dynamic types in context are looked up
607 * by context get index.
608 */
609 ret = -EINVAL;
610 goto end;
611 case OBJECT_TYPE_SEQUENCE:
612 case OBJECT_TYPE_ARRAY:
613 case OBJECT_TYPE_STRUCT:
614 case OBJECT_TYPE_VARIANT:
615 ERR("Sequences, arrays, struct and variant cannot be loaded (nested types).");
616 ret = -EINVAL;
617 goto end;
618 }
619 return 0;
620
621 end:
622 return ret;
623 }
624
625 /*
626 * Return 0 (discard), or raise the 0x1 flag (log event).
627 * Currently, other flags are kept for future extensions and have no
628 * effect.
629 */
630 uint64_t lttng_filter_interpret_bytecode(void *filter_data,
631 const char *filter_stack_data)
632 {
633 struct bytecode_runtime *bytecode = filter_data;
634 struct lttng_ctx *ctx = rcu_dereference(*bytecode->p.pctx);
635 void *pc, *next_pc, *start_pc;
636 int ret = -EINVAL;
637 uint64_t retval = 0;
638 struct estack _stack;
639 struct estack *stack = &_stack;
640 register int64_t ax = 0, bx = 0;
641 register enum entry_type ax_t = REG_UNKNOWN, bx_t = REG_UNKNOWN;
642 register int top = FILTER_STACK_EMPTY;
643 #ifndef INTERPRETER_USE_SWITCH
644 static void *dispatch[NR_FILTER_OPS] = {
645 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
646
647 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
648
649 /* binary */
650 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
651 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
652 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
653 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
654 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
655 [ FILTER_OP_BIT_RSHIFT ] = &&LABEL_FILTER_OP_BIT_RSHIFT,
656 [ FILTER_OP_BIT_LSHIFT ] = &&LABEL_FILTER_OP_BIT_LSHIFT,
657 [ FILTER_OP_BIT_AND ] = &&LABEL_FILTER_OP_BIT_AND,
658 [ FILTER_OP_BIT_OR ] = &&LABEL_FILTER_OP_BIT_OR,
659 [ FILTER_OP_BIT_XOR ] = &&LABEL_FILTER_OP_BIT_XOR,
660
661 /* binary comparators */
662 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
663 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
664 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
665 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
666 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
667 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
668
669 /* string binary comparator */
670 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
671 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
672 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
673 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
674 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
675 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
676
677 /* globbing pattern binary comparator */
678 [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
679 [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
680
681 /* s64 binary comparator */
682 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
683 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
684 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
685 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
686 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
687 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
688
689 /* double binary comparator */
690 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
691 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
692 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
693 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
694 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
695 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
696
697 /* Mixed S64-double binary comparators */
698 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
699 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
700 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
701 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
702 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
703 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
704
705 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
706 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
707 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
708 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
709 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
710 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
711
712 /* unary */
713 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
714 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
715 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
716 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
717 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
718 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
719 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
720 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
721 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
722
723 /* logical */
724 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
725 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
726
727 /* load field ref */
728 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
729 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
730 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
731 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
732 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
733
734 /* load from immediate operand */
735 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
736 [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
737 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
738 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
739
740 /* cast */
741 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
742 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
743 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
744
745 /* get context ref */
746 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
747 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
748 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
749 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
750
751 /* Instructions for recursive traversal through composed types. */
752 [ FILTER_OP_GET_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_CONTEXT_ROOT,
753 [ FILTER_OP_GET_APP_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_APP_CONTEXT_ROOT,
754 [ FILTER_OP_GET_PAYLOAD_ROOT ] = &&LABEL_FILTER_OP_GET_PAYLOAD_ROOT,
755
756 [ FILTER_OP_GET_SYMBOL ] = &&LABEL_FILTER_OP_GET_SYMBOL,
757 [ FILTER_OP_GET_SYMBOL_FIELD ] = &&LABEL_FILTER_OP_GET_SYMBOL_FIELD,
758 [ FILTER_OP_GET_INDEX_U16 ] = &&LABEL_FILTER_OP_GET_INDEX_U16,
759 [ FILTER_OP_GET_INDEX_U64 ] = &&LABEL_FILTER_OP_GET_INDEX_U64,
760
761 [ FILTER_OP_LOAD_FIELD ] = &&LABEL_FILTER_OP_LOAD_FIELD,
762 [ FILTER_OP_LOAD_FIELD_S8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S8,
763 [ FILTER_OP_LOAD_FIELD_S16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S16,
764 [ FILTER_OP_LOAD_FIELD_S32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S32,
765 [ FILTER_OP_LOAD_FIELD_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S64,
766 [ FILTER_OP_LOAD_FIELD_U8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U8,
767 [ FILTER_OP_LOAD_FIELD_U16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U16,
768 [ FILTER_OP_LOAD_FIELD_U32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U32,
769 [ FILTER_OP_LOAD_FIELD_U64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U64,
770 [ FILTER_OP_LOAD_FIELD_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_STRING,
771 [ FILTER_OP_LOAD_FIELD_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_SEQUENCE,
772 [ FILTER_OP_LOAD_FIELD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_DOUBLE,
773
774 [ FILTER_OP_UNARY_BIT_NOT ] = &&LABEL_FILTER_OP_UNARY_BIT_NOT,
775
776 [ FILTER_OP_RETURN_S64 ] = &&LABEL_FILTER_OP_RETURN_S64,
777 };
778 #endif /* #ifndef INTERPRETER_USE_SWITCH */
779
780 START_OP
781
782 OP(FILTER_OP_UNKNOWN):
783 OP(FILTER_OP_LOAD_FIELD_REF):
784 #ifdef INTERPRETER_USE_SWITCH
785 default:
786 #endif /* INTERPRETER_USE_SWITCH */
787 ERR("unknown bytecode op %u",
788 (unsigned int) *(filter_opcode_t *) pc);
789 ret = -EINVAL;
790 goto end;
791
792 OP(FILTER_OP_RETURN):
793 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
794 /* Handle dynamic typing. */
795 switch (estack_ax_t) {
796 case REG_S64:
797 retval = !!estack_ax_v;
798 break;
799 case REG_DOUBLE:
800 case REG_STRING:
801 case REG_STAR_GLOB_STRING:
802 default:
803 ret = -EINVAL;
804 goto end;
805 }
806 ret = 0;
807 goto end;
808
809 OP(FILTER_OP_RETURN_S64):
810 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
811 retval = !!estack_ax_v;
812 ret = 0;
813 goto end;
814
815 /* binary */
816 OP(FILTER_OP_MUL):
817 OP(FILTER_OP_DIV):
818 OP(FILTER_OP_MOD):
819 OP(FILTER_OP_PLUS):
820 OP(FILTER_OP_MINUS):
821 ERR("unsupported bytecode op %u",
822 (unsigned int) *(filter_opcode_t *) pc);
823 ret = -EINVAL;
824 goto end;
825
826 OP(FILTER_OP_EQ):
827 {
828 /* Dynamic typing. */
829 switch (estack_ax_t) {
830 case REG_S64:
831 switch (estack_bx_t) {
832 case REG_S64:
833 JUMP_TO(FILTER_OP_EQ_S64);
834 case REG_DOUBLE:
835 JUMP_TO(FILTER_OP_EQ_DOUBLE_S64);
836 case REG_STRING: /* Fall-through */
837 case REG_STAR_GLOB_STRING:
838 ret = -EINVAL;
839 goto end;
840 default:
841 ERR("Unknown filter register type (%d)",
842 (int) estack_bx_t);
843 ret = -EINVAL;
844 goto end;
845 }
846 break;
847 case REG_DOUBLE:
848 switch (estack_bx_t) {
849 case REG_S64:
850 JUMP_TO(FILTER_OP_EQ_S64_DOUBLE);
851 case REG_DOUBLE:
852 JUMP_TO(FILTER_OP_EQ_DOUBLE);
853 case REG_STRING: /* Fall-through */
854 case REG_STAR_GLOB_STRING:
855 ret = -EINVAL;
856 goto end;
857 default:
858 ERR("Unknown filter register type (%d)",
859 (int) estack_bx_t);
860 ret = -EINVAL;
861 goto end;
862 }
863 break;
864 case REG_STRING:
865 switch (estack_bx_t) {
866 case REG_S64: /* Fall-through */
867 case REG_DOUBLE:
868 ret = -EINVAL;
869 goto end;
870 case REG_STRING:
871 JUMP_TO(FILTER_OP_EQ_STRING);
872 case REG_STAR_GLOB_STRING:
873 JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
874 default:
875 ERR("Unknown filter register type (%d)",
876 (int) estack_bx_t);
877 ret = -EINVAL;
878 goto end;
879 }
880 break;
881 case REG_STAR_GLOB_STRING:
882 switch (estack_bx_t) {
883 case REG_S64: /* Fall-through */
884 case REG_DOUBLE:
885 ret = -EINVAL;
886 goto end;
887 case REG_STRING:
888 JUMP_TO(FILTER_OP_EQ_STAR_GLOB_STRING);
889 case REG_STAR_GLOB_STRING:
890 ret = -EINVAL;
891 goto end;
892 default:
893 ERR("Unknown filter register type (%d)",
894 (int) estack_bx_t);
895 ret = -EINVAL;
896 goto end;
897 }
898 break;
899 default:
900 ERR("Unknown filter register type (%d)",
901 (int) estack_ax_t);
902 ret = -EINVAL;
903 goto end;
904 }
905 }
906 OP(FILTER_OP_NE):
907 {
908 /* Dynamic typing. */
909 switch (estack_ax_t) {
910 case REG_S64:
911 switch (estack_bx_t) {
912 case REG_S64:
913 JUMP_TO(FILTER_OP_NE_S64);
914 case REG_DOUBLE:
915 JUMP_TO(FILTER_OP_NE_DOUBLE_S64);
916 case REG_STRING: /* Fall-through */
917 case REG_STAR_GLOB_STRING:
918 ret = -EINVAL;
919 goto end;
920 default:
921 ERR("Unknown filter register type (%d)",
922 (int) estack_bx_t);
923 ret = -EINVAL;
924 goto end;
925 }
926 break;
927 case REG_DOUBLE:
928 switch (estack_bx_t) {
929 case REG_S64:
930 JUMP_TO(FILTER_OP_NE_S64_DOUBLE);
931 case REG_DOUBLE:
932 JUMP_TO(FILTER_OP_NE_DOUBLE);
933 case REG_STRING: /* Fall-through */
934 case REG_STAR_GLOB_STRING:
935 ret = -EINVAL;
936 goto end;
937 default:
938 ERR("Unknown filter register type (%d)",
939 (int) estack_bx_t);
940 ret = -EINVAL;
941 goto end;
942 }
943 break;
944 case REG_STRING:
945 switch (estack_bx_t) {
946 case REG_S64: /* Fall-through */
947 case REG_DOUBLE:
948 ret = -EINVAL;
949 goto end;
950 case REG_STRING:
951 JUMP_TO(FILTER_OP_NE_STRING);
952 case REG_STAR_GLOB_STRING:
953 JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
954 default:
955 ERR("Unknown filter register type (%d)",
956 (int) estack_bx_t);
957 ret = -EINVAL;
958 goto end;
959 }
960 break;
961 case REG_STAR_GLOB_STRING:
962 switch (estack_bx_t) {
963 case REG_S64: /* Fall-through */
964 case REG_DOUBLE:
965 ret = -EINVAL;
966 goto end;
967 case REG_STRING:
968 JUMP_TO(FILTER_OP_NE_STAR_GLOB_STRING);
969 case REG_STAR_GLOB_STRING:
970 ret = -EINVAL;
971 goto end;
972 default:
973 ERR("Unknown filter register type (%d)",
974 (int) estack_bx_t);
975 ret = -EINVAL;
976 goto end;
977 }
978 break;
979 default:
980 ERR("Unknown filter register type (%d)",
981 (int) estack_ax_t);
982 ret = -EINVAL;
983 goto end;
984 }
985 }
986 OP(FILTER_OP_GT):
987 {
988 /* Dynamic typing. */
989 switch (estack_ax_t) {
990 case REG_S64:
991 switch (estack_bx_t) {
992 case REG_S64:
993 JUMP_TO(FILTER_OP_GT_S64);
994 case REG_DOUBLE:
995 JUMP_TO(FILTER_OP_GT_DOUBLE_S64);
996 case REG_STRING: /* Fall-through */
997 case REG_STAR_GLOB_STRING:
998 ret = -EINVAL;
999 goto end;
1000 default:
1001 ERR("Unknown filter register type (%d)",
1002 (int) estack_bx_t);
1003 ret = -EINVAL;
1004 goto end;
1005 }
1006 break;
1007 case REG_DOUBLE:
1008 switch (estack_bx_t) {
1009 case REG_S64:
1010 JUMP_TO(FILTER_OP_GT_S64_DOUBLE);
1011 case REG_DOUBLE:
1012 JUMP_TO(FILTER_OP_GT_DOUBLE);
1013 case REG_STRING: /* Fall-through */
1014 case REG_STAR_GLOB_STRING:
1015 ret = -EINVAL;
1016 goto end;
1017 default:
1018 ERR("Unknown filter register type (%d)",
1019 (int) estack_bx_t);
1020 ret = -EINVAL;
1021 goto end;
1022 }
1023 break;
1024 case REG_STRING:
1025 switch (estack_bx_t) {
1026 case REG_S64: /* Fall-through */
1027 case REG_DOUBLE: /* Fall-through */
1028 case REG_STAR_GLOB_STRING:
1029 ret = -EINVAL;
1030 goto end;
1031 case REG_STRING:
1032 JUMP_TO(FILTER_OP_GT_STRING);
1033 default:
1034 ERR("Unknown filter register type (%d)",
1035 (int) estack_bx_t);
1036 ret = -EINVAL;
1037 goto end;
1038 }
1039 break;
1040 default:
1041 ERR("Unknown filter register type (%d)",
1042 (int) estack_ax_t);
1043 ret = -EINVAL;
1044 goto end;
1045 }
1046 }
1047 OP(FILTER_OP_LT):
1048 {
1049 /* Dynamic typing. */
1050 switch (estack_ax_t) {
1051 case REG_S64:
1052 switch (estack_bx_t) {
1053 case REG_S64:
1054 JUMP_TO(FILTER_OP_LT_S64);
1055 case REG_DOUBLE:
1056 JUMP_TO(FILTER_OP_LT_DOUBLE_S64);
1057 case REG_STRING: /* Fall-through */
1058 case REG_STAR_GLOB_STRING:
1059 ret = -EINVAL;
1060 goto end;
1061 default:
1062 ERR("Unknown filter register type (%d)",
1063 (int) estack_bx_t);
1064 ret = -EINVAL;
1065 goto end;
1066 }
1067 break;
1068 case REG_DOUBLE:
1069 switch (estack_bx_t) {
1070 case REG_S64:
1071 JUMP_TO(FILTER_OP_LT_S64_DOUBLE);
1072 case REG_DOUBLE:
1073 JUMP_TO(FILTER_OP_LT_DOUBLE);
1074 case REG_STRING: /* Fall-through */
1075 case REG_STAR_GLOB_STRING:
1076 ret = -EINVAL;
1077 goto end;
1078 default:
1079 ERR("Unknown filter register type (%d)",
1080 (int) estack_bx_t);
1081 ret = -EINVAL;
1082 goto end;
1083 }
1084 break;
1085 case REG_STRING:
1086 switch (estack_bx_t) {
1087 case REG_S64: /* Fall-through */
1088 case REG_DOUBLE: /* Fall-through */
1089 case REG_STAR_GLOB_STRING:
1090 ret = -EINVAL;
1091 goto end;
1092 case REG_STRING:
1093 JUMP_TO(FILTER_OP_LT_STRING);
1094 default:
1095 ERR("Unknown filter register type (%d)",
1096 (int) estack_bx_t);
1097 ret = -EINVAL;
1098 goto end;
1099 }
1100 break;
1101 default:
1102 ERR("Unknown filter register type (%d)",
1103 (int) estack_ax_t);
1104 ret = -EINVAL;
1105 goto end;
1106 }
1107 }
1108 OP(FILTER_OP_GE):
1109 {
1110 /* Dynamic typing. */
1111 switch (estack_ax_t) {
1112 case REG_S64:
1113 switch (estack_bx_t) {
1114 case REG_S64:
1115 JUMP_TO(FILTER_OP_GE_S64);
1116 case REG_DOUBLE:
1117 JUMP_TO(FILTER_OP_GE_DOUBLE_S64);
1118 case REG_STRING: /* Fall-through */
1119 case REG_STAR_GLOB_STRING:
1120 ret = -EINVAL;
1121 goto end;
1122 default:
1123 ERR("Unknown filter register type (%d)",
1124 (int) estack_bx_t);
1125 ret = -EINVAL;
1126 goto end;
1127 }
1128 break;
1129 case REG_DOUBLE:
1130 switch (estack_bx_t) {
1131 case REG_S64:
1132 JUMP_TO(FILTER_OP_GE_S64_DOUBLE);
1133 case REG_DOUBLE:
1134 JUMP_TO(FILTER_OP_GE_DOUBLE);
1135 case REG_STRING: /* Fall-through */
1136 case REG_STAR_GLOB_STRING:
1137 ret = -EINVAL;
1138 goto end;
1139 default:
1140 ERR("Unknown filter register type (%d)",
1141 (int) estack_bx_t);
1142 ret = -EINVAL;
1143 goto end;
1144 }
1145 break;
1146 case REG_STRING:
1147 switch (estack_bx_t) {
1148 case REG_S64: /* Fall-through */
1149 case REG_DOUBLE: /* Fall-through */
1150 case REG_STAR_GLOB_STRING:
1151 ret = -EINVAL;
1152 goto end;
1153 case REG_STRING:
1154 JUMP_TO(FILTER_OP_GE_STRING);
1155 default:
1156 ERR("Unknown filter register type (%d)",
1157 (int) estack_bx_t);
1158 ret = -EINVAL;
1159 goto end;
1160 }
1161 break;
1162 default:
1163 ERR("Unknown filter register type (%d)",
1164 (int) estack_ax_t);
1165 ret = -EINVAL;
1166 goto end;
1167 }
1168 }
1169 OP(FILTER_OP_LE):
1170 {
1171 /* Dynamic typing. */
1172 switch (estack_ax_t) {
1173 case REG_S64:
1174 switch (estack_bx_t) {
1175 case REG_S64:
1176 JUMP_TO(FILTER_OP_LE_S64);
1177 case REG_DOUBLE:
1178 JUMP_TO(FILTER_OP_LE_DOUBLE_S64);
1179 case REG_STRING: /* Fall-through */
1180 case REG_STAR_GLOB_STRING:
1181 ret = -EINVAL;
1182 goto end;
1183 default:
1184 ERR("Unknown filter register type (%d)",
1185 (int) estack_bx_t);
1186 ret = -EINVAL;
1187 goto end;
1188 }
1189 break;
1190 case REG_DOUBLE:
1191 switch (estack_bx_t) {
1192 case REG_S64:
1193 JUMP_TO(FILTER_OP_LE_S64_DOUBLE);
1194 case REG_DOUBLE:
1195 JUMP_TO(FILTER_OP_LE_DOUBLE);
1196 case REG_STRING: /* Fall-through */
1197 case REG_STAR_GLOB_STRING:
1198 ret = -EINVAL;
1199 goto end;
1200 default:
1201 ERR("Unknown filter register type (%d)",
1202 (int) estack_bx_t);
1203 ret = -EINVAL;
1204 goto end;
1205 }
1206 break;
1207 case REG_STRING:
1208 switch (estack_bx_t) {
1209 case REG_S64: /* Fall-through */
1210 case REG_DOUBLE: /* Fall-through */
1211 case REG_STAR_GLOB_STRING:
1212 ret = -EINVAL;
1213 goto end;
1214 case REG_STRING:
1215 JUMP_TO(FILTER_OP_LE_STRING);
1216 default:
1217 ERR("Unknown filter register type (%d)",
1218 (int) estack_bx_t);
1219 ret = -EINVAL;
1220 goto end;
1221 }
1222 break;
1223 default:
1224 ERR("Unknown filter register type (%d)",
1225 (int) estack_ax_t);
1226 ret = -EINVAL;
1227 goto end;
1228 }
1229 }
1230
1231 OP(FILTER_OP_EQ_STRING):
1232 {
1233 int res;
1234
1235 res = (stack_strcmp(stack, top, "==") == 0);
1236 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1237 estack_ax_v = res;
1238 estack_ax_t = REG_S64;
1239 next_pc += sizeof(struct binary_op);
1240 PO;
1241 }
1242 OP(FILTER_OP_NE_STRING):
1243 {
1244 int res;
1245
1246 res = (stack_strcmp(stack, top, "!=") != 0);
1247 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1248 estack_ax_v = res;
1249 estack_ax_t = REG_S64;
1250 next_pc += sizeof(struct binary_op);
1251 PO;
1252 }
1253 OP(FILTER_OP_GT_STRING):
1254 {
1255 int res;
1256
1257 res = (stack_strcmp(stack, top, ">") > 0);
1258 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1259 estack_ax_v = res;
1260 estack_ax_t = REG_S64;
1261 next_pc += sizeof(struct binary_op);
1262 PO;
1263 }
1264 OP(FILTER_OP_LT_STRING):
1265 {
1266 int res;
1267
1268 res = (stack_strcmp(stack, top, "<") < 0);
1269 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1270 estack_ax_v = res;
1271 estack_ax_t = REG_S64;
1272 next_pc += sizeof(struct binary_op);
1273 PO;
1274 }
1275 OP(FILTER_OP_GE_STRING):
1276 {
1277 int res;
1278
1279 res = (stack_strcmp(stack, top, ">=") >= 0);
1280 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1281 estack_ax_v = res;
1282 estack_ax_t = REG_S64;
1283 next_pc += sizeof(struct binary_op);
1284 PO;
1285 }
1286 OP(FILTER_OP_LE_STRING):
1287 {
1288 int res;
1289
1290 res = (stack_strcmp(stack, top, "<=") <= 0);
1291 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1292 estack_ax_v = res;
1293 estack_ax_t = REG_S64;
1294 next_pc += sizeof(struct binary_op);
1295 PO;
1296 }
1297
1298 OP(FILTER_OP_EQ_STAR_GLOB_STRING):
1299 {
1300 int res;
1301
1302 res = (stack_star_glob_match(stack, top, "==") == 0);
1303 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1304 estack_ax_v = res;
1305 estack_ax_t = REG_S64;
1306 next_pc += sizeof(struct binary_op);
1307 PO;
1308 }
1309 OP(FILTER_OP_NE_STAR_GLOB_STRING):
1310 {
1311 int res;
1312
1313 res = (stack_star_glob_match(stack, top, "!=") != 0);
1314 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1315 estack_ax_v = res;
1316 estack_ax_t = REG_S64;
1317 next_pc += sizeof(struct binary_op);
1318 PO;
1319 }
1320
1321 OP(FILTER_OP_EQ_S64):
1322 {
1323 int res;
1324
1325 res = (estack_bx_v == estack_ax_v);
1326 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1327 estack_ax_v = res;
1328 estack_ax_t = REG_S64;
1329 next_pc += sizeof(struct binary_op);
1330 PO;
1331 }
1332 OP(FILTER_OP_NE_S64):
1333 {
1334 int res;
1335
1336 res = (estack_bx_v != estack_ax_v);
1337 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1338 estack_ax_v = res;
1339 estack_ax_t = REG_S64;
1340 next_pc += sizeof(struct binary_op);
1341 PO;
1342 }
1343 OP(FILTER_OP_GT_S64):
1344 {
1345 int res;
1346
1347 res = (estack_bx_v > estack_ax_v);
1348 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1349 estack_ax_v = res;
1350 estack_ax_t = REG_S64;
1351 next_pc += sizeof(struct binary_op);
1352 PO;
1353 }
1354 OP(FILTER_OP_LT_S64):
1355 {
1356 int res;
1357
1358 res = (estack_bx_v < estack_ax_v);
1359 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1360 estack_ax_v = res;
1361 estack_ax_t = REG_S64;
1362 next_pc += sizeof(struct binary_op);
1363 PO;
1364 }
1365 OP(FILTER_OP_GE_S64):
1366 {
1367 int res;
1368
1369 res = (estack_bx_v >= estack_ax_v);
1370 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1371 estack_ax_v = res;
1372 estack_ax_t = REG_S64;
1373 next_pc += sizeof(struct binary_op);
1374 PO;
1375 }
1376 OP(FILTER_OP_LE_S64):
1377 {
1378 int res;
1379
1380 res = (estack_bx_v <= estack_ax_v);
1381 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1382 estack_ax_v = res;
1383 estack_ax_t = REG_S64;
1384 next_pc += sizeof(struct binary_op);
1385 PO;
1386 }
1387
1388 OP(FILTER_OP_EQ_DOUBLE):
1389 {
1390 int res;
1391
1392 res = (estack_bx(stack, top)->u.d == estack_ax(stack, top)->u.d);
1393 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1394 estack_ax_v = res;
1395 estack_ax_t = REG_S64;
1396 next_pc += sizeof(struct binary_op);
1397 PO;
1398 }
1399 OP(FILTER_OP_NE_DOUBLE):
1400 {
1401 int res;
1402
1403 res = (estack_bx(stack, top)->u.d != estack_ax(stack, top)->u.d);
1404 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1405 estack_ax_v = res;
1406 estack_ax_t = REG_S64;
1407 next_pc += sizeof(struct binary_op);
1408 PO;
1409 }
1410 OP(FILTER_OP_GT_DOUBLE):
1411 {
1412 int res;
1413
1414 res = (estack_bx(stack, top)->u.d > estack_ax(stack, top)->u.d);
1415 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1416 estack_ax_v = res;
1417 estack_ax_t = REG_S64;
1418 next_pc += sizeof(struct binary_op);
1419 PO;
1420 }
1421 OP(FILTER_OP_LT_DOUBLE):
1422 {
1423 int res;
1424
1425 res = (estack_bx(stack, top)->u.d < estack_ax(stack, top)->u.d);
1426 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1427 estack_ax_v = res;
1428 estack_ax_t = REG_S64;
1429 next_pc += sizeof(struct binary_op);
1430 PO;
1431 }
1432 OP(FILTER_OP_GE_DOUBLE):
1433 {
1434 int res;
1435
1436 res = (estack_bx(stack, top)->u.d >= estack_ax(stack, top)->u.d);
1437 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1438 estack_ax_v = res;
1439 estack_ax_t = REG_S64;
1440 next_pc += sizeof(struct binary_op);
1441 PO;
1442 }
1443 OP(FILTER_OP_LE_DOUBLE):
1444 {
1445 int res;
1446
1447 res = (estack_bx(stack, top)->u.d <= estack_ax(stack, top)->u.d);
1448 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1449 estack_ax_v = res;
1450 estack_ax_t = REG_S64;
1451 next_pc += sizeof(struct binary_op);
1452 PO;
1453 }
1454
1455 /* Mixed S64-double binary comparators */
1456 OP(FILTER_OP_EQ_DOUBLE_S64):
1457 {
1458 int res;
1459
1460 res = (estack_bx(stack, top)->u.d == estack_ax_v);
1461 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1462 estack_ax_v = res;
1463 estack_ax_t = REG_S64;
1464 next_pc += sizeof(struct binary_op);
1465 PO;
1466 }
1467 OP(FILTER_OP_NE_DOUBLE_S64):
1468 {
1469 int res;
1470
1471 res = (estack_bx(stack, top)->u.d != estack_ax_v);
1472 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1473 estack_ax_v = res;
1474 estack_ax_t = REG_S64;
1475 next_pc += sizeof(struct binary_op);
1476 PO;
1477 }
1478 OP(FILTER_OP_GT_DOUBLE_S64):
1479 {
1480 int res;
1481
1482 res = (estack_bx(stack, top)->u.d > estack_ax_v);
1483 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1484 estack_ax_v = res;
1485 estack_ax_t = REG_S64;
1486 next_pc += sizeof(struct binary_op);
1487 PO;
1488 }
1489 OP(FILTER_OP_LT_DOUBLE_S64):
1490 {
1491 int res;
1492
1493 res = (estack_bx(stack, top)->u.d < estack_ax_v);
1494 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1495 estack_ax_v = res;
1496 estack_ax_t = REG_S64;
1497 next_pc += sizeof(struct binary_op);
1498 PO;
1499 }
1500 OP(FILTER_OP_GE_DOUBLE_S64):
1501 {
1502 int res;
1503
1504 res = (estack_bx(stack, top)->u.d >= estack_ax_v);
1505 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1506 estack_ax_v = res;
1507 estack_ax_t = REG_S64;
1508 next_pc += sizeof(struct binary_op);
1509 PO;
1510 }
1511 OP(FILTER_OP_LE_DOUBLE_S64):
1512 {
1513 int res;
1514
1515 res = (estack_bx(stack, top)->u.d <= estack_ax_v);
1516 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1517 estack_ax_v = res;
1518 estack_ax_t = REG_S64;
1519 next_pc += sizeof(struct binary_op);
1520 PO;
1521 }
1522
1523 OP(FILTER_OP_EQ_S64_DOUBLE):
1524 {
1525 int res;
1526
1527 res = (estack_bx_v == estack_ax(stack, top)->u.d);
1528 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1529 estack_ax_v = res;
1530 estack_ax_t = REG_S64;
1531 next_pc += sizeof(struct binary_op);
1532 PO;
1533 }
1534 OP(FILTER_OP_NE_S64_DOUBLE):
1535 {
1536 int res;
1537
1538 res = (estack_bx_v != estack_ax(stack, top)->u.d);
1539 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1540 estack_ax_v = res;
1541 estack_ax_t = REG_S64;
1542 next_pc += sizeof(struct binary_op);
1543 PO;
1544 }
1545 OP(FILTER_OP_GT_S64_DOUBLE):
1546 {
1547 int res;
1548
1549 res = (estack_bx_v > estack_ax(stack, top)->u.d);
1550 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1551 estack_ax_v = res;
1552 estack_ax_t = REG_S64;
1553 next_pc += sizeof(struct binary_op);
1554 PO;
1555 }
1556 OP(FILTER_OP_LT_S64_DOUBLE):
1557 {
1558 int res;
1559
1560 res = (estack_bx_v < estack_ax(stack, top)->u.d);
1561 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1562 estack_ax_v = res;
1563 estack_ax_t = REG_S64;
1564 next_pc += sizeof(struct binary_op);
1565 PO;
1566 }
1567 OP(FILTER_OP_GE_S64_DOUBLE):
1568 {
1569 int res;
1570
1571 res = (estack_bx_v >= estack_ax(stack, top)->u.d);
1572 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1573 estack_ax_v = res;
1574 estack_ax_t = REG_S64;
1575 next_pc += sizeof(struct binary_op);
1576 PO;
1577 }
1578 OP(FILTER_OP_LE_S64_DOUBLE):
1579 {
1580 int res;
1581
1582 res = (estack_bx_v <= estack_ax(stack, top)->u.d);
1583 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1584 estack_ax_v = res;
1585 estack_ax_t = REG_S64;
1586 next_pc += sizeof(struct binary_op);
1587 PO;
1588 }
1589 OP(FILTER_OP_BIT_RSHIFT):
1590 {
1591 int64_t res;
1592
1593 /* Dynamic typing. */
1594 if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
1595 ret = -EINVAL;
1596 goto end;
1597 }
1598 /* Catch undefined behavior. */
1599 if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
1600 ret = -EINVAL;
1601 goto end;
1602 }
1603 res = ((uint64_t) estack_bx_v >> (uint32_t) estack_ax_v);
1604 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1605 estack_ax_v = res;
1606 estack_ax_t = REG_S64;
1607 next_pc += sizeof(struct binary_op);
1608 PO;
1609 }
1610 OP(FILTER_OP_BIT_LSHIFT):
1611 {
1612 int64_t res;
1613
1614 /* Dynamic typing. */
1615 if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
1616 ret = -EINVAL;
1617 goto end;
1618 }
1619 /* Catch undefined behavior. */
1620 if (caa_unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
1621 ret = -EINVAL;
1622 goto end;
1623 }
1624 res = ((uint64_t) estack_bx_v << (uint32_t) estack_ax_v);
1625 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1626 estack_ax_v = res;
1627 estack_ax_t = REG_S64;
1628 next_pc += sizeof(struct binary_op);
1629 PO;
1630 }
1631 OP(FILTER_OP_BIT_AND):
1632 {
1633 int64_t res;
1634
1635 /* Dynamic typing. */
1636 if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
1637 ret = -EINVAL;
1638 goto end;
1639 }
1640
1641 res = ((uint64_t) estack_bx_v & (uint64_t) estack_ax_v);
1642 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1643 estack_ax_v = res;
1644 estack_ax_t = REG_S64;
1645 next_pc += sizeof(struct binary_op);
1646 PO;
1647 }
1648 OP(FILTER_OP_BIT_OR):
1649 {
1650 int64_t res;
1651
1652 /* Dynamic typing. */
1653 if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
1654 ret = -EINVAL;
1655 goto end;
1656 }
1657
1658 res = ((uint64_t) estack_bx_v | (uint64_t) estack_ax_v);
1659 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1660 estack_ax_v = res;
1661 estack_ax_t = REG_S64;
1662 next_pc += sizeof(struct binary_op);
1663 PO;
1664 }
1665 OP(FILTER_OP_BIT_XOR):
1666 {
1667 int64_t res;
1668
1669 /* Dynamic typing. */
1670 if (estack_ax_t != REG_S64 || estack_bx_t != REG_S64) {
1671 ret = -EINVAL;
1672 goto end;
1673 }
1674
1675 res = ((uint64_t) estack_bx_v ^ (uint64_t) estack_ax_v);
1676 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1677 estack_ax_v = res;
1678 estack_ax_t = REG_S64;
1679 next_pc += sizeof(struct binary_op);
1680 PO;
1681 }
1682
1683 /* unary */
1684 OP(FILTER_OP_UNARY_PLUS):
1685 {
1686 /* Dynamic typing. */
1687 switch (estack_ax_t) {
1688 case REG_S64: /* Fall-through. */
1689 JUMP_TO(FILTER_OP_UNARY_PLUS_S64);
1690 case REG_DOUBLE:
1691 JUMP_TO(FILTER_OP_UNARY_PLUS_DOUBLE);
1692 case REG_STRING: /* Fall-through */
1693 case REG_STAR_GLOB_STRING:
1694 ret = -EINVAL;
1695 goto end;
1696 default:
1697 ERR("Unknown filter register type (%d)",
1698 (int) estack_ax_t);
1699 ret = -EINVAL;
1700 goto end;
1701 }
1702 }
1703 OP(FILTER_OP_UNARY_MINUS):
1704 {
1705 /* Dynamic typing. */
1706 switch (estack_ax_t) {
1707 case REG_S64:
1708 JUMP_TO(FILTER_OP_UNARY_MINUS_S64);
1709 case REG_DOUBLE:
1710 JUMP_TO(FILTER_OP_UNARY_MINUS_DOUBLE);
1711 case REG_STRING: /* Fall-through */
1712 case REG_STAR_GLOB_STRING:
1713 ret = -EINVAL;
1714 goto end;
1715 default:
1716 ERR("Unknown filter register type (%d)",
1717 (int) estack_ax_t);
1718 ret = -EINVAL;
1719 goto end;
1720 }
1721 }
1722 OP(FILTER_OP_UNARY_NOT):
1723 {
1724 /* Dynamic typing. */
1725 switch (estack_ax_t) {
1726 case REG_S64:
1727 JUMP_TO(FILTER_OP_UNARY_NOT_S64);
1728 case REG_DOUBLE:
1729 JUMP_TO(FILTER_OP_UNARY_NOT_DOUBLE);
1730 case REG_STRING: /* Fall-through */
1731 case REG_STAR_GLOB_STRING:
1732 ret = -EINVAL;
1733 goto end;
1734 default:
1735 ERR("Unknown filter register type (%d)",
1736 (int) estack_ax_t);
1737 ret = -EINVAL;
1738 goto end;
1739 }
1740 next_pc += sizeof(struct unary_op);
1741 PO;
1742 }
1743
1744 OP(FILTER_OP_UNARY_BIT_NOT):
1745 {
1746 /* Dynamic typing. */
1747 if (estack_ax_t != REG_S64) {
1748 ret = -EINVAL;
1749 goto end;
1750 }
1751
1752 estack_ax_v = ~(uint64_t) estack_ax_v;
1753 next_pc += sizeof(struct unary_op);
1754 PO;
1755 }
1756
1757 OP(FILTER_OP_UNARY_PLUS_S64):
1758 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
1759 {
1760 next_pc += sizeof(struct unary_op);
1761 PO;
1762 }
1763 OP(FILTER_OP_UNARY_MINUS_S64):
1764 {
1765 estack_ax_v = -estack_ax_v;
1766 next_pc += sizeof(struct unary_op);
1767 PO;
1768 }
1769 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
1770 {
1771 estack_ax(stack, top)->u.d = -estack_ax(stack, top)->u.d;
1772 next_pc += sizeof(struct unary_op);
1773 PO;
1774 }
1775 OP(FILTER_OP_UNARY_NOT_S64):
1776 {
1777 estack_ax_v = !estack_ax_v;
1778 next_pc += sizeof(struct unary_op);
1779 PO;
1780 }
1781 OP(FILTER_OP_UNARY_NOT_DOUBLE):
1782 {
1783 estack_ax_v = !estack_ax(stack, top)->u.d;
1784 estack_ax_t = REG_S64;
1785 next_pc += sizeof(struct unary_op);
1786 PO;
1787 }
1788
1789 /* logical */
1790 OP(FILTER_OP_AND):
1791 {
1792 struct logical_op *insn = (struct logical_op *) pc;
1793
1794 if (estack_ax_t != REG_S64) {
1795 ret = -EINVAL;
1796 goto end;
1797 }
1798 /* If AX is 0, skip and evaluate to 0 */
1799 if (unlikely(estack_ax_v == 0)) {
1800 dbg_printf("Jumping to bytecode offset %u\n",
1801 (unsigned int) insn->skip_offset);
1802 next_pc = start_pc + insn->skip_offset;
1803 } else {
1804 /* Pop 1 when jump not taken */
1805 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1806 next_pc += sizeof(struct logical_op);
1807 }
1808 PO;
1809 }
1810 OP(FILTER_OP_OR):
1811 {
1812 struct logical_op *insn = (struct logical_op *) pc;
1813
1814 if (estack_ax_t != REG_S64) {
1815 ret = -EINVAL;
1816 goto end;
1817 }
1818 /* If AX is nonzero, skip and evaluate to 1 */
1819 if (unlikely(estack_ax_v != 0)) {
1820 estack_ax_v = 1;
1821 dbg_printf("Jumping to bytecode offset %u\n",
1822 (unsigned int) insn->skip_offset);
1823 next_pc = start_pc + insn->skip_offset;
1824 } else {
1825 /* Pop 1 when jump not taken */
1826 estack_pop(stack, top, ax, bx, ax_t, bx_t);
1827 next_pc += sizeof(struct logical_op);
1828 }
1829 PO;
1830 }
1831
1832
1833 /* load field ref */
1834 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
1835 {
1836 struct load_op *insn = (struct load_op *) pc;
1837 struct field_ref *ref = (struct field_ref *) insn->data;
1838
1839 dbg_printf("load field ref offset %u type string\n",
1840 ref->offset);
1841 estack_push(stack, top, ax, bx, ax_t, bx_t);
1842 estack_ax(stack, top)->u.s.str =
1843 *(const char * const *) &filter_stack_data[ref->offset];
1844 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1845 dbg_printf("Filter warning: loading a NULL string.\n");
1846 ret = -EINVAL;
1847 goto end;
1848 }
1849 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
1850 estack_ax(stack, top)->u.s.literal_type =
1851 ESTACK_STRING_LITERAL_TYPE_NONE;
1852 estack_ax_t = REG_STRING;
1853 dbg_printf("ref load string %s\n", estack_ax(stack, top)->u.s.str);
1854 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1855 PO;
1856 }
1857
1858 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
1859 {
1860 struct load_op *insn = (struct load_op *) pc;
1861 struct field_ref *ref = (struct field_ref *) insn->data;
1862
1863 dbg_printf("load field ref offset %u type sequence\n",
1864 ref->offset);
1865 estack_push(stack, top, ax, bx, ax_t, bx_t);
1866 estack_ax(stack, top)->u.s.seq_len =
1867 *(unsigned long *) &filter_stack_data[ref->offset];
1868 estack_ax(stack, top)->u.s.str =
1869 *(const char **) (&filter_stack_data[ref->offset
1870 + sizeof(unsigned long)]);
1871 estack_ax_t = REG_STRING;
1872 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1873 dbg_printf("Filter warning: loading a NULL sequence.\n");
1874 ret = -EINVAL;
1875 goto end;
1876 }
1877 estack_ax(stack, top)->u.s.literal_type =
1878 ESTACK_STRING_LITERAL_TYPE_NONE;
1879 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1880 PO;
1881 }
1882
1883 OP(FILTER_OP_LOAD_FIELD_REF_S64):
1884 {
1885 struct load_op *insn = (struct load_op *) pc;
1886 struct field_ref *ref = (struct field_ref *) insn->data;
1887
1888 dbg_printf("load field ref offset %u type s64\n",
1889 ref->offset);
1890 estack_push(stack, top, ax, bx, ax_t, bx_t);
1891 estack_ax_v =
1892 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
1893 estack_ax_t = REG_S64;
1894 dbg_printf("ref load s64 %" PRIi64 "\n", estack_ax_v);
1895 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1896 PO;
1897 }
1898
1899 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
1900 {
1901 struct load_op *insn = (struct load_op *) pc;
1902 struct field_ref *ref = (struct field_ref *) insn->data;
1903
1904 dbg_printf("load field ref offset %u type double\n",
1905 ref->offset);
1906 estack_push(stack, top, ax, bx, ax_t, bx_t);
1907 memcpy(&estack_ax(stack, top)->u.d, &filter_stack_data[ref->offset],
1908 sizeof(struct literal_double));
1909 estack_ax_t = REG_DOUBLE;
1910 dbg_printf("ref load double %g\n", estack_ax(stack, top)->u.d);
1911 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1912 PO;
1913 }
1914
1915 /* load from immediate operand */
1916 OP(FILTER_OP_LOAD_STRING):
1917 {
1918 struct load_op *insn = (struct load_op *) pc;
1919
1920 dbg_printf("load string %s\n", insn->data);
1921 estack_push(stack, top, ax, bx, ax_t, bx_t);
1922 estack_ax(stack, top)->u.s.str = insn->data;
1923 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
1924 estack_ax(stack, top)->u.s.literal_type =
1925 ESTACK_STRING_LITERAL_TYPE_PLAIN;
1926 estack_ax_t = REG_STRING;
1927 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1928 PO;
1929 }
1930
1931 OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
1932 {
1933 struct load_op *insn = (struct load_op *) pc;
1934
1935 dbg_printf("load globbing pattern %s\n", insn->data);
1936 estack_push(stack, top, ax, bx, ax_t, bx_t);
1937 estack_ax(stack, top)->u.s.str = insn->data;
1938 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
1939 estack_ax(stack, top)->u.s.literal_type =
1940 ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
1941 estack_ax_t = REG_STAR_GLOB_STRING;
1942 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1943 PO;
1944 }
1945
1946 OP(FILTER_OP_LOAD_S64):
1947 {
1948 struct load_op *insn = (struct load_op *) pc;
1949
1950 estack_push(stack, top, ax, bx, ax_t, bx_t);
1951 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
1952 estack_ax_t = REG_S64;
1953 dbg_printf("load s64 %" PRIi64 "\n", estack_ax_v);
1954 next_pc += sizeof(struct load_op)
1955 + sizeof(struct literal_numeric);
1956 PO;
1957 }
1958
1959 OP(FILTER_OP_LOAD_DOUBLE):
1960 {
1961 struct load_op *insn = (struct load_op *) pc;
1962
1963 estack_push(stack, top, ax, bx, ax_t, bx_t);
1964 memcpy(&estack_ax(stack, top)->u.d, insn->data,
1965 sizeof(struct literal_double));
1966 estack_ax_t = REG_DOUBLE;
1967 dbg_printf("load double %g\n", estack_ax(stack, top)->u.d);
1968 next_pc += sizeof(struct load_op)
1969 + sizeof(struct literal_double);
1970 PO;
1971 }
1972
1973 /* cast */
1974 OP(FILTER_OP_CAST_TO_S64):
1975 {
1976 /* Dynamic typing. */
1977 switch (estack_ax_t) {
1978 case REG_S64:
1979 JUMP_TO(FILTER_OP_CAST_NOP);
1980 case REG_DOUBLE:
1981 JUMP_TO(FILTER_OP_CAST_DOUBLE_TO_S64);
1982 case REG_STRING: /* Fall-through */
1983 case REG_STAR_GLOB_STRING:
1984 ret = -EINVAL;
1985 goto end;
1986 default:
1987 ERR("Unknown filter register type (%d)",
1988 (int) estack_ax_t);
1989 ret = -EINVAL;
1990 goto end;
1991 }
1992 }
1993
1994 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
1995 {
1996 estack_ax_v = (int64_t) estack_ax(stack, top)->u.d;
1997 estack_ax_t = REG_S64;
1998 next_pc += sizeof(struct cast_op);
1999 PO;
2000 }
2001
2002 OP(FILTER_OP_CAST_NOP):
2003 {
2004 next_pc += sizeof(struct cast_op);
2005 PO;
2006 }
2007
2008 /* get context ref */
2009 OP(FILTER_OP_GET_CONTEXT_REF):
2010 {
2011 struct load_op *insn = (struct load_op *) pc;
2012 struct field_ref *ref = (struct field_ref *) insn->data;
2013 struct lttng_ctx_field *ctx_field;
2014 struct lttng_ctx_value v;
2015
2016 dbg_printf("get context ref offset %u type dynamic\n",
2017 ref->offset);
2018 ctx_field = &ctx->fields[ref->offset];
2019 ctx_field->get_value(ctx_field, &v);
2020 estack_push(stack, top, ax, bx, ax_t, bx_t);
2021 switch (v.sel) {
2022 case LTTNG_UST_DYNAMIC_TYPE_NONE:
2023 ret = -EINVAL;
2024 goto end;
2025 case LTTNG_UST_DYNAMIC_TYPE_S64:
2026 estack_ax_v = v.u.s64;
2027 estack_ax_t = REG_S64;
2028 dbg_printf("ref get context dynamic s64 %" PRIi64 "\n", estack_ax_v);
2029 break;
2030 case LTTNG_UST_DYNAMIC_TYPE_DOUBLE:
2031 estack_ax(stack, top)->u.d = v.u.d;
2032 estack_ax_t = REG_DOUBLE;
2033 dbg_printf("ref get context dynamic double %g\n", estack_ax(stack, top)->u.d);
2034 break;
2035 case LTTNG_UST_DYNAMIC_TYPE_STRING:
2036 estack_ax(stack, top)->u.s.str = v.u.str;
2037 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
2038 dbg_printf("Filter warning: loading a NULL string.\n");
2039 ret = -EINVAL;
2040 goto end;
2041 }
2042 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
2043 estack_ax(stack, top)->u.s.literal_type =
2044 ESTACK_STRING_LITERAL_TYPE_NONE;
2045 dbg_printf("ref get context dynamic string %s\n", estack_ax(stack, top)->u.s.str);
2046 estack_ax_t = REG_STRING;
2047 break;
2048 default:
2049 dbg_printf("Filter warning: unknown dynamic type (%d).\n", (int) v.sel);
2050 ret = -EINVAL;
2051 goto end;
2052 }
2053 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
2054 PO;
2055 }
2056
2057 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
2058 {
2059 struct load_op *insn = (struct load_op *) pc;
2060 struct field_ref *ref = (struct field_ref *) insn->data;
2061 struct lttng_ctx_field *ctx_field;
2062 struct lttng_ctx_value v;
2063
2064 dbg_printf("get context ref offset %u type string\n",
2065 ref->offset);
2066 ctx_field = &ctx->fields[ref->offset];
2067 ctx_field->get_value(ctx_field, &v);
2068 estack_push(stack, top, ax, bx, ax_t, bx_t);
2069 estack_ax(stack, top)->u.s.str = v.u.str;
2070 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
2071 dbg_printf("Filter warning: loading a NULL string.\n");
2072 ret = -EINVAL;
2073 goto end;
2074 }
2075 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
2076 estack_ax(stack, top)->u.s.literal_type =
2077 ESTACK_STRING_LITERAL_TYPE_NONE;
2078 estack_ax_t = REG_STRING;
2079 dbg_printf("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
2080 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
2081 PO;
2082 }
2083
2084 OP(FILTER_OP_GET_CONTEXT_REF_S64):
2085 {
2086 struct load_op *insn = (struct load_op *) pc;
2087 struct field_ref *ref = (struct field_ref *) insn->data;
2088 struct lttng_ctx_field *ctx_field;
2089 struct lttng_ctx_value v;
2090
2091 dbg_printf("get context ref offset %u type s64\n",
2092 ref->offset);
2093 ctx_field = &ctx->fields[ref->offset];
2094 ctx_field->get_value(ctx_field, &v);
2095 estack_push(stack, top, ax, bx, ax_t, bx_t);
2096 estack_ax_v = v.u.s64;
2097 estack_ax_t = REG_S64;
2098 dbg_printf("ref get context s64 %" PRIi64 "\n", estack_ax_v);
2099 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
2100 PO;
2101 }
2102
2103 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
2104 {
2105 struct load_op *insn = (struct load_op *) pc;
2106 struct field_ref *ref = (struct field_ref *) insn->data;
2107 struct lttng_ctx_field *ctx_field;
2108 struct lttng_ctx_value v;
2109
2110 dbg_printf("get context ref offset %u type double\n",
2111 ref->offset);
2112 ctx_field = &ctx->fields[ref->offset];
2113 ctx_field->get_value(ctx_field, &v);
2114 estack_push(stack, top, ax, bx, ax_t, bx_t);
2115 memcpy(&estack_ax(stack, top)->u.d, &v.u.d, sizeof(struct literal_double));
2116 estack_ax_t = REG_DOUBLE;
2117 dbg_printf("ref get context double %g\n", estack_ax(stack, top)->u.d);
2118 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
2119 PO;
2120 }
2121
2122 OP(FILTER_OP_GET_CONTEXT_ROOT):
2123 {
2124 dbg_printf("op get context root\n");
2125 estack_push(stack, top, ax, bx, ax_t, bx_t);
2126 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_CONTEXT;
2127 /* "field" only needed for variants. */
2128 estack_ax(stack, top)->u.ptr.field = NULL;
2129 estack_ax_t = REG_PTR;
2130 next_pc += sizeof(struct load_op);
2131 PO;
2132 }
2133
2134 OP(FILTER_OP_GET_APP_CONTEXT_ROOT):
2135 {
2136 dbg_printf("op get app context root\n");
2137 estack_push(stack, top, ax, bx, ax_t, bx_t);
2138 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_APP_CONTEXT;
2139 /* "field" only needed for variants. */
2140 estack_ax(stack, top)->u.ptr.field = NULL;
2141 estack_ax_t = REG_PTR;
2142 next_pc += sizeof(struct load_op);
2143 PO;
2144 }
2145
2146 OP(FILTER_OP_GET_PAYLOAD_ROOT):
2147 {
2148 dbg_printf("op get app payload root\n");
2149 estack_push(stack, top, ax, bx, ax_t, bx_t);
2150 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_PAYLOAD;
2151 estack_ax(stack, top)->u.ptr.ptr = filter_stack_data;
2152 /* "field" only needed for variants. */
2153 estack_ax(stack, top)->u.ptr.field = NULL;
2154 estack_ax_t = REG_PTR;
2155 next_pc += sizeof(struct load_op);
2156 PO;
2157 }
2158
2159 OP(FILTER_OP_GET_SYMBOL):
2160 {
2161 dbg_printf("op get symbol\n");
2162 switch (estack_ax(stack, top)->u.ptr.type) {
2163 case LOAD_OBJECT:
2164 ERR("Nested fields not implemented yet.");
2165 ret = -EINVAL;
2166 goto end;
2167 case LOAD_ROOT_CONTEXT:
2168 case LOAD_ROOT_APP_CONTEXT:
2169 case LOAD_ROOT_PAYLOAD:
2170 /*
2171 * symbol lookup is performed by
2172 * specialization.
2173 */
2174 ret = -EINVAL;
2175 goto end;
2176 }
2177 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
2178 PO;
2179 }
2180
2181 OP(FILTER_OP_GET_SYMBOL_FIELD):
2182 {
2183 /*
2184 * Used for first variant encountered in a
2185 * traversal. Variants are not implemented yet.
2186 */
2187 ret = -EINVAL;
2188 goto end;
2189 }
2190
2191 OP(FILTER_OP_GET_INDEX_U16):
2192 {
2193 struct load_op *insn = (struct load_op *) pc;
2194 struct get_index_u16 *index = (struct get_index_u16 *) insn->data;
2195
2196 dbg_printf("op get index u16\n");
2197 ret = dynamic_get_index(ctx, bytecode, index->index, estack_ax(stack, top));
2198 if (ret)
2199 goto end;
2200 estack_ax_v = estack_ax(stack, top)->u.v;
2201 estack_ax_t = estack_ax(stack, top)->type;
2202 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
2203 PO;
2204 }
2205
2206 OP(FILTER_OP_GET_INDEX_U64):
2207 {
2208 struct load_op *insn = (struct load_op *) pc;
2209 struct get_index_u64 *index = (struct get_index_u64 *) insn->data;
2210
2211 dbg_printf("op get index u64\n");
2212 ret = dynamic_get_index(ctx, bytecode, index->index, estack_ax(stack, top));
2213 if (ret)
2214 goto end;
2215 estack_ax_v = estack_ax(stack, top)->u.v;
2216 estack_ax_t = estack_ax(stack, top)->type;
2217 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
2218 PO;
2219 }
2220
2221 OP(FILTER_OP_LOAD_FIELD):
2222 {
2223 dbg_printf("op load field\n");
2224 ret = dynamic_load_field(estack_ax(stack, top));
2225 if (ret)
2226 goto end;
2227 estack_ax_v = estack_ax(stack, top)->u.v;
2228 estack_ax_t = estack_ax(stack, top)->type;
2229 next_pc += sizeof(struct load_op);
2230 PO;
2231 }
2232
2233 OP(FILTER_OP_LOAD_FIELD_S8):
2234 {
2235 dbg_printf("op load field s8\n");
2236
2237 estack_ax_v = *(int8_t *) estack_ax(stack, top)->u.ptr.ptr;
2238 estack_ax_t = REG_S64;
2239 next_pc += sizeof(struct load_op);
2240 PO;
2241 }
2242 OP(FILTER_OP_LOAD_FIELD_S16):
2243 {
2244 dbg_printf("op load field s16\n");
2245
2246 estack_ax_v = *(int16_t *) estack_ax(stack, top)->u.ptr.ptr;
2247 estack_ax_t = REG_S64;
2248 next_pc += sizeof(struct load_op);
2249 PO;
2250 }
2251 OP(FILTER_OP_LOAD_FIELD_S32):
2252 {
2253 dbg_printf("op load field s32\n");
2254
2255 estack_ax_v = *(int32_t *) estack_ax(stack, top)->u.ptr.ptr;
2256 estack_ax_t = REG_S64;
2257 next_pc += sizeof(struct load_op);
2258 PO;
2259 }
2260 OP(FILTER_OP_LOAD_FIELD_S64):
2261 {
2262 dbg_printf("op load field s64\n");
2263
2264 estack_ax_v = *(int64_t *) estack_ax(stack, top)->u.ptr.ptr;
2265 estack_ax_t = REG_S64;
2266 next_pc += sizeof(struct load_op);
2267 PO;
2268 }
2269 OP(FILTER_OP_LOAD_FIELD_U8):
2270 {
2271 dbg_printf("op load field u8\n");
2272
2273 estack_ax_v = *(uint8_t *) estack_ax(stack, top)->u.ptr.ptr;
2274 estack_ax_t = REG_S64;
2275 next_pc += sizeof(struct load_op);
2276 PO;
2277 }
2278 OP(FILTER_OP_LOAD_FIELD_U16):
2279 {
2280 dbg_printf("op load field u16\n");
2281
2282 estack_ax_v = *(uint16_t *) estack_ax(stack, top)->u.ptr.ptr;
2283 estack_ax_t = REG_S64;
2284 next_pc += sizeof(struct load_op);
2285 PO;
2286 }
2287 OP(FILTER_OP_LOAD_FIELD_U32):
2288 {
2289 dbg_printf("op load field u32\n");
2290
2291 estack_ax_v = *(uint32_t *) estack_ax(stack, top)->u.ptr.ptr;
2292 estack_ax_t = REG_S64;
2293 next_pc += sizeof(struct load_op);
2294 PO;
2295 }
2296 OP(FILTER_OP_LOAD_FIELD_U64):
2297 {
2298 dbg_printf("op load field u64\n");
2299
2300 estack_ax_v = *(uint64_t *) estack_ax(stack, top)->u.ptr.ptr;
2301 estack_ax_t = REG_S64;
2302 next_pc += sizeof(struct load_op);
2303 PO;
2304 }
2305 OP(FILTER_OP_LOAD_FIELD_DOUBLE):
2306 {
2307 dbg_printf("op load field double\n");
2308
2309 memcpy(&estack_ax(stack, top)->u.d,
2310 estack_ax(stack, top)->u.ptr.ptr,
2311 sizeof(struct literal_double));
2312 estack_ax(stack, top)->type = REG_DOUBLE;
2313 next_pc += sizeof(struct load_op);
2314 PO;
2315 }
2316
2317 OP(FILTER_OP_LOAD_FIELD_STRING):
2318 {
2319 const char *str;
2320
2321 dbg_printf("op load field string\n");
2322 str = (const char *) estack_ax(stack, top)->u.ptr.ptr;
2323 estack_ax(stack, top)->u.s.str = str;
2324 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
2325 dbg_printf("Filter warning: loading a NULL string.\n");
2326 ret = -EINVAL;
2327 goto end;
2328 }
2329 estack_ax(stack, top)->u.s.seq_len = SIZE_MAX;
2330 estack_ax(stack, top)->u.s.literal_type =
2331 ESTACK_STRING_LITERAL_TYPE_NONE;
2332 estack_ax(stack, top)->type = REG_STRING;
2333 next_pc += sizeof(struct load_op);
2334 PO;
2335 }
2336
2337 OP(FILTER_OP_LOAD_FIELD_SEQUENCE):
2338 {
2339 const char *ptr;
2340
2341 dbg_printf("op load field string sequence\n");
2342 ptr = estack_ax(stack, top)->u.ptr.ptr;
2343 estack_ax(stack, top)->u.s.seq_len = *(unsigned long *) ptr;
2344 estack_ax(stack, top)->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
2345 estack_ax(stack, top)->type = REG_STRING;
2346 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
2347 dbg_printf("Filter warning: loading a NULL sequence.\n");
2348 ret = -EINVAL;
2349 goto end;
2350 }
2351 estack_ax(stack, top)->u.s.literal_type =
2352 ESTACK_STRING_LITERAL_TYPE_NONE;
2353 next_pc += sizeof(struct load_op);
2354 PO;
2355 }
2356
2357 END_OP
2358 end:
2359 /* Return _DISCARD on error. */
2360 if (ret)
2361 return LTTNG_FILTER_DISCARD;
2362 return retval;
2363 }
2364
2365 #undef START_OP
2366 #undef OP
2367 #undef PO
2368 #undef END_OP
This page took 0.110726 seconds and 4 git commands to generate.