Decouple `struct lttng_session` from filter code
[lttng-ust.git] / liblttng-ust / lttng-filter-specialize.c
CommitLineData
97b58163
MD
1/*
2 * lttng-filter-specialize.c
3 *
4 * LTTng UST filter code specializer.
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>
fb31eb73 29#include <stdint.h>
b4051ad8 30
97b58163 31#include "lttng-filter.h"
47e5f13e 32#include <lttng/align.h>
97b58163 33
47e5f13e
MD
34static int lttng_fls(int val)
35{
36 int r = 32;
37 unsigned int x = (unsigned int) val;
38
39 if (!x)
40 return 0;
41 if (!(x & 0xFFFF0000U)) {
42 x <<= 16;
43 r -= 16;
44 }
45 if (!(x & 0xFF000000U)) {
46 x <<= 8;
47 r -= 8;
48 }
49 if (!(x & 0xF0000000U)) {
50 x <<= 4;
51 r -= 4;
52 }
53 if (!(x & 0xC0000000U)) {
54 x <<= 2;
55 r -= 2;
56 }
57 if (!(x & 0x80000000U)) {
58 r -= 1;
59 }
60 return r;
61}
62
63static int get_count_order(unsigned int count)
64{
65 int order;
66
67 order = lttng_fls(count) - 1;
68 if (count & (count - 1))
69 order++;
70 return order;
71}
72
73static ssize_t bytecode_reserve_data(struct bytecode_runtime *runtime,
74 size_t align, size_t len)
75{
76 ssize_t ret;
b72687b8 77 size_t padding = lttng_ust_offset_align(runtime->data_len, align);
47e5f13e
MD
78 size_t new_len = runtime->data_len + padding + len;
79 size_t new_alloc_len = new_len;
80 size_t old_alloc_len = runtime->data_alloc_len;
81
82 if (new_len > FILTER_MAX_DATA_LEN)
83 return -EINVAL;
84
85 if (new_alloc_len > old_alloc_len) {
86 char *newptr;
87
88 new_alloc_len =
89 max_t(size_t, 1U << get_count_order(new_alloc_len), old_alloc_len << 1);
90 newptr = realloc(runtime->data, new_alloc_len);
91 if (!newptr)
92 return -ENOMEM;
93 runtime->data = newptr;
94 /* We zero directly the memory from start of allocation. */
95 memset(&runtime->data[old_alloc_len], 0, new_alloc_len - old_alloc_len);
96 runtime->data_alloc_len = new_alloc_len;
97 }
98 runtime->data_len += padding;
99 ret = runtime->data_len;
100 runtime->data_len += len;
101 return ret;
102}
103
104static ssize_t bytecode_push_data(struct bytecode_runtime *runtime,
105 const void *p, size_t align, size_t len)
106{
107 ssize_t offset;
108
109 offset = bytecode_reserve_data(runtime, align, len);
110 if (offset < 0)
111 return -ENOMEM;
112 memcpy(&runtime->data[offset], p, len);
113 return offset;
114}
115
116static int specialize_load_field(struct vstack_entry *stack_top,
117 struct load_op *insn)
118{
119 int ret;
120
121 switch (stack_top->load.type) {
122 case LOAD_OBJECT:
123 break;
124 case LOAD_ROOT_CONTEXT:
125 case LOAD_ROOT_APP_CONTEXT:
126 case LOAD_ROOT_PAYLOAD:
127 default:
128 dbg_printf("Filter warning: cannot load root, missing field name.\n");
129 ret = -EINVAL;
130 goto end;
131 }
132 switch (stack_top->load.object_type) {
133 case OBJECT_TYPE_S8:
134 dbg_printf("op load field s8\n");
135 stack_top->type = REG_S64;
136 if (!stack_top->load.rev_bo)
137 insn->op = FILTER_OP_LOAD_FIELD_S8;
138 break;
139 case OBJECT_TYPE_S16:
140 dbg_printf("op load field s16\n");
141 stack_top->type = REG_S64;
142 if (!stack_top->load.rev_bo)
143 insn->op = FILTER_OP_LOAD_FIELD_S16;
144 break;
145 case OBJECT_TYPE_S32:
146 dbg_printf("op load field s32\n");
147 stack_top->type = REG_S64;
148 if (!stack_top->load.rev_bo)
149 insn->op = FILTER_OP_LOAD_FIELD_S32;
150 break;
151 case OBJECT_TYPE_S64:
152 dbg_printf("op load field s64\n");
153 stack_top->type = REG_S64;
154 if (!stack_top->load.rev_bo)
155 insn->op = FILTER_OP_LOAD_FIELD_S64;
156 break;
157 case OBJECT_TYPE_U8:
158 dbg_printf("op load field u8\n");
159 stack_top->type = REG_S64;
160 insn->op = FILTER_OP_LOAD_FIELD_U8;
161 break;
162 case OBJECT_TYPE_U16:
163 dbg_printf("op load field u16\n");
164 stack_top->type = REG_S64;
165 if (!stack_top->load.rev_bo)
166 insn->op = FILTER_OP_LOAD_FIELD_U16;
167 break;
168 case OBJECT_TYPE_U32:
169 dbg_printf("op load field u32\n");
170 stack_top->type = REG_S64;
171 if (!stack_top->load.rev_bo)
172 insn->op = FILTER_OP_LOAD_FIELD_U32;
173 break;
174 case OBJECT_TYPE_U64:
175 dbg_printf("op load field u64\n");
176 stack_top->type = REG_S64;
177 if (!stack_top->load.rev_bo)
178 insn->op = FILTER_OP_LOAD_FIELD_U64;
179 break;
180 case OBJECT_TYPE_DOUBLE:
181 stack_top->type = REG_DOUBLE;
182 insn->op = FILTER_OP_LOAD_FIELD_DOUBLE;
183 break;
184 case OBJECT_TYPE_STRING:
185 dbg_printf("op load field string\n");
186 stack_top->type = REG_STRING;
187 insn->op = FILTER_OP_LOAD_FIELD_STRING;
188 break;
189 case OBJECT_TYPE_STRING_SEQUENCE:
190 dbg_printf("op load field string sequence\n");
191 stack_top->type = REG_STRING;
192 insn->op = FILTER_OP_LOAD_FIELD_SEQUENCE;
193 break;
194 case OBJECT_TYPE_DYNAMIC:
195 dbg_printf("op load field dynamic\n");
196 stack_top->type = REG_UNKNOWN;
197 /* Don't specialize load op. */
198 break;
199 case OBJECT_TYPE_SEQUENCE:
200 case OBJECT_TYPE_ARRAY:
201 case OBJECT_TYPE_STRUCT:
202 case OBJECT_TYPE_VARIANT:
203 ERR("Sequences, arrays, struct and variant cannot be loaded (nested types).");
204 ret = -EINVAL;
205 goto end;
206 }
207 return 0;
208
209end:
210 return ret;
211}
212
213static int specialize_get_index_object_type(enum object_type *otype,
214 int signedness, uint32_t elem_len)
215{
216 switch (elem_len) {
217 case 8:
218 if (signedness)
219 *otype = OBJECT_TYPE_S8;
220 else
221 *otype = OBJECT_TYPE_U8;
222 break;
223 case 16:
224 if (signedness)
225 *otype = OBJECT_TYPE_S16;
226 else
227 *otype = OBJECT_TYPE_U16;
228 break;
229 case 32:
230 if (signedness)
231 *otype = OBJECT_TYPE_S32;
232 else
233 *otype = OBJECT_TYPE_U32;
234 break;
235 case 64:
236 if (signedness)
237 *otype = OBJECT_TYPE_S64;
238 else
239 *otype = OBJECT_TYPE_U64;
240 break;
241 default:
242 return -EINVAL;
243 }
244 return 0;
245}
246
247static int specialize_get_index(struct bytecode_runtime *runtime,
248 struct load_op *insn, uint64_t index,
249 struct vstack_entry *stack_top,
250 int idx_len)
251{
252 int ret;
253 struct filter_get_index_data gid;
254 ssize_t data_offset;
255
256 memset(&gid, 0, sizeof(gid));
257 switch (stack_top->load.type) {
258 case LOAD_OBJECT:
259 switch (stack_top->load.object_type) {
260 case OBJECT_TYPE_ARRAY:
261 {
218deb69 262 const struct lttng_integer_type *integer_type;
47e5f13e
MD
263 const struct lttng_event_field *field;
264 uint32_t elem_len, num_elems;
265 int signedness;
266
267 field = stack_top->load.field;
218deb69
MD
268 switch (field->type.atype) {
269 case atype_array:
270 integer_type = &field->type.u.legacy.array.elem_type.u.basic.integer;
271 num_elems = field->type.u.legacy.array.length;
272 break;
273 case atype_array_nestable:
274 if (field->type.u.array_nestable.elem_type->atype != atype_integer) {
275 ret = -EINVAL;
276 goto end;
277 }
278 integer_type = &field->type.u.array_nestable.elem_type->u.integer;
279 num_elems = field->type.u.array_nestable.length;
280 break;
281 default:
282 ret = -EINVAL;
283 goto end;
284 }
285 elem_len = integer_type->size;
286 signedness = integer_type->signedness;
47e5f13e
MD
287 if (index >= num_elems) {
288 ret = -EINVAL;
289 goto end;
290 }
291 ret = specialize_get_index_object_type(&stack_top->load.object_type,
292 signedness, elem_len);
293 if (ret)
294 goto end;
295 gid.offset = index * (elem_len / CHAR_BIT);
296 gid.array_len = num_elems * (elem_len / CHAR_BIT);
297 gid.elem.type = stack_top->load.object_type;
298 gid.elem.len = elem_len;
218deb69 299 if (integer_type->reverse_byte_order)
47e5f13e
MD
300 gid.elem.rev_bo = true;
301 stack_top->load.rev_bo = gid.elem.rev_bo;
302 break;
303 }
304 case OBJECT_TYPE_SEQUENCE:
305 {
218deb69 306 const struct lttng_integer_type *integer_type;
47e5f13e
MD
307 const struct lttng_event_field *field;
308 uint32_t elem_len;
309 int signedness;
310
311 field = stack_top->load.field;
218deb69
MD
312 switch (field->type.atype) {
313 case atype_sequence:
314 integer_type = &field->type.u.legacy.sequence.elem_type.u.basic.integer;
315 break;
316 case atype_sequence_nestable:
317 if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) {
318 ret = -EINVAL;
319 goto end;
320 }
321 integer_type = &field->type.u.sequence_nestable.elem_type->u.integer;
322 break;
323 default:
324 ret = -EINVAL;
325 goto end;
326 }
327 elem_len = integer_type->size;
328 signedness = integer_type->signedness;
47e5f13e
MD
329 ret = specialize_get_index_object_type(&stack_top->load.object_type,
330 signedness, elem_len);
331 if (ret)
332 goto end;
333 gid.offset = index * (elem_len / CHAR_BIT);
334 gid.elem.type = stack_top->load.object_type;
335 gid.elem.len = elem_len;
218deb69 336 if (integer_type->reverse_byte_order)
47e5f13e
MD
337 gid.elem.rev_bo = true;
338 stack_top->load.rev_bo = gid.elem.rev_bo;
339 break;
340 }
341 case OBJECT_TYPE_STRUCT:
342 /* Only generated by the specialize phase. */
343 case OBJECT_TYPE_VARIANT: /* Fall-through */
344 default:
345 ERR("Unexpected get index type %d",
346 (int) stack_top->load.object_type);
347 ret = -EINVAL;
348 goto end;
349 }
350 break;
351 case LOAD_ROOT_CONTEXT:
352 case LOAD_ROOT_APP_CONTEXT:
353 case LOAD_ROOT_PAYLOAD:
354 ERR("Index lookup for root field not implemented yet.");
355 ret = -EINVAL;
356 goto end;
357 }
358 data_offset = bytecode_push_data(runtime, &gid,
359 __alignof__(gid), sizeof(gid));
360 if (data_offset < 0) {
361 ret = -EINVAL;
362 goto end;
363 }
364 switch (idx_len) {
365 case 2:
366 ((struct get_index_u16 *) insn->data)->index = data_offset;
367 break;
368 case 8:
369 ((struct get_index_u64 *) insn->data)->index = data_offset;
370 break;
371 default:
372 ret = -EINVAL;
373 goto end;
374 }
375
376 return 0;
377
378end:
379 return ret;
380}
381
382static int specialize_context_lookup_name(struct lttng_ctx *ctx,
383 struct bytecode_runtime *bytecode,
384 struct load_op *insn)
385{
386 uint16_t offset;
387 const char *name;
388
389 offset = ((struct get_symbol *) insn->data)->offset;
390 name = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + offset;
391 return lttng_get_context_index(ctx, name);
392}
393
394static int specialize_load_object(const struct lttng_event_field *field,
395 struct vstack_load *load, bool is_context)
396{
397 load->type = LOAD_OBJECT;
398 /*
399 * LTTng-UST layout all integer fields as s64 on the stack for the filter.
400 */
401 switch (field->type.atype) {
402 case atype_integer:
218deb69 403 if (field->type.u.integer.signedness)
47e5f13e
MD
404 load->object_type = OBJECT_TYPE_S64;
405 else
406 load->object_type = OBJECT_TYPE_U64;
407 load->rev_bo = false;
408 break;
409 case atype_enum:
218deb69 410 case atype_enum_nestable:
47e5f13e 411 {
218deb69 412 const struct lttng_integer_type *itype;
47e5f13e 413
218deb69
MD
414 if (field->type.atype == atype_enum) {
415 itype = &field->type.u.legacy.basic.enumeration.container_type;
416 } else {
417 itype = &field->type.u.enum_nestable.container_type->u.integer;
418 }
47e5f13e
MD
419 if (itype->signedness)
420 load->object_type = OBJECT_TYPE_S64;
421 else
422 load->object_type = OBJECT_TYPE_U64;
423 load->rev_bo = false;
424 break;
425 }
426 case atype_array:
218deb69
MD
427 if (field->type.u.legacy.array.elem_type.atype != atype_integer) {
428 ERR("Array nesting only supports integer types.");
429 return -EINVAL;
430 }
431 if (is_context) {
432 load->object_type = OBJECT_TYPE_STRING;
433 } else {
434 if (field->type.u.legacy.array.elem_type.u.basic.integer.encoding == lttng_encode_none) {
435 load->object_type = OBJECT_TYPE_ARRAY;
436 load->field = field;
437 } else {
438 load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
439 }
440 }
441 break;
442 case atype_array_nestable:
443 if (field->type.u.array_nestable.elem_type->atype != atype_integer) {
47e5f13e
MD
444 ERR("Array nesting only supports integer types.");
445 return -EINVAL;
446 }
447 if (is_context) {
448 load->object_type = OBJECT_TYPE_STRING;
449 } else {
218deb69 450 if (field->type.u.array_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
47e5f13e
MD
451 load->object_type = OBJECT_TYPE_ARRAY;
452 load->field = field;
453 } else {
454 load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
455 }
456 }
457 break;
458 case atype_sequence:
218deb69
MD
459 if (field->type.u.legacy.sequence.elem_type.atype != atype_integer) {
460 ERR("Sequence nesting only supports integer types.");
461 return -EINVAL;
462 }
463 if (is_context) {
464 load->object_type = OBJECT_TYPE_STRING;
465 } else {
466 if (field->type.u.legacy.sequence.elem_type.u.basic.integer.encoding == lttng_encode_none) {
467 load->object_type = OBJECT_TYPE_SEQUENCE;
468 load->field = field;
469 } else {
470 load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
471 }
472 }
473 break;
474 case atype_sequence_nestable:
475 if (field->type.u.sequence_nestable.elem_type->atype != atype_integer) {
47e5f13e
MD
476 ERR("Sequence nesting only supports integer types.");
477 return -EINVAL;
478 }
479 if (is_context) {
480 load->object_type = OBJECT_TYPE_STRING;
481 } else {
218deb69 482 if (field->type.u.sequence_nestable.elem_type->u.integer.encoding == lttng_encode_none) {
47e5f13e
MD
483 load->object_type = OBJECT_TYPE_SEQUENCE;
484 load->field = field;
485 } else {
486 load->object_type = OBJECT_TYPE_STRING_SEQUENCE;
487 }
488 }
489 break;
218deb69 490
47e5f13e
MD
491 case atype_string:
492 load->object_type = OBJECT_TYPE_STRING;
493 break;
494 case atype_float:
495 load->object_type = OBJECT_TYPE_DOUBLE;
496 break;
497 case atype_dynamic:
498 load->object_type = OBJECT_TYPE_DYNAMIC;
8d3190bd 499 break;
47e5f13e
MD
500 case atype_struct:
501 ERR("Structure type cannot be loaded.");
502 return -EINVAL;
503 default:
504 ERR("Unknown type: %d", (int) field->type.atype);
505 return -EINVAL;
506 }
507 return 0;
508}
509
b77aaa1b 510static int specialize_context_lookup(struct lttng_ctx *ctx,
47e5f13e
MD
511 struct bytecode_runtime *runtime,
512 struct load_op *insn,
513 struct vstack_load *load)
514{
515 int idx, ret;
516 struct lttng_ctx_field *ctx_field;
517 struct lttng_event_field *field;
518 struct filter_get_index_data gid;
519 ssize_t data_offset;
520
b77aaa1b 521 idx = specialize_context_lookup_name(ctx, runtime, insn);
47e5f13e
MD
522 if (idx < 0) {
523 return -ENOENT;
524 }
b77aaa1b 525 ctx_field = &ctx->fields[idx];
47e5f13e
MD
526 field = &ctx_field->event_field;
527 ret = specialize_load_object(field, load, true);
528 if (ret)
529 return ret;
530 /* Specialize each get_symbol into a get_index. */
531 insn->op = FILTER_OP_GET_INDEX_U16;
532 memset(&gid, 0, sizeof(gid));
533 gid.ctx_index = idx;
534 gid.elem.type = load->object_type;
535 data_offset = bytecode_push_data(runtime, &gid,
536 __alignof__(gid), sizeof(gid));
537 if (data_offset < 0) {
538 return -EINVAL;
539 }
540 ((struct get_index_u16 *) insn->data)->index = data_offset;
541 return 0;
542}
543
b77aaa1b 544static int specialize_app_context_lookup(struct lttng_ctx **pctx,
47e5f13e
MD
545 struct bytecode_runtime *runtime,
546 struct load_op *insn,
547 struct vstack_load *load)
548{
549 uint16_t offset;
550 const char *orig_name;
551 char *name = NULL;
552 int idx, ret;
553 struct lttng_ctx_field *ctx_field;
554 struct lttng_event_field *field;
555 struct filter_get_index_data gid;
556 ssize_t data_offset;
557
558 offset = ((struct get_symbol *) insn->data)->offset;
559 orig_name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset;
560 name = zmalloc(strlen(orig_name) + strlen("$app.") + 1);
561 if (!name) {
562 ret = -ENOMEM;
563 goto end;
564 }
565 strcpy(name, "$app.");
566 strcat(name, orig_name);
b77aaa1b 567 idx = lttng_get_context_index(*pctx, name);
47e5f13e
MD
568 if (idx < 0) {
569 assert(lttng_context_is_app(name));
570 ret = lttng_ust_add_app_context_to_ctx_rcu(name,
b77aaa1b 571 pctx);
47e5f13e
MD
572 if (ret)
573 return ret;
b77aaa1b 574 idx = lttng_get_context_index(*pctx, name);
47e5f13e
MD
575 if (idx < 0)
576 return -ENOENT;
577 }
b77aaa1b 578 ctx_field = &(*pctx)->fields[idx];
47e5f13e
MD
579 field = &ctx_field->event_field;
580 ret = specialize_load_object(field, load, true);
581 if (ret)
582 goto end;
583 /* Specialize each get_symbol into a get_index. */
584 insn->op = FILTER_OP_GET_INDEX_U16;
585 memset(&gid, 0, sizeof(gid));
586 gid.ctx_index = idx;
587 gid.elem.type = load->object_type;
588 data_offset = bytecode_push_data(runtime, &gid,
589 __alignof__(gid), sizeof(gid));
590 if (data_offset < 0) {
591 ret = -EINVAL;
592 goto end;
593 }
594 ((struct get_index_u16 *) insn->data)->index = data_offset;
595 ret = 0;
596end:
597 free(name);
598 return ret;
599}
600
601static int specialize_event_payload_lookup(struct lttng_event *event,
602 struct bytecode_runtime *runtime,
603 struct load_op *insn,
604 struct vstack_load *load)
605{
606 const char *name;
607 uint16_t offset;
608 const struct lttng_event_desc *desc = event->desc;
609 unsigned int i, nr_fields;
610 bool found = false;
611 uint32_t field_offset = 0;
612 const struct lttng_event_field *field;
613 int ret;
614 struct filter_get_index_data gid;
615 ssize_t data_offset;
616
617 nr_fields = desc->nr_fields;
618 offset = ((struct get_symbol *) insn->data)->offset;
619 name = runtime->p.bc->bc.data + runtime->p.bc->bc.reloc_offset + offset;
620 for (i = 0; i < nr_fields; i++) {
621 field = &desc->fields[i];
218deb69
MD
622 if (field->u.ext.nofilter) {
623 continue;
624 }
47e5f13e
MD
625 if (!strcmp(field->name, name)) {
626 found = true;
627 break;
628 }
629 /* compute field offset on stack */
630 switch (field->type.atype) {
631 case atype_integer:
632 case atype_enum:
218deb69 633 case atype_enum_nestable:
47e5f13e
MD
634 field_offset += sizeof(int64_t);
635 break;
636 case atype_array:
218deb69 637 case atype_array_nestable:
47e5f13e 638 case atype_sequence:
218deb69 639 case atype_sequence_nestable:
47e5f13e
MD
640 field_offset += sizeof(unsigned long);
641 field_offset += sizeof(void *);
642 break;
643 case atype_string:
644 field_offset += sizeof(void *);
645 break;
646 case atype_float:
647 field_offset += sizeof(double);
648 break;
649 default:
650 ret = -EINVAL;
651 goto end;
652 }
653 }
654 if (!found) {
655 ret = -EINVAL;
656 goto end;
657 }
658
659 ret = specialize_load_object(field, load, false);
660 if (ret)
661 goto end;
662
663 /* Specialize each get_symbol into a get_index. */
664 insn->op = FILTER_OP_GET_INDEX_U16;
665 memset(&gid, 0, sizeof(gid));
666 gid.offset = field_offset;
667 gid.elem.type = load->object_type;
668 data_offset = bytecode_push_data(runtime, &gid,
669 __alignof__(gid), sizeof(gid));
670 if (data_offset < 0) {
671 ret = -EINVAL;
672 goto end;
673 }
674 ((struct get_index_u16 *) insn->data)->index = data_offset;
675 ret = 0;
676end:
677 return ret;
678}
679
680int lttng_filter_specialize_bytecode(struct lttng_event *event,
681 struct bytecode_runtime *bytecode)
97b58163
MD
682{
683 void *pc, *next_pc, *start_pc;
684 int ret = -EINVAL;
0305960f
MD
685 struct vstack _stack;
686 struct vstack *stack = &_stack;
b77aaa1b 687 struct lttng_ctx **pctx = bytecode->p.pctx;
97b58163 688
0305960f 689 vstack_init(stack);
97b58163 690
47e5f13e 691 start_pc = &bytecode->code[0];
97b58163
MD
692 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
693 pc = next_pc) {
694 switch (*(filter_opcode_t *) pc) {
695 case FILTER_OP_UNKNOWN:
696 default:
697 ERR("unknown bytecode op %u\n",
698 (unsigned int) *(filter_opcode_t *) pc);
699 ret = -EINVAL;
700 goto end;
701
702 case FILTER_OP_RETURN:
93c591bb
MD
703 if (vstack_ax(stack)->type == REG_S64)
704 *(filter_opcode_t *) pc = FILTER_OP_RETURN_S64;
705 ret = 0;
706 goto end;
707
708 case FILTER_OP_RETURN_S64:
709 if (vstack_ax(stack)->type != REG_S64) {
710 ERR("Unexpected register type\n");
711 ret = -EINVAL;
712 goto end;
713 }
97b58163
MD
714 ret = 0;
715 goto end;
716
717 /* binary */
718 case FILTER_OP_MUL:
719 case FILTER_OP_DIV:
720 case FILTER_OP_MOD:
721 case FILTER_OP_PLUS:
722 case FILTER_OP_MINUS:
97b58163
MD
723 ERR("unsupported bytecode op %u\n",
724 (unsigned int) *(filter_opcode_t *) pc);
725 ret = -EINVAL;
726 goto end;
727
728 case FILTER_OP_EQ:
729 {
730 struct binary_op *insn = (struct binary_op *) pc;
731
0305960f 732 switch(vstack_ax(stack)->type) {
97b58163
MD
733 default:
734 ERR("unknown register type\n");
735 ret = -EINVAL;
736 goto end;
737
738 case REG_STRING:
53569322
MD
739 if (vstack_bx(stack)->type == REG_UNKNOWN)
740 break;
3151a51d
PP
741 if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
742 insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
743 else
744 insn->op = FILTER_OP_EQ_STRING;
745 break;
746 case REG_STAR_GLOB_STRING:
747 if (vstack_bx(stack)->type == REG_UNKNOWN)
748 break;
749 insn->op = FILTER_OP_EQ_STAR_GLOB_STRING;
97b58163
MD
750 break;
751 case REG_S64:
53569322
MD
752 if (vstack_bx(stack)->type == REG_UNKNOWN)
753 break;
0305960f 754 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
755 insn->op = FILTER_OP_EQ_S64;
756 else
dbea82ec 757 insn->op = FILTER_OP_EQ_DOUBLE_S64;
97b58163
MD
758 break;
759 case REG_DOUBLE:
53569322
MD
760 if (vstack_bx(stack)->type == REG_UNKNOWN)
761 break;
dbea82ec
MD
762 if (vstack_bx(stack)->type == REG_S64)
763 insn->op = FILTER_OP_EQ_S64_DOUBLE;
764 else
765 insn->op = FILTER_OP_EQ_DOUBLE;
97b58163 766 break;
53569322
MD
767 case REG_UNKNOWN:
768 break; /* Dynamic typing. */
97b58163 769 }
0305960f
MD
770 /* Pop 2, push 1 */
771 if (vstack_pop(stack)) {
772 ret = -EINVAL;
773 goto end;
774 }
775 vstack_ax(stack)->type = REG_S64;
97b58163
MD
776 next_pc += sizeof(struct binary_op);
777 break;
778 }
779
780 case FILTER_OP_NE:
781 {
782 struct binary_op *insn = (struct binary_op *) pc;
783
0305960f 784 switch(vstack_ax(stack)->type) {
97b58163
MD
785 default:
786 ERR("unknown register type\n");
787 ret = -EINVAL;
788 goto end;
789
790 case REG_STRING:
53569322
MD
791 if (vstack_bx(stack)->type == REG_UNKNOWN)
792 break;
3151a51d
PP
793 if (vstack_bx(stack)->type == REG_STAR_GLOB_STRING)
794 insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
795 else
796 insn->op = FILTER_OP_NE_STRING;
797 break;
798 case REG_STAR_GLOB_STRING:
799 if (vstack_bx(stack)->type == REG_UNKNOWN)
800 break;
801 insn->op = FILTER_OP_NE_STAR_GLOB_STRING;
97b58163
MD
802 break;
803 case REG_S64:
53569322
MD
804 if (vstack_bx(stack)->type == REG_UNKNOWN)
805 break;
0305960f 806 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
807 insn->op = FILTER_OP_NE_S64;
808 else
dbea82ec 809 insn->op = FILTER_OP_NE_DOUBLE_S64;
97b58163
MD
810 break;
811 case REG_DOUBLE:
53569322
MD
812 if (vstack_bx(stack)->type == REG_UNKNOWN)
813 break;
dbea82ec
MD
814 if (vstack_bx(stack)->type == REG_S64)
815 insn->op = FILTER_OP_NE_S64_DOUBLE;
816 else
817 insn->op = FILTER_OP_NE_DOUBLE;
97b58163 818 break;
53569322
MD
819 case REG_UNKNOWN:
820 break; /* Dynamic typing. */
97b58163 821 }
0305960f
MD
822 /* Pop 2, push 1 */
823 if (vstack_pop(stack)) {
824 ret = -EINVAL;
825 goto end;
826 }
827 vstack_ax(stack)->type = REG_S64;
97b58163
MD
828 next_pc += sizeof(struct binary_op);
829 break;
830 }
831
832 case FILTER_OP_GT:
833 {
834 struct binary_op *insn = (struct binary_op *) pc;
835
0305960f 836 switch(vstack_ax(stack)->type) {
97b58163
MD
837 default:
838 ERR("unknown register type\n");
839 ret = -EINVAL;
840 goto end;
841
3151a51d
PP
842 case REG_STAR_GLOB_STRING:
843 ERR("invalid register type for > binary operator\n");
844 ret = -EINVAL;
845 goto end;
97b58163 846 case REG_STRING:
53569322
MD
847 if (vstack_bx(stack)->type == REG_UNKNOWN)
848 break;
97b58163
MD
849 insn->op = FILTER_OP_GT_STRING;
850 break;
851 case REG_S64:
53569322
MD
852 if (vstack_bx(stack)->type == REG_UNKNOWN)
853 break;
0305960f 854 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
855 insn->op = FILTER_OP_GT_S64;
856 else
dbea82ec 857 insn->op = FILTER_OP_GT_DOUBLE_S64;
97b58163
MD
858 break;
859 case REG_DOUBLE:
53569322
MD
860 if (vstack_bx(stack)->type == REG_UNKNOWN)
861 break;
dbea82ec
MD
862 if (vstack_bx(stack)->type == REG_S64)
863 insn->op = FILTER_OP_GT_S64_DOUBLE;
864 else
865 insn->op = FILTER_OP_GT_DOUBLE;
97b58163 866 break;
53569322
MD
867 case REG_UNKNOWN:
868 break; /* Dynamic typing. */
97b58163 869 }
0305960f
MD
870 /* Pop 2, push 1 */
871 if (vstack_pop(stack)) {
872 ret = -EINVAL;
873 goto end;
874 }
875 vstack_ax(stack)->type = REG_S64;
97b58163
MD
876 next_pc += sizeof(struct binary_op);
877 break;
878 }
879
880 case FILTER_OP_LT:
881 {
882 struct binary_op *insn = (struct binary_op *) pc;
883
0305960f 884 switch(vstack_ax(stack)->type) {
97b58163
MD
885 default:
886 ERR("unknown register type\n");
887 ret = -EINVAL;
888 goto end;
889
3151a51d
PP
890 case REG_STAR_GLOB_STRING:
891 ERR("invalid register type for < binary operator\n");
892 ret = -EINVAL;
893 goto end;
97b58163 894 case REG_STRING:
53569322
MD
895 if (vstack_bx(stack)->type == REG_UNKNOWN)
896 break;
97b58163
MD
897 insn->op = FILTER_OP_LT_STRING;
898 break;
899 case REG_S64:
53569322
MD
900 if (vstack_bx(stack)->type == REG_UNKNOWN)
901 break;
0305960f 902 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
903 insn->op = FILTER_OP_LT_S64;
904 else
dbea82ec 905 insn->op = FILTER_OP_LT_DOUBLE_S64;
97b58163
MD
906 break;
907 case REG_DOUBLE:
53569322
MD
908 if (vstack_bx(stack)->type == REG_UNKNOWN)
909 break;
dbea82ec
MD
910 if (vstack_bx(stack)->type == REG_S64)
911 insn->op = FILTER_OP_LT_S64_DOUBLE;
912 else
913 insn->op = FILTER_OP_LT_DOUBLE;
97b58163 914 break;
53569322
MD
915 case REG_UNKNOWN:
916 break; /* Dynamic typing. */
97b58163 917 }
0305960f
MD
918 /* Pop 2, push 1 */
919 if (vstack_pop(stack)) {
920 ret = -EINVAL;
921 goto end;
922 }
923 vstack_ax(stack)->type = REG_S64;
97b58163
MD
924 next_pc += sizeof(struct binary_op);
925 break;
926 }
927
928 case FILTER_OP_GE:
929 {
930 struct binary_op *insn = (struct binary_op *) pc;
931
0305960f 932 switch(vstack_ax(stack)->type) {
97b58163
MD
933 default:
934 ERR("unknown register type\n");
935 ret = -EINVAL;
936 goto end;
937
3151a51d
PP
938 case REG_STAR_GLOB_STRING:
939 ERR("invalid register type for >= binary operator\n");
940 ret = -EINVAL;
941 goto end;
97b58163 942 case REG_STRING:
53569322
MD
943 if (vstack_bx(stack)->type == REG_UNKNOWN)
944 break;
97b58163
MD
945 insn->op = FILTER_OP_GE_STRING;
946 break;
947 case REG_S64:
53569322
MD
948 if (vstack_bx(stack)->type == REG_UNKNOWN)
949 break;
0305960f 950 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
951 insn->op = FILTER_OP_GE_S64;
952 else
dbea82ec 953 insn->op = FILTER_OP_GE_DOUBLE_S64;
97b58163
MD
954 break;
955 case REG_DOUBLE:
53569322
MD
956 if (vstack_bx(stack)->type == REG_UNKNOWN)
957 break;
dbea82ec
MD
958 if (vstack_bx(stack)->type == REG_S64)
959 insn->op = FILTER_OP_GE_S64_DOUBLE;
960 else
961 insn->op = FILTER_OP_GE_DOUBLE;
97b58163 962 break;
53569322
MD
963 case REG_UNKNOWN:
964 break; /* Dynamic typing. */
97b58163 965 }
0305960f
MD
966 /* Pop 2, push 1 */
967 if (vstack_pop(stack)) {
968 ret = -EINVAL;
969 goto end;
970 }
971 vstack_ax(stack)->type = REG_S64;
97b58163
MD
972 next_pc += sizeof(struct binary_op);
973 break;
974 }
975 case FILTER_OP_LE:
976 {
977 struct binary_op *insn = (struct binary_op *) pc;
978
0305960f 979 switch(vstack_ax(stack)->type) {
97b58163
MD
980 default:
981 ERR("unknown register type\n");
982 ret = -EINVAL;
983 goto end;
984
3151a51d
PP
985 case REG_STAR_GLOB_STRING:
986 ERR("invalid register type for <= binary operator\n");
987 ret = -EINVAL;
988 goto end;
97b58163 989 case REG_STRING:
53569322
MD
990 if (vstack_bx(stack)->type == REG_UNKNOWN)
991 break;
97b58163
MD
992 insn->op = FILTER_OP_LE_STRING;
993 break;
994 case REG_S64:
53569322
MD
995 if (vstack_bx(stack)->type == REG_UNKNOWN)
996 break;
0305960f 997 if (vstack_bx(stack)->type == REG_S64)
97b58163
MD
998 insn->op = FILTER_OP_LE_S64;
999 else
dbea82ec 1000 insn->op = FILTER_OP_LE_DOUBLE_S64;
97b58163
MD
1001 break;
1002 case REG_DOUBLE:
53569322
MD
1003 if (vstack_bx(stack)->type == REG_UNKNOWN)
1004 break;
dbea82ec
MD
1005 if (vstack_bx(stack)->type == REG_S64)
1006 insn->op = FILTER_OP_LE_S64_DOUBLE;
1007 else
1008 insn->op = FILTER_OP_LE_DOUBLE;
97b58163 1009 break;
53569322
MD
1010 case REG_UNKNOWN:
1011 break; /* Dynamic typing. */
97b58163 1012 }
0305960f 1013 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1014 next_pc += sizeof(struct binary_op);
1015 break;
1016 }
1017
1018 case FILTER_OP_EQ_STRING:
1019 case FILTER_OP_NE_STRING:
1020 case FILTER_OP_GT_STRING:
1021 case FILTER_OP_LT_STRING:
1022 case FILTER_OP_GE_STRING:
1023 case FILTER_OP_LE_STRING:
3151a51d
PP
1024 case FILTER_OP_EQ_STAR_GLOB_STRING:
1025 case FILTER_OP_NE_STAR_GLOB_STRING:
97b58163
MD
1026 case FILTER_OP_EQ_S64:
1027 case FILTER_OP_NE_S64:
1028 case FILTER_OP_GT_S64:
1029 case FILTER_OP_LT_S64:
1030 case FILTER_OP_GE_S64:
1031 case FILTER_OP_LE_S64:
1032 case FILTER_OP_EQ_DOUBLE:
1033 case FILTER_OP_NE_DOUBLE:
1034 case FILTER_OP_GT_DOUBLE:
1035 case FILTER_OP_LT_DOUBLE:
1036 case FILTER_OP_GE_DOUBLE:
1037 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
1038 case FILTER_OP_EQ_DOUBLE_S64:
1039 case FILTER_OP_NE_DOUBLE_S64:
1040 case FILTER_OP_GT_DOUBLE_S64:
1041 case FILTER_OP_LT_DOUBLE_S64:
1042 case FILTER_OP_GE_DOUBLE_S64:
1043 case FILTER_OP_LE_DOUBLE_S64:
1044 case FILTER_OP_EQ_S64_DOUBLE:
1045 case FILTER_OP_NE_S64_DOUBLE:
1046 case FILTER_OP_GT_S64_DOUBLE:
1047 case FILTER_OP_LT_S64_DOUBLE:
1048 case FILTER_OP_GE_S64_DOUBLE:
1049 case FILTER_OP_LE_S64_DOUBLE:
0039e2d8
MD
1050 case FILTER_OP_BIT_RSHIFT:
1051 case FILTER_OP_BIT_LSHIFT:
47e5f13e
MD
1052 case FILTER_OP_BIT_AND:
1053 case FILTER_OP_BIT_OR:
1054 case FILTER_OP_BIT_XOR:
97b58163 1055 {
0305960f
MD
1056 /* Pop 2, push 1 */
1057 if (vstack_pop(stack)) {
1058 ret = -EINVAL;
1059 goto end;
1060 }
1061 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1062 next_pc += sizeof(struct binary_op);
1063 break;
1064 }
1065
1066 /* unary */
1067 case FILTER_OP_UNARY_PLUS:
1068 {
1069 struct unary_op *insn = (struct unary_op *) pc;
1070
0305960f 1071 switch(vstack_ax(stack)->type) {
97b58163
MD
1072 default:
1073 ERR("unknown register type\n");
1074 ret = -EINVAL;
1075 goto end;
1076
1077 case REG_S64:
1078 insn->op = FILTER_OP_UNARY_PLUS_S64;
1079 break;
1080 case REG_DOUBLE:
1081 insn->op = FILTER_OP_UNARY_PLUS_DOUBLE;
1082 break;
53569322
MD
1083 case REG_UNKNOWN: /* Dynamic typing. */
1084 break;
97b58163 1085 }
0305960f 1086 /* Pop 1, push 1 */
97b58163
MD
1087 next_pc += sizeof(struct unary_op);
1088 break;
1089 }
1090
1091 case FILTER_OP_UNARY_MINUS:
1092 {
1093 struct unary_op *insn = (struct unary_op *) pc;
1094
0305960f 1095 switch(vstack_ax(stack)->type) {
97b58163
MD
1096 default:
1097 ERR("unknown register type\n");
1098 ret = -EINVAL;
1099 goto end;
1100
1101 case REG_S64:
1102 insn->op = FILTER_OP_UNARY_MINUS_S64;
1103 break;
1104 case REG_DOUBLE:
1105 insn->op = FILTER_OP_UNARY_MINUS_DOUBLE;
1106 break;
53569322
MD
1107 case REG_UNKNOWN: /* Dynamic typing. */
1108 break;
97b58163 1109 }
0305960f 1110 /* Pop 1, push 1 */
97b58163
MD
1111 next_pc += sizeof(struct unary_op);
1112 break;
1113 }
1114
1115 case FILTER_OP_UNARY_NOT:
1116 {
1117 struct unary_op *insn = (struct unary_op *) pc;
1118
0305960f 1119 switch(vstack_ax(stack)->type) {
97b58163
MD
1120 default:
1121 ERR("unknown register type\n");
1122 ret = -EINVAL;
1123 goto end;
1124
1125 case REG_S64:
1126 insn->op = FILTER_OP_UNARY_NOT_S64;
1127 break;
1128 case REG_DOUBLE:
1129 insn->op = FILTER_OP_UNARY_NOT_DOUBLE;
1130 break;
53569322
MD
1131 case REG_UNKNOWN: /* Dynamic typing. */
1132 break;
97b58163 1133 }
0305960f 1134 /* Pop 1, push 1 */
97b58163
MD
1135 next_pc += sizeof(struct unary_op);
1136 break;
1137 }
1138
0039e2d8
MD
1139 case FILTER_OP_UNARY_BIT_NOT:
1140 {
1141 /* Pop 1, push 1 */
1142 next_pc += sizeof(struct unary_op);
1143 break;
1144 }
1145
97b58163
MD
1146 case FILTER_OP_UNARY_PLUS_S64:
1147 case FILTER_OP_UNARY_MINUS_S64:
1148 case FILTER_OP_UNARY_NOT_S64:
1149 case FILTER_OP_UNARY_PLUS_DOUBLE:
1150 case FILTER_OP_UNARY_MINUS_DOUBLE:
1151 case FILTER_OP_UNARY_NOT_DOUBLE:
1152 {
0305960f 1153 /* Pop 1, push 1 */
97b58163
MD
1154 next_pc += sizeof(struct unary_op);
1155 break;
1156 }
1157
1158 /* logical */
1159 case FILTER_OP_AND:
1160 case FILTER_OP_OR:
1161 {
b9f4cd79
MD
1162 /* Continue to next instruction */
1163 /* Pop 1 when jump not taken */
1164 if (vstack_pop(stack)) {
1165 ret = -EINVAL;
1166 goto end;
1167 }
97b58163
MD
1168 next_pc += sizeof(struct logical_op);
1169 break;
1170 }
1171
77aa5901 1172 /* load field ref */
97b58163
MD
1173 case FILTER_OP_LOAD_FIELD_REF:
1174 {
1175 ERR("Unknown field ref type\n");
1176 ret = -EINVAL;
1177 goto end;
1178 }
77aa5901
MD
1179 /* get context ref */
1180 case FILTER_OP_GET_CONTEXT_REF:
1181 {
53569322
MD
1182 if (vstack_push(stack)) {
1183 ret = -EINVAL;
1184 goto end;
1185 }
1186 vstack_ax(stack)->type = REG_UNKNOWN;
1187 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1188 break;
77aa5901 1189 }
97b58163
MD
1190 case FILTER_OP_LOAD_FIELD_REF_STRING:
1191 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
77aa5901 1192 case FILTER_OP_GET_CONTEXT_REF_STRING:
97b58163 1193 {
0305960f
MD
1194 if (vstack_push(stack)) {
1195 ret = -EINVAL;
1196 goto end;
1197 }
1198 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
1199 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1200 break;
1201 }
1202 case FILTER_OP_LOAD_FIELD_REF_S64:
77aa5901 1203 case FILTER_OP_GET_CONTEXT_REF_S64:
97b58163 1204 {
0305960f
MD
1205 if (vstack_push(stack)) {
1206 ret = -EINVAL;
1207 goto end;
1208 }
1209 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1210 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1211 break;
1212 }
1213 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901 1214 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
97b58163 1215 {
0305960f
MD
1216 if (vstack_push(stack)) {
1217 ret = -EINVAL;
1218 goto end;
1219 }
1220 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
1221 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1222 break;
1223 }
1224
77aa5901 1225 /* load from immediate operand */
97b58163
MD
1226 case FILTER_OP_LOAD_STRING:
1227 {
1228 struct load_op *insn = (struct load_op *) pc;
1229
0305960f
MD
1230 if (vstack_push(stack)) {
1231 ret = -EINVAL;
1232 goto end;
1233 }
1234 vstack_ax(stack)->type = REG_STRING;
97b58163
MD
1235 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1236 break;
1237 }
1238
3151a51d
PP
1239 case FILTER_OP_LOAD_STAR_GLOB_STRING:
1240 {
1241 struct load_op *insn = (struct load_op *) pc;
1242
1243 if (vstack_push(stack)) {
1244 ret = -EINVAL;
1245 goto end;
1246 }
1247 vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
1248 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1249 break;
1250 }
1251
97b58163
MD
1252 case FILTER_OP_LOAD_S64:
1253 {
0305960f
MD
1254 if (vstack_push(stack)) {
1255 ret = -EINVAL;
1256 goto end;
1257 }
1258 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1259 next_pc += sizeof(struct load_op)
1260 + sizeof(struct literal_numeric);
1261 break;
1262 }
1263
1264 case FILTER_OP_LOAD_DOUBLE:
1265 {
0305960f
MD
1266 if (vstack_push(stack)) {
1267 ret = -EINVAL;
1268 goto end;
1269 }
1270 vstack_ax(stack)->type = REG_DOUBLE;
97b58163
MD
1271 next_pc += sizeof(struct load_op)
1272 + sizeof(struct literal_double);
1273 break;
1274 }
1275
1276 /* cast */
1277 case FILTER_OP_CAST_TO_S64:
1278 {
1279 struct cast_op *insn = (struct cast_op *) pc;
1280
0305960f 1281 switch (vstack_ax(stack)->type) {
97b58163
MD
1282 default:
1283 ERR("unknown register type\n");
1284 ret = -EINVAL;
1285 goto end;
1286
1287 case REG_STRING:
3151a51d 1288 case REG_STAR_GLOB_STRING:
97b58163
MD
1289 ERR("Cast op can only be applied to numeric or floating point registers\n");
1290 ret = -EINVAL;
1291 goto end;
1292 case REG_S64:
1293 insn->op = FILTER_OP_CAST_NOP;
1294 break;
1295 case REG_DOUBLE:
1296 insn->op = FILTER_OP_CAST_DOUBLE_TO_S64;
1297 break;
53569322
MD
1298 case REG_UNKNOWN:
1299 break;
97b58163 1300 }
0305960f
MD
1301 /* Pop 1, push 1 */
1302 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1303 next_pc += sizeof(struct cast_op);
1304 break;
1305 }
1306 case FILTER_OP_CAST_DOUBLE_TO_S64:
1307 {
0305960f
MD
1308 /* Pop 1, push 1 */
1309 vstack_ax(stack)->type = REG_S64;
97b58163
MD
1310 next_pc += sizeof(struct cast_op);
1311 break;
1312 }
1313 case FILTER_OP_CAST_NOP:
1314 {
1315 next_pc += sizeof(struct cast_op);
1316 break;
1317 }
1318
47e5f13e
MD
1319 /*
1320 * Instructions for recursive traversal through composed types.
1321 */
1322 case FILTER_OP_GET_CONTEXT_ROOT:
1323 {
1324 if (vstack_push(stack)) {
1325 ret = -EINVAL;
1326 goto end;
1327 }
1328 vstack_ax(stack)->type = REG_PTR;
1329 vstack_ax(stack)->load.type = LOAD_ROOT_CONTEXT;
1330 next_pc += sizeof(struct load_op);
1331 break;
1332 }
1333 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1334 {
1335 if (vstack_push(stack)) {
1336 ret = -EINVAL;
1337 goto end;
1338 }
1339 vstack_ax(stack)->type = REG_PTR;
1340 vstack_ax(stack)->load.type = LOAD_ROOT_APP_CONTEXT;
1341 next_pc += sizeof(struct load_op);
1342 break;
1343 }
1344 case FILTER_OP_GET_PAYLOAD_ROOT:
1345 {
1346 if (vstack_push(stack)) {
1347 ret = -EINVAL;
1348 goto end;
1349 }
1350 vstack_ax(stack)->type = REG_PTR;
1351 vstack_ax(stack)->load.type = LOAD_ROOT_PAYLOAD;
1352 next_pc += sizeof(struct load_op);
1353 break;
1354 }
1355
1356 case FILTER_OP_LOAD_FIELD:
1357 {
1358 struct load_op *insn = (struct load_op *) pc;
1359
1360 assert(vstack_ax(stack)->type == REG_PTR);
1361 /* Pop 1, push 1 */
1362 ret = specialize_load_field(vstack_ax(stack), insn);
1363 if (ret)
1364 goto end;
1365
1366 next_pc += sizeof(struct load_op);
1367 break;
1368 }
1369
1370 case FILTER_OP_LOAD_FIELD_S8:
1371 case FILTER_OP_LOAD_FIELD_S16:
1372 case FILTER_OP_LOAD_FIELD_S32:
1373 case FILTER_OP_LOAD_FIELD_S64:
1374 case FILTER_OP_LOAD_FIELD_U8:
1375 case FILTER_OP_LOAD_FIELD_U16:
1376 case FILTER_OP_LOAD_FIELD_U32:
1377 case FILTER_OP_LOAD_FIELD_U64:
1378 {
1379 /* Pop 1, push 1 */
1380 vstack_ax(stack)->type = REG_S64;
1381 next_pc += sizeof(struct load_op);
1382 break;
1383 }
1384
1385 case FILTER_OP_LOAD_FIELD_STRING:
1386 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1387 {
1388 /* Pop 1, push 1 */
1389 vstack_ax(stack)->type = REG_STRING;
1390 next_pc += sizeof(struct load_op);
1391 break;
1392 }
1393
1394 case FILTER_OP_LOAD_FIELD_DOUBLE:
1395 {
1396 /* Pop 1, push 1 */
1397 vstack_ax(stack)->type = REG_DOUBLE;
1398 next_pc += sizeof(struct load_op);
1399 break;
1400 }
1401
1402 case FILTER_OP_GET_SYMBOL:
1403 {
1404 struct load_op *insn = (struct load_op *) pc;
1405
1406 dbg_printf("op get symbol\n");
1407 switch (vstack_ax(stack)->load.type) {
1408 case LOAD_OBJECT:
1409 ERR("Nested fields not implemented yet.");
1410 ret = -EINVAL;
1411 goto end;
1412 case LOAD_ROOT_CONTEXT:
1413 /* Lookup context field. */
b77aaa1b 1414 ret = specialize_context_lookup(*pctx,
47e5f13e
MD
1415 bytecode, insn,
1416 &vstack_ax(stack)->load);
1417 if (ret)
1418 goto end;
1419 break;
1420 case LOAD_ROOT_APP_CONTEXT:
1421 /* Lookup app context field. */
b77aaa1b 1422 ret = specialize_app_context_lookup(pctx,
47e5f13e
MD
1423 bytecode, insn,
1424 &vstack_ax(stack)->load);
1425 if (ret)
1426 goto end;
1427 break;
1428 case LOAD_ROOT_PAYLOAD:
1429 /* Lookup event payload field. */
1430 ret = specialize_event_payload_lookup(event,
1431 bytecode, insn,
1432 &vstack_ax(stack)->load);
1433 if (ret)
1434 goto end;
1435 break;
1436 }
1437 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1438 break;
1439 }
1440
1441 case FILTER_OP_GET_SYMBOL_FIELD:
1442 {
1443 /* Always generated by specialize phase. */
1444 ret = -EINVAL;
1445 goto end;
1446 }
1447
1448 case FILTER_OP_GET_INDEX_U16:
1449 {
1450 struct load_op *insn = (struct load_op *) pc;
1451 struct get_index_u16 *index = (struct get_index_u16 *) insn->data;
1452
1453 dbg_printf("op get index u16\n");
1454 /* Pop 1, push 1 */
1455 ret = specialize_get_index(bytecode, insn, index->index,
1456 vstack_ax(stack), sizeof(*index));
1457 if (ret)
1458 goto end;
1459 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1460 break;
1461 }
1462
1463 case FILTER_OP_GET_INDEX_U64:
1464 {
1465 struct load_op *insn = (struct load_op *) pc;
1466 struct get_index_u64 *index = (struct get_index_u64 *) insn->data;
1467
1468 dbg_printf("op get index u64\n");
1469 /* Pop 1, push 1 */
1470 ret = specialize_get_index(bytecode, insn, index->index,
1471 vstack_ax(stack), sizeof(*index));
1472 if (ret)
1473 goto end;
1474 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1475 break;
1476 }
1477
97b58163
MD
1478 }
1479 }
1480end:
1481 return ret;
1482}
This page took 0.093627 seconds and 4 git commands to generate.