Cleanup: Move lttng-modules instrumentation headers
[lttng-modules.git] / lttng-filter-interpreter.c
CommitLineData
9f36eaed
MJ
1/* SPDX-License-Identifier: MIT
2 *
07dfc1d0
MD
3 * lttng-filter-interpreter.c
4 *
5 * LTTng modules filter interpreter.
6 *
bbf3aef5 7 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
07dfc1d0
MD
8 */
9
80bb2600 10#include <wrapper/uaccess.h>
63155590 11#include <wrapper/frame.h>
cbc19040 12#include <wrapper/types.h>
3834b99f 13#include <linux/swab.h>
f127e61e 14
2df37e95
MD
15#include <lttng/filter.h>
16#include <lttng/string-utils.h>
07dfc1d0 17
63155590
MD
18LTTNG_STACK_FRAME_NON_STANDARD(lttng_filter_interpret_bytecode);
19
f127e61e
MD
20/*
21 * get_char should be called with page fault handler disabled if it is expected
22 * to handle user-space read.
23 */
24static
25char get_char(struct estack_entry *reg, size_t offset)
26{
27 if (unlikely(offset >= reg->u.s.seq_len))
28 return '\0';
29 if (reg->u.s.user) {
30 char c;
31
32 /* Handle invalid access as end of string. */
80bb2600 33 if (unlikely(!lttng_access_ok(VERIFY_READ,
f127e61e
MD
34 reg->u.s.user_str + offset,
35 sizeof(c))))
36 return '\0';
37 /* Handle fault (nonzero return value) as end of string. */
38 if (unlikely(__copy_from_user_inatomic(&c,
39 reg->u.s.user_str + offset,
40 sizeof(c))))
41 return '\0';
42 return c;
43 } else {
44 return reg->u.s.str[offset];
45 }
46}
47
07dfc1d0
MD
48/*
49 * -1: wildcard found.
50 * -2: unknown escape char.
51 * 0: normal char.
52 */
07dfc1d0 53static
f127e61e 54int parse_char(struct estack_entry *reg, char *c, size_t *offset)
07dfc1d0 55{
f127e61e 56 switch (*c) {
07dfc1d0 57 case '\\':
f127e61e
MD
58 (*offset)++;
59 *c = get_char(reg, *offset);
60 switch (*c) {
07dfc1d0
MD
61 case '\\':
62 case '*':
63 return 0;
64 default:
65 return -2;
66 }
67 case '*':
68 return -1;
69 default:
70 return 0;
71 }
72}
73
02aca193
PP
74static
75char get_char_at_cb(size_t at, void *data)
76{
77 return get_char(data, at);
78}
79
80static
81int stack_star_glob_match(struct estack *stack, int top, const char *cmp_type)
82{
83 bool has_user = false;
84 mm_segment_t old_fs;
85 int result;
86 struct estack_entry *pattern_reg;
87 struct estack_entry *candidate_reg;
88
89 if (estack_bx(stack, top)->u.s.user
90 || estack_ax(stack, top)->u.s.user) {
91 has_user = true;
92 old_fs = get_fs();
93 set_fs(KERNEL_DS);
94 pagefault_disable();
95 }
96
97 /* Find out which side is the pattern vs. the candidate. */
98 if (estack_ax(stack, top)->u.s.literal_type == ESTACK_STRING_LITERAL_TYPE_STAR_GLOB) {
99 pattern_reg = estack_ax(stack, top);
100 candidate_reg = estack_bx(stack, top);
101 } else {
102 pattern_reg = estack_bx(stack, top);
103 candidate_reg = estack_ax(stack, top);
104 }
105
106 /* Perform the match operation. */
107 result = !strutils_star_glob_match_char_cb(get_char_at_cb,
108 pattern_reg, get_char_at_cb, candidate_reg);
109 if (has_user) {
110 pagefault_enable();
111 set_fs(old_fs);
112 }
113
114 return result;
115}
116
07dfc1d0
MD
117static
118int stack_strcmp(struct estack *stack, int top, const char *cmp_type)
119{
f127e61e
MD
120 size_t offset_bx = 0, offset_ax = 0;
121 int diff, has_user = 0;
122 mm_segment_t old_fs;
123
124 if (estack_bx(stack, top)->u.s.user
125 || estack_ax(stack, top)->u.s.user) {
126 has_user = 1;
127 old_fs = get_fs();
128 set_fs(KERNEL_DS);
129 pagefault_disable();
130 }
07dfc1d0
MD
131
132 for (;;) {
f127e61e 133 int ret;
07dfc1d0 134 int escaped_r0 = 0;
f127e61e 135 char char_bx, char_ax;
07dfc1d0 136
f127e61e
MD
137 char_bx = get_char(estack_bx(stack, top), offset_bx);
138 char_ax = get_char(estack_ax(stack, top), offset_ax);
139
140 if (unlikely(char_bx == '\0')) {
141 if (char_ax == '\0') {
142 diff = 0;
143 break;
07dfc1d0 144 } else {
02aca193
PP
145 if (estack_ax(stack, top)->u.s.literal_type ==
146 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
147 ret = parse_char(estack_ax(stack, top),
148 &char_ax, &offset_ax);
149 if (ret == -1) {
150 diff = 0;
151 break;
152 }
07dfc1d0 153 }
f127e61e
MD
154 diff = -1;
155 break;
07dfc1d0
MD
156 }
157 }
f127e61e 158 if (unlikely(char_ax == '\0')) {
02aca193
PP
159 if (estack_bx(stack, top)->u.s.literal_type ==
160 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
abfd272b
MD
161 ret = parse_char(estack_bx(stack, top),
162 &char_bx, &offset_bx);
163 if (ret == -1) {
164 diff = 0;
165 break;
07dfc1d0 166 }
07dfc1d0 167 }
abfd272b
MD
168 diff = 1;
169 break;
07dfc1d0 170 }
02aca193
PP
171 if (estack_bx(stack, top)->u.s.literal_type ==
172 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
173 ret = parse_char(estack_bx(stack, top),
174 &char_bx, &offset_bx);
07dfc1d0 175 if (ret == -1) {
f127e61e
MD
176 diff = 0;
177 break;
07dfc1d0
MD
178 } else if (ret == -2) {
179 escaped_r0 = 1;
180 }
181 /* else compare both char */
182 }
02aca193
PP
183 if (estack_ax(stack, top)->u.s.literal_type ==
184 ESTACK_STRING_LITERAL_TYPE_PLAIN) {
f127e61e
MD
185 ret = parse_char(estack_ax(stack, top),
186 &char_ax, &offset_ax);
07dfc1d0 187 if (ret == -1) {
f127e61e
MD
188 diff = 0;
189 break;
07dfc1d0 190 } else if (ret == -2) {
f127e61e
MD
191 if (!escaped_r0) {
192 diff = -1;
193 break;
194 }
07dfc1d0 195 } else {
f127e61e
MD
196 if (escaped_r0) {
197 diff = 1;
198 break;
199 }
07dfc1d0
MD
200 }
201 } else {
f127e61e
MD
202 if (escaped_r0) {
203 diff = 1;
204 break;
205 }
07dfc1d0 206 }
f127e61e 207 diff = char_bx - char_ax;
07dfc1d0
MD
208 if (diff != 0)
209 break;
f127e61e
MD
210 offset_bx++;
211 offset_ax++;
212 }
213 if (has_user) {
214 pagefault_enable();
215 set_fs(old_fs);
07dfc1d0
MD
216 }
217 return diff;
218}
219
220uint64_t lttng_filter_false(void *filter_data,
79150a49 221 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
222 const char *filter_stack_data)
223{
224 return 0;
225}
226
227#ifdef INTERPRETER_USE_SWITCH
228
229/*
230 * Fallback for compilers that do not support taking address of labels.
231 */
232
233#define START_OP \
234 start_pc = &bytecode->data[0]; \
235 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len; \
236 pc = next_pc) { \
237 dbg_printk("Executing op %s (%u)\n", \
238 lttng_filter_print_op((unsigned int) *(filter_opcode_t *) pc), \
239 (unsigned int) *(filter_opcode_t *) pc); \
240 switch (*(filter_opcode_t *) pc) {
241
242#define OP(name) case name
243
244#define PO break
245
246#define END_OP } \
247 }
248
249#else
250
251/*
252 * Dispatch-table based interpreter.
253 */
254
255#define START_OP \
3834b99f 256 start_pc = &bytecode->code[0]; \
07dfc1d0
MD
257 pc = next_pc = start_pc; \
258 if (unlikely(pc - start_pc >= bytecode->len)) \
259 goto end; \
260 goto *dispatch[*(filter_opcode_t *) pc];
261
262#define OP(name) \
263LABEL_##name
264
265#define PO \
266 pc = next_pc; \
267 goto *dispatch[*(filter_opcode_t *) pc];
268
269#define END_OP
270
271#endif
272
3834b99f
MD
273static int context_get_index(struct lttng_probe_ctx *lttng_probe_ctx,
274 struct load_ptr *ptr,
275 uint32_t idx)
276{
277
278 struct lttng_ctx_field *ctx_field;
279 struct lttng_event_field *field;
280 union lttng_ctx_value v;
281
282 ctx_field = &lttng_static_ctx->fields[idx];
283 field = &ctx_field->event_field;
284 ptr->type = LOAD_OBJECT;
285 /* field is only used for types nested within variants. */
286 ptr->field = NULL;
287
288 switch (field->type.atype) {
289 case atype_integer:
290 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
ceabb767 291 if (field->type.u.integer.signedness) {
3834b99f
MD
292 ptr->object_type = OBJECT_TYPE_S64;
293 ptr->u.s64 = v.s64;
294 ptr->ptr = &ptr->u.s64;
295 } else {
296 ptr->object_type = OBJECT_TYPE_U64;
297 ptr->u.u64 = v.s64; /* Cast. */
298 ptr->ptr = &ptr->u.u64;
299 }
300 break;
ceabb767 301 case atype_enum_nestable:
3834b99f
MD
302 {
303 const struct lttng_integer_type *itype =
ceabb767 304 &field->type.u.enum_nestable.container_type->u.integer;
3834b99f
MD
305
306 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
307 if (itype->signedness) {
308 ptr->object_type = OBJECT_TYPE_S64;
309 ptr->u.s64 = v.s64;
310 ptr->ptr = &ptr->u.s64;
311 } else {
312 ptr->object_type = OBJECT_TYPE_U64;
313 ptr->u.u64 = v.s64; /* Cast. */
314 ptr->ptr = &ptr->u.u64;
315 }
316 break;
317 }
ceabb767
MD
318 case atype_array_nestable:
319 if (!lttng_is_bytewise_integer(field->type.u.array_nestable.elem_type)) {
3834b99f
MD
320 printk(KERN_WARNING "Array nesting only supports integer types.\n");
321 return -EINVAL;
322 }
ceabb767 323 if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
3834b99f
MD
324 printk(KERN_WARNING "Only string arrays are supported for contexts.\n");
325 return -EINVAL;
326 }
327 ptr->object_type = OBJECT_TYPE_STRING;
328 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
329 ptr->ptr = v.str;
330 break;
ceabb767
MD
331 case atype_sequence_nestable:
332 if (!lttng_is_bytewise_integer(field->type.u.sequence_nestable.elem_type)) {
3834b99f
MD
333 printk(KERN_WARNING "Sequence nesting only supports integer types.\n");
334 return -EINVAL;
335 }
ceabb767 336 if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
3834b99f
MD
337 printk(KERN_WARNING "Only string sequences are supported for contexts.\n");
338 return -EINVAL;
339 }
340 ptr->object_type = OBJECT_TYPE_STRING;
341 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
342 ptr->ptr = v.str;
343 break;
3834b99f
MD
344 case atype_string:
345 ptr->object_type = OBJECT_TYPE_STRING;
346 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
347 ptr->ptr = v.str;
348 break;
ceabb767 349 case atype_struct_nestable:
3834b99f
MD
350 printk(KERN_WARNING "Structure type cannot be loaded.\n");
351 return -EINVAL;
ceabb767
MD
352 case atype_variant_nestable:
353 printk(KERN_WARNING "Variant type cannot be loaded.\n");
354 return -EINVAL;
3834b99f
MD
355 default:
356 printk(KERN_WARNING "Unknown type: %d", (int) field->type.atype);
357 return -EINVAL;
358 }
359 return 0;
360}
361
362static int dynamic_get_index(struct lttng_probe_ctx *lttng_probe_ctx,
363 struct bytecode_runtime *runtime,
364 uint64_t index, struct estack_entry *stack_top)
365{
366 int ret;
367 const struct filter_get_index_data *gid;
368
369 /*
370 * Types nested within variants need to perform dynamic lookup
371 * based on the field descriptions. LTTng-UST does not implement
372 * variants for now.
373 */
374 if (stack_top->u.ptr.field)
375 return -EINVAL;
376 gid = (const struct filter_get_index_data *) &runtime->data[index];
377 switch (stack_top->u.ptr.type) {
378 case LOAD_OBJECT:
379 switch (stack_top->u.ptr.object_type) {
380 case OBJECT_TYPE_ARRAY:
381 {
382 const char *ptr;
383
384 WARN_ON_ONCE(gid->offset >= gid->array_len);
385 /* Skip count (unsigned long) */
386 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
387 ptr = ptr + gid->offset;
388 stack_top->u.ptr.ptr = ptr;
389 stack_top->u.ptr.object_type = gid->elem.type;
390 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
391 /* field is only used for types nested within variants. */
392 stack_top->u.ptr.field = NULL;
393 break;
394 }
395 case OBJECT_TYPE_SEQUENCE:
396 {
397 const char *ptr;
398 size_t ptr_seq_len;
399
400 ptr = *(const char **) (stack_top->u.ptr.ptr + sizeof(unsigned long));
401 ptr_seq_len = *(unsigned long *) stack_top->u.ptr.ptr;
402 if (gid->offset >= gid->elem.len * ptr_seq_len) {
403 ret = -EINVAL;
404 goto end;
405 }
406 ptr = ptr + gid->offset;
407 stack_top->u.ptr.ptr = ptr;
408 stack_top->u.ptr.object_type = gid->elem.type;
409 stack_top->u.ptr.rev_bo = gid->elem.rev_bo;
410 /* field is only used for types nested within variants. */
411 stack_top->u.ptr.field = NULL;
412 break;
413 }
414 case OBJECT_TYPE_STRUCT:
415 printk(KERN_WARNING "Nested structures are not supported yet.\n");
416 ret = -EINVAL;
417 goto end;
418 case OBJECT_TYPE_VARIANT:
419 default:
420 printk(KERN_WARNING "Unexpected get index type %d",
421 (int) stack_top->u.ptr.object_type);
422 ret = -EINVAL;
423 goto end;
424 }
425 break;
426 case LOAD_ROOT_CONTEXT:
427 case LOAD_ROOT_APP_CONTEXT: /* Fall-through */
428 {
429 ret = context_get_index(lttng_probe_ctx,
430 &stack_top->u.ptr,
431 gid->ctx_index);
432 if (ret) {
433 goto end;
434 }
435 break;
436 }
437 case LOAD_ROOT_PAYLOAD:
438 stack_top->u.ptr.ptr += gid->offset;
439 if (gid->elem.type == OBJECT_TYPE_STRING)
440 stack_top->u.ptr.ptr = *(const char * const *) stack_top->u.ptr.ptr;
441 stack_top->u.ptr.object_type = gid->elem.type;
442 stack_top->u.ptr.type = LOAD_OBJECT;
443 /* field is only used for types nested within variants. */
444 stack_top->u.ptr.field = NULL;
445 break;
446 }
447 return 0;
448
449end:
450 return ret;
451}
452
453static int dynamic_load_field(struct estack_entry *stack_top)
454{
455 int ret;
456
457 switch (stack_top->u.ptr.type) {
458 case LOAD_OBJECT:
459 break;
460 case LOAD_ROOT_CONTEXT:
461 case LOAD_ROOT_APP_CONTEXT:
462 case LOAD_ROOT_PAYLOAD:
463 default:
464 dbg_printk("Filter warning: cannot load root, missing field name.\n");
465 ret = -EINVAL;
466 goto end;
467 }
468 switch (stack_top->u.ptr.object_type) {
469 case OBJECT_TYPE_S8:
470 dbg_printk("op load field s8\n");
471 stack_top->u.v = *(int8_t *) stack_top->u.ptr.ptr;
472 break;
473 case OBJECT_TYPE_S16:
474 {
475 int16_t tmp;
476
477 dbg_printk("op load field s16\n");
478 tmp = *(int16_t *) stack_top->u.ptr.ptr;
479 if (stack_top->u.ptr.rev_bo)
480 __swab16s(&tmp);
481 stack_top->u.v = tmp;
482 break;
483 }
484 case OBJECT_TYPE_S32:
485 {
486 int32_t tmp;
487
488 dbg_printk("op load field s32\n");
489 tmp = *(int32_t *) stack_top->u.ptr.ptr;
490 if (stack_top->u.ptr.rev_bo)
491 __swab32s(&tmp);
492 stack_top->u.v = tmp;
493 break;
494 }
495 case OBJECT_TYPE_S64:
496 {
497 int64_t tmp;
498
499 dbg_printk("op load field s64\n");
500 tmp = *(int64_t *) stack_top->u.ptr.ptr;
501 if (stack_top->u.ptr.rev_bo)
502 __swab64s(&tmp);
503 stack_top->u.v = tmp;
504 break;
505 }
506 case OBJECT_TYPE_U8:
507 dbg_printk("op load field u8\n");
508 stack_top->u.v = *(uint8_t *) stack_top->u.ptr.ptr;
509 break;
510 case OBJECT_TYPE_U16:
511 {
512 uint16_t tmp;
513
514 dbg_printk("op load field s16\n");
515 tmp = *(uint16_t *) stack_top->u.ptr.ptr;
516 if (stack_top->u.ptr.rev_bo)
517 __swab16s(&tmp);
518 stack_top->u.v = tmp;
519 break;
520 }
521 case OBJECT_TYPE_U32:
522 {
523 uint32_t tmp;
524
525 dbg_printk("op load field u32\n");
526 tmp = *(uint32_t *) stack_top->u.ptr.ptr;
527 if (stack_top->u.ptr.rev_bo)
528 __swab32s(&tmp);
529 stack_top->u.v = tmp;
530 break;
531 }
532 case OBJECT_TYPE_U64:
533 {
534 uint64_t tmp;
535
536 dbg_printk("op load field u64\n");
537 tmp = *(uint64_t *) stack_top->u.ptr.ptr;
538 if (stack_top->u.ptr.rev_bo)
539 __swab64s(&tmp);
540 stack_top->u.v = tmp;
541 break;
542 }
543 case OBJECT_TYPE_STRING:
544 {
545 const char *str;
546
547 dbg_printk("op load field string\n");
548 str = (const char *) stack_top->u.ptr.ptr;
549 stack_top->u.s.str = str;
550 if (unlikely(!stack_top->u.s.str)) {
551 dbg_printk("Filter warning: loading a NULL string.\n");
552 ret = -EINVAL;
553 goto end;
554 }
4efe037b 555 stack_top->u.s.seq_len = LTTNG_SIZE_MAX;
3834b99f
MD
556 stack_top->u.s.literal_type =
557 ESTACK_STRING_LITERAL_TYPE_NONE;
558 break;
559 }
560 case OBJECT_TYPE_STRING_SEQUENCE:
561 {
562 const char *ptr;
563
564 dbg_printk("op load field string sequence\n");
565 ptr = stack_top->u.ptr.ptr;
566 stack_top->u.s.seq_len = *(unsigned long *) ptr;
567 stack_top->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
568 if (unlikely(!stack_top->u.s.str)) {
569 dbg_printk("Filter warning: loading a NULL sequence.\n");
570 ret = -EINVAL;
571 goto end;
572 }
573 stack_top->u.s.literal_type =
574 ESTACK_STRING_LITERAL_TYPE_NONE;
575 break;
576 }
577 case OBJECT_TYPE_DYNAMIC:
578 /*
579 * Dynamic types in context are looked up
580 * by context get index.
581 */
582 ret = -EINVAL;
583 goto end;
584 case OBJECT_TYPE_DOUBLE:
585 ret = -EINVAL;
586 goto end;
587 case OBJECT_TYPE_SEQUENCE:
588 case OBJECT_TYPE_ARRAY:
589 case OBJECT_TYPE_STRUCT:
590 case OBJECT_TYPE_VARIANT:
591 printk(KERN_WARNING "Sequences, arrays, struct and variant cannot be loaded (nested types).\n");
592 ret = -EINVAL;
593 goto end;
594 }
595 return 0;
596
597end:
598 return ret;
599}
600
07dfc1d0
MD
601/*
602 * Return 0 (discard), or raise the 0x1 flag (log event).
603 * Currently, other flags are kept for future extensions and have no
604 * effect.
605 */
606uint64_t lttng_filter_interpret_bytecode(void *filter_data,
79150a49 607 struct lttng_probe_ctx *lttng_probe_ctx,
07dfc1d0
MD
608 const char *filter_stack_data)
609{
610 struct bytecode_runtime *bytecode = filter_data;
611 void *pc, *next_pc, *start_pc;
612 int ret = -EINVAL;
613 uint64_t retval = 0;
614 struct estack _stack;
615 struct estack *stack = &_stack;
616 register int64_t ax = 0, bx = 0;
617 register int top = FILTER_STACK_EMPTY;
618#ifndef INTERPRETER_USE_SWITCH
619 static void *dispatch[NR_FILTER_OPS] = {
620 [ FILTER_OP_UNKNOWN ] = &&LABEL_FILTER_OP_UNKNOWN,
621
622 [ FILTER_OP_RETURN ] = &&LABEL_FILTER_OP_RETURN,
623
624 /* binary */
625 [ FILTER_OP_MUL ] = &&LABEL_FILTER_OP_MUL,
626 [ FILTER_OP_DIV ] = &&LABEL_FILTER_OP_DIV,
627 [ FILTER_OP_MOD ] = &&LABEL_FILTER_OP_MOD,
628 [ FILTER_OP_PLUS ] = &&LABEL_FILTER_OP_PLUS,
629 [ FILTER_OP_MINUS ] = &&LABEL_FILTER_OP_MINUS,
e16c054b
MD
630 [ FILTER_OP_BIT_RSHIFT ] = &&LABEL_FILTER_OP_BIT_RSHIFT,
631 [ FILTER_OP_BIT_LSHIFT ] = &&LABEL_FILTER_OP_BIT_LSHIFT,
3834b99f
MD
632 [ FILTER_OP_BIT_AND ] = &&LABEL_FILTER_OP_BIT_AND,
633 [ FILTER_OP_BIT_OR ] = &&LABEL_FILTER_OP_BIT_OR,
634 [ FILTER_OP_BIT_XOR ] = &&LABEL_FILTER_OP_BIT_XOR,
07dfc1d0
MD
635
636 /* binary comparators */
637 [ FILTER_OP_EQ ] = &&LABEL_FILTER_OP_EQ,
638 [ FILTER_OP_NE ] = &&LABEL_FILTER_OP_NE,
639 [ FILTER_OP_GT ] = &&LABEL_FILTER_OP_GT,
640 [ FILTER_OP_LT ] = &&LABEL_FILTER_OP_LT,
641 [ FILTER_OP_GE ] = &&LABEL_FILTER_OP_GE,
642 [ FILTER_OP_LE ] = &&LABEL_FILTER_OP_LE,
643
644 /* string binary comparator */
645 [ FILTER_OP_EQ_STRING ] = &&LABEL_FILTER_OP_EQ_STRING,
646 [ FILTER_OP_NE_STRING ] = &&LABEL_FILTER_OP_NE_STRING,
647 [ FILTER_OP_GT_STRING ] = &&LABEL_FILTER_OP_GT_STRING,
648 [ FILTER_OP_LT_STRING ] = &&LABEL_FILTER_OP_LT_STRING,
649 [ FILTER_OP_GE_STRING ] = &&LABEL_FILTER_OP_GE_STRING,
650 [ FILTER_OP_LE_STRING ] = &&LABEL_FILTER_OP_LE_STRING,
651
02aca193
PP
652 /* globbing pattern binary comparator */
653 [ FILTER_OP_EQ_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_EQ_STAR_GLOB_STRING,
654 [ FILTER_OP_NE_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_NE_STAR_GLOB_STRING,
655
07dfc1d0
MD
656 /* s64 binary comparator */
657 [ FILTER_OP_EQ_S64 ] = &&LABEL_FILTER_OP_EQ_S64,
658 [ FILTER_OP_NE_S64 ] = &&LABEL_FILTER_OP_NE_S64,
659 [ FILTER_OP_GT_S64 ] = &&LABEL_FILTER_OP_GT_S64,
660 [ FILTER_OP_LT_S64 ] = &&LABEL_FILTER_OP_LT_S64,
661 [ FILTER_OP_GE_S64 ] = &&LABEL_FILTER_OP_GE_S64,
662 [ FILTER_OP_LE_S64 ] = &&LABEL_FILTER_OP_LE_S64,
663
664 /* double binary comparator */
665 [ FILTER_OP_EQ_DOUBLE ] = &&LABEL_FILTER_OP_EQ_DOUBLE,
666 [ FILTER_OP_NE_DOUBLE ] = &&LABEL_FILTER_OP_NE_DOUBLE,
667 [ FILTER_OP_GT_DOUBLE ] = &&LABEL_FILTER_OP_GT_DOUBLE,
668 [ FILTER_OP_LT_DOUBLE ] = &&LABEL_FILTER_OP_LT_DOUBLE,
669 [ FILTER_OP_GE_DOUBLE ] = &&LABEL_FILTER_OP_GE_DOUBLE,
670 [ FILTER_OP_LE_DOUBLE ] = &&LABEL_FILTER_OP_LE_DOUBLE,
671
672 /* Mixed S64-double binary comparators */
673 [ FILTER_OP_EQ_DOUBLE_S64 ] = &&LABEL_FILTER_OP_EQ_DOUBLE_S64,
674 [ FILTER_OP_NE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_NE_DOUBLE_S64,
675 [ FILTER_OP_GT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GT_DOUBLE_S64,
676 [ FILTER_OP_LT_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LT_DOUBLE_S64,
677 [ FILTER_OP_GE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_GE_DOUBLE_S64,
678 [ FILTER_OP_LE_DOUBLE_S64 ] = &&LABEL_FILTER_OP_LE_DOUBLE_S64,
679
680 [ FILTER_OP_EQ_S64_DOUBLE ] = &&LABEL_FILTER_OP_EQ_S64_DOUBLE,
681 [ FILTER_OP_NE_S64_DOUBLE ] = &&LABEL_FILTER_OP_NE_S64_DOUBLE,
682 [ FILTER_OP_GT_S64_DOUBLE ] = &&LABEL_FILTER_OP_GT_S64_DOUBLE,
683 [ FILTER_OP_LT_S64_DOUBLE ] = &&LABEL_FILTER_OP_LT_S64_DOUBLE,
684 [ FILTER_OP_GE_S64_DOUBLE ] = &&LABEL_FILTER_OP_GE_S64_DOUBLE,
685 [ FILTER_OP_LE_S64_DOUBLE ] = &&LABEL_FILTER_OP_LE_S64_DOUBLE,
686
687 /* unary */
688 [ FILTER_OP_UNARY_PLUS ] = &&LABEL_FILTER_OP_UNARY_PLUS,
689 [ FILTER_OP_UNARY_MINUS ] = &&LABEL_FILTER_OP_UNARY_MINUS,
690 [ FILTER_OP_UNARY_NOT ] = &&LABEL_FILTER_OP_UNARY_NOT,
691 [ FILTER_OP_UNARY_PLUS_S64 ] = &&LABEL_FILTER_OP_UNARY_PLUS_S64,
692 [ FILTER_OP_UNARY_MINUS_S64 ] = &&LABEL_FILTER_OP_UNARY_MINUS_S64,
693 [ FILTER_OP_UNARY_NOT_S64 ] = &&LABEL_FILTER_OP_UNARY_NOT_S64,
694 [ FILTER_OP_UNARY_PLUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_PLUS_DOUBLE,
695 [ FILTER_OP_UNARY_MINUS_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_MINUS_DOUBLE,
696 [ FILTER_OP_UNARY_NOT_DOUBLE ] = &&LABEL_FILTER_OP_UNARY_NOT_DOUBLE,
697
698 /* logical */
699 [ FILTER_OP_AND ] = &&LABEL_FILTER_OP_AND,
700 [ FILTER_OP_OR ] = &&LABEL_FILTER_OP_OR,
701
702 /* load field ref */
703 [ FILTER_OP_LOAD_FIELD_REF ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF,
704 [ FILTER_OP_LOAD_FIELD_REF_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_STRING,
705 [ FILTER_OP_LOAD_FIELD_REF_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_SEQUENCE,
706 [ FILTER_OP_LOAD_FIELD_REF_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_S64,
707 [ FILTER_OP_LOAD_FIELD_REF_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_DOUBLE,
708
709 /* load from immediate operand */
710 [ FILTER_OP_LOAD_STRING ] = &&LABEL_FILTER_OP_LOAD_STRING,
02aca193 711 [ FILTER_OP_LOAD_STAR_GLOB_STRING ] = &&LABEL_FILTER_OP_LOAD_STAR_GLOB_STRING,
07dfc1d0
MD
712 [ FILTER_OP_LOAD_S64 ] = &&LABEL_FILTER_OP_LOAD_S64,
713 [ FILTER_OP_LOAD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_DOUBLE,
714
715 /* cast */
716 [ FILTER_OP_CAST_TO_S64 ] = &&LABEL_FILTER_OP_CAST_TO_S64,
717 [ FILTER_OP_CAST_DOUBLE_TO_S64 ] = &&LABEL_FILTER_OP_CAST_DOUBLE_TO_S64,
718 [ FILTER_OP_CAST_NOP ] = &&LABEL_FILTER_OP_CAST_NOP,
719
720 /* get context ref */
721 [ FILTER_OP_GET_CONTEXT_REF ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF,
722 [ FILTER_OP_GET_CONTEXT_REF_STRING ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_STRING,
723 [ FILTER_OP_GET_CONTEXT_REF_S64 ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_S64,
724 [ FILTER_OP_GET_CONTEXT_REF_DOUBLE ] = &&LABEL_FILTER_OP_GET_CONTEXT_REF_DOUBLE,
f127e61e
MD
725
726 /* load userspace field ref */
727 [ FILTER_OP_LOAD_FIELD_REF_USER_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_STRING,
728 [ FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE,
3834b99f
MD
729
730 /* Instructions for recursive traversal through composed types. */
731 [ FILTER_OP_GET_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_CONTEXT_ROOT,
732 [ FILTER_OP_GET_APP_CONTEXT_ROOT ] = &&LABEL_FILTER_OP_GET_APP_CONTEXT_ROOT,
733 [ FILTER_OP_GET_PAYLOAD_ROOT ] = &&LABEL_FILTER_OP_GET_PAYLOAD_ROOT,
734
735 [ FILTER_OP_GET_SYMBOL ] = &&LABEL_FILTER_OP_GET_SYMBOL,
736 [ FILTER_OP_GET_SYMBOL_FIELD ] = &&LABEL_FILTER_OP_GET_SYMBOL_FIELD,
737 [ FILTER_OP_GET_INDEX_U16 ] = &&LABEL_FILTER_OP_GET_INDEX_U16,
738 [ FILTER_OP_GET_INDEX_U64 ] = &&LABEL_FILTER_OP_GET_INDEX_U64,
739
740 [ FILTER_OP_LOAD_FIELD ] = &&LABEL_FILTER_OP_LOAD_FIELD,
741 [ FILTER_OP_LOAD_FIELD_S8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S8,
742 [ FILTER_OP_LOAD_FIELD_S16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S16,
743 [ FILTER_OP_LOAD_FIELD_S32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S32,
744 [ FILTER_OP_LOAD_FIELD_S64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_S64,
745 [ FILTER_OP_LOAD_FIELD_U8 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U8,
746 [ FILTER_OP_LOAD_FIELD_U16 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U16,
747 [ FILTER_OP_LOAD_FIELD_U32 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U32,
748 [ FILTER_OP_LOAD_FIELD_U64 ] = &&LABEL_FILTER_OP_LOAD_FIELD_U64,
749 [ FILTER_OP_LOAD_FIELD_STRING ] = &&LABEL_FILTER_OP_LOAD_FIELD_STRING,
750 [ FILTER_OP_LOAD_FIELD_SEQUENCE ] = &&LABEL_FILTER_OP_LOAD_FIELD_SEQUENCE,
751 [ FILTER_OP_LOAD_FIELD_DOUBLE ] = &&LABEL_FILTER_OP_LOAD_FIELD_DOUBLE,
e16c054b
MD
752
753 [ FILTER_OP_UNARY_BIT_NOT ] = &&LABEL_FILTER_OP_UNARY_BIT_NOT,
57ba4b41
MD
754
755 [ FILTER_OP_RETURN_S64 ] = &&LABEL_FILTER_OP_RETURN_S64,
07dfc1d0
MD
756 };
757#endif /* #ifndef INTERPRETER_USE_SWITCH */
758
759 START_OP
760
761 OP(FILTER_OP_UNKNOWN):
762 OP(FILTER_OP_LOAD_FIELD_REF):
763 OP(FILTER_OP_GET_CONTEXT_REF):
764#ifdef INTERPRETER_USE_SWITCH
765 default:
766#endif /* INTERPRETER_USE_SWITCH */
767 printk(KERN_WARNING "unknown bytecode op %u\n",
768 (unsigned int) *(filter_opcode_t *) pc);
769 ret = -EINVAL;
770 goto end;
771
772 OP(FILTER_OP_RETURN):
57ba4b41 773 OP(FILTER_OP_RETURN_S64):
07dfc1d0
MD
774 /* LTTNG_FILTER_DISCARD or LTTNG_FILTER_RECORD_FLAG */
775 retval = !!estack_ax_v;
776 ret = 0;
777 goto end;
778
779 /* binary */
780 OP(FILTER_OP_MUL):
781 OP(FILTER_OP_DIV):
782 OP(FILTER_OP_MOD):
783 OP(FILTER_OP_PLUS):
784 OP(FILTER_OP_MINUS):
07dfc1d0
MD
785 printk(KERN_WARNING "unsupported bytecode op %u\n",
786 (unsigned int) *(filter_opcode_t *) pc);
787 ret = -EINVAL;
788 goto end;
789
790 OP(FILTER_OP_EQ):
791 OP(FILTER_OP_NE):
792 OP(FILTER_OP_GT):
793 OP(FILTER_OP_LT):
794 OP(FILTER_OP_GE):
795 OP(FILTER_OP_LE):
796 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
797 (unsigned int) *(filter_opcode_t *) pc);
798 ret = -EINVAL;
799 goto end;
800
801 OP(FILTER_OP_EQ_STRING):
802 {
803 int res;
804
805 res = (stack_strcmp(stack, top, "==") == 0);
806 estack_pop(stack, top, ax, bx);
807 estack_ax_v = res;
808 next_pc += sizeof(struct binary_op);
809 PO;
810 }
811 OP(FILTER_OP_NE_STRING):
812 {
813 int res;
814
815 res = (stack_strcmp(stack, top, "!=") != 0);
816 estack_pop(stack, top, ax, bx);
817 estack_ax_v = res;
818 next_pc += sizeof(struct binary_op);
819 PO;
820 }
821 OP(FILTER_OP_GT_STRING):
822 {
823 int res;
824
825 res = (stack_strcmp(stack, top, ">") > 0);
826 estack_pop(stack, top, ax, bx);
827 estack_ax_v = res;
828 next_pc += sizeof(struct binary_op);
829 PO;
830 }
831 OP(FILTER_OP_LT_STRING):
832 {
833 int res;
834
835 res = (stack_strcmp(stack, top, "<") < 0);
836 estack_pop(stack, top, ax, bx);
837 estack_ax_v = res;
838 next_pc += sizeof(struct binary_op);
839 PO;
840 }
841 OP(FILTER_OP_GE_STRING):
842 {
843 int res;
844
845 res = (stack_strcmp(stack, top, ">=") >= 0);
846 estack_pop(stack, top, ax, bx);
847 estack_ax_v = res;
848 next_pc += sizeof(struct binary_op);
849 PO;
850 }
851 OP(FILTER_OP_LE_STRING):
852 {
853 int res;
854
855 res = (stack_strcmp(stack, top, "<=") <= 0);
856 estack_pop(stack, top, ax, bx);
857 estack_ax_v = res;
858 next_pc += sizeof(struct binary_op);
859 PO;
860 }
861
02aca193
PP
862 OP(FILTER_OP_EQ_STAR_GLOB_STRING):
863 {
864 int res;
865
866 res = (stack_star_glob_match(stack, top, "==") == 0);
867 estack_pop(stack, top, ax, bx);
868 estack_ax_v = res;
869 next_pc += sizeof(struct binary_op);
870 PO;
871 }
872 OP(FILTER_OP_NE_STAR_GLOB_STRING):
873 {
874 int res;
875
876 res = (stack_star_glob_match(stack, top, "!=") != 0);
877 estack_pop(stack, top, ax, bx);
878 estack_ax_v = res;
879 next_pc += sizeof(struct binary_op);
880 PO;
881 }
882
07dfc1d0
MD
883 OP(FILTER_OP_EQ_S64):
884 {
885 int res;
886
887 res = (estack_bx_v == estack_ax_v);
888 estack_pop(stack, top, ax, bx);
889 estack_ax_v = res;
890 next_pc += sizeof(struct binary_op);
891 PO;
892 }
893 OP(FILTER_OP_NE_S64):
894 {
895 int res;
896
897 res = (estack_bx_v != estack_ax_v);
898 estack_pop(stack, top, ax, bx);
899 estack_ax_v = res;
900 next_pc += sizeof(struct binary_op);
901 PO;
902 }
903 OP(FILTER_OP_GT_S64):
904 {
905 int res;
906
907 res = (estack_bx_v > estack_ax_v);
908 estack_pop(stack, top, ax, bx);
909 estack_ax_v = res;
910 next_pc += sizeof(struct binary_op);
911 PO;
912 }
913 OP(FILTER_OP_LT_S64):
914 {
915 int res;
916
917 res = (estack_bx_v < estack_ax_v);
918 estack_pop(stack, top, ax, bx);
919 estack_ax_v = res;
920 next_pc += sizeof(struct binary_op);
921 PO;
922 }
923 OP(FILTER_OP_GE_S64):
924 {
925 int res;
926
927 res = (estack_bx_v >= estack_ax_v);
928 estack_pop(stack, top, ax, bx);
929 estack_ax_v = res;
930 next_pc += sizeof(struct binary_op);
931 PO;
932 }
933 OP(FILTER_OP_LE_S64):
934 {
935 int res;
936
937 res = (estack_bx_v <= estack_ax_v);
938 estack_pop(stack, top, ax, bx);
939 estack_ax_v = res;
940 next_pc += sizeof(struct binary_op);
941 PO;
942 }
943
944 OP(FILTER_OP_EQ_DOUBLE):
945 OP(FILTER_OP_NE_DOUBLE):
946 OP(FILTER_OP_GT_DOUBLE):
947 OP(FILTER_OP_LT_DOUBLE):
948 OP(FILTER_OP_GE_DOUBLE):
949 OP(FILTER_OP_LE_DOUBLE):
950 {
951 BUG_ON(1);
952 PO;
953 }
954
955 /* Mixed S64-double binary comparators */
956 OP(FILTER_OP_EQ_DOUBLE_S64):
957 OP(FILTER_OP_NE_DOUBLE_S64):
958 OP(FILTER_OP_GT_DOUBLE_S64):
959 OP(FILTER_OP_LT_DOUBLE_S64):
960 OP(FILTER_OP_GE_DOUBLE_S64):
961 OP(FILTER_OP_LE_DOUBLE_S64):
962 OP(FILTER_OP_EQ_S64_DOUBLE):
963 OP(FILTER_OP_NE_S64_DOUBLE):
964 OP(FILTER_OP_GT_S64_DOUBLE):
965 OP(FILTER_OP_LT_S64_DOUBLE):
966 OP(FILTER_OP_GE_S64_DOUBLE):
967 OP(FILTER_OP_LE_S64_DOUBLE):
968 {
969 BUG_ON(1);
970 PO;
971 }
e16c054b
MD
972 OP(FILTER_OP_BIT_RSHIFT):
973 {
974 int64_t res;
975
ea13ec96
MD
976 /* Catch undefined behavior. */
977 if (unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
978 ret = -EINVAL;
979 goto end;
980 }
f8d42740 981 res = ((uint64_t) estack_bx_v >> (uint32_t) estack_ax_v);
e16c054b
MD
982 estack_pop(stack, top, ax, bx);
983 estack_ax_v = res;
984 next_pc += sizeof(struct binary_op);
985 PO;
986 }
987 OP(FILTER_OP_BIT_LSHIFT):
988 {
989 int64_t res;
990
ea13ec96
MD
991 /* Catch undefined behavior. */
992 if (unlikely(estack_ax_v < 0 || estack_ax_v >= 64)) {
993 ret = -EINVAL;
994 goto end;
995 }
f8d42740 996 res = ((uint64_t) estack_bx_v << (uint32_t) estack_ax_v);
e16c054b
MD
997 estack_pop(stack, top, ax, bx);
998 estack_ax_v = res;
999 next_pc += sizeof(struct binary_op);
1000 PO;
1001 }
3834b99f
MD
1002 OP(FILTER_OP_BIT_AND):
1003 {
1004 int64_t res;
1005
f8d42740 1006 res = ((uint64_t) estack_bx_v & (uint64_t) estack_ax_v);
3834b99f
MD
1007 estack_pop(stack, top, ax, bx);
1008 estack_ax_v = res;
1009 next_pc += sizeof(struct binary_op);
1010 PO;
1011 }
1012 OP(FILTER_OP_BIT_OR):
1013 {
1014 int64_t res;
1015
f8d42740 1016 res = ((uint64_t) estack_bx_v | (uint64_t) estack_ax_v);
3834b99f
MD
1017 estack_pop(stack, top, ax, bx);
1018 estack_ax_v = res;
1019 next_pc += sizeof(struct binary_op);
1020 PO;
1021 }
1022 OP(FILTER_OP_BIT_XOR):
1023 {
1024 int64_t res;
1025
f8d42740 1026 res = ((uint64_t) estack_bx_v ^ (uint64_t) estack_ax_v);
3834b99f
MD
1027 estack_pop(stack, top, ax, bx);
1028 estack_ax_v = res;
1029 next_pc += sizeof(struct binary_op);
1030 PO;
1031 }
07dfc1d0
MD
1032
1033 /* unary */
1034 OP(FILTER_OP_UNARY_PLUS):
1035 OP(FILTER_OP_UNARY_MINUS):
1036 OP(FILTER_OP_UNARY_NOT):
1037 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
1038 (unsigned int) *(filter_opcode_t *) pc);
1039 ret = -EINVAL;
1040 goto end;
1041
1042
e16c054b
MD
1043 OP(FILTER_OP_UNARY_BIT_NOT):
1044 {
f8d42740 1045 estack_ax_v = ~(uint64_t) estack_ax_v;
e16c054b
MD
1046 next_pc += sizeof(struct unary_op);
1047 PO;
1048 }
1049
07dfc1d0
MD
1050 OP(FILTER_OP_UNARY_PLUS_S64):
1051 {
1052 next_pc += sizeof(struct unary_op);
1053 PO;
1054 }
1055 OP(FILTER_OP_UNARY_MINUS_S64):
1056 {
1057 estack_ax_v = -estack_ax_v;
1058 next_pc += sizeof(struct unary_op);
1059 PO;
1060 }
1061 OP(FILTER_OP_UNARY_PLUS_DOUBLE):
1062 OP(FILTER_OP_UNARY_MINUS_DOUBLE):
1063 {
1064 BUG_ON(1);
1065 PO;
1066 }
1067 OP(FILTER_OP_UNARY_NOT_S64):
1068 {
1069 estack_ax_v = !estack_ax_v;
1070 next_pc += sizeof(struct unary_op);
1071 PO;
1072 }
1073 OP(FILTER_OP_UNARY_NOT_DOUBLE):
1074 {
1075 BUG_ON(1);
1076 PO;
1077 }
1078
1079 /* logical */
1080 OP(FILTER_OP_AND):
1081 {
1082 struct logical_op *insn = (struct logical_op *) pc;
1083
1084 /* If AX is 0, skip and evaluate to 0 */
1085 if (unlikely(estack_ax_v == 0)) {
1086 dbg_printk("Jumping to bytecode offset %u\n",
1087 (unsigned int) insn->skip_offset);
1088 next_pc = start_pc + insn->skip_offset;
1089 } else {
1090 /* Pop 1 when jump not taken */
1091 estack_pop(stack, top, ax, bx);
1092 next_pc += sizeof(struct logical_op);
1093 }
1094 PO;
1095 }
1096 OP(FILTER_OP_OR):
1097 {
1098 struct logical_op *insn = (struct logical_op *) pc;
1099
1100 /* If AX is nonzero, skip and evaluate to 1 */
1101
1102 if (unlikely(estack_ax_v != 0)) {
1103 estack_ax_v = 1;
1104 dbg_printk("Jumping to bytecode offset %u\n",
1105 (unsigned int) insn->skip_offset);
1106 next_pc = start_pc + insn->skip_offset;
1107 } else {
1108 /* Pop 1 when jump not taken */
1109 estack_pop(stack, top, ax, bx);
1110 next_pc += sizeof(struct logical_op);
1111 }
1112 PO;
1113 }
1114
1115
1116 /* load field ref */
1117 OP(FILTER_OP_LOAD_FIELD_REF_STRING):
1118 {
1119 struct load_op *insn = (struct load_op *) pc;
1120 struct field_ref *ref = (struct field_ref *) insn->data;
1121
1122 dbg_printk("load field ref offset %u type string\n",
1123 ref->offset);
1124 estack_push(stack, top, ax, bx);
1125 estack_ax(stack, top)->u.s.str =
1126 *(const char * const *) &filter_stack_data[ref->offset];
1127 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1128 dbg_printk("Filter warning: loading a NULL string.\n");
1129 ret = -EINVAL;
1130 goto end;
1131 }
cbc19040 1132 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1133 estack_ax(stack, top)->u.s.literal_type =
1134 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1135 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1136 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
1137 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1138 PO;
1139 }
1140
1141 OP(FILTER_OP_LOAD_FIELD_REF_SEQUENCE):
1142 {
1143 struct load_op *insn = (struct load_op *) pc;
1144 struct field_ref *ref = (struct field_ref *) insn->data;
1145
1146 dbg_printk("load field ref offset %u type sequence\n",
1147 ref->offset);
1148 estack_push(stack, top, ax, bx);
1149 estack_ax(stack, top)->u.s.seq_len =
1150 *(unsigned long *) &filter_stack_data[ref->offset];
1151 estack_ax(stack, top)->u.s.str =
1152 *(const char **) (&filter_stack_data[ref->offset
1153 + sizeof(unsigned long)]);
1154 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1155 dbg_printk("Filter warning: loading a NULL sequence.\n");
1156 ret = -EINVAL;
1157 goto end;
1158 }
02aca193
PP
1159 estack_ax(stack, top)->u.s.literal_type =
1160 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1161 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1162 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1163 PO;
1164 }
1165
1166 OP(FILTER_OP_LOAD_FIELD_REF_S64):
1167 {
1168 struct load_op *insn = (struct load_op *) pc;
1169 struct field_ref *ref = (struct field_ref *) insn->data;
1170
1171 dbg_printk("load field ref offset %u type s64\n",
1172 ref->offset);
1173 estack_push(stack, top, ax, bx);
1174 estack_ax_v =
1175 ((struct literal_numeric *) &filter_stack_data[ref->offset])->v;
1176 dbg_printk("ref load s64 %lld\n",
1177 (long long) estack_ax_v);
1178 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1179 PO;
1180 }
1181
1182 OP(FILTER_OP_LOAD_FIELD_REF_DOUBLE):
1183 {
1184 BUG_ON(1);
1185 PO;
1186 }
1187
1188 /* load from immediate operand */
1189 OP(FILTER_OP_LOAD_STRING):
1190 {
1191 struct load_op *insn = (struct load_op *) pc;
1192
1193 dbg_printk("load string %s\n", insn->data);
1194 estack_push(stack, top, ax, bx);
1195 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 1196 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1197 estack_ax(stack, top)->u.s.literal_type =
1198 ESTACK_STRING_LITERAL_TYPE_PLAIN;
1199 estack_ax(stack, top)->u.s.user = 0;
1200 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1201 PO;
1202 }
1203
1204 OP(FILTER_OP_LOAD_STAR_GLOB_STRING):
1205 {
1206 struct load_op *insn = (struct load_op *) pc;
1207
1208 dbg_printk("load globbing pattern %s\n", insn->data);
1209 estack_push(stack, top, ax, bx);
1210 estack_ax(stack, top)->u.s.str = insn->data;
cbc19040 1211 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1212 estack_ax(stack, top)->u.s.literal_type =
1213 ESTACK_STRING_LITERAL_TYPE_STAR_GLOB;
f127e61e 1214 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1215 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1216 PO;
1217 }
1218
1219 OP(FILTER_OP_LOAD_S64):
1220 {
1221 struct load_op *insn = (struct load_op *) pc;
1222
1223 estack_push(stack, top, ax, bx);
1224 estack_ax_v = ((struct literal_numeric *) insn->data)->v;
1225 dbg_printk("load s64 %lld\n",
1226 (long long) estack_ax_v);
1227 next_pc += sizeof(struct load_op)
1228 + sizeof(struct literal_numeric);
1229 PO;
1230 }
1231
1232 OP(FILTER_OP_LOAD_DOUBLE):
1233 {
1234 BUG_ON(1);
1235 PO;
1236 }
1237
1238 /* cast */
1239 OP(FILTER_OP_CAST_TO_S64):
1240 printk(KERN_WARNING "unsupported non-specialized bytecode op %u\n",
1241 (unsigned int) *(filter_opcode_t *) pc);
1242 ret = -EINVAL;
1243 goto end;
1244
1245 OP(FILTER_OP_CAST_DOUBLE_TO_S64):
1246 {
1247 BUG_ON(1);
1248 PO;
1249 }
1250
1251 OP(FILTER_OP_CAST_NOP):
1252 {
1253 next_pc += sizeof(struct cast_op);
1254 PO;
1255 }
1256
1257 /* get context ref */
1258 OP(FILTER_OP_GET_CONTEXT_REF_STRING):
1259 {
1260 struct load_op *insn = (struct load_op *) pc;
1261 struct field_ref *ref = (struct field_ref *) insn->data;
1262 struct lttng_ctx_field *ctx_field;
1263 union lttng_ctx_value v;
1264
1265 dbg_printk("get context ref offset %u type string\n",
1266 ref->offset);
1267 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 1268 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
1269 estack_push(stack, top, ax, bx);
1270 estack_ax(stack, top)->u.s.str = v.str;
1271 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1272 dbg_printk("Filter warning: loading a NULL string.\n");
1273 ret = -EINVAL;
1274 goto end;
1275 }
cbc19040 1276 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1277 estack_ax(stack, top)->u.s.literal_type =
1278 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e 1279 estack_ax(stack, top)->u.s.user = 0;
07dfc1d0
MD
1280 dbg_printk("ref get context string %s\n", estack_ax(stack, top)->u.s.str);
1281 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1282 PO;
1283 }
1284
1285 OP(FILTER_OP_GET_CONTEXT_REF_S64):
1286 {
1287 struct load_op *insn = (struct load_op *) pc;
1288 struct field_ref *ref = (struct field_ref *) insn->data;
1289 struct lttng_ctx_field *ctx_field;
1290 union lttng_ctx_value v;
1291
1292 dbg_printk("get context ref offset %u type s64\n",
1293 ref->offset);
1294 ctx_field = &lttng_static_ctx->fields[ref->offset];
79150a49 1295 ctx_field->get_value(ctx_field, lttng_probe_ctx, &v);
07dfc1d0
MD
1296 estack_push(stack, top, ax, bx);
1297 estack_ax_v = v.s64;
1298 dbg_printk("ref get context s64 %lld\n",
1299 (long long) estack_ax_v);
1300 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1301 PO;
1302 }
1303
1304 OP(FILTER_OP_GET_CONTEXT_REF_DOUBLE):
1305 {
1306 BUG_ON(1);
1307 PO;
1308 }
1309
f127e61e
MD
1310 /* load userspace field ref */
1311 OP(FILTER_OP_LOAD_FIELD_REF_USER_STRING):
1312 {
1313 struct load_op *insn = (struct load_op *) pc;
1314 struct field_ref *ref = (struct field_ref *) insn->data;
1315
1316 dbg_printk("load field ref offset %u type user string\n",
1317 ref->offset);
1318 estack_push(stack, top, ax, bx);
5b4ad89f 1319 estack_ax(stack, top)->u.s.user_str =
f127e61e
MD
1320 *(const char * const *) &filter_stack_data[ref->offset];
1321 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1322 dbg_printk("Filter warning: loading a NULL string.\n");
1323 ret = -EINVAL;
1324 goto end;
1325 }
cbc19040 1326 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
02aca193
PP
1327 estack_ax(stack, top)->u.s.literal_type =
1328 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e
MD
1329 estack_ax(stack, top)->u.s.user = 1;
1330 dbg_printk("ref load string %s\n", estack_ax(stack, top)->u.s.str);
1331 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1332 PO;
1333 }
1334
1335 OP(FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE):
1336 {
1337 struct load_op *insn = (struct load_op *) pc;
1338 struct field_ref *ref = (struct field_ref *) insn->data;
1339
1340 dbg_printk("load field ref offset %u type user sequence\n",
1341 ref->offset);
1342 estack_push(stack, top, ax, bx);
1343 estack_ax(stack, top)->u.s.seq_len =
1344 *(unsigned long *) &filter_stack_data[ref->offset];
5b4ad89f 1345 estack_ax(stack, top)->u.s.user_str =
f127e61e
MD
1346 *(const char **) (&filter_stack_data[ref->offset
1347 + sizeof(unsigned long)]);
1348 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1349 dbg_printk("Filter warning: loading a NULL sequence.\n");
1350 ret = -EINVAL;
1351 goto end;
1352 }
02aca193
PP
1353 estack_ax(stack, top)->u.s.literal_type =
1354 ESTACK_STRING_LITERAL_TYPE_NONE;
f127e61e
MD
1355 estack_ax(stack, top)->u.s.user = 1;
1356 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1357 PO;
1358 }
1359
3834b99f
MD
1360 OP(FILTER_OP_GET_CONTEXT_ROOT):
1361 {
1362 dbg_printk("op get context root\n");
1363 estack_push(stack, top, ax, bx);
1364 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_CONTEXT;
1365 /* "field" only needed for variants. */
1366 estack_ax(stack, top)->u.ptr.field = NULL;
1367 next_pc += sizeof(struct load_op);
1368 PO;
1369 }
1370
1371 OP(FILTER_OP_GET_APP_CONTEXT_ROOT):
1372 {
1373 BUG_ON(1);
1374 PO;
1375 }
1376
1377 OP(FILTER_OP_GET_PAYLOAD_ROOT):
1378 {
1379 dbg_printk("op get app payload root\n");
1380 estack_push(stack, top, ax, bx);
1381 estack_ax(stack, top)->u.ptr.type = LOAD_ROOT_PAYLOAD;
1382 estack_ax(stack, top)->u.ptr.ptr = filter_stack_data;
1383 /* "field" only needed for variants. */
1384 estack_ax(stack, top)->u.ptr.field = NULL;
1385 next_pc += sizeof(struct load_op);
1386 PO;
1387 }
1388
1389 OP(FILTER_OP_GET_SYMBOL):
1390 {
1391 dbg_printk("op get symbol\n");
1392 switch (estack_ax(stack, top)->u.ptr.type) {
1393 case LOAD_OBJECT:
1394 printk(KERN_WARNING "Nested fields not implemented yet.\n");
1395 ret = -EINVAL;
1396 goto end;
1397 case LOAD_ROOT_CONTEXT:
1398 case LOAD_ROOT_APP_CONTEXT:
1399 case LOAD_ROOT_PAYLOAD:
1400 /*
1401 * symbol lookup is performed by
1402 * specialization.
1403 */
1404 ret = -EINVAL;
1405 goto end;
1406 }
1407 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1408 PO;
1409 }
1410
1411 OP(FILTER_OP_GET_SYMBOL_FIELD):
1412 {
1413 /*
1414 * Used for first variant encountered in a
1415 * traversal. Variants are not implemented yet.
1416 */
1417 ret = -EINVAL;
1418 goto end;
1419 }
1420
1421 OP(FILTER_OP_GET_INDEX_U16):
1422 {
1423 struct load_op *insn = (struct load_op *) pc;
1424 struct get_index_u16 *index = (struct get_index_u16 *) insn->data;
1425
1426 dbg_printk("op get index u16\n");
1427 ret = dynamic_get_index(lttng_probe_ctx, bytecode, index->index, estack_ax(stack, top));
1428 if (ret)
1429 goto end;
1430 estack_ax_v = estack_ax(stack, top)->u.v;
1431 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1432 PO;
1433 }
1434
1435 OP(FILTER_OP_GET_INDEX_U64):
1436 {
1437 struct load_op *insn = (struct load_op *) pc;
1438 struct get_index_u64 *index = (struct get_index_u64 *) insn->data;
1439
1440 dbg_printk("op get index u64\n");
1441 ret = dynamic_get_index(lttng_probe_ctx, bytecode, index->index, estack_ax(stack, top));
1442 if (ret)
1443 goto end;
1444 estack_ax_v = estack_ax(stack, top)->u.v;
1445 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1446 PO;
1447 }
1448
1449 OP(FILTER_OP_LOAD_FIELD):
1450 {
1451 dbg_printk("op load field\n");
1452 ret = dynamic_load_field(estack_ax(stack, top));
1453 if (ret)
1454 goto end;
1455 estack_ax_v = estack_ax(stack, top)->u.v;
1456 next_pc += sizeof(struct load_op);
1457 PO;
1458 }
1459
1460 OP(FILTER_OP_LOAD_FIELD_S8):
1461 {
1462 dbg_printk("op load field s8\n");
1463
1464 estack_ax_v = *(int8_t *) estack_ax(stack, top)->u.ptr.ptr;
1465 next_pc += sizeof(struct load_op);
1466 PO;
1467 }
1468 OP(FILTER_OP_LOAD_FIELD_S16):
1469 {
1470 dbg_printk("op load field s16\n");
1471
1472 estack_ax_v = *(int16_t *) estack_ax(stack, top)->u.ptr.ptr;
1473 next_pc += sizeof(struct load_op);
1474 PO;
1475 }
1476 OP(FILTER_OP_LOAD_FIELD_S32):
1477 {
1478 dbg_printk("op load field s32\n");
1479
1480 estack_ax_v = *(int32_t *) estack_ax(stack, top)->u.ptr.ptr;
1481 next_pc += sizeof(struct load_op);
1482 PO;
1483 }
1484 OP(FILTER_OP_LOAD_FIELD_S64):
1485 {
1486 dbg_printk("op load field s64\n");
1487
1488 estack_ax_v = *(int64_t *) estack_ax(stack, top)->u.ptr.ptr;
1489 next_pc += sizeof(struct load_op);
1490 PO;
1491 }
1492 OP(FILTER_OP_LOAD_FIELD_U8):
1493 {
1494 dbg_printk("op load field u8\n");
1495
1496 estack_ax_v = *(uint8_t *) estack_ax(stack, top)->u.ptr.ptr;
1497 next_pc += sizeof(struct load_op);
1498 PO;
1499 }
1500 OP(FILTER_OP_LOAD_FIELD_U16):
1501 {
1502 dbg_printk("op load field u16\n");
1503
1504 estack_ax_v = *(uint16_t *) estack_ax(stack, top)->u.ptr.ptr;
1505 next_pc += sizeof(struct load_op);
1506 PO;
1507 }
1508 OP(FILTER_OP_LOAD_FIELD_U32):
1509 {
1510 dbg_printk("op load field u32\n");
1511
1512 estack_ax_v = *(uint32_t *) estack_ax(stack, top)->u.ptr.ptr;
1513 next_pc += sizeof(struct load_op);
1514 PO;
1515 }
1516 OP(FILTER_OP_LOAD_FIELD_U64):
1517 {
1518 dbg_printk("op load field u64\n");
1519
1520 estack_ax_v = *(uint64_t *) estack_ax(stack, top)->u.ptr.ptr;
1521 next_pc += sizeof(struct load_op);
1522 PO;
1523 }
1524 OP(FILTER_OP_LOAD_FIELD_DOUBLE):
1525 {
1526 ret = -EINVAL;
1527 goto end;
1528 }
1529
1530 OP(FILTER_OP_LOAD_FIELD_STRING):
1531 {
1532 const char *str;
1533
1534 dbg_printk("op load field string\n");
1535 str = (const char *) estack_ax(stack, top)->u.ptr.ptr;
1536 estack_ax(stack, top)->u.s.str = str;
1537 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1538 dbg_printk("Filter warning: loading a NULL string.\n");
1539 ret = -EINVAL;
1540 goto end;
1541 }
4efe037b 1542 estack_ax(stack, top)->u.s.seq_len = LTTNG_SIZE_MAX;
3834b99f
MD
1543 estack_ax(stack, top)->u.s.literal_type =
1544 ESTACK_STRING_LITERAL_TYPE_NONE;
1545 next_pc += sizeof(struct load_op);
1546 PO;
1547 }
1548
1549 OP(FILTER_OP_LOAD_FIELD_SEQUENCE):
1550 {
1551 const char *ptr;
1552
1553 dbg_printk("op load field string sequence\n");
1554 ptr = estack_ax(stack, top)->u.ptr.ptr;
1555 estack_ax(stack, top)->u.s.seq_len = *(unsigned long *) ptr;
1556 estack_ax(stack, top)->u.s.str = *(const char **) (ptr + sizeof(unsigned long));
1557 if (unlikely(!estack_ax(stack, top)->u.s.str)) {
1558 dbg_printk("Filter warning: loading a NULL sequence.\n");
1559 ret = -EINVAL;
1560 goto end;
1561 }
1562 estack_ax(stack, top)->u.s.literal_type =
1563 ESTACK_STRING_LITERAL_TYPE_NONE;
1564 next_pc += sizeof(struct load_op);
1565 PO;
1566 }
1567
07dfc1d0
MD
1568 END_OP
1569end:
1570 /* return 0 (discard) on error */
1571 if (ret)
1572 return 0;
1573 return retval;
1574}
1575
1576#undef START_OP
1577#undef OP
1578#undef PO
1579#undef END_OP
This page took 0.095314 seconds and 4 git commands to generate.