From 615faa3620d52be5ead7b08436ea0167f9946ec3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 4 Dec 2018 10:36:24 +0300 Subject: [PATCH] statement_count: record how many statements there are in a function This is useful for Spectre stuff. With Spectre, the CPU can speculate a certain number of operations in advance. Smatch doesn't work at the level of operations, so I am using statements instead as a rough stand in for operations. Signed-off-by: Dan Carpenter --- Makefile | 3 +- check_list.h | 1 + smatch.h | 1 + smatch_data/db/fixup_kernel.sh | 1 + smatch_statement_count.c | 88 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 smatch_statement_count.c diff --git a/Makefile b/Makefile index fe3af882..d77fd2b2 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,8 @@ SMATCH_FILES=smatch_flow.o smatch_conditions.o smatch_slist.o smatch_states.o \ smatch_fn_arg_link.o smatch_about_fn_ptr_arg.o smatch_mtag.o \ smatch_mtag_map.o smatch_mtag_data.o \ smatch_param_to_mtag_data.o smatch_mem_tracker.o smatch_array_values.o \ - smatch_nul_terminator.o smatch_assigned_expr.o smatch_kernel_user_data.o + smatch_nul_terminator.o smatch_assigned_expr.o smatch_kernel_user_data.o \ + smatch_statement_count.o SMATCH_CHECKS=$(shell ls check_*.c | sed -e 's/\.c/.o/') SMATCH_DATA=smatch_data/kernel.allocation_funcs \ diff --git a/check_list.h b/check_list.h index 055e6304..ce2fa45b 100644 --- a/check_list.h +++ b/check_list.h @@ -69,6 +69,7 @@ CK(register_param_to_mtag_data) CK(register_array_values) CK(register_nul_terminator) CK(register_nul_terminator_param_set) +CK(register_statement_count) CK(register_kernel_user_data2) CK(register_kernel_user_data3) diff --git a/smatch.h b/smatch.h index 61c83e4c..e4606aa7 100644 --- a/smatch.h +++ b/smatch.h @@ -751,6 +751,7 @@ enum info_type { CONSTRAINT_REQUIRED = 1033, NOSPEC = 1035, NOSPEC_WB = 1036, + STMT_CNT = 1037, TERMINATED = 1038, /* put random temporary stuff in the 7000-7999 range for testing */ diff --git a/smatch_data/db/fixup_kernel.sh b/smatch_data/db/fixup_kernel.sh index 0eaf7b95..0a323cf3 100755 --- a/smatch_data/db/fixup_kernel.sh +++ b/smatch_data/db/fixup_kernel.sh @@ -91,6 +91,7 @@ insert into return_states values ('faked', '__kmalloc', 0, 1, '16', 0, 0, -1 insert into return_states values ('faked', '__kmalloc', 0, 1, '16', 0, 103, 0, '\$', '0'); insert into return_states values ('faked', '__kmalloc', 0, 2, '0,500000000-577777777', 0, 0, -1, '', ''); insert into return_states values ('faked', '__kmalloc', 0, 2, '0,500000000-577777777', 0, 103, 0, '\$', '1-4000000'); +insert into return_states values ('faked', '__kmalloc', 0, 2, '0,500000000-577777777', 0, 1037, -1, '', 400); insert into return_states values ('faked', '__kmalloc', 0, 3, '0', 0, 0, -1, '', ''); insert into return_states values ('faked', '__kmalloc', 0, 3, '0', 0, 103, 0, '\$', '4000000-long_max'); diff --git a/smatch_statement_count.c b/smatch_statement_count.c new file mode 100644 index 00000000..1bc63834 --- /dev/null +++ b/smatch_statement_count.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2018 Oracle. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt + */ + +#include +#include "parse.h" +#include "smatch.h" +#include "smatch_slist.h" +#include "smatch_extra.h" + +static int my_id; + +static struct smatch_state *merge_states(struct smatch_state *s1, struct smatch_state *s2) +{ + int left, right, min; + + left = PTR_INT(s1->data); + right = PTR_INT(s2->data); + + min = left; + if (right < min) + min = right; + return alloc_state_num(min); +} + +long get_stmt_cnt(void) +{ + struct smatch_state *state; + + state = get_state(my_id, "stmts", NULL); + if (!state) + return 0; + return (long)state->data; +} + +static void match_statement(struct statement *stmt) +{ + int cnt; + + cnt = get_stmt_cnt(); + cnt++; + set_state(my_id, "stmts", NULL, alloc_state_num(cnt)); +} + +static void insert_return_info(int return_id, char *return_ranges, struct expression *expr) +{ + char buf[32]; + int cnt; + + cnt = get_stmt_cnt(); + snprintf(buf, sizeof(buf), "%d", cnt); + sql_insert_return_states(return_id, return_ranges, STMT_CNT, -1, "", buf); +} + +static void select_return_info(struct expression *expr, int param, char *key, char *value) +{ + int cnt, add; + + cnt = get_stmt_cnt(); + add = atoi(value); + + set_state(my_id, "stmts", NULL, alloc_state_num(cnt + add)); +} + +void register_statement_count(int id) +{ + my_id = id; + + add_hook(match_statement, STMT_HOOK); + add_merge_hook(my_id, &merge_states); + + add_split_return_callback(&insert_return_info); + select_return_states_hook(STMT_CNT, &select_return_info); +} + -- 2.11.4.GIT