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