ranges: commit range_lists_equiv() so that bool_implications compiles...
[smatch.git] / smatch_db.c
blob31dfdae2fec734b3e800a5d2d7a5e09df58c399a
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 struct member_info_callback {
28 int owner;
29 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state);
31 ALLOCATOR(member_info_callback, "caller_info callbacks");
32 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
33 static struct member_info_cb_list *member_callbacks;
35 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
37 char *err = NULL;
38 int rc;
40 if (option_no_db || !db)
41 return;
43 rc = sqlite3_exec(db, sql, callback, 0, &err);
44 if (rc != SQLITE_OK)
45 fprintf(stderr, "SQL error #2: %s\n", err);
48 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
50 struct def_callback *def_callback = __alloc_def_callback(0);
52 def_callback->hook_type = type;
53 def_callback->callback = callback;
54 add_ptr_list(&callbacks, def_callback);
57 void add_member_info_callback(int owner, void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
59 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
61 member_callback->owner = owner;
62 member_callback->callback = callback;
63 add_ptr_list(&member_callbacks, member_callback);
66 static struct range_list *return_range_list;
67 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
69 struct range_list *rl = NULL;
71 if (argc != 1)
72 return 0;
74 get_value_ranges(argv[0], &rl);
75 return_range_list = range_list_union(return_range_list, rl);
77 return 0;
80 struct range_list *db_return_vals(struct expression *expr)
82 struct symbol *sym;
83 static char sql_filter[1024];
85 if (expr->type != EXPR_CALL)
86 return NULL;
87 if (expr->fn->type != EXPR_SYMBOL)
88 return NULL;
89 sym = expr->fn->symbol;
90 if (!sym)
91 return NULL;
93 if (sym->ctype.modifiers & MOD_STATIC) {
94 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
95 get_filename(), sym->ident->name);
96 } else {
97 snprintf(sql_filter, 1024, "function = '%s';", sym->ident->name);
100 return_range_list = NULL;
101 run_sql(db_return_callback, "select value from return_info where %s",
102 sql_filter);
103 return return_range_list;
106 static void match_call_hack(struct expression *expr)
108 char *name;
111 * we just want to record something in the database so that if we have
112 * two calls like: frob(4); frob(some_unkown); then on the recieving
113 * side we know that sometimes frob is called with unknown parameters.
116 name = get_fnptr_name(expr->fn);
117 if (!name)
118 return;
119 if (ptr_list_empty(expr->args))
120 return;
121 sm_msg("info: passes param_value '%s' -1 '$$' min-max", name);
122 free_string(name);
125 static void print_struct_members(char *fn, struct expression *expr, int param, struct state_list *slist,
126 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
128 struct sm_state *sm;
129 char *name;
130 struct symbol *sym;
131 int len;
132 char printed_name[256];
133 int is_address = 0;
135 expr = strip_expr(expr);
136 if (expr->type == EXPR_PREOP && expr->op == '&') {
137 expr = strip_expr(expr->unop);
138 is_address = 1;
141 name = get_variable_from_expr(expr, &sym);
142 if (!name || !sym)
143 goto free;
145 len = strlen(name);
146 FOR_EACH_PTR(slist, sm) {
147 if (sm->sym != sym)
148 continue;
149 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
150 continue;
151 if (is_address)
152 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
153 else
154 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
155 callback(fn, param, printed_name, sm->state);
156 } END_FOR_EACH_PTR(sm);
157 free:
158 free_string(name);
161 static void match_call_info(struct expression *expr)
163 struct member_info_callback *cb;
164 struct expression *arg;
165 struct state_list *slist;
166 char *name;
167 int i;
169 name = get_fnptr_name(expr->fn);
170 if (!name)
171 return;
173 FOR_EACH_PTR(member_callbacks, cb) {
174 slist = get_all_states(cb->owner);
175 i = 0;
176 FOR_EACH_PTR(expr->args, arg) {
177 print_struct_members(name, arg, i, slist, cb->callback);
178 i++;
179 } END_FOR_EACH_PTR(arg);
180 } END_FOR_EACH_PTR(cb);
182 free_string(name);
183 free_slist(&slist);
186 static int get_param(int param, char **name, struct symbol **sym)
188 struct symbol *arg;
189 int i;
191 i = 0;
192 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
194 * this is a temporary hack to work around a bug (I think in sparse?)
195 * 2.6.37-rc1:fs/reiserfs/journal.o
196 * If there is a function definition without parameter name found
197 * after a function implementation then it causes a crash.
198 * int foo() {}
199 * int bar(char *);
201 if (arg->ident->name < (char *)100)
202 continue;
203 if (i == param && arg->ident->name) {
204 *name = arg->ident->name;
205 *sym = arg;
206 return TRUE;
208 i++;
209 } END_FOR_EACH_PTR(arg);
211 return FALSE;
214 static struct state_list *final_states;
215 static int prev_func_id = -1;
216 static int db_callback(void *unused, int argc, char **argv, char **azColName)
218 int func_id;
219 long type;
220 long param;
221 char *name;
222 struct symbol *sym;
223 struct def_callback *def_callback;
225 if (argc != 5)
226 return 0;
228 func_id = atoi(argv[0]);
229 errno = 0;
230 type = strtol(argv[1], NULL, 10);
231 param = strtol(argv[2], NULL, 10);
232 if (errno)
233 return 0;
235 if (prev_func_id == -1)
236 prev_func_id = func_id;
237 if (func_id != prev_func_id) {
238 merge_slist(&final_states, __pop_fake_cur_slist());
239 __push_fake_cur_slist();
240 __unnullify_path();
241 prev_func_id = func_id;
244 if (param == -1 || !get_param(param, &name, &sym))
245 return 0;
247 FOR_EACH_PTR(callbacks, def_callback) {
248 if (def_callback->hook_type == type)
249 def_callback->callback(name, sym, argv[3], argv[4]);
250 } END_FOR_EACH_PTR(def_callback);
252 return 0;
255 static void get_direct_callers(struct symbol *sym)
257 char sql_filter[1024];
259 if (sym->ctype.modifiers & MOD_STATIC) {
260 snprintf(sql_filter, 1024,
261 "file = '%s' and function = '%s' order by function_id;",
262 get_filename(), sym->ident->name);
263 } else {
264 snprintf(sql_filter, 1024,
265 "function = '%s' order by function_id;",
266 sym->ident->name);
269 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
270 " where %s", sql_filter);
273 static char *ptr_name;
274 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
276 if (!ptr_name)
277 ptr_name = alloc_string(argv[0]);
278 return 0;
281 static void get_function_pointer_callers(struct symbol *sym)
283 ptr_name = NULL;
284 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
285 sym->ident->name);
286 if (!ptr_name)
287 return;
289 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
290 " where function = '%s' order by function_id", ptr_name);
293 static void match_data_from_db(struct symbol *sym)
295 struct sm_state *sm;
297 if (!sym || !sym->ident || !sym->ident->name)
298 return;
300 __push_fake_cur_slist();
301 __unnullify_path();
302 prev_func_id = -1;
304 get_direct_callers(sym);
305 get_function_pointer_callers(sym);
307 merge_slist(&final_states, __pop_fake_cur_slist());
309 FOR_EACH_PTR(final_states, sm) {
310 __set_sm(sm);
311 } END_FOR_EACH_PTR(sm);
313 free_slist(&final_states);
316 static void match_function_assign(struct expression *expr)
318 struct expression *right = expr->right;
319 struct symbol *sym;
320 char *fn_name;
321 char *ptr_name;
323 if (right->type == EXPR_PREOP && right->op == '&')
324 right = right->unop;
325 if (right->type != EXPR_SYMBOL)
326 return;
327 sym = get_type(right);
328 if (!sym || sym->type != SYM_FN)
329 return;
331 fn_name = get_variable_from_expr(right, NULL);
332 ptr_name = get_fnptr_name(expr->left);
333 if (!fn_name || !ptr_name)
334 goto free;
336 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
338 free:
339 free_string(fn_name);
340 free_string(ptr_name);
343 static void print_initializer_list(struct expression_list *expr_list,
344 struct symbol *struct_type)
346 struct expression *expr;
347 struct symbol *base_type;
349 FOR_EACH_PTR(expr_list, expr) {
350 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
351 print_initializer_list(expr->idx_expression->expr_list, struct_type);
352 continue;
354 if (expr->type != EXPR_IDENTIFIER)
355 continue;
356 if (!expr->expr_ident)
357 continue;
358 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
359 continue;
360 base_type = get_type(expr->ident_expression);
361 if (!base_type || base_type->type != SYM_FN)
362 continue;
363 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
364 expr->expr_ident->name,
365 expr->ident_expression->symbol_name->name);
366 } END_FOR_EACH_PTR(expr);
370 static void global_variable(struct symbol *sym)
372 struct symbol *struct_type;
374 if (!sym->ident)
375 return;
376 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
377 return;
378 struct_type = get_base_type(sym);
379 if (!struct_type)
380 return;
381 if (struct_type->type == SYM_ARRAY) {
382 struct_type = get_base_type(struct_type);
383 if (!struct_type)
384 return;
386 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
387 return;
388 print_initializer_list(sym->initializer->expr_list, struct_type);
391 void open_smatch_db(void)
393 #ifdef SQLITE_OPEN_READONLY
394 int rc;
396 if (option_no_db)
397 return;
399 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
400 if (rc != SQLITE_OK) {
401 option_no_db = 1;
402 return;
404 return;
405 #else
406 option_no_db = 1;
407 return;
408 #endif
411 void register_definition_db_callbacks(int id)
413 if (option_info) {
414 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
415 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
416 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
417 add_hook(&global_variable, BASE_HOOK);
418 add_hook(&global_variable, DECLARATION_HOOK);
421 if (option_no_db)
422 return;
424 add_hook(&match_data_from_db, FUNC_DEF_HOOK);