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