2 * lttng-filter-validator.c
4 * LTTng modules filter bytecode validator.
6 * Copyright (C) 2010-2014 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
23 #include <linux/types.h>
24 #include <linux/jhash.h>
25 #include <linux/slab.h>
27 #include "wrapper/list.h"
28 #include "lttng-filter.h"
30 #define MERGE_POINT_TABLE_BITS 7
31 #define MERGE_POINT_TABLE_SIZE (1U << MERGE_POINT_TABLE_BITS)
33 /* merge point table node */
35 struct hlist_node node
;
37 /* Context at merge point */
39 unsigned long target_pc
;
43 struct hlist_head mp_head
[MERGE_POINT_TABLE_SIZE
];
47 int lttng_hash_match(struct mp_node
*mp_node
, unsigned long key_pc
)
49 if (mp_node
->target_pc
== key_pc
)
56 int merge_points_compare(const struct vstack
*stacka
,
57 const struct vstack
*stackb
)
61 if (stacka
->top
!= stackb
->top
)
63 len
= stacka
->top
+ 1;
64 WARN_ON_ONCE(len
< 0);
65 for (i
= 0; i
< len
; i
++) {
66 if (stacka
->e
[i
].type
!= stackb
->e
[i
].type
)
73 int merge_point_add_check(struct mp_table
*mp_table
, unsigned long target_pc
,
74 const struct vstack
*stack
)
76 struct mp_node
*mp_node
;
77 unsigned long hash
= jhash_1word(target_pc
, 0);
78 struct hlist_head
*head
;
79 struct mp_node
*lookup_node
;
82 dbg_printk("Filter: adding merge point at offset %lu, hash %lu\n",
84 mp_node
= kzalloc(sizeof(struct mp_node
), GFP_KERNEL
);
87 mp_node
->target_pc
= target_pc
;
88 memcpy(&mp_node
->stack
, stack
, sizeof(mp_node
->stack
));
90 head
= &mp_table
->mp_head
[hash
& (MERGE_POINT_TABLE_SIZE
- 1)];
91 lttng_hlist_for_each_entry(lookup_node
, head
, node
) {
92 if (lttng_hash_match(lookup_node
, target_pc
)) {
98 /* Key already present */
99 dbg_printk("Filter: compare merge points for offset %lu, hash %lu\n",
102 if (merge_points_compare(stack
, &lookup_node
->stack
)) {
103 printk(KERN_WARNING
"Merge points differ for offset %lu\n",
108 hlist_add_head(&mp_node
->node
, head
);
113 * Binary comparators use top of stack and top of stack -1.
116 int bin_op_compare_check(struct vstack
*stack
, const char *str
)
118 if (unlikely(!vstack_ax(stack
) || !vstack_bx(stack
)))
121 switch (vstack_ax(stack
)->type
) {
127 switch (vstack_bx(stack
)->type
) {
139 switch (vstack_bx(stack
)->type
) {
158 printk(KERN_WARNING
"type mismatch for '%s' binary operator\n", str
);
163 * Validate bytecode range overflow within the validation pass.
164 * Called for each instruction encountered.
167 int bytecode_validate_overflow(struct bytecode_runtime
*bytecode
,
168 void *start_pc
, void *pc
)
172 switch (*(filter_opcode_t
*) pc
) {
173 case FILTER_OP_UNKNOWN
:
176 printk(KERN_WARNING
"unknown bytecode op %u\n",
177 (unsigned int) *(filter_opcode_t
*) pc
);
182 case FILTER_OP_RETURN
:
184 if (unlikely(pc
+ sizeof(struct return_op
)
185 > start_pc
+ bytecode
->len
)) {
196 case FILTER_OP_MINUS
:
197 case FILTER_OP_RSHIFT
:
198 case FILTER_OP_LSHIFT
:
199 case FILTER_OP_BIN_AND
:
200 case FILTER_OP_BIN_OR
:
201 case FILTER_OP_BIN_XOR
:
202 case FILTER_OP_EQ_DOUBLE
:
203 case FILTER_OP_NE_DOUBLE
:
204 case FILTER_OP_GT_DOUBLE
:
205 case FILTER_OP_LT_DOUBLE
:
206 case FILTER_OP_GE_DOUBLE
:
207 case FILTER_OP_LE_DOUBLE
:
209 case FILTER_OP_EQ_DOUBLE_S64
:
210 case FILTER_OP_NE_DOUBLE_S64
:
211 case FILTER_OP_GT_DOUBLE_S64
:
212 case FILTER_OP_LT_DOUBLE_S64
:
213 case FILTER_OP_GE_DOUBLE_S64
:
214 case FILTER_OP_LE_DOUBLE_S64
:
215 case FILTER_OP_EQ_S64_DOUBLE
:
216 case FILTER_OP_NE_S64_DOUBLE
:
217 case FILTER_OP_GT_S64_DOUBLE
:
218 case FILTER_OP_LT_S64_DOUBLE
:
219 case FILTER_OP_GE_S64_DOUBLE
:
220 case FILTER_OP_LE_S64_DOUBLE
:
221 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
222 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
223 case FILTER_OP_LOAD_DOUBLE
:
224 case FILTER_OP_CAST_DOUBLE_TO_S64
:
225 case FILTER_OP_UNARY_PLUS_DOUBLE
:
226 case FILTER_OP_UNARY_MINUS_DOUBLE
:
227 case FILTER_OP_UNARY_NOT_DOUBLE
:
229 printk(KERN_WARNING
"unsupported bytecode op %u\n",
230 (unsigned int) *(filter_opcode_t
*) pc
);
241 case FILTER_OP_EQ_STRING
:
242 case FILTER_OP_NE_STRING
:
243 case FILTER_OP_GT_STRING
:
244 case FILTER_OP_LT_STRING
:
245 case FILTER_OP_GE_STRING
:
246 case FILTER_OP_LE_STRING
:
247 case FILTER_OP_EQ_S64
:
248 case FILTER_OP_NE_S64
:
249 case FILTER_OP_GT_S64
:
250 case FILTER_OP_LT_S64
:
251 case FILTER_OP_GE_S64
:
252 case FILTER_OP_LE_S64
:
254 if (unlikely(pc
+ sizeof(struct binary_op
)
255 > start_pc
+ bytecode
->len
)) {
262 case FILTER_OP_UNARY_PLUS
:
263 case FILTER_OP_UNARY_MINUS
:
264 case FILTER_OP_UNARY_NOT
:
265 case FILTER_OP_UNARY_PLUS_S64
:
266 case FILTER_OP_UNARY_MINUS_S64
:
267 case FILTER_OP_UNARY_NOT_S64
:
269 if (unlikely(pc
+ sizeof(struct unary_op
)
270 > start_pc
+ bytecode
->len
)) {
280 if (unlikely(pc
+ sizeof(struct logical_op
)
281 > start_pc
+ bytecode
->len
)) {
288 case FILTER_OP_LOAD_FIELD_REF
:
290 printk(KERN_WARNING
"Unknown field ref type\n");
294 /* get context ref */
295 case FILTER_OP_GET_CONTEXT_REF
:
297 printk(KERN_WARNING
"Unknown field ref type\n");
301 case FILTER_OP_LOAD_FIELD_REF_STRING
:
302 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
303 case FILTER_OP_LOAD_FIELD_REF_USER_STRING
:
304 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE
:
305 case FILTER_OP_LOAD_FIELD_REF_S64
:
306 case FILTER_OP_GET_CONTEXT_REF_STRING
:
307 case FILTER_OP_GET_CONTEXT_REF_S64
:
309 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct field_ref
)
310 > start_pc
+ bytecode
->len
)) {
316 /* load from immediate operand */
317 case FILTER_OP_LOAD_STRING
:
319 struct load_op
*insn
= (struct load_op
*) pc
;
320 uint32_t str_len
, maxlen
;
322 if (unlikely(pc
+ sizeof(struct load_op
)
323 > start_pc
+ bytecode
->len
)) {
328 maxlen
= start_pc
+ bytecode
->len
- pc
- sizeof(struct load_op
);
329 str_len
= strnlen(insn
->data
, maxlen
);
330 if (unlikely(str_len
>= maxlen
)) {
331 /* Final '\0' not found within range */
337 case FILTER_OP_LOAD_S64
:
339 if (unlikely(pc
+ sizeof(struct load_op
) + sizeof(struct literal_numeric
)
340 > start_pc
+ bytecode
->len
)) {
346 case FILTER_OP_CAST_TO_S64
:
347 case FILTER_OP_CAST_NOP
:
349 if (unlikely(pc
+ sizeof(struct cast_op
)
350 > start_pc
+ bytecode
->len
)) {
362 unsigned long delete_all_nodes(struct mp_table
*mp_table
)
364 struct mp_node
*mp_node
;
365 struct hlist_node
*tmp
;
366 unsigned long nr_nodes
= 0;
369 for (i
= 0; i
< MERGE_POINT_TABLE_SIZE
; i
++) {
370 struct hlist_head
*head
;
372 head
= &mp_table
->mp_head
[i
];
373 lttng_hlist_for_each_entry_safe(mp_node
, tmp
, head
, node
) {
387 int validate_instruction_context(struct bytecode_runtime
*bytecode
,
388 struct vstack
*stack
,
394 switch (*(filter_opcode_t
*) pc
) {
395 case FILTER_OP_UNKNOWN
:
398 printk(KERN_WARNING
"unknown bytecode op %u\n",
399 (unsigned int) *(filter_opcode_t
*) pc
);
404 case FILTER_OP_RETURN
:
414 case FILTER_OP_MINUS
:
415 case FILTER_OP_RSHIFT
:
416 case FILTER_OP_LSHIFT
:
417 case FILTER_OP_BIN_AND
:
418 case FILTER_OP_BIN_OR
:
419 case FILTER_OP_BIN_XOR
:
421 case FILTER_OP_EQ_DOUBLE
:
422 case FILTER_OP_NE_DOUBLE
:
423 case FILTER_OP_GT_DOUBLE
:
424 case FILTER_OP_LT_DOUBLE
:
425 case FILTER_OP_GE_DOUBLE
:
426 case FILTER_OP_LE_DOUBLE
:
427 case FILTER_OP_EQ_DOUBLE_S64
:
428 case FILTER_OP_NE_DOUBLE_S64
:
429 case FILTER_OP_GT_DOUBLE_S64
:
430 case FILTER_OP_LT_DOUBLE_S64
:
431 case FILTER_OP_GE_DOUBLE_S64
:
432 case FILTER_OP_LE_DOUBLE_S64
:
433 case FILTER_OP_EQ_S64_DOUBLE
:
434 case FILTER_OP_NE_S64_DOUBLE
:
435 case FILTER_OP_GT_S64_DOUBLE
:
436 case FILTER_OP_LT_S64_DOUBLE
:
437 case FILTER_OP_GE_S64_DOUBLE
:
438 case FILTER_OP_LE_S64_DOUBLE
:
439 case FILTER_OP_UNARY_PLUS_DOUBLE
:
440 case FILTER_OP_UNARY_MINUS_DOUBLE
:
441 case FILTER_OP_UNARY_NOT_DOUBLE
:
442 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
443 case FILTER_OP_LOAD_DOUBLE
:
444 case FILTER_OP_CAST_DOUBLE_TO_S64
:
445 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
447 printk(KERN_WARNING
"unsupported bytecode op %u\n",
448 (unsigned int) *(filter_opcode_t
*) pc
);
455 ret
= bin_op_compare_check(stack
, "==");
462 ret
= bin_op_compare_check(stack
, "!=");
469 ret
= bin_op_compare_check(stack
, ">");
476 ret
= bin_op_compare_check(stack
, "<");
483 ret
= bin_op_compare_check(stack
, ">=");
490 ret
= bin_op_compare_check(stack
, "<=");
496 case FILTER_OP_EQ_STRING
:
497 case FILTER_OP_NE_STRING
:
498 case FILTER_OP_GT_STRING
:
499 case FILTER_OP_LT_STRING
:
500 case FILTER_OP_GE_STRING
:
501 case FILTER_OP_LE_STRING
:
503 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
504 printk(KERN_WARNING
"Empty stack\n");
508 if (vstack_ax(stack
)->type
!= REG_STRING
509 || vstack_bx(stack
)->type
!= REG_STRING
) {
510 printk(KERN_WARNING
"Unexpected register type for string comparator\n");
517 case FILTER_OP_EQ_S64
:
518 case FILTER_OP_NE_S64
:
519 case FILTER_OP_GT_S64
:
520 case FILTER_OP_LT_S64
:
521 case FILTER_OP_GE_S64
:
522 case FILTER_OP_LE_S64
:
524 if (!vstack_ax(stack
) || !vstack_bx(stack
)) {
525 printk(KERN_WARNING
"Empty stack\n");
529 if (vstack_ax(stack
)->type
!= REG_S64
530 || vstack_bx(stack
)->type
!= REG_S64
) {
531 printk(KERN_WARNING
"Unexpected register type for s64 comparator\n");
539 case FILTER_OP_UNARY_PLUS
:
540 case FILTER_OP_UNARY_MINUS
:
541 case FILTER_OP_UNARY_NOT
:
543 if (!vstack_ax(stack
)) {
544 printk(KERN_WARNING
"Empty stack\n");
548 switch (vstack_ax(stack
)->type
) {
551 printk(KERN_WARNING
"unknown register type\n");
556 printk(KERN_WARNING
"Unary op can only be applied to numeric or floating point registers\n");
565 case FILTER_OP_UNARY_PLUS_S64
:
566 case FILTER_OP_UNARY_MINUS_S64
:
567 case FILTER_OP_UNARY_NOT_S64
:
569 if (!vstack_ax(stack
)) {
570 printk(KERN_WARNING
"Empty stack\n");
574 if (vstack_ax(stack
)->type
!= REG_S64
) {
575 printk(KERN_WARNING
"Invalid register type\n");
586 struct logical_op
*insn
= (struct logical_op
*) pc
;
588 if (!vstack_ax(stack
)) {
589 printk(KERN_WARNING
"Empty stack\n");
593 if (vstack_ax(stack
)->type
!= REG_S64
) {
594 printk(KERN_WARNING
"Logical comparator expects S64 register\n");
599 dbg_printk("Validate jumping to bytecode offset %u\n",
600 (unsigned int) insn
->skip_offset
);
601 if (unlikely(start_pc
+ insn
->skip_offset
<= pc
)) {
602 printk(KERN_WARNING
"Loops are not allowed in bytecode\n");
610 case FILTER_OP_LOAD_FIELD_REF
:
612 printk(KERN_WARNING
"Unknown field ref type\n");
616 case FILTER_OP_LOAD_FIELD_REF_STRING
:
617 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
618 case FILTER_OP_LOAD_FIELD_REF_USER_STRING
:
619 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE
:
621 struct load_op
*insn
= (struct load_op
*) pc
;
622 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
624 dbg_printk("Validate load field ref offset %u type string\n",
628 case FILTER_OP_LOAD_FIELD_REF_S64
:
630 struct load_op
*insn
= (struct load_op
*) pc
;
631 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
633 dbg_printk("Validate load field ref offset %u type s64\n",
638 /* load from immediate operand */
639 case FILTER_OP_LOAD_STRING
:
644 case FILTER_OP_LOAD_S64
:
649 case FILTER_OP_CAST_TO_S64
:
651 struct cast_op
*insn
= (struct cast_op
*) pc
;
653 if (!vstack_ax(stack
)) {
654 printk(KERN_WARNING
"Empty stack\n");
658 switch (vstack_ax(stack
)->type
) {
661 printk(KERN_WARNING
"unknown register type\n");
666 printk(KERN_WARNING
"Cast op can only be applied to numeric or floating point registers\n");
672 if (insn
->op
== FILTER_OP_CAST_DOUBLE_TO_S64
) {
673 if (vstack_ax(stack
)->type
!= REG_DOUBLE
) {
674 printk(KERN_WARNING
"Cast expects double\n");
681 case FILTER_OP_CAST_NOP
:
686 /* get context ref */
687 case FILTER_OP_GET_CONTEXT_REF
:
689 printk(KERN_WARNING
"Unknown get context ref type\n");
693 case FILTER_OP_GET_CONTEXT_REF_STRING
:
695 struct load_op
*insn
= (struct load_op
*) pc
;
696 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
698 dbg_printk("Validate get context ref offset %u type string\n",
702 case FILTER_OP_GET_CONTEXT_REF_S64
:
704 struct load_op
*insn
= (struct load_op
*) pc
;
705 struct field_ref
*ref
= (struct field_ref
*) insn
->data
;
707 dbg_printk("Validate get context ref offset %u type s64\n",
723 int validate_instruction_all_contexts(struct bytecode_runtime
*bytecode
,
724 struct mp_table
*mp_table
,
725 struct vstack
*stack
,
730 unsigned long target_pc
= pc
- start_pc
;
732 struct hlist_head
*head
;
733 struct mp_node
*mp_node
;
735 /* Validate the context resulting from the previous instruction */
736 ret
= validate_instruction_context(bytecode
, stack
, start_pc
, pc
);
740 /* Validate merge points */
741 hash
= jhash_1word(target_pc
, 0);
742 head
= &mp_table
->mp_head
[hash
& (MERGE_POINT_TABLE_SIZE
- 1)];
743 lttng_hlist_for_each_entry(mp_node
, head
, node
) {
744 if (lttng_hash_match(mp_node
, target_pc
)) {
750 dbg_printk("Filter: validate merge point at offset %lu\n",
752 if (merge_points_compare(stack
, &mp_node
->stack
)) {
753 printk(KERN_WARNING
"Merge points differ for offset %lu\n",
757 /* Once validated, we can remove the merge point */
758 dbg_printk("Filter: remove merge point at offset %lu\n",
760 hlist_del(&mp_node
->node
);
767 * >0: going to next insn.
768 * 0: success, stop iteration.
772 int exec_insn(struct bytecode_runtime
*bytecode
,
773 struct mp_table
*mp_table
,
774 struct vstack
*stack
,
779 void *next_pc
= *_next_pc
;
781 switch (*(filter_opcode_t
*) pc
) {
782 case FILTER_OP_UNKNOWN
:
785 printk(KERN_WARNING
"unknown bytecode op %u\n",
786 (unsigned int) *(filter_opcode_t
*) pc
);
791 case FILTER_OP_RETURN
:
793 if (!vstack_ax(stack
)) {
794 printk(KERN_WARNING
"Empty stack\n");
807 case FILTER_OP_MINUS
:
808 case FILTER_OP_RSHIFT
:
809 case FILTER_OP_LSHIFT
:
810 case FILTER_OP_BIN_AND
:
811 case FILTER_OP_BIN_OR
:
812 case FILTER_OP_BIN_XOR
:
814 case FILTER_OP_EQ_DOUBLE
:
815 case FILTER_OP_NE_DOUBLE
:
816 case FILTER_OP_GT_DOUBLE
:
817 case FILTER_OP_LT_DOUBLE
:
818 case FILTER_OP_GE_DOUBLE
:
819 case FILTER_OP_LE_DOUBLE
:
820 case FILTER_OP_EQ_DOUBLE_S64
:
821 case FILTER_OP_NE_DOUBLE_S64
:
822 case FILTER_OP_GT_DOUBLE_S64
:
823 case FILTER_OP_LT_DOUBLE_S64
:
824 case FILTER_OP_GE_DOUBLE_S64
:
825 case FILTER_OP_LE_DOUBLE_S64
:
826 case FILTER_OP_EQ_S64_DOUBLE
:
827 case FILTER_OP_NE_S64_DOUBLE
:
828 case FILTER_OP_GT_S64_DOUBLE
:
829 case FILTER_OP_LT_S64_DOUBLE
:
830 case FILTER_OP_GE_S64_DOUBLE
:
831 case FILTER_OP_LE_S64_DOUBLE
:
832 case FILTER_OP_UNARY_PLUS_DOUBLE
:
833 case FILTER_OP_UNARY_MINUS_DOUBLE
:
834 case FILTER_OP_UNARY_NOT_DOUBLE
:
835 case FILTER_OP_LOAD_FIELD_REF_DOUBLE
:
836 case FILTER_OP_GET_CONTEXT_REF_DOUBLE
:
837 case FILTER_OP_LOAD_DOUBLE
:
838 case FILTER_OP_CAST_DOUBLE_TO_S64
:
840 printk(KERN_WARNING
"unsupported bytecode op %u\n",
841 (unsigned int) *(filter_opcode_t
*) pc
);
852 case FILTER_OP_EQ_STRING
:
853 case FILTER_OP_NE_STRING
:
854 case FILTER_OP_GT_STRING
:
855 case FILTER_OP_LT_STRING
:
856 case FILTER_OP_GE_STRING
:
857 case FILTER_OP_LE_STRING
:
858 case FILTER_OP_EQ_S64
:
859 case FILTER_OP_NE_S64
:
860 case FILTER_OP_GT_S64
:
861 case FILTER_OP_LT_S64
:
862 case FILTER_OP_GE_S64
:
863 case FILTER_OP_LE_S64
:
866 if (vstack_pop(stack
)) {
870 if (!vstack_ax(stack
)) {
871 printk(KERN_WARNING
"Empty stack\n");
875 vstack_ax(stack
)->type
= REG_S64
;
876 next_pc
+= sizeof(struct binary_op
);
881 case FILTER_OP_UNARY_PLUS
:
882 case FILTER_OP_UNARY_MINUS
:
883 case FILTER_OP_UNARY_NOT
:
884 case FILTER_OP_UNARY_PLUS_S64
:
885 case FILTER_OP_UNARY_MINUS_S64
:
886 case FILTER_OP_UNARY_NOT_S64
:
889 if (!vstack_ax(stack
)) {
890 printk(KERN_WARNING
"Empty stack\n");
894 vstack_ax(stack
)->type
= REG_S64
;
895 next_pc
+= sizeof(struct unary_op
);
903 struct logical_op
*insn
= (struct logical_op
*) pc
;
906 /* Add merge point to table */
907 merge_ret
= merge_point_add_check(mp_table
,
908 insn
->skip_offset
, stack
);
913 /* Continue to next instruction */
914 /* Pop 1 when jump not taken */
915 if (vstack_pop(stack
)) {
919 next_pc
+= sizeof(struct logical_op
);
924 case FILTER_OP_LOAD_FIELD_REF
:
926 printk(KERN_WARNING
"Unknown field ref type\n");
930 /* get context ref */
931 case FILTER_OP_GET_CONTEXT_REF
:
933 printk(KERN_WARNING
"Unknown get context ref type\n");
937 case FILTER_OP_LOAD_FIELD_REF_STRING
:
938 case FILTER_OP_LOAD_FIELD_REF_SEQUENCE
:
939 case FILTER_OP_GET_CONTEXT_REF_STRING
:
940 case FILTER_OP_LOAD_FIELD_REF_USER_STRING
:
941 case FILTER_OP_LOAD_FIELD_REF_USER_SEQUENCE
:
943 if (vstack_push(stack
)) {
947 vstack_ax(stack
)->type
= REG_STRING
;
948 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
951 case FILTER_OP_LOAD_FIELD_REF_S64
:
952 case FILTER_OP_GET_CONTEXT_REF_S64
:
954 if (vstack_push(stack
)) {
958 vstack_ax(stack
)->type
= REG_S64
;
959 next_pc
+= sizeof(struct load_op
) + sizeof(struct field_ref
);
963 /* load from immediate operand */
964 case FILTER_OP_LOAD_STRING
:
966 struct load_op
*insn
= (struct load_op
*) pc
;
968 if (vstack_push(stack
)) {
972 vstack_ax(stack
)->type
= REG_STRING
;
973 next_pc
+= sizeof(struct load_op
) + strlen(insn
->data
) + 1;
977 case FILTER_OP_LOAD_S64
:
979 if (vstack_push(stack
)) {
983 vstack_ax(stack
)->type
= REG_S64
;
984 next_pc
+= sizeof(struct load_op
)
985 + sizeof(struct literal_numeric
);
989 case FILTER_OP_CAST_TO_S64
:
992 if (!vstack_ax(stack
)) {
993 printk(KERN_WARNING
"Empty stack\n");
997 vstack_ax(stack
)->type
= REG_S64
;
998 next_pc
+= sizeof(struct cast_op
);
1001 case FILTER_OP_CAST_NOP
:
1003 next_pc
+= sizeof(struct cast_op
);
1009 *_next_pc
= next_pc
;
1014 * Never called concurrently (hash seed is shared).
1016 int lttng_filter_validate_bytecode(struct bytecode_runtime
*bytecode
)
1018 struct mp_table
*mp_table
;
1019 void *pc
, *next_pc
, *start_pc
;
1021 struct vstack stack
;
1023 vstack_init(&stack
);
1025 mp_table
= kzalloc(sizeof(*mp_table
), GFP_KERNEL
);
1027 printk(KERN_WARNING
"Error allocating hash table for bytecode validation\n");
1030 start_pc
= &bytecode
->data
[0];
1031 for (pc
= next_pc
= start_pc
; pc
- start_pc
< bytecode
->len
;
1033 ret
= bytecode_validate_overflow(bytecode
, start_pc
, pc
);
1036 printk(KERN_WARNING
"filter bytecode overflow\n");
1039 dbg_printk("Validating op %s (%u)\n",
1040 lttng_filter_print_op((unsigned int) *(filter_opcode_t
*) pc
),
1041 (unsigned int) *(filter_opcode_t
*) pc
);
1044 * For each instruction, validate the current context
1045 * (traversal of entire execution flow), and validate
1046 * all merge points targeting this instruction.
1048 ret
= validate_instruction_all_contexts(bytecode
, mp_table
,
1049 &stack
, start_pc
, pc
);
1052 ret
= exec_insn(bytecode
, mp_table
, &stack
, &next_pc
, pc
);
1057 if (delete_all_nodes(mp_table
)) {
1059 printk(KERN_WARNING
"Unexpected merge points\n");