fill_db_function_ptr: fixup formatting changes fallout
[smatch.git] / smatch_db.c
blobf4759dd0b91132fda3480c013c562a521eac8a7c
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"
16 static sqlite3 *db;
18 struct def_callback {
19 int hook_type;
20 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
22 ALLOCATOR(def_callback, "definition db hook callbacks");
23 DECLARE_PTR_LIST(callback_list, struct def_callback);
24 static struct callback_list *callbacks;
26 struct member_info_callback {
27 int owner;
28 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state);
30 ALLOCATOR(member_info_callback, "caller_info callbacks");
31 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
32 static struct member_info_cb_list *member_callbacks;
34 void sql_exec(int (*callback)(void*, int, char**, char**), const char *sql)
36 char *err = NULL;
37 int rc;
39 if (option_no_db || !db)
40 return;
42 rc = sqlite3_exec(db, sql, callback, 0, &err);
43 if (rc != SQLITE_OK) {
44 fprintf(stderr, "SQL error #2: %s\n", err);
45 exit(1);
49 void add_definition_db_callback(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
51 struct def_callback *def_callback = __alloc_def_callback(0);
53 def_callback->hook_type = type;
54 def_callback->callback = callback;
55 add_ptr_list(&callbacks, def_callback);
58 void add_member_info_callback(int owner, void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
60 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
62 member_callback->owner = owner;
63 member_callback->callback = callback;
64 add_ptr_list(&member_callbacks, member_callback);
67 static void match_call_hack(struct expression *expr)
69 char *name;
72 * we just want to record something in the database so that if we have
73 * two calls like: frob(4); frob(some_unkown); then on the recieving
74 * side we know that sometimes frob is called with unknown parameters.
77 name = get_fnptr_name(expr->fn);
78 if (!name)
79 return;
80 if (ptr_list_empty(expr->args))
81 return;
82 sm_msg("info: passes param_value '%s' -1 '$$' min-max", name);
83 free_string(name);
86 static void print_struct_members(char *fn, struct expression *expr, int param, struct state_list *slist,
87 void (*callback)(char *fn, int param, char *printed_name, struct smatch_state *state))
89 struct sm_state *sm;
90 char *name;
91 struct symbol *sym;
92 int len;
93 char printed_name[256];
94 int is_address = 0;
96 expr = strip_expr(expr);
97 if (expr->type == EXPR_PREOP && expr->op == '&') {
98 expr = strip_expr(expr->unop);
99 is_address = 1;
102 name = get_variable_from_expr(expr, &sym);
103 if (!name || !sym)
104 goto free;
106 len = strlen(name);
107 FOR_EACH_PTR(slist, sm) {
108 if (sm->sym != sym)
109 continue;
110 if (strncmp(name, sm->name, len) || sm->name[len] == '\0')
111 continue;
112 if (is_address)
113 snprintf(printed_name, sizeof(printed_name), "$$->%s", sm->name + len + 1);
114 else
115 snprintf(printed_name, sizeof(printed_name), "$$%s", sm->name + len);
116 callback(fn, param, printed_name, sm->state);
117 } END_FOR_EACH_PTR(sm);
118 free:
119 free_string(name);
122 static void match_call_info(struct expression *expr)
124 struct member_info_callback *cb;
125 struct expression *arg;
126 struct state_list *slist;
127 char *name;
128 int i;
130 name = get_fnptr_name(expr->fn);
131 if (!name)
132 return;
134 FOR_EACH_PTR(member_callbacks, cb) {
135 slist = get_all_states(cb->owner);
136 i = 0;
137 FOR_EACH_PTR(expr->args, arg) {
138 print_struct_members(name, arg, i, slist, cb->callback);
139 i++;
140 } END_FOR_EACH_PTR(arg);
141 } END_FOR_EACH_PTR(cb);
143 free_string(name);
144 free_slist(&slist);
147 static unsigned long call_count;
148 static int db_count_callback(void *unused, int argc, char **argv, char **azColName)
150 call_count += strtoul(argv[0], NULL, 10);
151 return 0;
154 static int get_param(int param, char **name, struct symbol **sym)
156 struct symbol *arg;
157 int i;
159 i = 0;
160 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
162 * this is a temporary hack to work around a bug (I think in sparse?)
163 * 2.6.37-rc1:fs/reiserfs/journal.o
164 * If there is a function definition without parameter name found
165 * after a function implementation then it causes a crash.
166 * int foo() {}
167 * int bar(char *);
169 if (arg->ident->name < (char *)100)
170 continue;
171 if (i == param && arg->ident->name) {
172 *name = arg->ident->name;
173 *sym = arg;
174 return TRUE;
176 i++;
177 } END_FOR_EACH_PTR(arg);
179 return FALSE;
182 static struct state_list *final_states;
183 static int prev_func_id = -1;
184 static int db_callback(void *unused, int argc, char **argv, char **azColName)
186 int func_id;
187 long type;
188 long param;
189 char *name;
190 struct symbol *sym;
191 struct def_callback *def_callback;
193 if (argc != 5)
194 return 0;
196 func_id = atoi(argv[0]);
197 errno = 0;
198 type = strtol(argv[1], NULL, 10);
199 param = strtol(argv[2], NULL, 10);
200 if (errno)
201 return 0;
203 if (prev_func_id == -1)
204 prev_func_id = func_id;
205 if (func_id != prev_func_id) {
206 merge_slist(&final_states, __pop_fake_cur_slist());
207 __push_fake_cur_slist();
208 prev_func_id = func_id;
211 if (param == -1 || !get_param(param, &name, &sym))
212 return 0;
214 FOR_EACH_PTR(callbacks, def_callback) {
215 if (def_callback->hook_type == type)
216 def_callback->callback(name, sym, argv[3], argv[4]);
217 } END_FOR_EACH_PTR(def_callback);
219 return 0;
222 static void get_direct_callers(struct symbol *sym)
224 char sql_filter[1024];
226 if (sym->ctype.modifiers & MOD_STATIC) {
227 snprintf(sql_filter, 1024,
228 "file = '%s' and function = '%s' order by function_id;",
229 get_filename(), sym->ident->name);
230 } else {
231 snprintf(sql_filter, 1024,
232 "function = '%s' order by function_id;",
233 sym->ident->name);
236 run_sql(db_count_callback, "select count(*) from caller_info where %s",
237 sql_filter);
238 if (call_count == 0 || call_count > 100)
239 return;
241 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
242 " where %s", sql_filter);
245 static char *ptr_name;
246 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
248 if (!ptr_name)
249 ptr_name = alloc_string(argv[0]);
250 return 0;
253 static void get_function_pointer_callers(struct symbol *sym)
255 ptr_name = NULL;
256 run_sql(get_ptr_name, "select ptr from function_ptr where function = '%s'",
257 sym->ident->name);
258 if (!ptr_name)
259 return;
261 run_sql(db_count_callback, "select count(*) from caller_info where function = '%s'",
262 ptr_name);
263 if (call_count == 0 || call_count > 100)
264 return;
266 run_sql(db_callback, "select function_id, type, parameter, key, value from caller_info"
267 " where function = '%s' order by function_id", ptr_name);
270 static void match_data_from_db(struct symbol *sym)
272 struct sm_state *sm;
274 if (!sym || !sym->ident || !sym->ident->name)
275 return;
277 __push_fake_cur_slist();
278 prev_func_id = -1;
280 call_count = 0;
281 get_direct_callers(sym);
282 get_function_pointer_callers(sym);
284 merge_slist(&final_states, __pop_fake_cur_slist());
286 if (call_count > 100) {
287 free_slist(&final_states);
288 return;
290 FOR_EACH_PTR(final_states, sm) {
291 __set_sm(sm);
292 } END_FOR_EACH_PTR(sm);
294 free_slist(&final_states);
297 static void match_function_assign(struct expression *expr)
299 struct expression *right = expr->right;
300 struct symbol *sym;
301 char *fn_name;
302 char *ptr_name;
304 if (right->type == EXPR_PREOP && right->op == '&')
305 right = right->unop;
306 if (right->type != EXPR_SYMBOL)
307 return;
308 sym = get_type(right);
309 if (!sym || sym->type != SYM_FN)
310 return;
312 fn_name = get_variable_from_expr(right, NULL);
313 ptr_name = get_fnptr_name(expr->left);
314 if (!fn_name || !ptr_name)
315 goto free;
317 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name, fn_name);
319 free:
320 free_string(fn_name);
321 free_string(ptr_name);
324 static void print_initializer_list(struct expression_list *expr_list,
325 struct symbol *struct_type)
327 struct expression *expr;
328 struct symbol *base_type;
330 FOR_EACH_PTR(expr_list, expr) {
331 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
332 print_initializer_list(expr->idx_expression->expr_list, struct_type);
333 continue;
335 if (expr->type != EXPR_IDENTIFIER)
336 continue;
337 if (!expr->expr_ident)
338 continue;
339 if (!expr->ident_expression || !expr->ident_expression->symbol_name)
340 continue;
341 base_type = get_type(expr->ident_expression);
342 if (!base_type || base_type->type != SYM_FN)
343 continue;
344 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type->ident->name,
345 expr->expr_ident->name,
346 expr->ident_expression->symbol_name->name);
347 } END_FOR_EACH_PTR(expr);
351 static void global_variable(struct symbol *sym)
353 struct symbol *struct_type;
355 if (!sym->ident)
356 return;
357 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
358 return;
359 struct_type = get_base_type(sym);
360 if (!struct_type)
361 return;
362 if (struct_type->type == SYM_ARRAY) {
363 struct_type = get_base_type(struct_type);
364 if (!struct_type)
365 return;
366 sm_msg("here in sets_fn_ptr %d %p", struct_type->type, struct_type->ident);
368 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
369 return;
370 print_initializer_list(sym->initializer->expr_list, struct_type);
373 void open_smatch_db(void)
375 #ifdef SQLITE_OPEN_READONLY
376 int rc;
378 if (option_no_db)
379 return;
381 rc = sqlite3_open_v2("smatch_db.sqlite", &db, SQLITE_OPEN_READONLY, NULL);
382 if (rc != SQLITE_OK) {
383 option_no_db = 1;
384 return;
386 return;
387 #else
388 option_no_db = 1;
389 return;
390 #endif
393 void register_definition_db_callbacks(int id)
395 if (option_info) {
396 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
397 add_hook(&match_call_hack, FUNCTION_CALL_HOOK);
398 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
399 add_hook(&global_variable, BASE_HOOK);
400 add_hook(&global_variable, DECLARATION_HOOK);
403 if (option_no_db)
404 return;
406 add_hook(&match_data_from_db, FUNC_DEF_HOOK);