4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
14 #include "smatch_slist.h"
15 #include "smatch_extra.h"
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
{
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 returned_member_callback
{
37 void (*callback
)(char *return_ranges
, char *printed_name
, struct smatch_state
*state
);
39 ALLOCATOR(returned_member_callback
, "returned member callbacks");
40 DECLARE_PTR_LIST(returned_member_cb_list
, struct returned_member_callback
);
41 static struct returned_member_cb_list
*returned_member_callbacks
;
43 struct call_implies_callback
{
45 void (*callback
)(struct expression
*arg
, char *value
);
47 ALLOCATOR(call_implies_callback
, "call_implies callbacks");
48 DECLARE_PTR_LIST(call_implies_cb_list
, struct call_implies_callback
);
49 static struct call_implies_cb_list
*call_implies_cb_list
;
52 int get_return_id(void)
57 void sql_exec(int (*callback
)(void*, int, char**, char**), const char *sql
)
62 if (option_no_db
|| !db
)
65 rc
= sqlite3_exec(db
, sql
, callback
, 0, &err
);
66 if (rc
!= SQLITE_OK
) {
67 fprintf(stderr
, "SQL error #2: %s\n", err
);
68 fprintf(stderr
, "SQL: '%s'\n", sql
);
72 void add_definition_db_callback(void (*callback
)(const char *name
, struct symbol
*sym
, char *key
, char *value
), int type
)
74 struct def_callback
*def_callback
= __alloc_def_callback(0);
76 def_callback
->hook_type
= type
;
77 def_callback
->callback
= callback
;
78 add_ptr_list(&callbacks
, def_callback
);
82 * These call backs are used when the --info option is turned on to print struct
83 * member information. For example foo->bar could have a state in
84 * smatch_extra.c and also check_user.c.
86 void add_member_info_callback(int owner
, void (*callback
)(char *fn
, char *global_static
, int param
, char *printed_name
, struct smatch_state
*state
))
88 struct member_info_callback
*member_callback
= __alloc_member_info_callback(0);
90 member_callback
->owner
= owner
;
91 member_callback
->callback
= callback
;
92 add_ptr_list(&member_callbacks
, member_callback
);
95 void add_returned_member_callback(int owner
, void (*callback
)(char *return_ranges
, char *printed_name
, struct smatch_state
*state
))
97 struct returned_member_callback
*member_callback
= __alloc_returned_member_callback(0);
99 member_callback
->owner
= owner
;
100 member_callback
->callback
= callback
;
101 add_ptr_list(&returned_member_callbacks
, member_callback
);
104 void add_db_fn_call_callback(int type
, void (*callback
)(struct expression
*arg
, char *value
))
106 struct call_implies_callback
*cb
= __alloc_call_implies_callback(0);
109 cb
->callback
= callback
;
110 add_ptr_list(&call_implies_cb_list
, cb
);
113 static struct symbol
*return_type
;
114 static struct range_list
*return_range_list
;
115 static int db_return_callback(void *unused
, int argc
, char **argv
, char **azColName
)
120 sm_msg("return type %d", type_positive_bits(return_type
));
121 parse_value_ranges_type(return_type
, argv
[0], &return_range_list
);
125 struct range_list
*db_return_vals(struct expression
*expr
)
128 static char sql_filter
[1024];
130 if (expr
->type
!= EXPR_CALL
)
132 if (expr
->fn
->type
!= EXPR_SYMBOL
)
134 return_type
= get_type(expr
);
137 sym
= expr
->fn
->symbol
;
141 if (sym
->ctype
.modifiers
& MOD_STATIC
) {
142 snprintf(sql_filter
, 1024, "file = '%s' and function = '%s';",
143 get_filename(), sym
->ident
->name
);
145 snprintf(sql_filter
, 1024, "function = '%s' and static = 0;",
149 return_range_list
= NULL
;
150 run_sql(db_return_callback
, "select return from return_values where %s",
152 return return_range_list
;
155 static void match_call_hack(struct expression
*expr
)
160 * we just want to record something in the database so that if we have
161 * two calls like: frob(4); frob(some_unkown); then on the receiving
162 * side we know that sometimes frob is called with unknown parameters.
165 name
= get_fnptr_name(expr
->fn
);
168 sm_msg("info: call_marker '%s' %s", name
, is_static(expr
->fn
) ? "static" : "global");
172 static void print_struct_members(char *fn
, char *global_static
, struct expression
*expr
, int param
, struct state_list
*slist
,
173 void (*callback
)(char *fn
, char *global_static
, int param
, char *printed_name
, struct smatch_state
*state
))
179 char printed_name
[256];
182 expr
= strip_expr(expr
);
183 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&') {
184 expr
= strip_expr(expr
->unop
);
188 name
= get_variable_from_expr(expr
, &sym
);
193 FOR_EACH_PTR(slist
, sm
) {
196 if (strncmp(name
, sm
->name
, len
) || sm
->name
[len
] == '\0')
199 snprintf(printed_name
, sizeof(printed_name
), "$$->%s", sm
->name
+ len
+ 1);
201 snprintf(printed_name
, sizeof(printed_name
), "$$%s", sm
->name
+ len
);
202 callback(fn
, global_static
, param
, printed_name
, sm
->state
);
203 } END_FOR_EACH_PTR(sm
);
208 static void match_call_info(struct expression
*expr
)
210 struct member_info_callback
*cb
;
211 struct expression
*arg
;
212 struct state_list
*slist
;
217 name
= get_fnptr_name(expr
->fn
);
221 if (is_static(expr
->fn
))
222 gs
= (char *)"static";
224 gs
= (char *)"global";
226 FOR_EACH_PTR(member_callbacks
, cb
) {
227 slist
= get_all_states(cb
->owner
);
229 FOR_EACH_PTR(expr
->args
, arg
) {
230 print_struct_members(name
, gs
, arg
, i
, slist
, cb
->callback
);
232 } END_FOR_EACH_PTR(arg
);
234 } END_FOR_EACH_PTR(cb
);
239 static int get_param(int param
, char **name
, struct symbol
**sym
)
245 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, arg
) {
247 * this is a temporary hack to work around a bug (I think in sparse?)
248 * 2.6.37-rc1:fs/reiserfs/journal.o
249 * If there is a function definition without parameter name found
250 * after a function implementation then it causes a crash.
254 if (arg
->ident
->name
< (char *)100)
256 if (i
== param
&& arg
->ident
->name
) {
257 *name
= arg
->ident
->name
;
262 } END_FOR_EACH_PTR(arg
);
267 static struct state_list
*final_states
;
268 static int prev_func_id
= -1;
269 static int db_callback(void *unused
, int argc
, char **argv
, char **azColName
)
275 struct symbol
*sym
= NULL
;
276 struct def_callback
*def_callback
;
281 func_id
= atoi(argv
[0]);
283 type
= strtol(argv
[1], NULL
, 10);
284 param
= strtol(argv
[2], NULL
, 10);
288 if (prev_func_id
== -1)
289 prev_func_id
= func_id
;
290 if (func_id
!= prev_func_id
) {
291 merge_slist(&final_states
, __pop_fake_cur_slist());
292 __push_fake_cur_slist();
294 prev_func_id
= func_id
;
297 if (type
== INTERNAL
)
299 if (param
>= 0 && !get_param(param
, &name
, &sym
))
302 FOR_EACH_PTR(callbacks
, def_callback
) {
303 if (def_callback
->hook_type
== type
)
304 def_callback
->callback(name
, sym
, argv
[3], argv
[4]);
305 } END_FOR_EACH_PTR(def_callback
);
310 static void get_direct_callers(struct symbol
*sym
)
312 char sql_filter
[1024];
314 if (sym
->ctype
.modifiers
& MOD_STATIC
) {
315 snprintf(sql_filter
, 1024,
316 "file = '%s' and function = '%s' order by function_id;",
317 get_filename(), sym
->ident
->name
);
319 snprintf(sql_filter
, 1024,
320 "function = '%s' and static = 0 order by function_id;",
324 run_sql(db_callback
, "select function_id, type, parameter, key, value from caller_info"
325 " where %s", sql_filter
);
328 static char *ptr_name
;
329 static int get_ptr_name(void *unused
, int argc
, char **argv
, char **azColName
)
332 ptr_name
= alloc_string(argv
[0]);
336 static void get_function_pointer_callers(struct symbol
*sym
)
339 run_sql(get_ptr_name
, "select ptr from function_ptr where function = '%s'",
344 run_sql(db_callback
, "select function_id, type, parameter, key, value from caller_info"
345 " where function = '%s' order by function_id", ptr_name
);
348 static void match_data_from_db(struct symbol
*sym
)
352 if (!sym
|| !sym
->ident
|| !sym
->ident
->name
)
355 __push_fake_cur_slist();
359 get_direct_callers(sym
);
360 get_function_pointer_callers(sym
);
362 merge_slist(&final_states
, __pop_fake_cur_slist());
364 FOR_EACH_PTR(final_states
, sm
) {
366 } END_FOR_EACH_PTR(sm
);
368 free_slist(&final_states
);
371 static void match_function_assign(struct expression
*expr
)
373 struct expression
*right
= expr
->right
;
378 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
380 if (right
->type
!= EXPR_SYMBOL
)
382 sym
= get_type(right
);
383 if (!sym
|| sym
->type
!= SYM_FN
)
386 fn_name
= get_variable_from_expr(right
, NULL
);
387 ptr_name
= get_fnptr_name(expr
->left
);
388 if (!fn_name
|| !ptr_name
)
391 sm_msg("info: sets_fn_ptr '%s' '%s'", ptr_name
, fn_name
);
394 free_string(fn_name
);
395 free_string(ptr_name
);
398 static struct expression
*call_implies_call_expr
;
399 static int call_implies_callbacks(void *unused
, int argc
, char **argv
, char **azColName
)
401 struct call_implies_callback
*cb
;
402 struct expression
*arg
= NULL
;
409 type
= atoi(argv
[1]);
410 param
= atoi(argv
[2]);
412 FOR_EACH_PTR(call_implies_cb_list
, cb
) {
413 if (cb
->type
!= type
)
416 arg
= get_argument_from_call_expr(call_implies_call_expr
->args
, param
);
420 cb
->callback(arg
, argv
[3]);
421 } END_FOR_EACH_PTR(cb
);
426 static void match_call_implies(struct expression
*expr
)
429 static char sql_filter
[1024];
431 if (expr
->fn
->type
!= EXPR_SYMBOL
)
433 sym
= expr
->fn
->symbol
;
437 if (sym
->ctype
.modifiers
& MOD_STATIC
) {
438 snprintf(sql_filter
, 1024, "file = '%s' and function = '%s';",
439 get_filename(), sym
->ident
->name
);
441 snprintf(sql_filter
, 1024, "function = '%s' and static = 0;",
445 call_implies_call_expr
= expr
;
446 run_sql(call_implies_callbacks
,
447 "select function, type, parameter, value from call_implies where %s",
452 static void print_initializer_list(struct expression_list
*expr_list
,
453 struct symbol
*struct_type
)
455 struct expression
*expr
;
456 struct symbol
*base_type
;
458 FOR_EACH_PTR(expr_list
, expr
) {
459 if (expr
->type
== EXPR_INDEX
&& expr
->idx_expression
&& expr
->idx_expression
->type
== EXPR_INITIALIZER
) {
460 print_initializer_list(expr
->idx_expression
->expr_list
, struct_type
);
463 if (expr
->type
!= EXPR_IDENTIFIER
)
465 if (!expr
->expr_ident
)
467 if (!expr
->ident_expression
|| !expr
->ident_expression
->symbol_name
)
469 base_type
= get_type(expr
->ident_expression
);
470 if (!base_type
|| base_type
->type
!= SYM_FN
)
472 sm_msg("info: sets_fn_ptr '(struct %s)->%s' '%s'", struct_type
->ident
->name
,
473 expr
->expr_ident
->name
,
474 expr
->ident_expression
->symbol_name
->name
);
475 } END_FOR_EACH_PTR(expr
);
478 static void global_variable(struct symbol
*sym
)
480 struct symbol
*struct_type
;
484 if (!sym
->initializer
|| sym
->initializer
->type
!= EXPR_INITIALIZER
)
486 struct_type
= get_base_type(sym
);
489 if (struct_type
->type
== SYM_ARRAY
) {
490 struct_type
= get_base_type(struct_type
);
494 if (struct_type
->type
!= SYM_STRUCT
|| !struct_type
->ident
)
496 print_initializer_list(sym
->initializer
->expr_list
, struct_type
);
499 static void match_return_info(struct expression
*ret_value
)
501 struct range_list
*rl
;
503 get_implied_range_list(ret_value
, &rl
);
504 rl
= cast_rl(cur_func_return_type(), rl
);
505 sm_msg("info: return_marker %d '%s' %s",
506 get_return_id(), show_ranges(rl
), global_static());
509 static void print_returned_struct_members(struct expression
*expr
)
511 struct returned_member_callback
*cb
;
512 struct state_list
*slist
;
515 struct range_list
*rl
;
518 char member_name
[256];
521 type
= get_type(expr
);
522 if (!type
|| type
->type
!= SYM_PTR
)
524 type
= get_real_base_type(type
);
525 if (!type
|| type
->type
!= SYM_STRUCT
)
527 name
= get_variable_from_expr(expr
, NULL
);
531 if (!get_implied_range_list(expr
, &rl
))
533 return_ranges
= show_ranges(rl
);
535 member_name
[sizeof(member_name
) - 1] = '\0';
536 strcpy(member_name
, "$$");
539 FOR_EACH_PTR(returned_member_callbacks
, cb
) {
540 slist
= get_all_states(cb
->owner
);
541 FOR_EACH_PTR(slist
, sm
) {
542 if (strncmp(sm
->name
, name
, len
) != 0)
544 if (strncmp(sm
->name
+ len
, "->", 2) != 0)
546 strncpy(member_name
+ 2, sm
->name
+ len
, sizeof(member_name
) - 2);
547 cb
->callback(return_ranges
, member_name
, sm
->state
);
548 } END_FOR_EACH_PTR(sm
);
550 } END_FOR_EACH_PTR(cb
);
555 static void match_end_func_info(struct symbol
*sym
)
557 if (__path_is_null())
559 sm_msg("info: return_marker %d '' %s", get_return_id(), global_static());
562 static void match_function_def(struct symbol
*sym
)
567 static void match_return(struct expression
*ret_value
)
572 static void match_end_func(struct symbol
*sym
)
577 void open_smatch_db(void)
579 #ifdef SQLITE_OPEN_READONLY
585 rc
= sqlite3_open_v2("smatch_db.sqlite", &db
, SQLITE_OPEN_READONLY
, NULL
);
586 if (rc
!= SQLITE_OK
) {
597 void register_definition_db_callbacks(int id
)
599 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
600 add_hook(&match_return
, RETURN_HOOK
);
601 add_hook(&match_end_func
, END_FUNC_HOOK
);
604 add_hook(&match_call_info
, FUNCTION_CALL_HOOK
);
605 add_hook(&match_call_hack
, FUNCTION_CALL_HOOK
);
606 add_hook(&match_function_assign
, ASSIGNMENT_HOOK
);
607 add_hook(&global_variable
, BASE_HOOK
);
608 add_hook(&global_variable
, DECLARATION_HOOK
);
609 add_hook(&match_return_info
, RETURN_HOOK
);
610 add_hook(&print_returned_struct_members
, RETURN_HOOK
);
611 add_hook(&match_end_func_info
, END_FUNC_HOOK
);
617 add_hook(&match_data_from_db
, FUNC_DEF_HOOK
);
618 add_hook(&match_call_implies
, FUNCTION_CALL_HOOK
);