extra, db: record a dummy output for every function call
[smatch.git] / smatch_db.c
blob7625d4f065f5ba683d733555d5bcbc5266896e19
1 /*
2 * smatch/smatch_db.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <string.h>
11 #include <errno.h>
12 #include <sqlite3.h>
13 #include "smatch.h"
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
17 static sqlite3 *db;
19 struct def_callback {
20 int hook_type;
21 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
23 ALLOCATOR(def_callback, "definition db hook callbacks");
24 DECLARE_PTR_LIST(callback_list, struct def_callback);
25 static struct callback_list *callbacks;
27 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
29 char *err = NULL;
30 int rc;
32 if (option_no_db || !db)
33 return;
35 rc = sqlite3_exec(db, sql, callback, 0, &err);
36 if (rc != SQLITE_OK) {
37 fprintf(stderr, "SQL error #2: %s\n", err);
38 exit(1);
42 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
44 struct def_callback *def_callback = __alloc_def_callback(0);
46 def_callback->hook_type = type;
47 def_callback->callback = callback;
48 add_ptr_list(&callbacks, def_callback);
51 static void match_call_hack(struct expression *expr)
53 char *name;
56 * we just want to record something in the database so that if we have
57 * two calls like: frob(4); frob(some_unkown); then on the recieving
58 * side we know that sometimes frob is called with unknown parameters.
61 name = get_fnptr_name(expr->fn);
62 if (!name)
63 return;
64 if (ptr_list_empty(expr->args))
65 return;
66 sm_msg("info: passes param_value '%s' -1 '$$' min-max", name);
67 free_string(name);
70 static unsigned long call_count;
71 static int db_count_callback(void *unused, int argc, char **argv, char **azColName)
73 call_count = strtoul(argv[0], NULL, 10);
74 return 0;
77 static int get_param(int param, char **name, struct symbol **sym)
79 struct symbol *arg;
80 int i;
82 i = 0;
83 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
85 * this is a temporary hack to work around a bug (I think in sparse?)
86 * 2.6.37-rc1:fs/reiserfs/journal.o
87 * If there is a function definition without parameter name found
88 * after a function implementation then it causes a crash.
89 * int foo() {}
90 * int bar(char *);
92 if (arg->ident->name < (char *)100)
93 continue;
94 if (i == param && arg->ident->name) {
95 *name = arg->ident->name;
96 *sym = arg;
97 return TRUE;
99 i++;
100 } END_FOR_EACH_PTR(arg);
102 return FALSE;
105 static struct state_list *final_states;
106 static int prev_func_id = -1;
107 static int db_callback(void *unused, int argc, char **argv, char **azColName)
109 int func_id;
110 long type;
111 long param;
112 char *name;
113 struct symbol *sym;
114 struct def_callback *def_callback;
116 if (argc != 5)
117 return 0;
119 func_id = atoi(argv[0]);
120 errno = 0;
121 type = strtol(argv[1], NULL, 10);
122 param = strtol(argv[2], NULL, 10);
123 if (errno)
124 return 0;
126 if (prev_func_id == -1)
127 prev_func_id = func_id;
128 if (func_id != prev_func_id) {
129 merge_slist(&final_states, __pop_fake_cur_slist());
130 __push_fake_cur_slist();
131 prev_func_id = func_id;
134 if (param == -1 || !get_param(param, &name, &sym))
135 return 0;
137 FOR_EACH_PTR(callbacks, def_callback) {
138 if (def_callback->hook_type == type)
139 def_callback->callback(name, sym, argv[3], argv[4]);
140 } END_FOR_EACH_PTR(def_callback);
142 return 0;
145 static void get_direct_callers(struct symbol *sym)
147 char sql_filter[1024];
149 if (sym->ctype.modifiers & MOD_STATIC) {
150 snprintf(sql_filter, 1024,
151 "file = '%s' and function = '%s' order by function_id;",
152 get_filename(), sym->ident->name);
153 } else {
154 snprintf(sql_filter, 1024,
155 "function = '%s' order by function_id;",
156 sym->ident->name);
159 call_count = 0;
160 run_sql(db_count_callback, "select count(*) from caller_info where %s",
161 sql_filter);
162 if (call_count == 0 || call_count > 100)
163 return;
165 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
166 " where %s", sql_filter);
169 static char *ptr_name;
170 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
172 if (!ptr_name)
173 ptr_name = alloc_string(argv[0]);
174 return 0;
177 static void get_function_pointer_callers(struct symbol *sym)
179 ptr_name = NULL;
180 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
181 sym->ident->name);
182 if (!ptr_name)
183 return;
185 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
186 " where function = '%s' order by function_id", ptr_name);
189 static void match_data_from_db(struct symbol *sym)
191 struct sm_state *sm;
193 if (!sym || !sym->ident || !sym->ident->name)
194 return;
196 __push_fake_cur_slist();
197 prev_func_id = -1;
199 get_direct_callers(sym);
200 get_function_pointer_callers(sym);
202 merge_slist(&final_states, __pop_fake_cur_slist());
204 FOR_EACH_PTR(final_states, sm) {
205 __set_sm(sm);
206 } END_FOR_EACH_PTR(sm);
208 free_slist(&final_states);
211 static void match_function_assign(struct expression *expr)
213 struct expression *right = expr->right;
214 struct symbol *sym;
215 char *fn_name;
216 char *ptr_name;
218 if (right->type == EXPR_PREOP && right->op == '&')
219 right = right->unop;
220 if (right->type != EXPR_SYMBOL)
221 return;
222 sym = get_type(right);
223 if (!sym || sym->type != SYM_FN)
224 return;
226 fn_name = get_variable_from_expr(right, NULL);
227 ptr_name = get_fnptr_name(expr->left);
228 if (!fn_name || !ptr_name)
229 goto free;
231 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
233 free:
234 free_string(fn_name);
235 free_string(ptr_name);
238 static void global_variable(struct symbol *sym)
240 struct symbol *struct_type;
241 struct symbol *base_type;
242 struct expression *expr;
244 if (!sym->ident)
245 return;
246 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
247 return;
248 struct_type = get_base_type(sym);
249 if (!struct_type || struct_type->type != SYM_STRUCT ||
250 !struct_type->ident)
251 return;
253 FOR_EACH_PTR(sym->initializer->expr_list, expr) {
254 if (expr->type != EXPR_IDENTIFIER)
255 continue;
256 if (!expr->expr_ident)
257 continue;
258 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
259 continue;
260 base_type = get_type(expr->ident_expression);
261 if (!base_type || base_type->type != SYM_FN)
262 continue;
263 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
264 expr->expr_ident->name,
265 expr->ident_expression->symbol_name->name);
266 } END_FOR_EACH_PTR(expr);
269 void open_smatch_db(void)
271 #ifdef SQLITE_OPEN_READONLY
272 int rc;
274 if (option_no_db)
275 return;
277 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
278 if (rc != SQLITE_OK) {
279 option_no_db = 1;
280 return;
282 return;
283 #else
284 option_no_db = 1;
285 return;
286 #endif
289 void register_definition_db_callbacks(int id)
291 if (option_info) {
292 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
293 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
294 add_hook(&global_variable, BASE_HOOK);
295 add_hook(&global_variable, DECLARATION_HOOK);
298 if (option_no_db)
299 return;
301 add_hook(&match_data_from_db, FUNC_DEF_HOOK);