Merge git://git.kernel.org/pub/scm/devel/sparse/sparse into merge
[smatch.git] / smatch_db.c
blob8a72b00fb57aa90cb9e270b9dc8bd5fc389dfeeb
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, char *global_static, 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 struct call_implies_callback {
36 int type;
37 void (*callback)(struct expression *arg, char *value);
39 ALLOCATOR(call_implies_callback, "call_implies callbacks");
40 DECLARE_PTR_LIST(call_implies_cb_list, struct call_implies_callback);
41 static struct call_implies_cb_list *call_implies_cb_list;
43 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
45 char *err = NULL;
46 int rc;
48 if (option_no_db || !db)
49 return;
51 rc = sqlite3_exec(db, sql, callback, 0, &err);
52 if (rc != SQLITE_OK)
53 fprintf(stderr, "SQL error #2: %s\n", err);
56 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
58 struct def_callback *def_callback = __alloc_def_callback(0);
60 def_callback->hook_type = type;
61 def_callback->callback = callback;
62 add_ptr_list(&callbacks, def_callback);
65 void add_member_info_callback(int owner, void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
67 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
69 member_callback->owner = owner;
70 member_callback->callback = callback;
71 add_ptr_list(&member_callbacks, member_callback);
74 void add_db_fn_call_callback(int type, void (*callback)(struct expression *arg, char *value))
76 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
78 cb->type = type;
79 cb->callback = callback;
80 add_ptr_list(&call_implies_cb_list, cb);
83 static struct range_list *return_range_list;
84 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
86 struct range_list *rl = NULL;
88 if (argc != 1)
89 return 0;
91 get_value_ranges(argv[0], &rl);
92 return_range_list = range_list_union(return_range_list, rl);
94 return 0;
97 struct range_list *db_return_vals(struct expression *expr)
99 struct symbol *sym;
100 static char sql_filter[1024];
102 if (expr->type != EXPR_CALL)
103 return NULL;
104 if (expr->fn->type != EXPR_SYMBOL)
105 return NULL;
106 sym = expr->fn->symbol;
107 if (!sym)
108 return NULL;
110 if (sym->ctype.modifiers & MOD_STATIC) {
111 snprintf(sql_filter, 1024, "file = '%s' and function = '%s' and type = %d;",
112 get_filename(), sym->ident->name, RETURN_VALUE);
113 } else {
114 snprintf(sql_filter, 1024, "function = '%s' and static = 0 and type = %d;",
115 sym->ident->name, RETURN_VALUE);
118 return_range_list = NULL;
119 run_sql(db_return_callback, "select value from return_info where %s",
120 sql_filter);
121 return return_range_list;
124 static void match_call_hack(struct expression *expr)
126 char *name;
129 * we just want to record something in the database so that if we have
130 * two calls like: frob(4); frob(some_unkown); then on the recieving
131 * side we know that sometimes frob is called with unknown parameters.
134 name = get_fnptr_name(expr->fn);
135 if (!name)
136 return;
137 if (ptr_list_empty(expr->args))
138 return;
139 sm_msg("info: passes param_value '%s' -1 '$$' min-max %s",
140 name, is_static(expr->fn) ? "static" : "global");
141 free_string(name);
144 static void print_struct_members(char *fn, char *global_static, struct expression *expr, int param, struct state_list *slist,
145 void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
147 struct sm_state *sm;
148 char *name;
149 struct symbol *sym;
150 int len;
151 char printed_name[256];
152 int is_address = 0;
154 expr = strip_expr(expr);
155 if (expr->type == EXPR_PREOP && expr->op == '&') {
156 expr = strip_expr(expr->unop);
157 is_address = 1;
160 name = get_variable_from_expr(expr, &sym);
161 if (!name || !sym)
162 goto free;
164 len = strlen(name);
165 FOR_EACH_PTR(slist, sm) {
166 if (sm->sym != sym)
167 continue;
168 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
169 continue;
170 if (is_address)
171 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
172 else
173 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
174 callback(fn, global_static, param, printed_name, sm->state);
175 } END_FOR_EACH_PTR(sm);
176 free:
177 free_string(name);
180 static void match_call_info(struct expression *expr)
182 struct member_info_callback *cb;
183 struct expression *arg;
184 struct state_list *slist;
185 char *name;
186 int i;
187 char *gs;
189 name = get_fnptr_name(expr->fn);
190 if (!name)
191 return;
193 if (is_static(expr->fn))
194 gs = (char *)"static";
195 else
196 gs = (char *)"global";
198 FOR_EACH_PTR(member_callbacks, cb) {
199 slist = get_all_states(cb->owner);
200 i = 0;
201 FOR_EACH_PTR(expr->args, arg) {
202 print_struct_members(name, gs, arg, i, slist, cb->callback);
203 i++;
204 } END_FOR_EACH_PTR(arg);
205 } END_FOR_EACH_PTR(cb);
207 free_string(name);
208 free_slist(&slist);
211 static int get_param(int param, char **name, struct symbol **sym)
213 struct symbol *arg;
214 int i;
216 i = 0;
217 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
219 * this is a temporary hack to work around a bug (I think in sparse?)
220 * 2.6.37-rc1:fs/reiserfs/journal.o
221 * If there is a function definition without parameter name found
222 * after a function implementation then it causes a crash.
223 * int foo() {}
224 * int bar(char *);
226 if (arg->ident->name < (char *)100)
227 continue;
228 if (i == param && arg->ident->name) {
229 *name = arg->ident->name;
230 *sym = arg;
231 return TRUE;
233 i++;
234 } END_FOR_EACH_PTR(arg);
236 return FALSE;
239 static struct state_list *final_states;
240 static int prev_func_id = -1;
241 static int db_callback(void *unused, int argc, char **argv, char **azColName)
243 int func_id;
244 long type;
245 long param;
246 char *name;
247 struct symbol *sym;
248 struct def_callback *def_callback;
250 if (argc != 5)
251 return 0;
253 func_id = atoi(argv[0]);
254 errno = 0;
255 type = strtol(argv[1], NULL, 10);
256 param = strtol(argv[2], NULL, 10);
257 if (errno)
258 return 0;
260 if (prev_func_id == -1)
261 prev_func_id = func_id;
262 if (func_id != prev_func_id) {
263 merge_slist(&final_states, __pop_fake_cur_slist());
264 __push_fake_cur_slist();
265 __unnullify_path();
266 prev_func_id = func_id;
269 if (param == -1 || !get_param(param, &name, &sym))
270 return 0;
272 FOR_EACH_PTR(callbacks, def_callback) {
273 if (def_callback->hook_type == type)
274 def_callback->callback(name, sym, argv[3], argv[4]);
275 } END_FOR_EACH_PTR(def_callback);
277 return 0;
280 static void get_direct_callers(struct symbol *sym)
282 char sql_filter[1024];
284 if (sym->ctype.modifiers & MOD_STATIC) {
285 snprintf(sql_filter, 1024,
286 "file = '%s' and function = '%s' order by function_id;",
287 get_filename(), sym->ident->name);
288 } else {
289 snprintf(sql_filter, 1024,
290 "function = '%s' and static = 0 order by function_id;",
291 sym->ident->name);
294 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
295 " where %s", sql_filter);
298 static char *ptr_name;
299 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
301 if (!ptr_name)
302 ptr_name = alloc_string(argv[0]);
303 return 0;
306 static void get_function_pointer_callers(struct symbol *sym)
308 ptr_name = NULL;
309 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
310 sym->ident->name);
311 if (!ptr_name)
312 return;
314 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
315 " where function = '%s' order by function_id", ptr_name);
318 static void match_data_from_db(struct symbol *sym)
320 struct sm_state *sm;
322 if (!sym || !sym->ident || !sym->ident->name)
323 return;
325 __push_fake_cur_slist();
326 __unnullify_path();
327 prev_func_id = -1;
329 get_direct_callers(sym);
330 get_function_pointer_callers(sym);
332 merge_slist(&final_states, __pop_fake_cur_slist());
334 FOR_EACH_PTR(final_states, sm) {
335 __set_sm(sm);
336 } END_FOR_EACH_PTR(sm);
338 free_slist(&final_states);
341 static void match_function_assign(struct expression *expr)
343 struct expression *right = expr->right;
344 struct symbol *sym;
345 char *fn_name;
346 char *ptr_name;
348 if (right->type == EXPR_PREOP && right->op == '&')
349 right = right->unop;
350 if (right->type != EXPR_SYMBOL)
351 return;
352 sym = get_type(right);
353 if (!sym || sym->type != SYM_FN)
354 return;
356 fn_name = get_variable_from_expr(right, NULL);
357 ptr_name = get_fnptr_name(expr->left);
358 if (!fn_name || !ptr_name)
359 goto free;
361 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
363 free:
364 free_string(fn_name);
365 free_string(ptr_name);
368 static struct expression *call_implies_call_expr;
369 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
371 struct call_implies_callback *cb;
372 struct expression *arg;
373 int type;
374 int param;
376 if (argc != 4)
377 return 0;
379 type = atoi(argv[1]);
380 param = atoi(argv[2]);
382 FOR_EACH_PTR(call_implies_cb_list, cb) {
383 if (cb->type != type)
384 continue;
385 arg = get_argument_from_call_expr(call_implies_call_expr->args, param);
386 if (!arg)
387 continue;
388 cb->callback(arg, argv[3]);
389 } END_FOR_EACH_PTR(cb);
391 return 0;
394 static void match_call_implies(struct expression *expr)
396 struct symbol *sym;
397 static char sql_filter[1024];
399 if (expr->fn->type != EXPR_SYMBOL)
400 return;
401 sym = expr->fn->symbol;
402 if (!sym)
403 return;
405 if (sym->ctype.modifiers & MOD_STATIC) {
406 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
407 get_filename(), sym->ident->name);
408 } else {
409 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
410 sym->ident->name);
413 call_implies_call_expr = expr;
414 run_sql(call_implies_callbacks,
415 "select function, type, parameter, value from call_implies where %s",
416 sql_filter);
417 return;
420 static void print_initializer_list(struct expression_list *expr_list,
421 struct symbol *struct_type)
423 struct expression *expr;
424 struct symbol *base_type;
426 FOR_EACH_PTR(expr_list, expr) {
427 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
428 print_initializer_list(expr->idx_expression->expr_list, struct_type);
429 continue;
431 if (expr->type != EXPR_IDENTIFIER)
432 continue;
433 if (!expr->expr_ident)
434 continue;
435 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
436 continue;
437 base_type = get_type(expr->ident_expression);
438 if (!base_type || base_type->type != SYM_FN)
439 continue;
440 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
441 expr->expr_ident->name,
442 expr->ident_expression->symbol_name->name);
443 } END_FOR_EACH_PTR(expr);
447 static void global_variable(struct symbol *sym)
449 struct symbol *struct_type;
451 if (!sym->ident)
452 return;
453 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
454 return;
455 struct_type = get_base_type(sym);
456 if (!struct_type)
457 return;
458 if (struct_type->type == SYM_ARRAY) {
459 struct_type = get_base_type(struct_type);
460 if (!struct_type)
461 return;
463 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
464 return;
465 print_initializer_list(sym->initializer->expr_list, struct_type);
468 void open_smatch_db(void)
470 #ifdef SQLITE_OPEN_READONLY
471 int rc;
473 if (option_no_db)
474 return;
476 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
477 if (rc != SQLITE_OK) {
478 option_no_db = 1;
479 return;
481 return;
482 #else
483 option_no_db = 1;
484 return;
485 #endif
488 void register_definition_db_callbacks(int id)
490 if (option_info) {
491 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
492 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
493 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
494 add_hook(&global_variable, BASE_HOOK);
495 add_hook(&global_variable, DECLARATION_HOOK);
498 if (option_no_db)
499 return;
501 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
502 add_hook(&match_call_implies, FUNCTION_CALL_HOOK);