db: get return states from function pointers if possible
authorDan Carpenter <dan.carpenter@oracle.com>
Tue, 27 May 2014 12:32:02 +0000 (27 15:32 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Tue, 27 May 2014 12:32:02 +0000 (27 15:32 +0300)
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 <dan.carpenter@oracle.com>
smatch_data/db/create_db.sh
smatch_data/db/function_ptr.idx
smatch_data/db/function_ptr.schema
smatch_data/db/mark_function_ptrs_searchable.pl [new file with mode: 0755]
smatch_db.c
smatch_function_hooks.c

index ae1c5bf..ca6fcda 100755 (executable)
@@ -34,3 +34,5 @@ for i in ${bin_dir}/*.idx ; do
     cat $i | sqlite3 $db_file
 done
 
+${bin_dir}/mark_function_ptrs_searchable.pl
+
index eedc2e5..e57536b 100644 (file)
@@ -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);
index 46bb9b9..20227b2 100644 (file)
@@ -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 (executable)
index 0000000..c89b827
--- /dev/null
@@ -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();
index 5c27a13..ec06daf 100644 (file)
@@ -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);
 }
 
index b697fc9..792b16b 100644 (file)
@@ -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);
 }