2 * lttng-filter-validator.c
4 * LTTng UST filter bytecode validator.
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "lttng-filter.h"
28 #include <urcu/rculfhash.h>
29 #include "lttng-hash-helper.h"
32 * Number of merge points for hash table size. Hash table initialized to
33 * that size, and we do not resize, because we do not want to trigger
34 * RCU worker thread execution: fall-back on linear traversal if number
35 * of merge points exceeds this value.
37 #define DEFAULT_NR_MERGE_POINTS 128
38 #define MIN_NR_BUCKETS 128
39 #define MAX_NR_BUCKETS 128
41 /* merge point table node */
43 struct cds_lfht_node node
;
45 /* Context at merge point */
47 unsigned long target_pc
;
50 static unsigned long lttng_hash_seed
;
51 static unsigned int lttng_hash_seed_ready
;
54 int lttng_hash_match(struct cds_lfht_node
*node
, const void *key
)
56 struct lfht_mp_node
*mp_node
=
57 caa_container_of(node
, struct lfht_mp_node
, node
);
58 unsigned long key_pc
= (unsigned long) key
;
60 if (mp_node
->target_pc
== key_pc
)
67 int merge_points_compare(const struct vstack
*stacka
,
68 const struct vstack
*stackb
)
72 if (stacka
->top
!= stackb
->top
)
74 len
= stacka
->top
+ 1;
76 for (i
= 0; i
< len
; i
++) {
77 if (stacka
->e
[i
].type
!= stackb
->e
[i
].type
)
84 int merge_point_add_check(struct cds_lfht
*ht
, unsigned long target_pc
,
85 const struct vstack
*stack
)
87 struct lfht_mp_node
*node
;
88 unsigned long hash
= lttng_hash_mix((const void *) target_pc
,
91 struct cds_lfht_node
*ret
;
93 dbg_printf("Filter: adding merge point at offset %lu, hash %lu\n",
95 node
= zmalloc(sizeof(struct lfht_mp_node
));
98 node
->target_pc
= target_pc
;
99 memcpy(&node
->stack
, stack
, sizeof(node
->stack
));
100 ret
= cds_lfht_add_unique(ht
, hash
, lttng_hash_match
,
101 (const void *) target_pc
, &node
->node
);
102 if (ret
!= &node
->node
) {
103 struct lfht_mp_node
*ret_mp
=
104 caa_container_of(ret
, struct lfht_mp_node
, node
);
106 /* Key already present */
107 dbg_printf("Filter: compare merge points for offset %lu, hash %lu\n",
110 if (merge_points_compare(stack
, &ret_mp
->stack
)) {
111 ERR("Merge points differ for offset %lu\n",
120 * Binary comparators use top of stack and top of stack -1.
123 int bin_op_compare_check(struct vstack
*stack
, const char *str
)
125 if (unlikely(!vstack_ax(stack
) || !vstack_bx(stack
)))
128 switch (vstack_ax(stack
)->type
) {
133 switch (vstack_bx(stack
)->type
) {
146 switch (vstack_bx(stack
)->type
) {
165 ERR("type mismatch for '%s' binary operator\n", str
);
170 * Validate bytecode range overflow within the validation pass.
171 * Called for each instruction encountered.
174 int bytecode_validate_overflow(struct bytecode_runtime
*bytecode
,
175 void *start_pc
, void *pc
)
179 switch (*(filter_opcode_t
*) pc
) {
180 case FILTER_OP_UNKNOWN
:
183 ERR("unknown bytecode op %u\n",
184 (unsigned int) *(filter_opcode_t
*) pc
);
189 case FILTER_OP_RETURN
:
191 if (unlikely(pc
+ sizeof(struct return_op
)
192 > start_pc
+ bytecode
->len
)) {
203 case FILTER_OP_MINUS
:
204 case FILTER_OP_RSHIFT
:
205 case FILTER_OP_LSHIFT
:
206 case FILTER_OP_BIN_AND
:
207 case FILTER_OP_BIN_OR
:
208 case FILTER_OP_BIN_XOR
:
210 ERR("unsupported bytecode op %u\n",
211 (unsigned int) *(filter_opcode_t
*) pc
);
222 case FILTER_OP_EQ_STRING
:
223 case FILTER_OP_NE_STRING
:
224 case FILTER_OP_GT_STRING
:
225 case FILTER_OP_LT_STRING
:
226 case FILTER_OP_GE_STRING
:
227 case FILTER_OP_LE_STRING
:
228 case FILTER_OP_EQ_S64
:
229 case FILTER_OP_NE_S64
:
230 case FILTER_OP_GT_S64
:
231 case FILTER_OP_LT_S64
:
232 case FILTER_OP_GE_S64
:
233 case FILTER_OP_LE_S64
:
234 case FILTER_OP_EQ_DOUBLE
:
235 case FILTER_OP_NE_DOUBLE
:
236 case FILTER_OP_GT_DOUBLE
:
237 case FILTER_OP_LT_DOUBLE
:
238 case FILTER_OP_GE_DOUBLE
:
239 case FILTER_OP_LE_DOUBLE
:
240 case FILTER_OP_EQ_DOUBLE_S64
:
241 case FILTER_OP_NE_DOUBLE_S64
:
242 case FILTER_OP_GT_DOUBLE_S64
:
243 case FILTER_OP_LT_DOUBLE_S64
:
244 case FILTER_OP_GE_DOUBLE_S64
:
245 case FILTER_OP_LE_DOUBLE_S64
:
246 case FILTER_OP_EQ_S64_DOUBLE
:
247 case FILTER_OP_NE_S64_DOUBLE
:
248 case FILTER_OP_GT_S64_DOUBLE
:
249 case FILTER_OP_LT_S64_DOUBLE
:
250 case FILTER_OP_GE_S64_DOUBLE
:
251 case FILTER_OP_LE_S64_DOUBLE
:
253 if (unlikely(pc
+ sizeof(struct binary_op
)
254 > start_pc
+ bytecode
->len
)) {
261 case FILTER_OP_UNARY_PLUS
:
262 case FILTER_OP_UNARY_MINUS
:
263 case FILTER_OP_UNARY_NOT
:
264 case FILTER_OP_UNARY_PLUS_S64
:
265 case FILTER_OP_UNARY_MINUS_S64
:
266 case FILTER_OP_UNARY_NOT_S64
:
267 case FILTER_OP_UNARY_PLUS_DOUBLE
:
268 case FILTER_OP_UNARY_MINUS_DOUBLE
:
269 case FILTER_OP_UNARY_NOT_DOUBLE
:
271 if (unlikely(pc
+ sizeof(struct unary_op
)
272 > start_pc
+ bytecode
->len
)) {
282 if (unlikely(pc
+ sizeof(struct logical_op
)
283 > start_pc
+ bytecode
->len
)) {
290 case FILTER_OP_LOAD_FIELD_REF
:
292 ERR("Unknown field ref type\n");
296 case FILTER_OP_LOAD_FIELD_REF_STRING
:
297 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
298 case FILTER_OP_LOAD_FIELD_REF_S64
:
299 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
301 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct field_ref
)
302 > start_pc
+ bytecode
->len
)) {
308 case FILTER_OP_LOAD_STRING
:
310 struct load_op
*insn
= (struct load_op
*) pc
;
311 uint32_t str_len
, maxlen
;
313 if (unlikely(pc
+ sizeof(struct load_op
)
314 > start_pc
+ bytecode
->len
)) {
319 maxlen
= start_pc
+ bytecode
->len
- pc
- sizeof(struct load_op
);
320 str_len
= strnlen(insn
->data
, maxlen
);
321 if (unlikely(str_len
>= maxlen
)) {
322 /* Final '\0' not found within range */
328 case FILTER_OP_LOAD_S64
:
330 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_numeric
)
331 > start_pc
+ bytecode
->len
)) {
337 case FILTER_OP_LOAD_DOUBLE
:
339 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_double
)
340 > start_pc
+ bytecode
->len
)) {
346 case FILTER_OP_CAST_TO_S64
:
347 case FILTER_OP_CAST_DOUBLE_TO_S64
:
348 case FILTER_OP_CAST_NOP
:
350 if (unlikely(pc
+ sizeof(struct cast_op
)
351 > start_pc
+ bytecode
->len
)) {
362 unsigned long delete_all_nodes(struct cds_lfht
*ht
)
364 struct cds_lfht_iter iter
;
365 struct lfht_mp_node
*node
;
366 unsigned long nr_nodes
= 0;
368 cds_lfht_for_each_entry(ht
, &iter
, node
, node
) {
371 ret
= cds_lfht_del(ht
, cds_lfht_iter_get_node(&iter
));
373 /* note: this hash table is never used concurrently */
386 int validate_instruction_context(struct bytecode_runtime
*bytecode
,
387 struct vstack
*stack
,
393 switch (*(filter_opcode_t
*) pc
) {
394 case FILTER_OP_UNKNOWN
:
397 ERR("unknown bytecode op %u\n",
398 (unsigned int) *(filter_opcode_t
*) pc
);
403 case FILTER_OP_RETURN
:
413 case FILTER_OP_MINUS
:
414 case FILTER_OP_RSHIFT
:
415 case FILTER_OP_LSHIFT
:
416 case FILTER_OP_BIN_AND
:
417 case FILTER_OP_BIN_OR
:
418 case FILTER_OP_BIN_XOR
:
420 ERR("unsupported bytecode op %u\n",
421 (unsigned int) *(filter_opcode_t
*) pc
);
428 ret
= bin_op_compare_check(stack
, "==");
435 ret
= bin_op_compare_check(stack
, "!=");
442 ret
= bin_op_compare_check(stack
, ">");
449 ret
= bin_op_compare_check(stack
, "<");
456 ret
= bin_op_compare_check(stack
, ">=");
463 ret
= bin_op_compare_check(stack
, "<=");
469 case FILTER_OP_EQ_STRING
:
470 case FILTER_OP_NE_STRING
:
471 case FILTER_OP_GT_STRING
:
472 case FILTER_OP_LT_STRING
:
473 case FILTER_OP_GE_STRING
:
474 case FILTER_OP_LE_STRING
:
476 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
477 ERR("Empty stack\n");
481 if (vstack_ax(stack
)->type
!= REG_STRING
482 || vstack_bx(stack
)->type
!= REG_STRING
) {
483 ERR("Unexpected register type for string comparator\n");
490 case FILTER_OP_EQ_S64
:
491 case FILTER_OP_NE_S64
:
492 case FILTER_OP_GT_S64
:
493 case FILTER_OP_LT_S64
:
494 case FILTER_OP_GE_S64
:
495 case FILTER_OP_LE_S64
:
497 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
498 ERR("Empty stack\n");
502 if (vstack_ax(stack
)->type
!= REG_S64
503 || vstack_bx(stack
)->type
!= REG_S64
) {
504 ERR("Unexpected register type for s64 comparator\n");
511 case FILTER_OP_EQ_DOUBLE
:
512 case FILTER_OP_NE_DOUBLE
:
513 case FILTER_OP_GT_DOUBLE
:
514 case FILTER_OP_LT_DOUBLE
:
515 case FILTER_OP_GE_DOUBLE
:
516 case FILTER_OP_LE_DOUBLE
:
518 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
519 ERR("Empty stack\n");
523 if (vstack_ax(stack
)->type
!= REG_DOUBLE
&& vstack_bx(stack
)->type
!= REG_DOUBLE
) {
524 ERR("Double operator should have two double registers\n");
531 case FILTER_OP_EQ_DOUBLE_S64
:
532 case FILTER_OP_NE_DOUBLE_S64
:
533 case FILTER_OP_GT_DOUBLE_S64
:
534 case FILTER_OP_LT_DOUBLE_S64
:
535 case FILTER_OP_GE_DOUBLE_S64
:
536 case FILTER_OP_LE_DOUBLE_S64
:
538 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
539 ERR("Empty stack\n");
543 if (vstack_ax(stack
)->type
!= REG_S64
&& vstack_bx(stack
)->type
!= REG_DOUBLE
) {
544 ERR("Double-S64 operator has unexpected register types\n");
551 case FILTER_OP_EQ_S64_DOUBLE
:
552 case FILTER_OP_NE_S64_DOUBLE
:
553 case FILTER_OP_GT_S64_DOUBLE
:
554 case FILTER_OP_LT_S64_DOUBLE
:
555 case FILTER_OP_GE_S64_DOUBLE
:
556 case FILTER_OP_LE_S64_DOUBLE
:
558 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
559 ERR("Empty stack\n");
563 if (vstack_ax(stack
)->type
!= REG_DOUBLE
&& vstack_bx(stack
)->type
!= REG_S64
) {
564 ERR("S64-Double operator has unexpected register types\n");
572 case FILTER_OP_UNARY_PLUS
:
573 case FILTER_OP_UNARY_MINUS
:
574 case FILTER_OP_UNARY_NOT
:
576 if (!vstack_ax(stack
)) {
577 ERR("Empty stack\n");
581 switch (vstack_ax(stack
)->type
) {
583 ERR("unknown register type\n");
588 ERR("Unary op can only be applied to numeric or floating point registers\n");
599 case FILTER_OP_UNARY_PLUS_S64
:
600 case FILTER_OP_UNARY_MINUS_S64
:
601 case FILTER_OP_UNARY_NOT_S64
:
603 if (!vstack_ax(stack
)) {
604 ERR("Empty stack\n");
608 if (vstack_ax(stack
)->type
!= REG_S64
) {
609 ERR("Invalid register type\n");
616 case FILTER_OP_UNARY_PLUS_DOUBLE
:
617 case FILTER_OP_UNARY_MINUS_DOUBLE
:
618 case FILTER_OP_UNARY_NOT_DOUBLE
:
620 if (!vstack_ax(stack
)) {
621 ERR("Empty stack\n");
625 if (vstack_ax(stack
)->type
!= REG_DOUBLE
) {
626 ERR("Invalid register type\n");
637 struct logical_op
*insn
= (struct logical_op
*) pc
;
639 if (!vstack_ax(stack
)) {
640 ERR("Empty stack\n");
644 if (vstack_ax(stack
)->type
!= REG_S64
) {
645 ERR("Logical comparator expects S64 register\n");
650 dbg_printf("Validate jumping to bytecode offset %u\n",
651 (unsigned int) insn
->skip_offset
);
652 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
653 ERR("Loops are not allowed in bytecode\n");
661 case FILTER_OP_LOAD_FIELD_REF
:
663 ERR("Unknown field ref type\n");
667 case FILTER_OP_LOAD_FIELD_REF_STRING
:
668 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
670 struct load_op
*insn
= (struct load_op
*) pc
;
671 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
673 dbg_printf("Validate load field ref offset %u type string\n",
677 case FILTER_OP_LOAD_FIELD_REF_S64
:
679 struct load_op
*insn
= (struct load_op
*) pc
;
680 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
682 dbg_printf("Validate load field ref offset %u type s64\n",
686 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
688 struct load_op
*insn
= (struct load_op
*) pc
;
689 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
691 dbg_printf("Validate load field ref offset %u type double\n",
696 case FILTER_OP_LOAD_STRING
:
701 case FILTER_OP_LOAD_S64
:
706 case FILTER_OP_LOAD_DOUBLE
:
711 case FILTER_OP_CAST_TO_S64
:
712 case FILTER_OP_CAST_DOUBLE_TO_S64
:
714 struct cast_op
*insn
= (struct cast_op
*) pc
;
716 if (!vstack_ax(stack
)) {
717 ERR("Empty stack\n");
721 switch (vstack_ax(stack
)->type
) {
723 ERR("unknown register type\n");
728 ERR("Cast op can only be applied to numeric or floating point registers\n");
736 if (insn
->op
== FILTER_OP_CAST_DOUBLE_TO_S64
) {
737 if (vstack_ax(stack
)->type
!= REG_DOUBLE
) {
738 ERR("Cast expects double\n");
745 case FILTER_OP_CAST_NOP
:
761 int validate_instruction_all_contexts(struct bytecode_runtime
*bytecode
,
762 struct cds_lfht
*merge_points
,
763 struct vstack
*stack
,
768 unsigned long target_pc
= pc
- start_pc
;
769 struct cds_lfht_iter iter
;
770 struct cds_lfht_node
*node
;
771 struct lfht_mp_node
*mp_node
;
774 /* Validate the context resulting from the previous instruction */
775 ret
= validate_instruction_context(bytecode
, stack
, start_pc
, pc
);
779 /* Validate merge points */
780 hash
= lttng_hash_mix((const void *) target_pc
, sizeof(target_pc
),
782 cds_lfht_lookup(merge_points
, hash
, lttng_hash_match
,
783 (const void *) target_pc
, &iter
);
784 node
= cds_lfht_iter_get_node(&iter
);
786 mp_node
= caa_container_of(node
, struct lfht_mp_node
, node
);
788 dbg_printf("Filter: validate merge point at offset %lu\n",
790 if (merge_points_compare(stack
, &mp_node
->stack
)) {
791 ERR("Merge points differ for offset %lu\n",
795 /* Once validated, we can remove the merge point */
796 dbg_printf("Filter: remove merge point at offset %lu\n",
798 ret
= cds_lfht_del(merge_points
, node
);
806 * >0: going to next insn.
807 * 0: success, stop iteration.
811 int exec_insn(struct bytecode_runtime
*bytecode
,
812 struct cds_lfht
*merge_points
,
813 struct vstack
*stack
,
818 void *next_pc
= *_next_pc
;
820 switch (*(filter_opcode_t
*) pc
) {
821 case FILTER_OP_UNKNOWN
:
824 ERR("unknown bytecode op %u\n",
825 (unsigned int) *(filter_opcode_t
*) pc
);
830 case FILTER_OP_RETURN
:
832 if (!vstack_ax(stack
)) {
833 ERR("Empty stack\n");
846 case FILTER_OP_MINUS
:
847 case FILTER_OP_RSHIFT
:
848 case FILTER_OP_LSHIFT
:
849 case FILTER_OP_BIN_AND
:
850 case FILTER_OP_BIN_OR
:
851 case FILTER_OP_BIN_XOR
:
853 ERR("unsupported bytecode op %u\n",
854 (unsigned int) *(filter_opcode_t
*) pc
);
865 case FILTER_OP_EQ_STRING
:
866 case FILTER_OP_NE_STRING
:
867 case FILTER_OP_GT_STRING
:
868 case FILTER_OP_LT_STRING
:
869 case FILTER_OP_GE_STRING
:
870 case FILTER_OP_LE_STRING
:
871 case FILTER_OP_EQ_S64
:
872 case FILTER_OP_NE_S64
:
873 case FILTER_OP_GT_S64
:
874 case FILTER_OP_LT_S64
:
875 case FILTER_OP_GE_S64
:
876 case FILTER_OP_LE_S64
:
877 case FILTER_OP_EQ_DOUBLE
:
878 case FILTER_OP_NE_DOUBLE
:
879 case FILTER_OP_GT_DOUBLE
:
880 case FILTER_OP_LT_DOUBLE
:
881 case FILTER_OP_GE_DOUBLE
:
882 case FILTER_OP_LE_DOUBLE
:
883 case FILTER_OP_EQ_DOUBLE_S64
:
884 case FILTER_OP_NE_DOUBLE_S64
:
885 case FILTER_OP_GT_DOUBLE_S64
:
886 case FILTER_OP_LT_DOUBLE_S64
:
887 case FILTER_OP_GE_DOUBLE_S64
:
888 case FILTER_OP_LE_DOUBLE_S64
:
889 case FILTER_OP_EQ_S64_DOUBLE
:
890 case FILTER_OP_NE_S64_DOUBLE
:
891 case FILTER_OP_GT_S64_DOUBLE
:
892 case FILTER_OP_LT_S64_DOUBLE
:
893 case FILTER_OP_GE_S64_DOUBLE
:
894 case FILTER_OP_LE_S64_DOUBLE
:
897 if (vstack_pop(stack
)) {
901 if (!vstack_ax(stack
)) {
902 ERR("Empty stack\n");
906 vstack_ax(stack
)->type
= REG_S64
;
907 next_pc
+= sizeof(struct binary_op
);
912 case FILTER_OP_UNARY_PLUS
:
913 case FILTER_OP_UNARY_MINUS
:
914 case FILTER_OP_UNARY_NOT
:
915 case FILTER_OP_UNARY_PLUS_S64
:
916 case FILTER_OP_UNARY_MINUS_S64
:
917 case FILTER_OP_UNARY_NOT_S64
:
920 if (!vstack_ax(stack
)) {
921 ERR("Empty stack\n");
925 vstack_ax(stack
)->type
= REG_S64
;
926 next_pc
+= sizeof(struct unary_op
);
930 case FILTER_OP_UNARY_PLUS_DOUBLE
:
931 case FILTER_OP_UNARY_MINUS_DOUBLE
:
932 case FILTER_OP_UNARY_NOT_DOUBLE
:
935 if (!vstack_ax(stack
)) {
936 ERR("Empty stack\n");
940 vstack_ax(stack
)->type
= REG_DOUBLE
;
941 next_pc
+= sizeof(struct unary_op
);
949 struct logical_op
*insn
= (struct logical_op
*) pc
;
952 /* Add merge point to table */
953 merge_ret
= merge_point_add_check(merge_points
,
954 insn
->skip_offset
, stack
);
959 /* Continue to next instruction */
960 /* Pop 1 when jump not taken */
961 if (vstack_pop(stack
)) {
965 next_pc
+= sizeof(struct logical_op
);
970 case FILTER_OP_LOAD_FIELD_REF
:
972 ERR("Unknown field ref type\n");
976 case FILTER_OP_LOAD_FIELD_REF_STRING
:
977 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
979 if (vstack_push(stack
)) {
983 vstack_ax(stack
)->type
= REG_STRING
;
984 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
987 case FILTER_OP_LOAD_FIELD_REF_S64
:
989 if (vstack_push(stack
)) {
993 vstack_ax(stack
)->type
= REG_S64
;
994 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
997 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
999 if (vstack_push(stack
)) {
1003 vstack_ax(stack
)->type
= REG_DOUBLE
;
1004 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
1008 case FILTER_OP_LOAD_STRING
:
1010 struct load_op
*insn
= (struct load_op
*) pc
;
1012 if (vstack_push(stack
)) {
1016 vstack_ax(stack
)->type
= REG_STRING
;
1017 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
1021 case FILTER_OP_LOAD_S64
:
1023 if (vstack_push(stack
)) {
1027 vstack_ax(stack
)->type
= REG_S64
;
1028 next_pc
+= sizeof(struct load_op
)
1029 + sizeof(struct literal_numeric
);
1033 case FILTER_OP_LOAD_DOUBLE
:
1035 if (vstack_push(stack
)) {
1039 vstack_ax(stack
)->type
= REG_DOUBLE
;
1040 next_pc
+= sizeof(struct load_op
)
1041 + sizeof(struct literal_double
);
1045 case FILTER_OP_CAST_TO_S64
:
1046 case FILTER_OP_CAST_DOUBLE_TO_S64
:
1049 if (!vstack_ax(stack
)) {
1050 ERR("Empty stack\n");
1054 vstack_ax(stack
)->type
= REG_S64
;
1055 next_pc
+= sizeof(struct cast_op
);
1058 case FILTER_OP_CAST_NOP
:
1060 next_pc
+= sizeof(struct cast_op
);
1066 *_next_pc
= next_pc
;
1071 * Never called concurrently (hash seed is shared).
1073 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
1075 struct cds_lfht
*merge_points
;
1076 void *pc
, *next_pc
, *start_pc
;
1078 struct vstack stack
;
1080 vstack_init(&stack
);
1082 if (!lttng_hash_seed_ready
) {
1083 lttng_hash_seed
= time(NULL
);
1084 lttng_hash_seed_ready
= 1;
1087 * Note: merge_points hash table used by single thread, and
1088 * never concurrently resized. Therefore, we can use it without
1089 * holding RCU read-side lock and free nodes without using
1092 merge_points
= cds_lfht_new(DEFAULT_NR_MERGE_POINTS
,
1093 MIN_NR_BUCKETS
, MAX_NR_BUCKETS
,
1095 if (!merge_points
) {
1096 ERR("Error allocating hash table for bytecode validation\n");
1099 start_pc
= &bytecode
->data
[0];
1100 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
1102 ret
= bytecode_validate_overflow(bytecode
, start_pc
, pc
);
1105 ERR("filter bytecode overflow\n");
1108 dbg_printf("Validating op %s (%u)\n",
1109 print_op((unsigned int) *(filter_opcode_t
*) pc
),
1110 (unsigned int) *(filter_opcode_t
*) pc
);
1113 * For each instruction, validate the current context
1114 * (traversal of entire execution flow), and validate
1115 * all merge points targeting this instruction.
1117 ret
= validate_instruction_all_contexts(bytecode
, merge_points
,
1118 &stack
, start_pc
, pc
);
1121 ret
= exec_insn(bytecode
, merge_points
, &stack
, &next_pc
, pc
);
1126 if (delete_all_nodes(merge_points
)) {
1128 ERR("Unexpected merge points\n");
1132 if (cds_lfht_destroy(merge_points
, NULL
)) {
1133 ERR("Error destroying hash table\n");