From cdbfdb56b417c388d3478cf7dfef421a3726f207 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 27 May 2014 15:32:02 +0300 Subject: [PATCH] db: get return states from function pointers if possible Sometimes if we call ->foo(a, b, c); and we know which functions implement ->foo() and it doesn't slow anything down to look up the return states then we should do that. Signed-off-by: Dan Carpenter --- smatch_data/db/create_db.sh | 2 + smatch_data/db/function_ptr.idx | 1 + smatch_data/db/function_ptr.schema | 2 +- smatch_data/db/mark_function_ptrs_searchable.pl | 50 +++++++++++++++++++++++++ smatch_db.c | 14 ++----- smatch_function_hooks.c | 37 ++++++++---------- 6 files changed, 73 insertions(+), 33 deletions(-) create mode 100755 smatch_data/db/mark_function_ptrs_searchable.pl diff --git a/smatch_data/db/create_db.sh b/smatch_data/db/create_db.sh index ae1c5bf1..ca6fcda0 100755 --- a/smatch_data/db/create_db.sh +++ b/smatch_data/db/create_db.sh @@ -34,3 +34,5 @@ for i in ${bin_dir}/*.idx ; do cat $i | sqlite3 $db_file done +${bin_dir}/mark_function_ptrs_searchable.pl + diff --git a/smatch_data/db/function_ptr.idx b/smatch_data/db/function_ptr.idx index eedc2e5e..e57536b8 100644 --- a/smatch_data/db/function_ptr.idx +++ b/smatch_data/db/function_ptr.idx @@ -1,2 +1,3 @@ CREATE INDEX fn_ptr_idx_file on function_ptr (file, function); CREATE INDEX fn_ptr_idx_nofile on function_ptr (function); +CREATE INDEX fn_ptr_idx_ptr on function_ptr (ptr); diff --git a/smatch_data/db/function_ptr.schema b/smatch_data/db/function_ptr.schema index 46bb9b9c..20227b24 100644 --- a/smatch_data/db/function_ptr.schema +++ b/smatch_data/db/function_ptr.schema @@ -1 +1 @@ -CREATE TABLE function_ptr (file varchar(128), function varchar(64), ptr varchar(256)); +CREATE TABLE function_ptr (file varchar(128), function varchar(64), ptr varchar(256), searchable integer); diff --git a/smatch_data/db/mark_function_ptrs_searchable.pl b/smatch_data/db/mark_function_ptrs_searchable.pl new file mode 100755 index 00000000..c89b8270 --- /dev/null +++ b/smatch_data/db/mark_function_ptrs_searchable.pl @@ -0,0 +1,50 @@ +#!/usr/bin/perl -w + +use strict; +use warnings; +use bigint; +use DBI; +use Data::Dumper; + +my $db = DBI->connect("dbi:SQLite:smatch_db.sqlite", "", "", {AutoCommit => 0}); + +$db->do("PRAGMA synchronous = OFF"); +$db->do("PRAGMA cache_size = 800000"); +$db->do("PRAGMA journal_mode = OFF"); +$db->do("PRAGMA count_changes = OFF"); +$db->do("PRAGMA temp_store = MEMORY"); +$db->do("PRAGMA locking = EXCLUSIVE"); + +my ($update, $sth, $fn_ptr, $ptr_to_ptr, $count); + +$update = $db->prepare_cached('UPDATE function_ptr set searchable = 1 where ptr = ?'); +$sth = $db->prepare('select distinct(ptr) from function_ptr;'); +$sth->execute(); + +while ($fn_ptr = $sth->fetchrow_array()) { + + # following a pointer to pointer chain is too complicated for now + $ptr_to_ptr = $db->selectrow_array("select function from function_ptr where ptr = '$fn_ptr' and function like '% %';"); + if ($ptr_to_ptr) { + next; + } + $ptr_to_ptr = $db->selectrow_array("select function from function_ptr where ptr = '$fn_ptr' and function like '%[]';"); + if ($ptr_to_ptr) { + next; + } + + $count = $db->selectrow_array("select count(*) from return_states join function_ptr where return_states.function == function_ptr.function and ptr = '$fn_ptr';"); + # if there are too many states then bail + if ($count > 1000) { + next; + } + # if there are no states at all then don't bother recording + if ($count == 0) { + next; + } + + $update->execute($fn_ptr); +} + +$db->commit(); +$db->disconnect(); diff --git a/smatch_db.c b/smatch_db.c index 5c27a132..ec06dafd 100644 --- a/smatch_db.c +++ b/smatch_db.c @@ -267,22 +267,14 @@ static void sql_select_return_states_pointer(const char *cols, { char *ptr; - ptr = get_fnptr_name(call); + ptr = get_fnptr_name(call->fn); if (!ptr) return; - row_count = 0; - run_sql(get_row_count, - "select count(*) from return_states join function_ptr where " - "return_states.function == function_ptr.function and ptr = '%s';", - ptr); - if (row_count > 1000) - return; - run_sql(callback, "select %s from return_states join function_ptr where " - "return_states.function == function_ptr.function and ptr = '%s' " - "order by return_id, type;", + "return_states.function == function_ptr.function and ptr = '%s'" + "and searchable = 1 order by return_id, type;", cols, ptr); } diff --git a/smatch_function_hooks.c b/smatch_function_hooks.c index b697fc92..792b16b9 100644 --- a/smatch_function_hooks.c +++ b/smatch_function_hooks.c @@ -393,9 +393,6 @@ void compare_db_return_states_callbacks(int comparison, struct expression *expr, struct stree *false_states; struct sm_state *sm; - if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol) - return; - db_info.comparison = comparison; db_info.expr = expr; db_info.rl = alloc_rl(sval, sval); @@ -488,8 +485,6 @@ static int db_return_states_assign(struct expression *expr) int handled = 0; right = strip_expr(expr->right); - if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol) - return 0; prev_return_id = -1; db_info.expr = expr; @@ -532,13 +527,16 @@ static void match_assign_call(struct expression *expr) const char *fn; struct expression *right; int handled = 0; + struct range_list *rl; if (expr->op != '=') return; right = strip_expr(expr->right); if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol) { - set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left))); + handled |= db_return_states_assign(expr); + if (!handled) + goto assigned_unknown; return; } if (is_fake_call(right)) { @@ -562,14 +560,13 @@ static void match_assign_call(struct expression *expr) handled |= assign_ranged_funcs(fn, expr, call_backs); handled |= handle_implied_return(expr); - if (!handled) { - struct range_list *rl; + if (handled) + return; - if (!get_implied_rl(expr->right, &rl)) - rl = alloc_whole_rl(get_type(expr->right)); - rl = cast_rl(get_type(expr->left), rl); - set_extra_expr_mod(expr->left, alloc_estate_rl(rl)); - } +assigned_unknown: + get_absolute_rl(expr->right, &rl); + rl = cast_rl(get_type(expr->left), rl); + set_extra_expr_mod(expr->left, alloc_estate_rl(rl)); } static int db_return_states_callback(void *unused, int argc, char **argv, char **azColName) @@ -614,8 +611,6 @@ static void db_return_states(struct expression *expr) struct sm_state *sm; struct stree *stree; - if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol) - return; if (!__get_cur_stree()) /* no return functions */ return; @@ -665,12 +660,12 @@ static void match_function_call(struct expression *expr) { struct call_back_list *call_backs; - if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol) - return; - call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name); - if (call_backs) - call_call_backs(call_backs, REGULAR_CALL, - expr->fn->symbol->ident->name, expr); + if (expr->fn->type == EXPR_SYMBOL && expr->fn->symbol) { + call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name); + if (call_backs) + call_call_backs(call_backs, REGULAR_CALL, + expr->fn->symbol->ident->name, expr); + } db_return_states_call(expr); } -- 2.11.4.GIT