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