db: improve error message
[smatch.git] / smatch_db.c
blob7e3c9518ab41f14cb4ddb428f22838c8b951dadc
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);
54 fprintf(stderr, "SQL: '%s'\n", sql);
58 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
60 struct def_callback *def_callback = __alloc_def_callback(0);
62 def_callback->hook_type = type;
63 def_callback->callback = callback;
64 add_ptr_list(&callbacks, def_callback);
67 void add_member_info_callback(int owner, void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
69 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
71 member_callback->owner = owner;
72 member_callback->callback = callback;
73 add_ptr_list(&member_callbacks, member_callback);
76 void add_db_fn_call_callback(int type, void (*callback)(struct expression *arg, char *value))
78 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
80 cb->type = type;
81 cb->callback = callback;
82 add_ptr_list(&call_implies_cb_list, cb);
85 static struct range_list *return_range_list;
86 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
88 if (argc != 1)
89 return 0;
90 get_value_ranges(argv[0], &return_range_list);
91 return 0;
94 struct range_list *db_return_vals(struct expression *expr)
96 struct symbol *sym;
97 static char sql_filter[1024];
99 if (expr->type != EXPR_CALL)
100 return NULL;
101 if (expr->fn->type != EXPR_SYMBOL)
102 return NULL;
103 sym = expr->fn->symbol;
104 if (!sym)
105 return NULL;
107 if (sym->ctype.modifiers & MOD_STATIC) {
108 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
109 get_filename(), sym->ident->name);
110 } else {
111 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
112 sym->ident->name);
115 return_range_list = NULL;
116 run_sql(db_return_callback, "select return from return_values where %s",
117 sql_filter);
118 return return_range_list;
121 static void match_call_hack(struct expression *expr)
123 char *name;
126 * we just want to record something in the database so that if we have
127 * two calls like: frob(4); frob(some_unkown); then on the receiving
128 * side we know that sometimes frob is called with unknown parameters.
131 name = get_fnptr_name(expr->fn);
132 if (!name)
133 return;
134 sm_msg("info: call_marker '%s' %s", name, is_static(expr->fn) ? "static" : "global");
135 free_string(name);
138 static void print_struct_members(char *fn, char *global_static, struct expression *expr, int param, struct state_list *slist,
139 void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
141 struct sm_state *sm;
142 char *name;
143 struct symbol *sym;
144 int len;
145 char printed_name[256];
146 int is_address = 0;
148 expr = strip_expr(expr);
149 if (expr->type == EXPR_PREOP && expr->op == '&') {
150 expr = strip_expr(expr->unop);
151 is_address = 1;
154 name = get_variable_from_expr(expr, &sym);
155 if (!name || !sym)
156 goto free;
158 len = strlen(name);
159 FOR_EACH_PTR(slist, sm) {
160 if (sm->sym != sym)
161 continue;
162 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
163 continue;
164 if (is_address)
165 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
166 else
167 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
168 callback(fn, global_static, param, printed_name, sm->state);
169 } END_FOR_EACH_PTR(sm);
170 free:
171 free_string(name);
174 static void match_call_info(struct expression *expr)
176 struct member_info_callback *cb;
177 struct expression *arg;
178 struct state_list *slist;
179 char *name;
180 int i;
181 char *gs;
183 name = get_fnptr_name(expr->fn);
184 if (!name)
185 return;
187 if (is_static(expr->fn))
188 gs = (char *)"static";
189 else
190 gs = (char *)"global";
192 FOR_EACH_PTR(member_callbacks, cb) {
193 slist = get_all_states(cb->owner);
194 i = 0;
195 FOR_EACH_PTR(expr->args, arg) {
196 print_struct_members(name, gs, arg, i, slist, cb->callback);
197 i++;
198 } END_FOR_EACH_PTR(arg);
199 } END_FOR_EACH_PTR(cb);
201 free_string(name);
202 free_slist(&slist);
205 static int get_param(int param, char **name, struct symbol **sym)
207 struct symbol *arg;
208 int i;
210 i = 0;
211 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
213 * this is a temporary hack to work around a bug (I think in sparse?)
214 * 2.6.37-rc1:fs/reiserfs/journal.o
215 * If there is a function definition without parameter name found
216 * after a function implementation then it causes a crash.
217 * int foo() {}
218 * int bar(char *);
220 if (arg->ident->name < (char *)100)
221 continue;
222 if (i == param && arg->ident->name) {
223 *name = arg->ident->name;
224 *sym = arg;
225 return TRUE;
227 i++;
228 } END_FOR_EACH_PTR(arg);
230 return FALSE;
233 static struct state_list *final_states;
234 static int prev_func_id = -1;
235 static int db_callback(void *unused, int argc, char **argv, char **azColName)
237 int func_id;
238 long type;
239 long param;
240 char *name = NULL;
241 struct symbol *sym = NULL;
242 struct def_callback *def_callback;
244 if (argc != 5)
245 return 0;
247 func_id = atoi(argv[0]);
248 errno = 0;
249 type = strtol(argv[1], NULL, 10);
250 param = strtol(argv[2], NULL, 10);
251 if (errno)
252 return 0;
254 if (prev_func_id == -1)
255 prev_func_id = func_id;
256 if (func_id != prev_func_id) {
257 merge_slist(&final_states, __pop_fake_cur_slist());
258 __push_fake_cur_slist();
259 __unnullify_path();
260 prev_func_id = func_id;
263 if (type == INTERNAL)
264 return 0;
265 if (param >= 0 && !get_param(param, &name, &sym))
266 return 0;
268 FOR_EACH_PTR(callbacks, def_callback) {
269 if (def_callback->hook_type == type)
270 def_callback->callback(name, sym, argv[3], argv[4]);
271 } END_FOR_EACH_PTR(def_callback);
273 return 0;
276 static void get_direct_callers(struct symbol *sym)
278 char sql_filter[1024];
280 if (sym->ctype.modifiers & MOD_STATIC) {
281 snprintf(sql_filter, 1024,
282 "file = '%s' and function = '%s' order by function_id;",
283 get_filename(), sym->ident->name);
284 } else {
285 snprintf(sql_filter, 1024,
286 "function = '%s' and static = 0 order by function_id;",
287 sym->ident->name);
290 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
291 " where %s", sql_filter);
294 static char *ptr_name;
295 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
297 if (!ptr_name)
298 ptr_name = alloc_string(argv[0]);
299 return 0;
302 static void get_function_pointer_callers(struct symbol *sym)
304 ptr_name = NULL;
305 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
306 sym->ident->name);
307 if (!ptr_name)
308 return;
310 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
311 " where function = '%s' order by function_id", ptr_name);
314 static void match_data_from_db(struct symbol *sym)
316 struct sm_state *sm;
318 if (!sym || !sym->ident || !sym->ident->name)
319 return;
321 __push_fake_cur_slist();
322 __unnullify_path();
323 prev_func_id = -1;
325 get_direct_callers(sym);
326 get_function_pointer_callers(sym);
328 merge_slist(&final_states, __pop_fake_cur_slist());
330 FOR_EACH_PTR(final_states, sm) {
331 __set_sm(sm);
332 } END_FOR_EACH_PTR(sm);
334 free_slist(&final_states);
337 static void match_function_assign(struct expression *expr)
339 struct expression *right = expr->right;
340 struct symbol *sym;
341 char *fn_name;
342 char *ptr_name;
344 if (right->type == EXPR_PREOP && right->op == '&')
345 right = right->unop;
346 if (right->type != EXPR_SYMBOL)
347 return;
348 sym = get_type(right);
349 if (!sym || sym->type != SYM_FN)
350 return;
352 fn_name = get_variable_from_expr(right, NULL);
353 ptr_name = get_fnptr_name(expr->left);
354 if (!fn_name || !ptr_name)
355 goto free;
357 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
359 free:
360 free_string(fn_name);
361 free_string(ptr_name);
364 static struct expression *call_implies_call_expr;
365 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
367 struct call_implies_callback *cb;
368 struct expression *arg = NULL;
369 int type;
370 int param;
372 if (argc != 4)
373 return 0;
375 type = atoi(argv[1]);
376 param = atoi(argv[2]);
378 FOR_EACH_PTR(call_implies_cb_list, cb) {
379 if (cb->type != type)
380 continue;
381 if (param != -1) {
382 arg = get_argument_from_call_expr(call_implies_call_expr->args, param);
383 if (!arg)
384 continue;
386 cb->callback(arg, argv[3]);
387 } END_FOR_EACH_PTR(cb);
389 return 0;
392 static void match_call_implies(struct expression *expr)
394 struct symbol *sym;
395 static char sql_filter[1024];
397 if (expr->fn->type != EXPR_SYMBOL)
398 return;
399 sym = expr->fn->symbol;
400 if (!sym)
401 return;
403 if (sym->ctype.modifiers & MOD_STATIC) {
404 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
405 get_filename(), sym->ident->name);
406 } else {
407 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
408 sym->ident->name);
411 call_implies_call_expr = expr;
412 run_sql(call_implies_callbacks,
413 "select function, type, parameter, value from call_implies where %s",
414 sql_filter);
415 return;
418 static void print_initializer_list(struct expression_list *expr_list,
419 struct symbol *struct_type)
421 struct expression *expr;
422 struct symbol *base_type;
424 FOR_EACH_PTR(expr_list, expr) {
425 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
426 print_initializer_list(expr->idx_expression->expr_list, struct_type);
427 continue;
429 if (expr->type != EXPR_IDENTIFIER)
430 continue;
431 if (!expr->expr_ident)
432 continue;
433 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
434 continue;
435 base_type = get_type(expr->ident_expression);
436 if (!base_type || base_type->type != SYM_FN)
437 continue;
438 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
439 expr->expr_ident->name,
440 expr->ident_expression->symbol_name->name);
441 } END_FOR_EACH_PTR(expr);
445 static void global_variable(struct symbol *sym)
447 struct symbol *struct_type;
449 if (!sym->ident)
450 return;
451 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
452 return;
453 struct_type = get_base_type(sym);
454 if (!struct_type)
455 return;
456 if (struct_type->type == SYM_ARRAY) {
457 struct_type = get_base_type(struct_type);
458 if (!struct_type)
459 return;
461 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
462 return;
463 print_initializer_list(sym->initializer->expr_list, struct_type);
466 void open_smatch_db(void)
468 #ifdef SQLITE_OPEN_READONLY
469 int rc;
471 if (option_no_db)
472 return;
474 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
475 if (rc != SQLITE_OK) {
476 option_no_db = 1;
477 return;
479 return;
480 #else
481 option_no_db = 1;
482 return;
483 #endif
486 void register_definition_db_callbacks(int id)
488 if (option_info) {
489 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
490 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
491 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
492 add_hook(&global_variable, BASE_HOOK);
493 add_hook(&global_variable, DECLARATION_HOOK);
496 if (option_no_db)
497 return;
499 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
500 add_hook(&match_call_implies, FUNCTION_CALL_HOOK);