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