type: fix get_binop_type() for bit shift operations
[smatch.git] / smatch_db.c
blob12a1daecf8ecad74c5079f309d357b1a5c81c024
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 static int return_id;
44 int get_return_id(void)
46 return return_id;
49 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
51 char *err = NULL;
52 int rc;
54 if (option_no_db || !db)
55 return;
57 rc = sqlite3_exec(db, sql, callback, 0, &err);
58 if (rc != SQLITE_OK) {
59 fprintf(stderr, "SQL error #2: %s\n", err);
60 fprintf(stderr, "SQL: '%s'\n", sql);
64 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
66 struct def_callback *def_callback = __alloc_def_callback(0);
68 def_callback->hook_type = type;
69 def_callback->callback = callback;
70 add_ptr_list(&callbacks, def_callback);
73 void add_member_info_callback(int owner, void (*callback)(char *fn, char *global_static, int param, char *printed_name, struct smatch_state *state))
75 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
77 member_callback->owner = owner;
78 member_callback->callback = callback;
79 add_ptr_list(&member_callbacks, member_callback);
82 void add_db_fn_call_callback(int type, void (*callback)(struct expression *arg, char *value))
84 struct call_implies_callback *cb = __alloc_call_implies_callback(0);
86 cb->type = type;
87 cb->callback = callback;
88 add_ptr_list(&call_implies_cb_list, cb);
91 static struct range_list *return_range_list;
92 static int db_return_callback(void *unused, int argc, char **argv, char **azColName)
94 if (argc != 1)
95 return 0;
96 get_value_ranges(argv[0], &return_range_list);
97 return 0;
100 struct range_list *db_return_vals(struct expression *expr)
102 struct symbol *sym;
103 static char sql_filter[1024];
105 if (expr->type != EXPR_CALL)
106 return NULL;
107 if (expr->fn->type != EXPR_SYMBOL)
108 return NULL;
109 sym = expr->fn->symbol;
110 if (!sym)
111 return NULL;
113 if (sym->ctype.modifiers & MOD_STATIC) {
114 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
115 get_filename(), sym->ident->name);
116 } else {
117 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
118 sym->ident->name);
121 return_range_list = NULL;
122 run_sql(db_return_callback, "select return from return_values where %s",
123 sql_filter);
124 return return_range_list;
127 static void match_call_hack(struct expression *expr)
129 char *name;
132 * we just want to record something in the database so that if we have
133 * two calls like: frob(4); frob(some_unkown); then on the receiving
134 * side we know that sometimes frob is called with unknown parameters.
137 name = get_fnptr_name(expr->fn);
138 if (!name)
139 return;
140 sm_msg("info: call_marker '%s' %s", 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 = NULL;
247 struct symbol *sym = NULL;
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 (type == INTERNAL)
270 return 0;
271 if (param >= 0 && !get_param(param, &name, &sym))
272 return 0;
274 FOR_EACH_PTR(callbacks, def_callback) {
275 if (def_callback->hook_type == type)
276 def_callback->callback(name, sym, argv[3], argv[4]);
277 } END_FOR_EACH_PTR(def_callback);
279 return 0;
282 static void get_direct_callers(struct symbol *sym)
284 char sql_filter[1024];
286 if (sym->ctype.modifiers & MOD_STATIC) {
287 snprintf(sql_filter, 1024,
288 "file = '%s' and function = '%s' order by function_id;",
289 get_filename(), sym->ident->name);
290 } else {
291 snprintf(sql_filter, 1024,
292 "function = '%s' and static = 0 order by function_id;",
293 sym->ident->name);
296 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
297 " where %s", sql_filter);
300 static char *ptr_name;
301 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
303 if (!ptr_name)
304 ptr_name = alloc_string(argv[0]);
305 return 0;
308 static void get_function_pointer_callers(struct symbol *sym)
310 ptr_name = NULL;
311 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
312 sym->ident->name);
313 if (!ptr_name)
314 return;
316 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
317 " where function = '%s' order by function_id", ptr_name);
320 static void match_data_from_db(struct symbol *sym)
322 struct sm_state *sm;
324 if (!sym || !sym->ident || !sym->ident->name)
325 return;
327 __push_fake_cur_slist();
328 __unnullify_path();
329 prev_func_id = -1;
331 get_direct_callers(sym);
332 get_function_pointer_callers(sym);
334 merge_slist(&final_states, __pop_fake_cur_slist());
336 FOR_EACH_PTR(final_states, sm) {
337 __set_sm(sm);
338 } END_FOR_EACH_PTR(sm);
340 free_slist(&final_states);
343 static void match_function_assign(struct expression *expr)
345 struct expression *right = expr->right;
346 struct symbol *sym;
347 char *fn_name;
348 char *ptr_name;
350 if (right->type == EXPR_PREOP && right->op == '&')
351 right = right->unop;
352 if (right->type != EXPR_SYMBOL)
353 return;
354 sym = get_type(right);
355 if (!sym || sym->type != SYM_FN)
356 return;
358 fn_name = get_variable_from_expr(right, NULL);
359 ptr_name = get_fnptr_name(expr->left);
360 if (!fn_name || !ptr_name)
361 goto free;
363 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
365 free:
366 free_string(fn_name);
367 free_string(ptr_name);
370 static struct expression *call_implies_call_expr;
371 static int call_implies_callbacks(void *unused, int argc, char **argv, char **azColName)
373 struct call_implies_callback *cb;
374 struct expression *arg = NULL;
375 int type;
376 int param;
378 if (argc != 4)
379 return 0;
381 type = atoi(argv[1]);
382 param = atoi(argv[2]);
384 FOR_EACH_PTR(call_implies_cb_list, cb) {
385 if (cb->type != type)
386 continue;
387 if (param != -1) {
388 arg = get_argument_from_call_expr(call_implies_call_expr->args, param);
389 if (!arg)
390 continue;
392 cb->callback(arg, argv[3]);
393 } END_FOR_EACH_PTR(cb);
395 return 0;
398 static void match_call_implies(struct expression *expr)
400 struct symbol *sym;
401 static char sql_filter[1024];
403 if (expr->fn->type != EXPR_SYMBOL)
404 return;
405 sym = expr->fn->symbol;
406 if (!sym)
407 return;
409 if (sym->ctype.modifiers & MOD_STATIC) {
410 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
411 get_filename(), sym->ident->name);
412 } else {
413 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
414 sym->ident->name);
417 call_implies_call_expr = expr;
418 run_sql(call_implies_callbacks,
419 "select function, type, parameter, value from call_implies where %s",
420 sql_filter);
421 return;
424 static void print_initializer_list(struct expression_list *expr_list,
425 struct symbol *struct_type)
427 struct expression *expr;
428 struct symbol *base_type;
430 FOR_EACH_PTR(expr_list, expr) {
431 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
432 print_initializer_list(expr->idx_expression->expr_list, struct_type);
433 continue;
435 if (expr->type != EXPR_IDENTIFIER)
436 continue;
437 if (!expr->expr_ident)
438 continue;
439 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
440 continue;
441 base_type = get_type(expr->ident_expression);
442 if (!base_type || base_type->type != SYM_FN)
443 continue;
444 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
445 expr->expr_ident->name,
446 expr->ident_expression->symbol_name->name);
447 } END_FOR_EACH_PTR(expr);
450 static void global_variable(struct symbol *sym)
452 struct symbol *struct_type;
454 if (!sym->ident)
455 return;
456 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
457 return;
458 struct_type = get_base_type(sym);
459 if (!struct_type)
460 return;
461 if (struct_type->type == SYM_ARRAY) {
462 struct_type = get_base_type(struct_type);
463 if (!struct_type)
464 return;
466 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
467 return;
468 print_initializer_list(sym->initializer->expr_list, struct_type);
471 static void match_return_info(struct expression *ret_value)
473 struct range_list *rl;
475 get_implied_range_list(ret_value, &rl);
476 sm_msg("info: return_marker %d '%s' %s",
477 get_return_id(), show_ranges(rl), global_static());
480 static void match_end_func_info(struct symbol *sym)
482 if (__path_is_null())
483 return;
484 sm_msg("info: return_marker %d '' %s", get_return_id(), global_static());
487 static void match_function_def(struct symbol *sym)
489 return_id = 0;
492 static void match_return(struct expression *ret_value)
494 return_id++;
497 static void match_end_func(struct symbol *sym)
499 return_id++;
502 void open_smatch_db(void)
504 #ifdef SQLITE_OPEN_READONLY
505 int rc;
507 if (option_no_db)
508 return;
510 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
511 if (rc != SQLITE_OK) {
512 option_no_db = 1;
513 return;
515 return;
516 #else
517 option_no_db = 1;
518 return;
519 #endif
522 void register_definition_db_callbacks(int id)
524 add_hook(&match_function_def, FUNC_DEF_HOOK);
525 add_hook(&match_return, RETURN_HOOK);
526 add_hook(&match_end_func, END_FUNC_HOOK);
528 if (option_info) {
529 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
530 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
531 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
532 add_hook(&global_variable, BASE_HOOK);
533 add_hook(&global_variable, DECLARATION_HOOK);
534 add_hook(&match_return_info, RETURN_HOOK);
535 add_hook(&match_end_func_info, END_FUNC_HOOK);
538 if (option_no_db)
539 return;
541 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
542 add_hook(&match_call_implies, FUNCTION_CALL_HOOK);