bytecode: allow interpreter to return any type
[lttng-ust.git] / liblttng-ust / lttng-filter-validator.c
CommitLineData
97b58163
MD
1/*
2 * lttng-filter-validator.c
3 *
4 * LTTng UST filter bytecode validator.
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
bf956ec0 27#define _LGPL_SOURCE
b4051ad8 28#include <stddef.h>
fb31eb73 29#include <stdint.h>
bf956ec0 30#include <time.h>
97b58163 31
fb31eb73 32#include <urcu-bp.h>
bf956ec0 33#include <urcu/rculfhash.h>
fb31eb73
FD
34
35#include "lttng-filter.h"
bf956ec0 36#include "lttng-hash-helper.h"
3151a51d 37#include "string-utils.h"
92495593 38#include "ust-events-internal.h"
bf956ec0 39
0305960f
MD
40/*
41 * Number of merge points for hash table size. Hash table initialized to
42 * that size, and we do not resize, because we do not want to trigger
43 * RCU worker thread execution: fall-back on linear traversal if number
44 * of merge points exceeds this value.
45 */
46#define DEFAULT_NR_MERGE_POINTS 128
47#define MIN_NR_BUCKETS 128
48#define MAX_NR_BUCKETS 128
49
bf956ec0
MD
50/* merge point table node */
51struct lfht_mp_node {
52 struct cds_lfht_node node;
53
54 /* Context at merge point */
0305960f 55 struct vstack stack;
bf956ec0
MD
56 unsigned long target_pc;
57};
58
59static unsigned long lttng_hash_seed;
60static unsigned int lttng_hash_seed_ready;
61
62static
63int lttng_hash_match(struct cds_lfht_node *node, const void *key)
64{
65 struct lfht_mp_node *mp_node =
66 caa_container_of(node, struct lfht_mp_node, node);
67 unsigned long key_pc = (unsigned long) key;
68
69 if (mp_node->target_pc == key_pc)
70 return 1;
71 else
72 return 0;
73}
74
75static
71c1ceeb
MD
76int merge_points_compare(const struct vstack *stacka,
77 const struct vstack *stackb)
78{
79 int i, len;
80
81 if (stacka->top != stackb->top)
82 return 1;
83 len = stacka->top + 1;
84 assert(len >= 0);
85 for (i = 0; i < len; i++) {
53569322
MD
86 if (stacka->e[i].type != REG_UNKNOWN
87 && stackb->e[i].type != REG_UNKNOWN
88 && stacka->e[i].type != stackb->e[i].type)
71c1ceeb
MD
89 return 1;
90 }
91 return 0;
92}
93
94static
95int merge_point_add_check(struct cds_lfht *ht, unsigned long target_pc,
0305960f 96 const struct vstack *stack)
bf956ec0
MD
97{
98 struct lfht_mp_node *node;
22389ecb 99 unsigned long hash = lttng_hash_mix((const char *) target_pc,
bf956ec0
MD
100 sizeof(target_pc),
101 lttng_hash_seed);
71c1ceeb 102 struct cds_lfht_node *ret;
bf956ec0
MD
103
104 dbg_printf("Filter: adding merge point at offset %lu, hash %lu\n",
105 target_pc, hash);
106 node = zmalloc(sizeof(struct lfht_mp_node));
107 if (!node)
108 return -ENOMEM;
109 node->target_pc = target_pc;
0305960f 110 memcpy(&node->stack, stack, sizeof(node->stack));
71c1ceeb 111 ret = cds_lfht_add_unique(ht, hash, lttng_hash_match,
22389ecb 112 (const char *) target_pc, &node->node);
71c1ceeb
MD
113 if (ret != &node->node) {
114 struct lfht_mp_node *ret_mp =
115 caa_container_of(ret, struct lfht_mp_node, node);
116
117 /* Key already present */
118 dbg_printf("Filter: compare merge points for offset %lu, hash %lu\n",
119 target_pc, hash);
120 free(node);
121 if (merge_points_compare(stack, &ret_mp->stack)) {
122 ERR("Merge points differ for offset %lu\n",
123 target_pc);
124 return -EINVAL;
125 }
126 }
bf956ec0
MD
127 return 0;
128}
129
130/*
0305960f 131 * Binary comparators use top of stack and top of stack -1.
53569322
MD
132 * Return 0 if typing is known to match, 1 if typing is dynamic
133 * (unknown), negative error value on error.
bf956ec0 134 */
97b58163 135static
3151a51d
PP
136int bin_op_compare_check(struct vstack *stack, filter_opcode_t opcode,
137 const char *str)
97b58163 138{
0305960f 139 if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
53569322 140 goto error_empty;
0305960f
MD
141
142 switch (vstack_ax(stack)->type) {
97b58163 143 default:
53569322 144 goto error_type;
97b58163 145
53569322
MD
146 case REG_UNKNOWN:
147 goto unknown;
97b58163 148 case REG_STRING:
0305960f 149 switch (vstack_bx(stack)->type) {
97b58163 150 default:
53569322 151 goto error_type;
97b58163 152
53569322
MD
153 case REG_UNKNOWN:
154 goto unknown;
97b58163
MD
155 case REG_STRING:
156 break;
3151a51d
PP
157 case REG_STAR_GLOB_STRING:
158 if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
159 goto error_mismatch;
160 }
161 break;
162 case REG_S64:
d97f9b78 163 case REG_U64:
3151a51d
PP
164 case REG_DOUBLE:
165 goto error_mismatch;
166 }
167 break;
168 case REG_STAR_GLOB_STRING:
169 switch (vstack_bx(stack)->type) {
170 default:
171 goto error_type;
172
173 case REG_UNKNOWN:
174 goto unknown;
175 case REG_STRING:
176 if (opcode != FILTER_OP_EQ && opcode != FILTER_OP_NE) {
177 goto error_mismatch;
178 }
179 break;
180 case REG_STAR_GLOB_STRING:
97b58163 181 case REG_S64:
d97f9b78 182 case REG_U64:
97b58163
MD
183 case REG_DOUBLE:
184 goto error_mismatch;
185 }
186 break;
187 case REG_S64:
d97f9b78 188 case REG_U64:
97b58163 189 case REG_DOUBLE:
0305960f 190 switch (vstack_bx(stack)->type) {
97b58163 191 default:
53569322 192 goto error_type;
97b58163 193
53569322
MD
194 case REG_UNKNOWN:
195 goto unknown;
97b58163 196 case REG_STRING:
3151a51d 197 case REG_STAR_GLOB_STRING:
97b58163 198 goto error_mismatch;
97b58163 199 case REG_S64:
d97f9b78 200 case REG_U64:
97b58163
MD
201 case REG_DOUBLE:
202 break;
203 }
204 break;
205 }
206 return 0;
207
53569322
MD
208unknown:
209 return 1;
0305960f 210
97b58163
MD
211error_mismatch:
212 ERR("type mismatch for '%s' binary operator\n", str);
213 return -EINVAL;
53569322
MD
214
215error_empty:
216 ERR("empty stack for '%s' binary operator\n", str);
217 return -EINVAL;
218
219error_type:
220 ERR("unknown type for '%s' binary operator\n", str);
221 return -EINVAL;
97b58163
MD
222}
223
47e5f13e
MD
224/*
225 * Binary bitwise operators use top of stack and top of stack -1.
226 * Return 0 if typing is known to match, 1 if typing is dynamic
227 * (unknown), negative error value on error.
228 */
229static
230int bin_op_bitwise_check(struct vstack *stack, filter_opcode_t opcode,
231 const char *str)
232{
233 if (unlikely(!vstack_ax(stack) || !vstack_bx(stack)))
234 goto error_empty;
235
236 switch (vstack_ax(stack)->type) {
237 default:
238 goto error_type;
239
240 case REG_UNKNOWN:
241 goto unknown;
242 case REG_S64:
d97f9b78 243 case REG_U64:
47e5f13e
MD
244 switch (vstack_bx(stack)->type) {
245 default:
246 goto error_type;
247
248 case REG_UNKNOWN:
249 goto unknown;
250 case REG_S64:
d97f9b78 251 case REG_U64:
47e5f13e
MD
252 break;
253 }
254 break;
255 }
256 return 0;
257
258unknown:
259 return 1;
260
261error_empty:
262 ERR("empty stack for '%s' binary operator\n", str);
263 return -EINVAL;
264
265error_type:
266 ERR("unknown type for '%s' binary operator\n", str);
267 return -EINVAL;
268}
269
270static
271int validate_get_symbol(struct bytecode_runtime *bytecode,
272 const struct get_symbol *sym)
273{
274 const char *str, *str_limit;
275 size_t len_limit;
276
277 if (sym->offset >= bytecode->p.bc->bc.len - bytecode->p.bc->bc.reloc_offset)
278 return -EINVAL;
279
280 str = bytecode->p.bc->bc.data + bytecode->p.bc->bc.reloc_offset + sym->offset;
281 str_limit = bytecode->p.bc->bc.data + bytecode->p.bc->bc.len;
282 len_limit = str_limit - str;
283 if (strnlen(str, len_limit) == len_limit)
284 return -EINVAL;
285 return 0;
286}
287
97b58163
MD
288/*
289 * Validate bytecode range overflow within the validation pass.
290 * Called for each instruction encountered.
291 */
292static
293int bytecode_validate_overflow(struct bytecode_runtime *bytecode,
22389ecb 294 char *start_pc, char *pc)
97b58163
MD
295{
296 int ret = 0;
297
298 switch (*(filter_opcode_t *) pc) {
299 case FILTER_OP_UNKNOWN:
300 default:
301 {
302 ERR("unknown bytecode op %u\n",
303 (unsigned int) *(filter_opcode_t *) pc);
304 ret = -EINVAL;
305 break;
306 }
307
308 case FILTER_OP_RETURN:
93c591bb 309 case FILTER_OP_RETURN_S64:
97b58163
MD
310 {
311 if (unlikely(pc + sizeof(struct return_op)
312 > start_pc + bytecode->len)) {
82513dbe 313 ret = -ERANGE;
97b58163
MD
314 }
315 break;
316 }
317
318 /* binary */
319 case FILTER_OP_MUL:
320 case FILTER_OP_DIV:
321 case FILTER_OP_MOD:
322 case FILTER_OP_PLUS:
323 case FILTER_OP_MINUS:
97b58163
MD
324 {
325 ERR("unsupported bytecode op %u\n",
326 (unsigned int) *(filter_opcode_t *) pc);
327 ret = -EINVAL;
328 break;
329 }
330
331 case FILTER_OP_EQ:
332 case FILTER_OP_NE:
333 case FILTER_OP_GT:
334 case FILTER_OP_LT:
335 case FILTER_OP_GE:
336 case FILTER_OP_LE:
337 case FILTER_OP_EQ_STRING:
338 case FILTER_OP_NE_STRING:
339 case FILTER_OP_GT_STRING:
340 case FILTER_OP_LT_STRING:
341 case FILTER_OP_GE_STRING:
342 case FILTER_OP_LE_STRING:
3151a51d
PP
343 case FILTER_OP_EQ_STAR_GLOB_STRING:
344 case FILTER_OP_NE_STAR_GLOB_STRING:
97b58163
MD
345 case FILTER_OP_EQ_S64:
346 case FILTER_OP_NE_S64:
347 case FILTER_OP_GT_S64:
348 case FILTER_OP_LT_S64:
349 case FILTER_OP_GE_S64:
350 case FILTER_OP_LE_S64:
351 case FILTER_OP_EQ_DOUBLE:
352 case FILTER_OP_NE_DOUBLE:
353 case FILTER_OP_GT_DOUBLE:
354 case FILTER_OP_LT_DOUBLE:
355 case FILTER_OP_GE_DOUBLE:
356 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
357 case FILTER_OP_EQ_DOUBLE_S64:
358 case FILTER_OP_NE_DOUBLE_S64:
359 case FILTER_OP_GT_DOUBLE_S64:
360 case FILTER_OP_LT_DOUBLE_S64:
361 case FILTER_OP_GE_DOUBLE_S64:
362 case FILTER_OP_LE_DOUBLE_S64:
363 case FILTER_OP_EQ_S64_DOUBLE:
364 case FILTER_OP_NE_S64_DOUBLE:
365 case FILTER_OP_GT_S64_DOUBLE:
366 case FILTER_OP_LT_S64_DOUBLE:
367 case FILTER_OP_GE_S64_DOUBLE:
368 case FILTER_OP_LE_S64_DOUBLE:
0039e2d8
MD
369 case FILTER_OP_BIT_RSHIFT:
370 case FILTER_OP_BIT_LSHIFT:
47e5f13e
MD
371 case FILTER_OP_BIT_AND:
372 case FILTER_OP_BIT_OR:
373 case FILTER_OP_BIT_XOR:
97b58163
MD
374 {
375 if (unlikely(pc + sizeof(struct binary_op)
376 > start_pc + bytecode->len)) {
82513dbe 377 ret = -ERANGE;
97b58163
MD
378 }
379 break;
380 }
381
382 /* unary */
383 case FILTER_OP_UNARY_PLUS:
384 case FILTER_OP_UNARY_MINUS:
385 case FILTER_OP_UNARY_NOT:
386 case FILTER_OP_UNARY_PLUS_S64:
387 case FILTER_OP_UNARY_MINUS_S64:
388 case FILTER_OP_UNARY_NOT_S64:
389 case FILTER_OP_UNARY_PLUS_DOUBLE:
390 case FILTER_OP_UNARY_MINUS_DOUBLE:
391 case FILTER_OP_UNARY_NOT_DOUBLE:
0039e2d8 392 case FILTER_OP_UNARY_BIT_NOT:
97b58163
MD
393 {
394 if (unlikely(pc + sizeof(struct unary_op)
395 > start_pc + bytecode->len)) {
82513dbe 396 ret = -ERANGE;
97b58163
MD
397 }
398 break;
399 }
400
401 /* logical */
402 case FILTER_OP_AND:
403 case FILTER_OP_OR:
404 {
405 if (unlikely(pc + sizeof(struct logical_op)
406 > start_pc + bytecode->len)) {
82513dbe 407 ret = -ERANGE;
97b58163
MD
408 }
409 break;
410 }
411
77aa5901 412 /* load field ref */
97b58163
MD
413 case FILTER_OP_LOAD_FIELD_REF:
414 {
415 ERR("Unknown field ref type\n");
416 ret = -EINVAL;
417 break;
418 }
47e5f13e 419
77aa5901
MD
420 /* get context ref */
421 case FILTER_OP_GET_CONTEXT_REF:
97b58163
MD
422 case FILTER_OP_LOAD_FIELD_REF_STRING:
423 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
424 case FILTER_OP_LOAD_FIELD_REF_S64:
425 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901
MD
426 case FILTER_OP_GET_CONTEXT_REF_STRING:
427 case FILTER_OP_GET_CONTEXT_REF_S64:
428 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
97b58163
MD
429 {
430 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct field_ref)
431 > start_pc + bytecode->len)) {
82513dbe 432 ret = -ERANGE;
97b58163
MD
433 }
434 break;
435 }
436
77aa5901 437 /* load from immediate operand */
97b58163 438 case FILTER_OP_LOAD_STRING:
3151a51d 439 case FILTER_OP_LOAD_STAR_GLOB_STRING:
97b58163
MD
440 {
441 struct load_op *insn = (struct load_op *) pc;
442 uint32_t str_len, maxlen;
443
444 if (unlikely(pc + sizeof(struct load_op)
445 > start_pc + bytecode->len)) {
82513dbe 446 ret = -ERANGE;
97b58163
MD
447 break;
448 }
449
450 maxlen = start_pc + bytecode->len - pc - sizeof(struct load_op);
451 str_len = strnlen(insn->data, maxlen);
452 if (unlikely(str_len >= maxlen)) {
453 /* Final '\0' not found within range */
82513dbe 454 ret = -ERANGE;
97b58163
MD
455 }
456 break;
457 }
458
459 case FILTER_OP_LOAD_S64:
460 {
461 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_numeric)
462 > start_pc + bytecode->len)) {
82513dbe 463 ret = -ERANGE;
97b58163
MD
464 }
465 break;
466 }
467
468 case FILTER_OP_LOAD_DOUBLE:
469 {
470 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct literal_double)
471 > start_pc + bytecode->len)) {
82513dbe 472 ret = -ERANGE;
97b58163
MD
473 }
474 break;
475 }
476
477 case FILTER_OP_CAST_TO_S64:
478 case FILTER_OP_CAST_DOUBLE_TO_S64:
479 case FILTER_OP_CAST_NOP:
480 {
481 if (unlikely(pc + sizeof(struct cast_op)
482 > start_pc + bytecode->len)) {
82513dbe 483 ret = -ERANGE;
97b58163
MD
484 }
485 break;
486 }
77aa5901 487
47e5f13e
MD
488 /*
489 * Instructions for recursive traversal through composed types.
490 */
491 case FILTER_OP_GET_CONTEXT_ROOT:
492 case FILTER_OP_GET_APP_CONTEXT_ROOT:
493 case FILTER_OP_GET_PAYLOAD_ROOT:
494 case FILTER_OP_LOAD_FIELD:
495 case FILTER_OP_LOAD_FIELD_S8:
496 case FILTER_OP_LOAD_FIELD_S16:
497 case FILTER_OP_LOAD_FIELD_S32:
498 case FILTER_OP_LOAD_FIELD_S64:
499 case FILTER_OP_LOAD_FIELD_U8:
500 case FILTER_OP_LOAD_FIELD_U16:
501 case FILTER_OP_LOAD_FIELD_U32:
502 case FILTER_OP_LOAD_FIELD_U64:
503 case FILTER_OP_LOAD_FIELD_STRING:
504 case FILTER_OP_LOAD_FIELD_SEQUENCE:
505 case FILTER_OP_LOAD_FIELD_DOUBLE:
506 if (unlikely(pc + sizeof(struct load_op)
507 > start_pc + bytecode->len)) {
508 ret = -ERANGE;
509 }
510 break;
511
512 case FILTER_OP_GET_SYMBOL:
513 {
514 struct load_op *insn = (struct load_op *) pc;
515 struct get_symbol *sym = (struct get_symbol *) insn->data;
516
517 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_symbol)
518 > start_pc + bytecode->len)) {
519 ret = -ERANGE;
90732639 520 break;
47e5f13e
MD
521 }
522 ret = validate_get_symbol(bytecode, sym);
523 break;
524 }
525
526 case FILTER_OP_GET_SYMBOL_FIELD:
527 ERR("Unexpected get symbol field");
528 ret = -EINVAL;
529 break;
530
531 case FILTER_OP_GET_INDEX_U16:
532 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u16)
533 > start_pc + bytecode->len)) {
534 ret = -ERANGE;
535 }
536 break;
537
538 case FILTER_OP_GET_INDEX_U64:
539 if (unlikely(pc + sizeof(struct load_op) + sizeof(struct get_index_u64)
540 > start_pc + bytecode->len)) {
541 ret = -ERANGE;
542 }
543 break;
97b58163
MD
544 }
545
546 return ret;
547}
548
bf956ec0
MD
549static
550unsigned long delete_all_nodes(struct cds_lfht *ht)
97b58163 551{
bf956ec0
MD
552 struct cds_lfht_iter iter;
553 struct lfht_mp_node *node;
554 unsigned long nr_nodes = 0;
97b58163 555
bf956ec0
MD
556 cds_lfht_for_each_entry(ht, &iter, node, node) {
557 int ret;
558
559 ret = cds_lfht_del(ht, cds_lfht_iter_get_node(&iter));
560 assert(!ret);
561 /* note: this hash table is never used concurrently */
562 free(node);
563 nr_nodes++;
97b58163 564 }
bf956ec0
MD
565 return nr_nodes;
566}
97b58163 567
bf956ec0
MD
568/*
569 * Return value:
53569322 570 * >=0: success
bf956ec0
MD
571 * <0: error
572 */
573static
574int validate_instruction_context(struct bytecode_runtime *bytecode,
0305960f 575 struct vstack *stack,
22389ecb
MD
576 char *start_pc,
577 char *pc)
bf956ec0
MD
578{
579 int ret = 0;
3151a51d 580 const filter_opcode_t opcode = *(filter_opcode_t *) pc;
bf956ec0 581
3151a51d 582 switch (opcode) {
bf956ec0
MD
583 case FILTER_OP_UNKNOWN:
584 default:
585 {
586 ERR("unknown bytecode op %u\n",
97b58163 587 (unsigned int) *(filter_opcode_t *) pc);
bf956ec0
MD
588 ret = -EINVAL;
589 goto end;
590 }
591
592 case FILTER_OP_RETURN:
93c591bb 593 case FILTER_OP_RETURN_S64:
bf956ec0
MD
594 {
595 goto end;
596 }
597
598 /* binary */
599 case FILTER_OP_MUL:
600 case FILTER_OP_DIV:
601 case FILTER_OP_MOD:
602 case FILTER_OP_PLUS:
603 case FILTER_OP_MINUS:
bf956ec0
MD
604 {
605 ERR("unsupported bytecode op %u\n",
3151a51d 606 (unsigned int) opcode);
bf956ec0
MD
607 ret = -EINVAL;
608 goto end;
609 }
97b58163 610
bf956ec0
MD
611 case FILTER_OP_EQ:
612 {
3151a51d 613 ret = bin_op_compare_check(stack, opcode, "==");
53569322 614 if (ret < 0)
bf956ec0
MD
615 goto end;
616 break;
617 }
618 case FILTER_OP_NE:
619 {
3151a51d 620 ret = bin_op_compare_check(stack, opcode, "!=");
53569322 621 if (ret < 0)
bf956ec0
MD
622 goto end;
623 break;
624 }
625 case FILTER_OP_GT:
626 {
3151a51d 627 ret = bin_op_compare_check(stack, opcode, ">");
53569322 628 if (ret < 0)
bf956ec0
MD
629 goto end;
630 break;
631 }
632 case FILTER_OP_LT:
633 {
3151a51d 634 ret = bin_op_compare_check(stack, opcode, "<");
53569322 635 if (ret < 0)
bf956ec0
MD
636 goto end;
637 break;
638 }
639 case FILTER_OP_GE:
640 {
3151a51d 641 ret = bin_op_compare_check(stack, opcode, ">=");
53569322 642 if (ret < 0)
bf956ec0
MD
643 goto end;
644 break;
645 }
646 case FILTER_OP_LE:
647 {
3151a51d 648 ret = bin_op_compare_check(stack, opcode, "<=");
53569322 649 if (ret < 0)
97b58163 650 goto end;
bf956ec0
MD
651 break;
652 }
97b58163 653
bf956ec0
MD
654 case FILTER_OP_EQ_STRING:
655 case FILTER_OP_NE_STRING:
656 case FILTER_OP_GT_STRING:
657 case FILTER_OP_LT_STRING:
658 case FILTER_OP_GE_STRING:
659 case FILTER_OP_LE_STRING:
660 {
0305960f
MD
661 if (!vstack_ax(stack) || !vstack_bx(stack)) {
662 ERR("Empty stack\n");
663 ret = -EINVAL;
664 goto end;
665 }
666 if (vstack_ax(stack)->type != REG_STRING
667 || vstack_bx(stack)->type != REG_STRING) {
bf956ec0 668 ERR("Unexpected register type for string comparator\n");
97b58163
MD
669 ret = -EINVAL;
670 goto end;
97b58163 671 }
bf956ec0
MD
672 break;
673 }
97b58163 674
3151a51d
PP
675 case FILTER_OP_EQ_STAR_GLOB_STRING:
676 case FILTER_OP_NE_STAR_GLOB_STRING:
677 {
678 if (!vstack_ax(stack) || !vstack_bx(stack)) {
679 ERR("Empty stack\n");
680 ret = -EINVAL;
681 goto end;
682 }
683 if (vstack_ax(stack)->type != REG_STAR_GLOB_STRING
684 && vstack_bx(stack)->type != REG_STAR_GLOB_STRING) {
685 ERR("Unexpected register type for globbing pattern comparator\n");
686 ret = -EINVAL;
687 goto end;
688 }
689 break;
690 }
691
bf956ec0
MD
692 case FILTER_OP_EQ_S64:
693 case FILTER_OP_NE_S64:
694 case FILTER_OP_GT_S64:
695 case FILTER_OP_LT_S64:
696 case FILTER_OP_GE_S64:
697 case FILTER_OP_LE_S64:
698 {
0305960f
MD
699 if (!vstack_ax(stack) || !vstack_bx(stack)) {
700 ERR("Empty stack\n");
701 ret = -EINVAL;
702 goto end;
703 }
d97f9b78
MD
704 switch (vstack_ax(stack)->type) {
705 case REG_S64:
706 case REG_U64:
707 break;
708 default:
709 ERR("Unexpected register type for s64 comparator\n");
710 ret = -EINVAL;
711 goto end;
712 }
713 switch (vstack_bx(stack)->type) {
714 case REG_S64:
715 case REG_U64:
716 break;
717 default:
bf956ec0
MD
718 ERR("Unexpected register type for s64 comparator\n");
719 ret = -EINVAL;
720 goto end;
97b58163 721 }
bf956ec0
MD
722 break;
723 }
97b58163 724
bf956ec0
MD
725 case FILTER_OP_EQ_DOUBLE:
726 case FILTER_OP_NE_DOUBLE:
727 case FILTER_OP_GT_DOUBLE:
728 case FILTER_OP_LT_DOUBLE:
729 case FILTER_OP_GE_DOUBLE:
730 case FILTER_OP_LE_DOUBLE:
731 {
0305960f
MD
732 if (!vstack_ax(stack) || !vstack_bx(stack)) {
733 ERR("Empty stack\n");
734 ret = -EINVAL;
735 goto end;
736 }
dbea82ec
MD
737 if (vstack_ax(stack)->type != REG_DOUBLE && vstack_bx(stack)->type != REG_DOUBLE) {
738 ERR("Double operator should have two double registers\n");
bf956ec0
MD
739 ret = -EINVAL;
740 goto end;
97b58163 741 }
dbea82ec
MD
742 break;
743 }
744
745 case FILTER_OP_EQ_DOUBLE_S64:
746 case FILTER_OP_NE_DOUBLE_S64:
747 case FILTER_OP_GT_DOUBLE_S64:
748 case FILTER_OP_LT_DOUBLE_S64:
749 case FILTER_OP_GE_DOUBLE_S64:
750 case FILTER_OP_LE_DOUBLE_S64:
751 {
752 if (!vstack_ax(stack) || !vstack_bx(stack)) {
753 ERR("Empty stack\n");
754 ret = -EINVAL;
755 goto end;
756 }
d97f9b78
MD
757 switch (vstack_ax(stack)->type) {
758 case REG_S64:
759 case REG_U64:
760 break;
761 default:
762 ERR("Double-S64 operator has unexpected register types\n");
763 ret = -EINVAL;
764 goto end;
765 }
766 switch (vstack_bx(stack)->type) {
767 case REG_DOUBLE:
768 break;
769 default:
dbea82ec
MD
770 ERR("Double-S64 operator has unexpected register types\n");
771 ret = -EINVAL;
772 goto end;
773 }
774 break;
775 }
776
777 case FILTER_OP_EQ_S64_DOUBLE:
778 case FILTER_OP_NE_S64_DOUBLE:
779 case FILTER_OP_GT_S64_DOUBLE:
780 case FILTER_OP_LT_S64_DOUBLE:
781 case FILTER_OP_GE_S64_DOUBLE:
782 case FILTER_OP_LE_S64_DOUBLE:
783 {
784 if (!vstack_ax(stack) || !vstack_bx(stack)) {
785 ERR("Empty stack\n");
786 ret = -EINVAL;
787 goto end;
788 }
d97f9b78
MD
789 switch (vstack_ax(stack)->type) {
790 case REG_DOUBLE:
791 break;
792 default:
793 ERR("S64-Double operator has unexpected register types\n");
794 ret = -EINVAL;
795 goto end;
796 }
797 switch (vstack_bx(stack)->type) {
798 case REG_S64:
799 case REG_U64:
800 break;
801 default:
dbea82ec 802 ERR("S64-Double operator has unexpected register types\n");
bf956ec0
MD
803 ret = -EINVAL;
804 goto end;
97b58163 805 }
bf956ec0
MD
806 break;
807 }
97b58163 808
0039e2d8
MD
809 case FILTER_OP_BIT_RSHIFT:
810 ret = bin_op_bitwise_check(stack, opcode, ">>");
811 if (ret < 0)
812 goto end;
813 break;
814 case FILTER_OP_BIT_LSHIFT:
815 ret = bin_op_bitwise_check(stack, opcode, "<<");
816 if (ret < 0)
817 goto end;
818 break;
47e5f13e
MD
819 case FILTER_OP_BIT_AND:
820 ret = bin_op_bitwise_check(stack, opcode, "&");
821 if (ret < 0)
822 goto end;
823 break;
824 case FILTER_OP_BIT_OR:
825 ret = bin_op_bitwise_check(stack, opcode, "|");
826 if (ret < 0)
827 goto end;
828 break;
829 case FILTER_OP_BIT_XOR:
830 ret = bin_op_bitwise_check(stack, opcode, "^");
831 if (ret < 0)
832 goto end;
833 break;
834
bf956ec0
MD
835 /* unary */
836 case FILTER_OP_UNARY_PLUS:
837 case FILTER_OP_UNARY_MINUS:
838 case FILTER_OP_UNARY_NOT:
839 {
0305960f
MD
840 if (!vstack_ax(stack)) {
841 ERR("Empty stack\n");
bf956ec0
MD
842 ret = -EINVAL;
843 goto end;
844 }
0305960f 845 switch (vstack_ax(stack)->type) {
bf956ec0
MD
846 default:
847 ERR("unknown register type\n");
848 ret = -EINVAL;
849 goto end;
97b58163 850
bf956ec0 851 case REG_STRING:
3151a51d 852 case REG_STAR_GLOB_STRING:
bf956ec0
MD
853 ERR("Unary op can only be applied to numeric or floating point registers\n");
854 ret = -EINVAL;
855 goto end;
856 case REG_S64:
857 break;
d97f9b78
MD
858 case REG_U64:
859 break;
bf956ec0 860 case REG_DOUBLE:
97b58163 861 break;
53569322
MD
862 case REG_UNKNOWN:
863 break;
97b58163 864 }
bf956ec0
MD
865 break;
866 }
0039e2d8
MD
867 case FILTER_OP_UNARY_BIT_NOT:
868 {
869 if (!vstack_ax(stack)) {
870 ERR("Empty stack\n");
871 ret = -EINVAL;
872 goto end;
873 }
874 switch (vstack_ax(stack)->type) {
875 default:
876 ERR("unknown register type\n");
877 ret = -EINVAL;
878 goto end;
879
880 case REG_STRING:
881 case REG_STAR_GLOB_STRING:
882 case REG_DOUBLE:
883 ERR("Unary bitwise op can only be applied to numeric registers\n");
884 ret = -EINVAL;
885 goto end;
886 case REG_S64:
887 break;
d97f9b78
MD
888 case REG_U64:
889 break;
0039e2d8
MD
890 case REG_UNKNOWN:
891 break;
892 }
893 break;
894 }
97b58163 895
bf956ec0
MD
896 case FILTER_OP_UNARY_PLUS_S64:
897 case FILTER_OP_UNARY_MINUS_S64:
898 case FILTER_OP_UNARY_NOT_S64:
899 {
0305960f
MD
900 if (!vstack_ax(stack)) {
901 ERR("Empty stack\n");
bf956ec0
MD
902 ret = -EINVAL;
903 goto end;
904 }
d97f9b78
MD
905 if (vstack_ax(stack)->type != REG_S64 &&
906 vstack_ax(stack)->type != REG_U64) {
bf956ec0
MD
907 ERR("Invalid register type\n");
908 ret = -EINVAL;
909 goto end;
97b58163 910 }
bf956ec0
MD
911 break;
912 }
97b58163 913
bf956ec0
MD
914 case FILTER_OP_UNARY_PLUS_DOUBLE:
915 case FILTER_OP_UNARY_MINUS_DOUBLE:
916 case FILTER_OP_UNARY_NOT_DOUBLE:
917 {
0305960f
MD
918 if (!vstack_ax(stack)) {
919 ERR("Empty stack\n");
bf956ec0
MD
920 ret = -EINVAL;
921 goto end;
97b58163 922 }
0305960f 923 if (vstack_ax(stack)->type != REG_DOUBLE) {
bf956ec0
MD
924 ERR("Invalid register type\n");
925 ret = -EINVAL;
926 goto end;
927 }
928 break;
929 }
97b58163 930
bf956ec0
MD
931 /* logical */
932 case FILTER_OP_AND:
933 case FILTER_OP_OR:
934 {
935 struct logical_op *insn = (struct logical_op *) pc;
97b58163 936
0305960f
MD
937 if (!vstack_ax(stack)) {
938 ERR("Empty stack\n");
939 ret = -EINVAL;
940 goto end;
941 }
53569322 942 if (vstack_ax(stack)->type != REG_S64
d97f9b78 943 && vstack_ax(stack)->type != REG_U64
53569322 944 && vstack_ax(stack)->type != REG_UNKNOWN) {
d97f9b78 945 ERR("Logical comparator expects S64, U64 or dynamic register\n");
bf956ec0
MD
946 ret = -EINVAL;
947 goto end;
97b58163
MD
948 }
949
bf956ec0
MD
950 dbg_printf("Validate jumping to bytecode offset %u\n",
951 (unsigned int) insn->skip_offset);
952 if (unlikely(start_pc + insn->skip_offset <= pc)) {
953 ERR("Loops are not allowed in bytecode\n");
97b58163
MD
954 ret = -EINVAL;
955 goto end;
956 }
bf956ec0
MD
957 break;
958 }
97b58163 959
77aa5901 960 /* load field ref */
bf956ec0
MD
961 case FILTER_OP_LOAD_FIELD_REF:
962 {
963 ERR("Unknown field ref type\n");
964 ret = -EINVAL;
965 goto end;
966 }
967 case FILTER_OP_LOAD_FIELD_REF_STRING:
968 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
969 {
970 struct load_op *insn = (struct load_op *) pc;
971 struct field_ref *ref = (struct field_ref *) insn->data;
972
bf956ec0
MD
973 dbg_printf("Validate load field ref offset %u type string\n",
974 ref->offset);
975 break;
976 }
977 case FILTER_OP_LOAD_FIELD_REF_S64:
978 {
979 struct load_op *insn = (struct load_op *) pc;
980 struct field_ref *ref = (struct field_ref *) insn->data;
97b58163 981
bf956ec0
MD
982 dbg_printf("Validate load field ref offset %u type s64\n",
983 ref->offset);
984 break;
985 }
986 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
987 {
988 struct load_op *insn = (struct load_op *) pc;
989 struct field_ref *ref = (struct field_ref *) insn->data;
97b58163 990
bf956ec0
MD
991 dbg_printf("Validate load field ref offset %u type double\n",
992 ref->offset);
993 break;
994 }
97b58163 995
77aa5901 996 /* load from immediate operand */
bf956ec0 997 case FILTER_OP_LOAD_STRING:
3151a51d 998 case FILTER_OP_LOAD_STAR_GLOB_STRING:
bf956ec0 999 {
bf956ec0
MD
1000 break;
1001 }
97b58163 1002
bf956ec0
MD
1003 case FILTER_OP_LOAD_S64:
1004 {
bf956ec0
MD
1005 break;
1006 }
97b58163 1007
bf956ec0
MD
1008 case FILTER_OP_LOAD_DOUBLE:
1009 {
bf956ec0
MD
1010 break;
1011 }
97b58163 1012
bf956ec0
MD
1013 case FILTER_OP_CAST_TO_S64:
1014 case FILTER_OP_CAST_DOUBLE_TO_S64:
1015 {
1016 struct cast_op *insn = (struct cast_op *) pc;
97b58163 1017
0305960f
MD
1018 if (!vstack_ax(stack)) {
1019 ERR("Empty stack\n");
bf956ec0
MD
1020 ret = -EINVAL;
1021 goto end;
1022 }
0305960f 1023 switch (vstack_ax(stack)->type) {
bf956ec0
MD
1024 default:
1025 ERR("unknown register type\n");
1026 ret = -EINVAL;
1027 goto end;
97b58163 1028
bf956ec0 1029 case REG_STRING:
3151a51d 1030 case REG_STAR_GLOB_STRING:
bf956ec0
MD
1031 ERR("Cast op can only be applied to numeric or floating point registers\n");
1032 ret = -EINVAL;
1033 goto end;
1034 case REG_S64:
1035 break;
d97f9b78
MD
1036 case REG_U64:
1037 break;
bf956ec0
MD
1038 case REG_DOUBLE:
1039 break;
53569322
MD
1040 case REG_UNKNOWN:
1041 break;
bf956ec0
MD
1042 }
1043 if (insn->op == FILTER_OP_CAST_DOUBLE_TO_S64) {
0305960f 1044 if (vstack_ax(stack)->type != REG_DOUBLE) {
bf956ec0 1045 ERR("Cast expects double\n");
97b58163
MD
1046 ret = -EINVAL;
1047 goto end;
97b58163 1048 }
97b58163 1049 }
bf956ec0
MD
1050 break;
1051 }
1052 case FILTER_OP_CAST_NOP:
1053 {
1054 break;
1055 }
1056
77aa5901
MD
1057 /* get context ref */
1058 case FILTER_OP_GET_CONTEXT_REF:
1059 {
53569322
MD
1060 struct load_op *insn = (struct load_op *) pc;
1061 struct field_ref *ref = (struct field_ref *) insn->data;
1062
1063 dbg_printf("Validate get context ref offset %u type dynamic\n",
1064 ref->offset);
1065 break;
77aa5901
MD
1066 }
1067 case FILTER_OP_GET_CONTEXT_REF_STRING:
1068 {
1069 struct load_op *insn = (struct load_op *) pc;
1070 struct field_ref *ref = (struct field_ref *) insn->data;
1071
1072 dbg_printf("Validate get context ref offset %u type string\n",
1073 ref->offset);
1074 break;
1075 }
1076 case FILTER_OP_GET_CONTEXT_REF_S64:
1077 {
1078 struct load_op *insn = (struct load_op *) pc;
1079 struct field_ref *ref = (struct field_ref *) insn->data;
1080
1081 dbg_printf("Validate get context ref offset %u type s64\n",
1082 ref->offset);
1083 break;
1084 }
1085 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
1086 {
1087 struct load_op *insn = (struct load_op *) pc;
1088 struct field_ref *ref = (struct field_ref *) insn->data;
1089
1090 dbg_printf("Validate get context ref offset %u type double\n",
1091 ref->offset);
1092 break;
1093 }
1094
47e5f13e
MD
1095 /*
1096 * Instructions for recursive traversal through composed types.
1097 */
1098 case FILTER_OP_GET_CONTEXT_ROOT:
1099 {
1100 dbg_printf("Validate get context root\n");
1101 break;
1102 }
1103 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1104 {
1105 dbg_printf("Validate get app context root\n");
1106 break;
1107 }
1108 case FILTER_OP_GET_PAYLOAD_ROOT:
1109 {
1110 dbg_printf("Validate get payload root\n");
1111 break;
1112 }
1113 case FILTER_OP_LOAD_FIELD:
1114 {
1115 /*
1116 * We tolerate that field type is unknown at validation,
1117 * because we are performing the load specialization in
1118 * a phase after validation.
1119 */
1120 dbg_printf("Validate load field\n");
1121 break;
1122 }
1123 case FILTER_OP_LOAD_FIELD_S8:
1124 {
1125 dbg_printf("Validate load field s8\n");
1126 break;
1127 }
1128 case FILTER_OP_LOAD_FIELD_S16:
1129 {
1130 dbg_printf("Validate load field s16\n");
1131 break;
1132 }
1133 case FILTER_OP_LOAD_FIELD_S32:
1134 {
1135 dbg_printf("Validate load field s32\n");
1136 break;
1137 }
1138 case FILTER_OP_LOAD_FIELD_S64:
1139 {
1140 dbg_printf("Validate load field s64\n");
1141 break;
1142 }
1143 case FILTER_OP_LOAD_FIELD_U8:
1144 {
1145 dbg_printf("Validate load field u8\n");
1146 break;
1147 }
1148 case FILTER_OP_LOAD_FIELD_U16:
1149 {
1150 dbg_printf("Validate load field u16\n");
1151 break;
1152 }
1153 case FILTER_OP_LOAD_FIELD_U32:
1154 {
1155 dbg_printf("Validate load field u32\n");
1156 break;
1157 }
1158 case FILTER_OP_LOAD_FIELD_U64:
1159 {
1160 dbg_printf("Validate load field u64\n");
1161 break;
1162 }
1163 case FILTER_OP_LOAD_FIELD_STRING:
1164 {
1165 dbg_printf("Validate load field string\n");
1166 break;
1167 }
1168 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1169 {
1170 dbg_printf("Validate load field sequence\n");
1171 break;
1172 }
1173 case FILTER_OP_LOAD_FIELD_DOUBLE:
1174 {
1175 dbg_printf("Validate load field double\n");
1176 break;
1177 }
1178
1179 case FILTER_OP_GET_SYMBOL:
1180 {
1181 struct load_op *insn = (struct load_op *) pc;
1182 struct get_symbol *sym = (struct get_symbol *) insn->data;
1183
1184 dbg_printf("Validate get symbol offset %u\n", sym->offset);
1185 break;
1186 }
1187
1188 case FILTER_OP_GET_SYMBOL_FIELD:
1189 {
1190 struct load_op *insn = (struct load_op *) pc;
1191 struct get_symbol *sym = (struct get_symbol *) insn->data;
1192
1193 dbg_printf("Validate get symbol field offset %u\n", sym->offset);
1194 break;
1195 }
1196
1197 case FILTER_OP_GET_INDEX_U16:
1198 {
1199 struct load_op *insn = (struct load_op *) pc;
1200 struct get_index_u16 *get_index = (struct get_index_u16 *) insn->data;
1201
1202 dbg_printf("Validate get index u16 index %u\n", get_index->index);
1203 break;
1204 }
1205
1206 case FILTER_OP_GET_INDEX_U64:
1207 {
1208 struct load_op *insn = (struct load_op *) pc;
1209 struct get_index_u64 *get_index = (struct get_index_u64 *) insn->data;
1210
1211 dbg_printf("Validate get index u64 index %" PRIu64 "\n", get_index->index);
1212 break;
1213 }
bf956ec0
MD
1214 }
1215end:
1216 return ret;
1217}
1218
1219/*
1220 * Return value:
1221 * 0: success
1222 * <0: error
1223 */
1224static
1225int validate_instruction_all_contexts(struct bytecode_runtime *bytecode,
1226 struct cds_lfht *merge_points,
0305960f 1227 struct vstack *stack,
22389ecb
MD
1228 char *start_pc,
1229 char *pc)
bf956ec0
MD
1230{
1231 int ret;
1232 unsigned long target_pc = pc - start_pc;
1233 struct cds_lfht_iter iter;
1234 struct cds_lfht_node *node;
71c1ceeb 1235 struct lfht_mp_node *mp_node;
bf956ec0
MD
1236 unsigned long hash;
1237
1238 /* Validate the context resulting from the previous instruction */
0305960f 1239 ret = validate_instruction_context(bytecode, stack, start_pc, pc);
53569322 1240 if (ret < 0)
bf956ec0
MD
1241 return ret;
1242
1243 /* Validate merge points */
22389ecb 1244 hash = lttng_hash_mix((const char *) target_pc, sizeof(target_pc),
bf956ec0 1245 lttng_hash_seed);
71c1ceeb 1246 cds_lfht_lookup(merge_points, hash, lttng_hash_match,
22389ecb 1247 (const char *) target_pc, &iter);
71c1ceeb
MD
1248 node = cds_lfht_iter_get_node(&iter);
1249 if (node) {
1250 mp_node = caa_container_of(node, struct lfht_mp_node, node);
3151a51d 1251
bf956ec0
MD
1252 dbg_printf("Filter: validate merge point at offset %lu\n",
1253 target_pc);
71c1ceeb
MD
1254 if (merge_points_compare(stack, &mp_node->stack)) {
1255 ERR("Merge points differ for offset %lu\n",
1256 target_pc);
1257 return -EINVAL;
1258 }
bf956ec0 1259 /* Once validated, we can remove the merge point */
71c1ceeb 1260 dbg_printf("Filter: remove merge point at offset %lu\n",
bf956ec0
MD
1261 target_pc);
1262 ret = cds_lfht_del(merge_points, node);
1263 assert(!ret);
1264 }
1265 return 0;
1266}
1267
1268/*
1269 * Return value:
1270 * >0: going to next insn.
1271 * 0: success, stop iteration.
1272 * <0: error
1273 */
1274static
1275int exec_insn(struct bytecode_runtime *bytecode,
1276 struct cds_lfht *merge_points,
0305960f 1277 struct vstack *stack,
22389ecb
MD
1278 char **_next_pc,
1279 char *pc)
bf956ec0
MD
1280{
1281 int ret = 1;
22389ecb 1282 char *next_pc = *_next_pc;
bf956ec0
MD
1283
1284 switch (*(filter_opcode_t *) pc) {
1285 case FILTER_OP_UNKNOWN:
1286 default:
1287 {
1288 ERR("unknown bytecode op %u\n",
1289 (unsigned int) *(filter_opcode_t *) pc);
1290 ret = -EINVAL;
1291 goto end;
1292 }
1293
1294 case FILTER_OP_RETURN:
1295 {
71c1ceeb
MD
1296 if (!vstack_ax(stack)) {
1297 ERR("Empty stack\n");
1298 ret = -EINVAL;
1299 goto end;
1300 }
47e5f13e
MD
1301 switch (vstack_ax(stack)->type) {
1302 case REG_S64:
d97f9b78 1303 case REG_U64:
09f78acb
FD
1304 case REG_DOUBLE:
1305 case REG_STRING:
1306 case REG_PTR:
47e5f13e
MD
1307 case REG_UNKNOWN:
1308 break;
1309 default:
1310 ERR("Unexpected register type %d at end of bytecode\n",
1311 (int) vstack_ax(stack)->type);
1312 ret = -EINVAL;
1313 goto end;
1314 }
1315
bf956ec0
MD
1316 ret = 0;
1317 goto end;
1318 }
93c591bb
MD
1319 case FILTER_OP_RETURN_S64:
1320 {
1321 if (!vstack_ax(stack)) {
1322 ERR("Empty stack\n");
1323 ret = -EINVAL;
1324 goto end;
1325 }
1326 switch (vstack_ax(stack)->type) {
1327 case REG_S64:
d97f9b78 1328 case REG_U64:
93c591bb
MD
1329 break;
1330 default:
1331 case REG_UNKNOWN:
1332 ERR("Unexpected register type %d at end of bytecode\n",
1333 (int) vstack_ax(stack)->type);
1334 ret = -EINVAL;
1335 goto end;
1336 }
1337
1338 ret = 0;
1339 goto end;
1340 }
bf956ec0
MD
1341
1342 /* binary */
1343 case FILTER_OP_MUL:
1344 case FILTER_OP_DIV:
1345 case FILTER_OP_MOD:
1346 case FILTER_OP_PLUS:
1347 case FILTER_OP_MINUS:
bf956ec0
MD
1348 {
1349 ERR("unsupported bytecode op %u\n",
1350 (unsigned int) *(filter_opcode_t *) pc);
1351 ret = -EINVAL;
1352 goto end;
1353 }
1354
1355 case FILTER_OP_EQ:
1356 case FILTER_OP_NE:
1357 case FILTER_OP_GT:
1358 case FILTER_OP_LT:
1359 case FILTER_OP_GE:
1360 case FILTER_OP_LE:
1361 case FILTER_OP_EQ_STRING:
1362 case FILTER_OP_NE_STRING:
1363 case FILTER_OP_GT_STRING:
1364 case FILTER_OP_LT_STRING:
1365 case FILTER_OP_GE_STRING:
1366 case FILTER_OP_LE_STRING:
3151a51d
PP
1367 case FILTER_OP_EQ_STAR_GLOB_STRING:
1368 case FILTER_OP_NE_STAR_GLOB_STRING:
bf956ec0
MD
1369 case FILTER_OP_EQ_S64:
1370 case FILTER_OP_NE_S64:
1371 case FILTER_OP_GT_S64:
1372 case FILTER_OP_LT_S64:
1373 case FILTER_OP_GE_S64:
1374 case FILTER_OP_LE_S64:
bf956ec0
MD
1375 case FILTER_OP_EQ_DOUBLE:
1376 case FILTER_OP_NE_DOUBLE:
1377 case FILTER_OP_GT_DOUBLE:
1378 case FILTER_OP_LT_DOUBLE:
1379 case FILTER_OP_GE_DOUBLE:
1380 case FILTER_OP_LE_DOUBLE:
dbea82ec
MD
1381 case FILTER_OP_EQ_DOUBLE_S64:
1382 case FILTER_OP_NE_DOUBLE_S64:
1383 case FILTER_OP_GT_DOUBLE_S64:
1384 case FILTER_OP_LT_DOUBLE_S64:
1385 case FILTER_OP_GE_DOUBLE_S64:
1386 case FILTER_OP_LE_DOUBLE_S64:
1387 case FILTER_OP_EQ_S64_DOUBLE:
1388 case FILTER_OP_NE_S64_DOUBLE:
1389 case FILTER_OP_GT_S64_DOUBLE:
1390 case FILTER_OP_LT_S64_DOUBLE:
1391 case FILTER_OP_GE_S64_DOUBLE:
1392 case FILTER_OP_LE_S64_DOUBLE:
d97f9b78
MD
1393 {
1394 /* Pop 2, push 1 */
1395 if (vstack_pop(stack)) {
1396 ret = -EINVAL;
1397 goto end;
1398 }
1399 if (!vstack_ax(stack)) {
1400 ERR("Empty stack\n");
1401 ret = -EINVAL;
1402 goto end;
1403 }
1404 switch (vstack_ax(stack)->type) {
1405 case REG_S64:
1406 case REG_U64:
1407 case REG_DOUBLE:
1408 case REG_STRING:
1409 case REG_STAR_GLOB_STRING:
1410 case REG_UNKNOWN:
1411 break;
1412 default:
1413 ERR("Unexpected register type %d for operation\n",
1414 (int) vstack_ax(stack)->type);
1415 ret = -EINVAL;
1416 goto end;
1417 }
1418
1419 vstack_ax(stack)->type = REG_S64;
1420 next_pc += sizeof(struct binary_op);
1421 break;
1422 }
1423
0039e2d8
MD
1424 case FILTER_OP_BIT_RSHIFT:
1425 case FILTER_OP_BIT_LSHIFT:
47e5f13e
MD
1426 case FILTER_OP_BIT_AND:
1427 case FILTER_OP_BIT_OR:
1428 case FILTER_OP_BIT_XOR:
bf956ec0 1429 {
0305960f
MD
1430 /* Pop 2, push 1 */
1431 if (vstack_pop(stack)) {
1432 ret = -EINVAL;
1433 goto end;
1434 }
1435 if (!vstack_ax(stack)) {
1436 ERR("Empty stack\n");
1437 ret = -EINVAL;
1438 goto end;
1439 }
47e5f13e
MD
1440 switch (vstack_ax(stack)->type) {
1441 case REG_S64:
d97f9b78 1442 case REG_U64:
47e5f13e
MD
1443 case REG_DOUBLE:
1444 case REG_STRING:
1445 case REG_STAR_GLOB_STRING:
1446 case REG_UNKNOWN:
1447 break;
1448 default:
1449 ERR("Unexpected register type %d for operation\n",
1450 (int) vstack_ax(stack)->type);
1451 ret = -EINVAL;
1452 goto end;
1453 }
1454
d97f9b78 1455 vstack_ax(stack)->type = REG_U64;
bf956ec0
MD
1456 next_pc += sizeof(struct binary_op);
1457 break;
1458 }
1459
1460 /* unary */
1461 case FILTER_OP_UNARY_PLUS:
1462 case FILTER_OP_UNARY_MINUS:
53569322
MD
1463 {
1464 /* Pop 1, push 1 */
1465 if (!vstack_ax(stack)) {
1466 ERR("Empty stack\n");
1467 ret = -EINVAL;
1468 goto end;
1469 }
47e5f13e
MD
1470 switch (vstack_ax(stack)->type) {
1471 case REG_UNKNOWN:
1472 case REG_DOUBLE:
1473 case REG_S64:
d97f9b78 1474 case REG_U64:
47e5f13e
MD
1475 break;
1476 default:
1477 ERR("Unexpected register type %d for operation\n",
1478 (int) vstack_ax(stack)->type);
1479 ret = -EINVAL;
1480 goto end;
1481 }
53569322
MD
1482 vstack_ax(stack)->type = REG_UNKNOWN;
1483 next_pc += sizeof(struct unary_op);
1484 break;
1485 }
1486
bf956ec0
MD
1487 case FILTER_OP_UNARY_PLUS_S64:
1488 case FILTER_OP_UNARY_MINUS_S64:
1489 case FILTER_OP_UNARY_NOT_S64:
47e5f13e
MD
1490 {
1491 /* Pop 1, push 1 */
1492 if (!vstack_ax(stack)) {
1493 ERR("Empty stack\n");
1494 ret = -EINVAL;
1495 goto end;
1496 }
1497 switch (vstack_ax(stack)->type) {
1498 case REG_S64:
d97f9b78 1499 case REG_U64:
47e5f13e
MD
1500 break;
1501 default:
1502 ERR("Unexpected register type %d for operation\n",
1503 (int) vstack_ax(stack)->type);
1504 ret = -EINVAL;
1505 goto end;
1506 }
1507
47e5f13e
MD
1508 next_pc += sizeof(struct unary_op);
1509 break;
1510 }
1511
1512 case FILTER_OP_UNARY_NOT:
1513 {
1514 /* Pop 1, push 1 */
1515 if (!vstack_ax(stack)) {
1516 ERR("Empty stack\n");
1517 ret = -EINVAL;
1518 goto end;
1519 }
1520 switch (vstack_ax(stack)->type) {
1521 case REG_UNKNOWN:
1522 case REG_DOUBLE:
1523 case REG_S64:
d97f9b78 1524 case REG_U64:
47e5f13e
MD
1525 break;
1526 default:
1527 ERR("Unexpected register type %d for operation\n",
1528 (int) vstack_ax(stack)->type);
1529 ret = -EINVAL;
1530 goto end;
1531 }
1532
47e5f13e
MD
1533 next_pc += sizeof(struct unary_op);
1534 break;
1535 }
1536
0039e2d8
MD
1537 case FILTER_OP_UNARY_BIT_NOT:
1538 {
1539 /* Pop 1, push 1 */
1540 if (!vstack_ax(stack)) {
1541 ERR("Empty stack\n");
1542 ret = -EINVAL;
1543 goto end;
1544 }
1545 switch (vstack_ax(stack)->type) {
1546 case REG_UNKNOWN:
1547 case REG_S64:
d97f9b78 1548 case REG_U64:
0039e2d8
MD
1549 break;
1550 case REG_DOUBLE:
1551 default:
1552 ERR("Unexpected register type %d for operation\n",
1553 (int) vstack_ax(stack)->type);
1554 ret = -EINVAL;
1555 goto end;
1556 }
1557
d97f9b78 1558 vstack_ax(stack)->type = REG_U64;
0039e2d8
MD
1559 next_pc += sizeof(struct unary_op);
1560 break;
1561 }
1562
53569322 1563 case FILTER_OP_UNARY_NOT_DOUBLE:
bf956ec0 1564 {
0305960f
MD
1565 /* Pop 1, push 1 */
1566 if (!vstack_ax(stack)) {
1567 ERR("Empty stack\n");
1568 ret = -EINVAL;
1569 goto end;
1570 }
47e5f13e
MD
1571 switch (vstack_ax(stack)->type) {
1572 case REG_DOUBLE:
1573 break;
1574 default:
1575 ERR("Incorrect register type %d for operation\n",
1576 (int) vstack_ax(stack)->type);
1577 ret = -EINVAL;
1578 goto end;
1579 }
1580
0305960f 1581 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1582 next_pc += sizeof(struct unary_op);
1583 break;
1584 }
1585
1586 case FILTER_OP_UNARY_PLUS_DOUBLE:
1587 case FILTER_OP_UNARY_MINUS_DOUBLE:
bf956ec0 1588 {
0305960f
MD
1589 /* Pop 1, push 1 */
1590 if (!vstack_ax(stack)) {
1591 ERR("Empty stack\n");
1592 ret = -EINVAL;
1593 goto end;
1594 }
47e5f13e
MD
1595 switch (vstack_ax(stack)->type) {
1596 case REG_DOUBLE:
1597 break;
1598 default:
1599 ERR("Incorrect register type %d for operation\n",
1600 (int) vstack_ax(stack)->type);
1601 ret = -EINVAL;
1602 goto end;
1603 }
1604
0305960f 1605 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1606 next_pc += sizeof(struct unary_op);
1607 break;
1608 }
1609
1610 /* logical */
1611 case FILTER_OP_AND:
1612 case FILTER_OP_OR:
1613 {
1614 struct logical_op *insn = (struct logical_op *) pc;
1615 int merge_ret;
1616
1617 /* Add merge point to table */
71c1ceeb
MD
1618 merge_ret = merge_point_add_check(merge_points,
1619 insn->skip_offset, stack);
bf956ec0
MD
1620 if (merge_ret) {
1621 ret = merge_ret;
1622 goto end;
97b58163 1623 }
47e5f13e
MD
1624
1625 if (!vstack_ax(stack)) {
1626 ERR("Empty stack\n");
1627 ret = -EINVAL;
1628 goto end;
1629 }
1630 /* There is always a cast-to-s64 operation before a or/and op. */
1631 switch (vstack_ax(stack)->type) {
1632 case REG_S64:
d97f9b78 1633 case REG_U64:
47e5f13e
MD
1634 break;
1635 default:
1636 ERR("Incorrect register type %d for operation\n",
1637 (int) vstack_ax(stack)->type);
1638 ret = -EINVAL;
1639 goto end;
1640 }
1641
bf956ec0 1642 /* Continue to next instruction */
71c1ceeb
MD
1643 /* Pop 1 when jump not taken */
1644 if (vstack_pop(stack)) {
1645 ret = -EINVAL;
1646 goto end;
1647 }
bf956ec0
MD
1648 next_pc += sizeof(struct logical_op);
1649 break;
1650 }
1651
77aa5901 1652 /* load field ref */
bf956ec0
MD
1653 case FILTER_OP_LOAD_FIELD_REF:
1654 {
1655 ERR("Unknown field ref type\n");
1656 ret = -EINVAL;
1657 goto end;
1658 }
77aa5901
MD
1659 /* get context ref */
1660 case FILTER_OP_GET_CONTEXT_REF:
1661 {
53569322
MD
1662 if (vstack_push(stack)) {
1663 ret = -EINVAL;
1664 goto end;
1665 }
1666 vstack_ax(stack)->type = REG_UNKNOWN;
1667 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1668 break;
77aa5901 1669 }
bf956ec0
MD
1670 case FILTER_OP_LOAD_FIELD_REF_STRING:
1671 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE:
77aa5901 1672 case FILTER_OP_GET_CONTEXT_REF_STRING:
bf956ec0 1673 {
0305960f
MD
1674 if (vstack_push(stack)) {
1675 ret = -EINVAL;
1676 goto end;
1677 }
1678 vstack_ax(stack)->type = REG_STRING;
bf956ec0
MD
1679 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1680 break;
1681 }
1682 case FILTER_OP_LOAD_FIELD_REF_S64:
77aa5901 1683 case FILTER_OP_GET_CONTEXT_REF_S64:
bf956ec0 1684 {
0305960f
MD
1685 if (vstack_push(stack)) {
1686 ret = -EINVAL;
1687 goto end;
1688 }
1689 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1690 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1691 break;
1692 }
1693 case FILTER_OP_LOAD_FIELD_REF_DOUBLE:
77aa5901 1694 case FILTER_OP_GET_CONTEXT_REF_DOUBLE:
bf956ec0 1695 {
0305960f
MD
1696 if (vstack_push(stack)) {
1697 ret = -EINVAL;
1698 goto end;
1699 }
1700 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1701 next_pc += sizeof(struct load_op) + sizeof(struct field_ref);
1702 break;
1703 }
1704
77aa5901 1705 /* load from immediate operand */
bf956ec0
MD
1706 case FILTER_OP_LOAD_STRING:
1707 {
1708 struct load_op *insn = (struct load_op *) pc;
1709
0305960f
MD
1710 if (vstack_push(stack)) {
1711 ret = -EINVAL;
1712 goto end;
1713 }
1714 vstack_ax(stack)->type = REG_STRING;
bf956ec0
MD
1715 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1716 break;
1717 }
1718
3151a51d
PP
1719 case FILTER_OP_LOAD_STAR_GLOB_STRING:
1720 {
1721 struct load_op *insn = (struct load_op *) pc;
1722
1723 if (vstack_push(stack)) {
1724 ret = -EINVAL;
1725 goto end;
1726 }
1727 vstack_ax(stack)->type = REG_STAR_GLOB_STRING;
1728 next_pc += sizeof(struct load_op) + strlen(insn->data) + 1;
1729 break;
1730 }
1731
bf956ec0
MD
1732 case FILTER_OP_LOAD_S64:
1733 {
0305960f
MD
1734 if (vstack_push(stack)) {
1735 ret = -EINVAL;
1736 goto end;
1737 }
1738 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1739 next_pc += sizeof(struct load_op)
1740 + sizeof(struct literal_numeric);
1741 break;
1742 }
1743
1744 case FILTER_OP_LOAD_DOUBLE:
1745 {
0305960f
MD
1746 if (vstack_push(stack)) {
1747 ret = -EINVAL;
1748 goto end;
1749 }
1750 vstack_ax(stack)->type = REG_DOUBLE;
bf956ec0
MD
1751 next_pc += sizeof(struct load_op)
1752 + sizeof(struct literal_double);
1753 break;
1754 }
1755
1756 case FILTER_OP_CAST_TO_S64:
1757 case FILTER_OP_CAST_DOUBLE_TO_S64:
1758 {
0305960f
MD
1759 /* Pop 1, push 1 */
1760 if (!vstack_ax(stack)) {
1761 ERR("Empty stack\n");
1762 ret = -EINVAL;
1763 goto end;
1764 }
47e5f13e
MD
1765 switch (vstack_ax(stack)->type) {
1766 case REG_S64:
d97f9b78 1767 case REG_U64:
47e5f13e
MD
1768 case REG_DOUBLE:
1769 case REG_UNKNOWN:
1770 break;
1771 default:
1772 ERR("Incorrect register type %d for cast\n",
1773 (int) vstack_ax(stack)->type);
1774 ret = -EINVAL;
1775 goto end;
1776 }
0305960f 1777 vstack_ax(stack)->type = REG_S64;
bf956ec0
MD
1778 next_pc += sizeof(struct cast_op);
1779 break;
1780 }
1781 case FILTER_OP_CAST_NOP:
1782 {
1783 next_pc += sizeof(struct cast_op);
1784 break;
1785 }
97b58163 1786
47e5f13e
MD
1787 /*
1788 * Instructions for recursive traversal through composed types.
1789 */
1790 case FILTER_OP_GET_CONTEXT_ROOT:
1791 case FILTER_OP_GET_APP_CONTEXT_ROOT:
1792 case FILTER_OP_GET_PAYLOAD_ROOT:
1793 {
1794 if (vstack_push(stack)) {
1795 ret = -EINVAL;
1796 goto end;
1797 }
1798 vstack_ax(stack)->type = REG_PTR;
1799 next_pc += sizeof(struct load_op);
1800 break;
1801 }
1802
1803 case FILTER_OP_LOAD_FIELD:
1804 {
1805 /* Pop 1, push 1 */
1806 if (!vstack_ax(stack)) {
1807 ERR("Empty stack\n");
1808 ret = -EINVAL;
1809 goto end;
1810 }
1811 if (vstack_ax(stack)->type != REG_PTR) {
1812 ERR("Expecting pointer on top of stack\n");
1813 ret = -EINVAL;
1814 goto end;
1815 }
1816 vstack_ax(stack)->type = REG_UNKNOWN;
1817 next_pc += sizeof(struct load_op);
1818 break;
1819 }
1820
1821 case FILTER_OP_LOAD_FIELD_S8:
1822 case FILTER_OP_LOAD_FIELD_S16:
1823 case FILTER_OP_LOAD_FIELD_S32:
1824 case FILTER_OP_LOAD_FIELD_S64:
d97f9b78
MD
1825 {
1826 /* Pop 1, push 1 */
1827 if (!vstack_ax(stack)) {
1828 ERR("Empty stack\n");
1829 ret = -EINVAL;
1830 goto end;
1831 }
1832 if (vstack_ax(stack)->type != REG_PTR) {
1833 ERR("Expecting pointer on top of stack\n");
1834 ret = -EINVAL;
1835 goto end;
1836 }
1837 vstack_ax(stack)->type = REG_S64;
1838 next_pc += sizeof(struct load_op);
1839 break;
1840 }
1841
47e5f13e
MD
1842 case FILTER_OP_LOAD_FIELD_U8:
1843 case FILTER_OP_LOAD_FIELD_U16:
1844 case FILTER_OP_LOAD_FIELD_U32:
1845 case FILTER_OP_LOAD_FIELD_U64:
1846 {
1847 /* Pop 1, push 1 */
1848 if (!vstack_ax(stack)) {
1849 ERR("Empty stack\n");
1850 ret = -EINVAL;
1851 goto end;
1852 }
1853 if (vstack_ax(stack)->type != REG_PTR) {
1854 ERR("Expecting pointer on top of stack\n");
1855 ret = -EINVAL;
1856 goto end;
1857 }
d97f9b78 1858 vstack_ax(stack)->type = REG_U64;
47e5f13e
MD
1859 next_pc += sizeof(struct load_op);
1860 break;
1861 }
1862
1863 case FILTER_OP_LOAD_FIELD_STRING:
1864 case FILTER_OP_LOAD_FIELD_SEQUENCE:
1865 {
1866 /* Pop 1, push 1 */
1867 if (!vstack_ax(stack)) {
1868 ERR("Empty stack\n");
1869 ret = -EINVAL;
1870 goto end;
1871 }
1872 if (vstack_ax(stack)->type != REG_PTR) {
1873 ERR("Expecting pointer on top of stack\n");
1874 ret = -EINVAL;
1875 goto end;
1876 }
1877 vstack_ax(stack)->type = REG_STRING;
1878 next_pc += sizeof(struct load_op);
1879 break;
1880 }
1881
1882 case FILTER_OP_LOAD_FIELD_DOUBLE:
1883 {
1884 /* Pop 1, push 1 */
1885 if (!vstack_ax(stack)) {
1886 ERR("Empty stack\n");
1887 ret = -EINVAL;
1888 goto end;
1889 }
1890 if (vstack_ax(stack)->type != REG_PTR) {
1891 ERR("Expecting pointer on top of stack\n");
1892 ret = -EINVAL;
1893 goto end;
1894 }
1895 vstack_ax(stack)->type = REG_DOUBLE;
1896 next_pc += sizeof(struct load_op);
1897 break;
1898 }
1899
1900 case FILTER_OP_GET_SYMBOL:
1901 case FILTER_OP_GET_SYMBOL_FIELD:
1902 {
1903 /* Pop 1, push 1 */
1904 if (!vstack_ax(stack)) {
1905 ERR("Empty stack\n");
1906 ret = -EINVAL;
1907 goto end;
1908 }
1909 if (vstack_ax(stack)->type != REG_PTR) {
1910 ERR("Expecting pointer on top of stack\n");
1911 ret = -EINVAL;
1912 goto end;
1913 }
1914 next_pc += sizeof(struct load_op) + sizeof(struct get_symbol);
1915 break;
1916 }
1917
1918 case FILTER_OP_GET_INDEX_U16:
1919 {
1920 /* Pop 1, push 1 */
1921 if (!vstack_ax(stack)) {
1922 ERR("Empty stack\n");
1923 ret = -EINVAL;
1924 goto end;
1925 }
1926 if (vstack_ax(stack)->type != REG_PTR) {
1927 ERR("Expecting pointer on top of stack\n");
1928 ret = -EINVAL;
1929 goto end;
1930 }
1931 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u16);
1932 break;
1933 }
1934
1935 case FILTER_OP_GET_INDEX_U64:
1936 {
1937 /* Pop 1, push 1 */
1938 if (!vstack_ax(stack)) {
1939 ERR("Empty stack\n");
1940 ret = -EINVAL;
1941 goto end;
1942 }
1943 if (vstack_ax(stack)->type != REG_PTR) {
1944 ERR("Expecting pointer on top of stack\n");
1945 ret = -EINVAL;
1946 goto end;
1947 }
1948 next_pc += sizeof(struct load_op) + sizeof(struct get_index_u64);
1949 break;
1950 }
1951
bf956ec0
MD
1952 }
1953end:
1954 *_next_pc = next_pc;
1955 return ret;
1956}
1957
1958/*
1959 * Never called concurrently (hash seed is shared).
1960 */
1961int lttng_filter_validate_bytecode(struct bytecode_runtime *bytecode)
1962{
1963 struct cds_lfht *merge_points;
22389ecb 1964 char *pc, *next_pc, *start_pc;
bf956ec0 1965 int ret = -EINVAL;
0305960f 1966 struct vstack stack;
bf956ec0 1967
0305960f 1968 vstack_init(&stack);
bf956ec0
MD
1969
1970 if (!lttng_hash_seed_ready) {
1971 lttng_hash_seed = time(NULL);
1972 lttng_hash_seed_ready = 1;
1973 }
1974 /*
1975 * Note: merge_points hash table used by single thread, and
1976 * never concurrently resized. Therefore, we can use it without
1977 * holding RCU read-side lock and free nodes without using
1978 * call_rcu.
1979 */
1980 merge_points = cds_lfht_new(DEFAULT_NR_MERGE_POINTS,
1981 MIN_NR_BUCKETS, MAX_NR_BUCKETS,
1982 0, NULL);
1983 if (!merge_points) {
1984 ERR("Error allocating hash table for bytecode validation\n");
1985 return -ENOMEM;
1986 }
47e5f13e 1987 start_pc = &bytecode->code[0];
bf956ec0
MD
1988 for (pc = next_pc = start_pc; pc - start_pc < bytecode->len;
1989 pc = next_pc) {
82513dbe
MD
1990 ret = bytecode_validate_overflow(bytecode, start_pc, pc);
1991 if (ret != 0) {
1992 if (ret == -ERANGE)
1993 ERR("filter bytecode overflow\n");
bf956ec0 1994 goto end;
97b58163 1995 }
bf956ec0
MD
1996 dbg_printf("Validating op %s (%u)\n",
1997 print_op((unsigned int) *(filter_opcode_t *) pc),
1998 (unsigned int) *(filter_opcode_t *) pc);
1999
2000 /*
2001 * For each instruction, validate the current context
2002 * (traversal of entire execution flow), and validate
53569322 2003 * all merge points targeting this instruction.
bf956ec0
MD
2004 */
2005 ret = validate_instruction_all_contexts(bytecode, merge_points,
0305960f 2006 &stack, start_pc, pc);
bf956ec0
MD
2007 if (ret)
2008 goto end;
0305960f 2009 ret = exec_insn(bytecode, merge_points, &stack, &next_pc, pc);
bf956ec0
MD
2010 if (ret <= 0)
2011 goto end;
97b58163
MD
2012 }
2013end:
bf956ec0
MD
2014 if (delete_all_nodes(merge_points)) {
2015 if (!ret) {
2016 ERR("Unexpected merge points\n");
2017 ret = -EINVAL;
2018 }
2019 }
2020 if (cds_lfht_destroy(merge_points, NULL)) {
2021 ERR("Error destroying hash table\n");
2022 }
97b58163
MD
2023 return ret;
2024}
This page took 0.117989 seconds and 4 git commands to generate.