2 * lttng-filter-validator.c
4 * LTTng UST filter bytecode validator.
6 * Copyright (C) 2010-2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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
30 #include "lttng-filter.h"
32 #include <urcu/rculfhash.h>
33 #include "lttng-hash-helper.h"
36 * Number of merge points for hash table size. Hash table initialized to
37 * that size, and we do not resize, because we do not want to trigger
38 * RCU worker thread execution: fall-back on linear traversal if number
39 * of merge points exceeds this value.
41 #define DEFAULT_NR_MERGE_POINTS 128
42 #define MIN_NR_BUCKETS 128
43 #define MAX_NR_BUCKETS 128
45 /* merge point table node */
47 struct cds_lfht_node node
;
49 /* Context at merge point */
51 unsigned long target_pc
;
54 static unsigned long lttng_hash_seed
;
55 static unsigned int lttng_hash_seed_ready
;
58 int lttng_hash_match(struct cds_lfht_node
*node
, const void *key
)
60 struct lfht_mp_node
*mp_node
=
61 caa_container_of(node
, struct lfht_mp_node
, node
);
62 unsigned long key_pc
= (unsigned long) key
;
64 if (mp_node
->target_pc
== key_pc
)
71 int merge_points_compare(const struct vstack
*stacka
,
72 const struct vstack
*stackb
)
76 if (stacka
->top
!= stackb
->top
)
78 len
= stacka
->top
+ 1;
80 for (i
= 0; i
< len
; i
++) {
81 if (stacka
->e
[i
].type
!= REG_UNKNOWN
82 && stackb
->e
[i
].type
!= REG_UNKNOWN
83 && stacka
->e
[i
].type
!= stackb
->e
[i
].type
)
90 int merge_point_add_check(struct cds_lfht
*ht
, unsigned long target_pc
,
91 const struct vstack
*stack
)
93 struct lfht_mp_node
*node
;
94 unsigned long hash
= lttng_hash_mix((const char *) target_pc
,
97 struct cds_lfht_node
*ret
;
99 dbg_printf("Filter: adding merge point at offset %lu, hash %lu\n",
101 node
= zmalloc(sizeof(struct lfht_mp_node
));
104 node
->target_pc
= target_pc
;
105 memcpy(&node
->stack
, stack
, sizeof(node
->stack
));
106 ret
= cds_lfht_add_unique(ht
, hash
, lttng_hash_match
,
107 (const char *) target_pc
, &node
->node
);
108 if (ret
!= &node
->node
) {
109 struct lfht_mp_node
*ret_mp
=
110 caa_container_of(ret
, struct lfht_mp_node
, node
);
112 /* Key already present */
113 dbg_printf("Filter: compare merge points for offset %lu, hash %lu\n",
116 if (merge_points_compare(stack
, &ret_mp
->stack
)) {
117 ERR("Merge points differ for offset %lu\n",
126 * Binary comparators use top of stack and top of stack -1.
127 * Return 0 if typing is known to match, 1 if typing is dynamic
128 * (unknown), negative error value on error.
131 int bin_op_compare_check(struct vstack
*stack
, const char *str
)
133 if (unlikely(!vstack_ax(stack
) || !vstack_bx(stack
)))
136 switch (vstack_ax(stack
)->type
) {
143 switch (vstack_bx(stack
)->type
) {
158 switch (vstack_bx(stack
)->type
) {
178 ERR("type mismatch for '%s' binary operator\n", str
);
182 ERR("empty stack for '%s' binary operator\n", str
);
186 ERR("unknown type for '%s' binary operator\n", str
);
191 * Validate bytecode range overflow within the validation pass.
192 * Called for each instruction encountered.
195 int bytecode_validate_overflow(struct bytecode_runtime
*bytecode
,
196 char *start_pc
, char *pc
)
200 switch (*(filter_opcode_t
*) pc
) {
201 case FILTER_OP_UNKNOWN
:
204 ERR("unknown bytecode op %u\n",
205 (unsigned int) *(filter_opcode_t
*) pc
);
210 case FILTER_OP_RETURN
:
212 if (unlikely(pc
+ sizeof(struct return_op
)
213 > start_pc
+ bytecode
->len
)) {
224 case FILTER_OP_MINUS
:
225 case FILTER_OP_RSHIFT
:
226 case FILTER_OP_LSHIFT
:
227 case FILTER_OP_BIN_AND
:
228 case FILTER_OP_BIN_OR
:
229 case FILTER_OP_BIN_XOR
:
231 ERR("unsupported bytecode op %u\n",
232 (unsigned int) *(filter_opcode_t
*) pc
);
243 case FILTER_OP_EQ_STRING
:
244 case FILTER_OP_NE_STRING
:
245 case FILTER_OP_GT_STRING
:
246 case FILTER_OP_LT_STRING
:
247 case FILTER_OP_GE_STRING
:
248 case FILTER_OP_LE_STRING
:
249 case FILTER_OP_EQ_S64
:
250 case FILTER_OP_NE_S64
:
251 case FILTER_OP_GT_S64
:
252 case FILTER_OP_LT_S64
:
253 case FILTER_OP_GE_S64
:
254 case FILTER_OP_LE_S64
:
255 case FILTER_OP_EQ_DOUBLE
:
256 case FILTER_OP_NE_DOUBLE
:
257 case FILTER_OP_GT_DOUBLE
:
258 case FILTER_OP_LT_DOUBLE
:
259 case FILTER_OP_GE_DOUBLE
:
260 case FILTER_OP_LE_DOUBLE
:
261 case FILTER_OP_EQ_DOUBLE_S64
:
262 case FILTER_OP_NE_DOUBLE_S64
:
263 case FILTER_OP_GT_DOUBLE_S64
:
264 case FILTER_OP_LT_DOUBLE_S64
:
265 case FILTER_OP_GE_DOUBLE_S64
:
266 case FILTER_OP_LE_DOUBLE_S64
:
267 case FILTER_OP_EQ_S64_DOUBLE
:
268 case FILTER_OP_NE_S64_DOUBLE
:
269 case FILTER_OP_GT_S64_DOUBLE
:
270 case FILTER_OP_LT_S64_DOUBLE
:
271 case FILTER_OP_GE_S64_DOUBLE
:
272 case FILTER_OP_LE_S64_DOUBLE
:
274 if (unlikely(pc
+ sizeof(struct binary_op
)
275 > start_pc
+ bytecode
->len
)) {
282 case FILTER_OP_UNARY_PLUS
:
283 case FILTER_OP_UNARY_MINUS
:
284 case FILTER_OP_UNARY_NOT
:
285 case FILTER_OP_UNARY_PLUS_S64
:
286 case FILTER_OP_UNARY_MINUS_S64
:
287 case FILTER_OP_UNARY_NOT_S64
:
288 case FILTER_OP_UNARY_PLUS_DOUBLE
:
289 case FILTER_OP_UNARY_MINUS_DOUBLE
:
290 case FILTER_OP_UNARY_NOT_DOUBLE
:
292 if (unlikely(pc
+ sizeof(struct unary_op
)
293 > start_pc
+ bytecode
->len
)) {
303 if (unlikely(pc
+ sizeof(struct logical_op
)
304 > start_pc
+ bytecode
->len
)) {
311 case FILTER_OP_LOAD_FIELD_REF
:
313 ERR("Unknown field ref type\n");
317 /* get context ref */
318 case FILTER_OP_GET_CONTEXT_REF
:
319 case FILTER_OP_LOAD_FIELD_REF_STRING
:
320 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
321 case FILTER_OP_LOAD_FIELD_REF_S64
:
322 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
323 case FILTER_OP_GET_CONTEXT_REF_STRING
:
324 case FILTER_OP_GET_CONTEXT_REF_S64
:
325 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
327 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct field_ref
)
328 > start_pc
+ bytecode
->len
)) {
334 /* load from immediate operand */
335 case FILTER_OP_LOAD_STRING
:
337 struct load_op
*insn
= (struct load_op
*) pc
;
338 uint32_t str_len
, maxlen
;
340 if (unlikely(pc
+ sizeof(struct load_op
)
341 > start_pc
+ bytecode
->len
)) {
346 maxlen
= start_pc
+ bytecode
->len
- pc
- sizeof(struct load_op
);
347 str_len
= strnlen(insn
->data
, maxlen
);
348 if (unlikely(str_len
>= maxlen
)) {
349 /* Final '\0' not found within range */
355 case FILTER_OP_LOAD_S64
:
357 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_numeric
)
358 > start_pc
+ bytecode
->len
)) {
364 case FILTER_OP_LOAD_DOUBLE
:
366 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_double
)
367 > start_pc
+ bytecode
->len
)) {
373 case FILTER_OP_CAST_TO_S64
:
374 case FILTER_OP_CAST_DOUBLE_TO_S64
:
375 case FILTER_OP_CAST_NOP
:
377 if (unlikely(pc
+ sizeof(struct cast_op
)
378 > start_pc
+ bytecode
->len
)) {
390 unsigned long delete_all_nodes(struct cds_lfht
*ht
)
392 struct cds_lfht_iter iter
;
393 struct lfht_mp_node
*node
;
394 unsigned long nr_nodes
= 0;
396 cds_lfht_for_each_entry(ht
, &iter
, node
, node
) {
399 ret
= cds_lfht_del(ht
, cds_lfht_iter_get_node(&iter
));
401 /* note: this hash table is never used concurrently */
414 int validate_instruction_context(struct bytecode_runtime
*bytecode
,
415 struct vstack
*stack
,
421 switch (*(filter_opcode_t
*) pc
) {
422 case FILTER_OP_UNKNOWN
:
425 ERR("unknown bytecode op %u\n",
426 (unsigned int) *(filter_opcode_t
*) pc
);
431 case FILTER_OP_RETURN
:
441 case FILTER_OP_MINUS
:
442 case FILTER_OP_RSHIFT
:
443 case FILTER_OP_LSHIFT
:
444 case FILTER_OP_BIN_AND
:
445 case FILTER_OP_BIN_OR
:
446 case FILTER_OP_BIN_XOR
:
448 ERR("unsupported bytecode op %u\n",
449 (unsigned int) *(filter_opcode_t
*) pc
);
456 ret
= bin_op_compare_check(stack
, "==");
463 ret
= bin_op_compare_check(stack
, "!=");
470 ret
= bin_op_compare_check(stack
, ">");
477 ret
= bin_op_compare_check(stack
, "<");
484 ret
= bin_op_compare_check(stack
, ">=");
491 ret
= bin_op_compare_check(stack
, "<=");
497 case FILTER_OP_EQ_STRING
:
498 case FILTER_OP_NE_STRING
:
499 case FILTER_OP_GT_STRING
:
500 case FILTER_OP_LT_STRING
:
501 case FILTER_OP_GE_STRING
:
502 case FILTER_OP_LE_STRING
:
504 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
505 ERR("Empty stack\n");
509 if (vstack_ax(stack
)->type
!= REG_STRING
510 || vstack_bx(stack
)->type
!= REG_STRING
) {
511 ERR("Unexpected register type for string comparator\n");
518 case FILTER_OP_EQ_S64
:
519 case FILTER_OP_NE_S64
:
520 case FILTER_OP_GT_S64
:
521 case FILTER_OP_LT_S64
:
522 case FILTER_OP_GE_S64
:
523 case FILTER_OP_LE_S64
:
525 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
526 ERR("Empty stack\n");
530 if (vstack_ax(stack
)->type
!= REG_S64
531 || vstack_bx(stack
)->type
!= REG_S64
) {
532 ERR("Unexpected register type for s64 comparator\n");
539 case FILTER_OP_EQ_DOUBLE
:
540 case FILTER_OP_NE_DOUBLE
:
541 case FILTER_OP_GT_DOUBLE
:
542 case FILTER_OP_LT_DOUBLE
:
543 case FILTER_OP_GE_DOUBLE
:
544 case FILTER_OP_LE_DOUBLE
:
546 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
547 ERR("Empty stack\n");
551 if (vstack_ax(stack
)->type
!= REG_DOUBLE
&& vstack_bx(stack
)->type
!= REG_DOUBLE
) {
552 ERR("Double operator should have two double registers\n");
559 case FILTER_OP_EQ_DOUBLE_S64
:
560 case FILTER_OP_NE_DOUBLE_S64
:
561 case FILTER_OP_GT_DOUBLE_S64
:
562 case FILTER_OP_LT_DOUBLE_S64
:
563 case FILTER_OP_GE_DOUBLE_S64
:
564 case FILTER_OP_LE_DOUBLE_S64
:
566 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
567 ERR("Empty stack\n");
571 if (vstack_ax(stack
)->type
!= REG_S64
&& vstack_bx(stack
)->type
!= REG_DOUBLE
) {
572 ERR("Double-S64 operator has unexpected register types\n");
579 case FILTER_OP_EQ_S64_DOUBLE
:
580 case FILTER_OP_NE_S64_DOUBLE
:
581 case FILTER_OP_GT_S64_DOUBLE
:
582 case FILTER_OP_LT_S64_DOUBLE
:
583 case FILTER_OP_GE_S64_DOUBLE
:
584 case FILTER_OP_LE_S64_DOUBLE
:
586 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
587 ERR("Empty stack\n");
591 if (vstack_ax(stack
)->type
!= REG_DOUBLE
&& vstack_bx(stack
)->type
!= REG_S64
) {
592 ERR("S64-Double operator has unexpected register types\n");
600 case FILTER_OP_UNARY_PLUS
:
601 case FILTER_OP_UNARY_MINUS
:
602 case FILTER_OP_UNARY_NOT
:
604 if (!vstack_ax(stack
)) {
605 ERR("Empty stack\n");
609 switch (vstack_ax(stack
)->type
) {
611 ERR("unknown register type\n");
616 ERR("Unary op can only be applied to numeric or floating point registers\n");
629 case FILTER_OP_UNARY_PLUS_S64
:
630 case FILTER_OP_UNARY_MINUS_S64
:
631 case FILTER_OP_UNARY_NOT_S64
:
633 if (!vstack_ax(stack
)) {
634 ERR("Empty stack\n");
638 if (vstack_ax(stack
)->type
!= REG_S64
) {
639 ERR("Invalid register type\n");
646 case FILTER_OP_UNARY_PLUS_DOUBLE
:
647 case FILTER_OP_UNARY_MINUS_DOUBLE
:
648 case FILTER_OP_UNARY_NOT_DOUBLE
:
650 if (!vstack_ax(stack
)) {
651 ERR("Empty stack\n");
655 if (vstack_ax(stack
)->type
!= REG_DOUBLE
) {
656 ERR("Invalid register type\n");
667 struct logical_op
*insn
= (struct logical_op
*) pc
;
669 if (!vstack_ax(stack
)) {
670 ERR("Empty stack\n");
674 if (vstack_ax(stack
)->type
!= REG_S64
675 && vstack_ax(stack
)->type
!= REG_UNKNOWN
) {
676 ERR("Logical comparator expects S64 or dynamic register\n");
681 dbg_printf("Validate jumping to bytecode offset %u\n",
682 (unsigned int) insn
->skip_offset
);
683 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
684 ERR("Loops are not allowed in bytecode\n");
692 case FILTER_OP_LOAD_FIELD_REF
:
694 ERR("Unknown field ref type\n");
698 case FILTER_OP_LOAD_FIELD_REF_STRING
:
699 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
701 struct load_op
*insn
= (struct load_op
*) pc
;
702 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
704 dbg_printf("Validate load field ref offset %u type string\n",
708 case FILTER_OP_LOAD_FIELD_REF_S64
:
710 struct load_op
*insn
= (struct load_op
*) pc
;
711 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
713 dbg_printf("Validate load field ref offset %u type s64\n",
717 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
719 struct load_op
*insn
= (struct load_op
*) pc
;
720 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
722 dbg_printf("Validate load field ref offset %u type double\n",
727 /* load from immediate operand */
728 case FILTER_OP_LOAD_STRING
:
733 case FILTER_OP_LOAD_S64
:
738 case FILTER_OP_LOAD_DOUBLE
:
743 case FILTER_OP_CAST_TO_S64
:
744 case FILTER_OP_CAST_DOUBLE_TO_S64
:
746 struct cast_op
*insn
= (struct cast_op
*) pc
;
748 if (!vstack_ax(stack
)) {
749 ERR("Empty stack\n");
753 switch (vstack_ax(stack
)->type
) {
755 ERR("unknown register type\n");
760 ERR("Cast op can only be applied to numeric or floating point registers\n");
770 if (insn
->op
== FILTER_OP_CAST_DOUBLE_TO_S64
) {
771 if (vstack_ax(stack
)->type
!= REG_DOUBLE
) {
772 ERR("Cast expects double\n");
779 case FILTER_OP_CAST_NOP
:
784 /* get context ref */
785 case FILTER_OP_GET_CONTEXT_REF
:
787 struct load_op
*insn
= (struct load_op
*) pc
;
788 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
790 dbg_printf("Validate get context ref offset %u type dynamic\n",
794 case FILTER_OP_GET_CONTEXT_REF_STRING
:
796 struct load_op
*insn
= (struct load_op
*) pc
;
797 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
799 dbg_printf("Validate get context ref offset %u type string\n",
803 case FILTER_OP_GET_CONTEXT_REF_S64
:
805 struct load_op
*insn
= (struct load_op
*) pc
;
806 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
808 dbg_printf("Validate get context ref offset %u type s64\n",
812 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
814 struct load_op
*insn
= (struct load_op
*) pc
;
815 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
817 dbg_printf("Validate get context ref offset %u type double\n",
833 int validate_instruction_all_contexts(struct bytecode_runtime
*bytecode
,
834 struct cds_lfht
*merge_points
,
835 struct vstack
*stack
,
840 unsigned long target_pc
= pc
- start_pc
;
841 struct cds_lfht_iter iter
;
842 struct cds_lfht_node
*node
;
843 struct lfht_mp_node
*mp_node
;
846 /* Validate the context resulting from the previous instruction */
847 ret
= validate_instruction_context(bytecode
, stack
, start_pc
, pc
);
851 /* Validate merge points */
852 hash
= lttng_hash_mix((const char *) target_pc
, sizeof(target_pc
),
854 cds_lfht_lookup(merge_points
, hash
, lttng_hash_match
,
855 (const char *) target_pc
, &iter
);
856 node
= cds_lfht_iter_get_node(&iter
);
858 mp_node
= caa_container_of(node
, struct lfht_mp_node
, node
);
860 dbg_printf("Filter: validate merge point at offset %lu\n",
862 if (merge_points_compare(stack
, &mp_node
->stack
)) {
863 ERR("Merge points differ for offset %lu\n",
867 /* Once validated, we can remove the merge point */
868 dbg_printf("Filter: remove merge point at offset %lu\n",
870 ret
= cds_lfht_del(merge_points
, node
);
878 * >0: going to next insn.
879 * 0: success, stop iteration.
883 int exec_insn(struct bytecode_runtime
*bytecode
,
884 struct cds_lfht
*merge_points
,
885 struct vstack
*stack
,
890 char *next_pc
= *_next_pc
;
892 switch (*(filter_opcode_t
*) pc
) {
893 case FILTER_OP_UNKNOWN
:
896 ERR("unknown bytecode op %u\n",
897 (unsigned int) *(filter_opcode_t
*) pc
);
902 case FILTER_OP_RETURN
:
904 if (!vstack_ax(stack
)) {
905 ERR("Empty stack\n");
918 case FILTER_OP_MINUS
:
919 case FILTER_OP_RSHIFT
:
920 case FILTER_OP_LSHIFT
:
921 case FILTER_OP_BIN_AND
:
922 case FILTER_OP_BIN_OR
:
923 case FILTER_OP_BIN_XOR
:
925 ERR("unsupported bytecode op %u\n",
926 (unsigned int) *(filter_opcode_t
*) pc
);
937 case FILTER_OP_EQ_STRING
:
938 case FILTER_OP_NE_STRING
:
939 case FILTER_OP_GT_STRING
:
940 case FILTER_OP_LT_STRING
:
941 case FILTER_OP_GE_STRING
:
942 case FILTER_OP_LE_STRING
:
943 case FILTER_OP_EQ_S64
:
944 case FILTER_OP_NE_S64
:
945 case FILTER_OP_GT_S64
:
946 case FILTER_OP_LT_S64
:
947 case FILTER_OP_GE_S64
:
948 case FILTER_OP_LE_S64
:
949 case FILTER_OP_EQ_DOUBLE
:
950 case FILTER_OP_NE_DOUBLE
:
951 case FILTER_OP_GT_DOUBLE
:
952 case FILTER_OP_LT_DOUBLE
:
953 case FILTER_OP_GE_DOUBLE
:
954 case FILTER_OP_LE_DOUBLE
:
955 case FILTER_OP_EQ_DOUBLE_S64
:
956 case FILTER_OP_NE_DOUBLE_S64
:
957 case FILTER_OP_GT_DOUBLE_S64
:
958 case FILTER_OP_LT_DOUBLE_S64
:
959 case FILTER_OP_GE_DOUBLE_S64
:
960 case FILTER_OP_LE_DOUBLE_S64
:
961 case FILTER_OP_EQ_S64_DOUBLE
:
962 case FILTER_OP_NE_S64_DOUBLE
:
963 case FILTER_OP_GT_S64_DOUBLE
:
964 case FILTER_OP_LT_S64_DOUBLE
:
965 case FILTER_OP_GE_S64_DOUBLE
:
966 case FILTER_OP_LE_S64_DOUBLE
:
969 if (vstack_pop(stack
)) {
973 if (!vstack_ax(stack
)) {
974 ERR("Empty stack\n");
978 vstack_ax(stack
)->type
= REG_S64
;
979 next_pc
+= sizeof(struct binary_op
);
984 case FILTER_OP_UNARY_PLUS
:
985 case FILTER_OP_UNARY_MINUS
:
988 if (!vstack_ax(stack
)) {
989 ERR("Empty stack\n");
993 vstack_ax(stack
)->type
= REG_UNKNOWN
;
994 next_pc
+= sizeof(struct unary_op
);
998 case FILTER_OP_UNARY_PLUS_S64
:
999 case FILTER_OP_UNARY_MINUS_S64
:
1000 case FILTER_OP_UNARY_NOT
:
1001 case FILTER_OP_UNARY_NOT_S64
:
1002 case FILTER_OP_UNARY_NOT_DOUBLE
:
1005 if (!vstack_ax(stack
)) {
1006 ERR("Empty stack\n");
1010 vstack_ax(stack
)->type
= REG_S64
;
1011 next_pc
+= sizeof(struct unary_op
);
1015 case FILTER_OP_UNARY_PLUS_DOUBLE
:
1016 case FILTER_OP_UNARY_MINUS_DOUBLE
:
1019 if (!vstack_ax(stack
)) {
1020 ERR("Empty stack\n");
1024 vstack_ax(stack
)->type
= REG_DOUBLE
;
1025 next_pc
+= sizeof(struct unary_op
);
1033 struct logical_op
*insn
= (struct logical_op
*) pc
;
1036 /* Add merge point to table */
1037 merge_ret
= merge_point_add_check(merge_points
,
1038 insn
->skip_offset
, stack
);
1043 /* Continue to next instruction */
1044 /* Pop 1 when jump not taken */
1045 if (vstack_pop(stack
)) {
1049 next_pc
+= sizeof(struct logical_op
);
1053 /* load field ref */
1054 case FILTER_OP_LOAD_FIELD_REF
:
1056 ERR("Unknown field ref type\n");
1060 /* get context ref */
1061 case FILTER_OP_GET_CONTEXT_REF
:
1063 if (vstack_push(stack
)) {
1067 vstack_ax(stack
)->type
= REG_UNKNOWN
;
1068 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1071 case FILTER_OP_LOAD_FIELD_REF_STRING
:
1072 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
1073 case FILTER_OP_GET_CONTEXT_REF_STRING
:
1075 if (vstack_push(stack
)) {
1079 vstack_ax(stack
)->type
= REG_STRING
;
1080 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1083 case FILTER_OP_LOAD_FIELD_REF_S64
:
1084 case FILTER_OP_GET_CONTEXT_REF_S64
:
1086 if (vstack_push(stack
)) {
1090 vstack_ax(stack
)->type
= REG_S64
;
1091 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1094 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
1095 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
1097 if (vstack_push(stack
)) {
1101 vstack_ax(stack
)->type
= REG_DOUBLE
;
1102 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1106 /* load from immediate operand */
1107 case FILTER_OP_LOAD_STRING
:
1109 struct load_op
*insn
= (struct load_op
*) pc
;
1111 if (vstack_push(stack
)) {
1115 vstack_ax(stack
)->type
= REG_STRING
;
1116 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1120 case FILTER_OP_LOAD_S64
:
1122 if (vstack_push(stack
)) {
1126 vstack_ax(stack
)->type
= REG_S64
;
1127 next_pc
+= sizeof(struct load_op
)
1128 + sizeof(struct literal_numeric
);
1132 case FILTER_OP_LOAD_DOUBLE
:
1134 if (vstack_push(stack
)) {
1138 vstack_ax(stack
)->type
= REG_DOUBLE
;
1139 next_pc
+= sizeof(struct load_op
)
1140 + sizeof(struct literal_double
);
1144 case FILTER_OP_CAST_TO_S64
:
1145 case FILTER_OP_CAST_DOUBLE_TO_S64
:
1148 if (!vstack_ax(stack
)) {
1149 ERR("Empty stack\n");
1153 vstack_ax(stack
)->type
= REG_S64
;
1154 next_pc
+= sizeof(struct cast_op
);
1157 case FILTER_OP_CAST_NOP
:
1159 next_pc
+= sizeof(struct cast_op
);
1165 *_next_pc
= next_pc
;
1170 * Never called concurrently (hash seed is shared).
1172 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
1174 struct cds_lfht
*merge_points
;
1175 char *pc
, *next_pc
, *start_pc
;
1177 struct vstack stack
;
1179 vstack_init(&stack
);
1181 if (!lttng_hash_seed_ready
) {
1182 lttng_hash_seed
= time(NULL
);
1183 lttng_hash_seed_ready
= 1;
1186 * Note: merge_points hash table used by single thread, and
1187 * never concurrently resized. Therefore, we can use it without
1188 * holding RCU read-side lock and free nodes without using
1191 merge_points
= cds_lfht_new(DEFAULT_NR_MERGE_POINTS
,
1192 MIN_NR_BUCKETS
, MAX_NR_BUCKETS
,
1194 if (!merge_points
) {
1195 ERR("Error allocating hash table for bytecode validation\n");
1198 start_pc
= &bytecode
->data
[0];
1199 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
1201 ret
= bytecode_validate_overflow(bytecode
, start_pc
, pc
);
1204 ERR("filter bytecode overflow\n");
1207 dbg_printf("Validating op %s (%u)\n",
1208 print_op((unsigned int) *(filter_opcode_t
*) pc
),
1209 (unsigned int) *(filter_opcode_t
*) pc
);
1212 * For each instruction, validate the current context
1213 * (traversal of entire execution flow), and validate
1214 * all merge points targeting this instruction.
1216 ret
= validate_instruction_all_contexts(bytecode
, merge_points
,
1217 &stack
, start_pc
, pc
);
1220 ret
= exec_insn(bytecode
, merge_points
, &stack
, &next_pc
, pc
);
1225 if (delete_all_nodes(merge_points
)) {
1227 ERR("Unexpected merge points\n");
1231 if (cds_lfht_destroy(merge_points
, NULL
)) {
1232 ERR("Error destroying hash table\n");