2 * Copyright (C) 2013 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * Track how functions are saved as various struct members or passed as
26 #include "smatch_slist.h"
30 static char *get_from__symbol_get(struct expression
*expr
)
32 struct expression
*arg
;
35 * typeof(&dib0070_attach) __a =
36 * ((((typeof(&dib0070_attach)) (__symbol_get("dib0070_attach")))) ?:
37 * (__request_module(true, "symbol:" "dib0070_attach"), (((typeof(&dib0070_attach))(__symbol_get("dib0070_attach"))))));
40 expr
= strip_expr(expr
);
42 if (expr
->type
!= EXPR_CALL
)
44 if (!sym_name_is("__symbol_get", expr
->fn
))
46 arg
= get_argument_from_call_expr(expr
->args
, 0);
47 if (!arg
|| arg
->type
!= EXPR_STRING
)
50 return alloc_string(arg
->string
->data
);
53 static int xxx_is_array(struct expression
*expr
)
57 expr
= strip_expr(expr
);
61 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*') {
62 expr
= strip_expr(expr
->unop
);
65 if (expr
->type
== EXPR_BINOP
&& expr
->op
== '+')
69 if (expr
->type
!= EXPR_BINOP
|| expr
->op
!= '+')
72 type
= get_type(expr
->left
);
75 if (type
->type
!= SYM_ARRAY
&& type
->type
!= SYM_PTR
)
81 static struct expression
*xxx_get_array_base(struct expression
*expr
)
83 if (!xxx_is_array(expr
))
85 expr
= strip_expr(expr
);
86 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*')
87 expr
= strip_expr(expr
->unop
);
88 if (expr
->type
!= EXPR_BINOP
|| expr
->op
!= '+')
90 return strip_parens(expr
->left
);
93 static char *get_array_ptr(struct expression
*expr
)
95 struct expression
*array
;
100 array
= xxx_get_array_base(expr
);
103 name
= get_member_name(array
);
105 return alloc_string(name
);
108 /* FIXME: is_array() should probably be is_array_element() */
109 type
= get_type(expr
);
110 if (!array
&& type
&& type
->type
== SYM_ARRAY
)
113 name
= expr_to_var(array
);
116 snprintf(buf
, sizeof(buf
), "%s[]", name
);
117 return alloc_string(buf
);
120 expr
= get_assigned_expr(expr
);
121 array
= xxx_get_array_base(expr
);
124 name
= expr_to_var(array
);
127 snprintf(buf
, sizeof(buf
), "%s[]", name
);
129 return alloc_string(buf
);
132 static int is_local_symbol(struct symbol
*sym
)
135 !(sym
->ctype
.modifiers
& MOD_TOPLEVEL
))
140 static char *ptr_prefix(struct symbol
*sym
)
142 static char buf
[128];
144 if (is_local_symbol(sym
))
145 snprintf(buf
, sizeof(buf
), "%s ptr", get_function());
146 else if (sym
&& toplevel(sym
->scope
))
147 snprintf(buf
, sizeof(buf
), "%s ptr", get_base_file());
149 snprintf(buf
, sizeof(buf
), "ptr");
154 char *get_returned_ptr(struct expression
*expr
)
160 if (expr
->type
!= EXPR_CALL
)
162 if (!expr
->fn
|| expr
->fn
->type
!= EXPR_SYMBOL
)
165 type
= get_type(expr
);
166 if (type
&& type
->type
== SYM_PTR
)
167 type
= get_real_base_type(type
);
168 if (!type
|| type
->type
!= SYM_FN
)
171 name
= expr_to_var(expr
->fn
);
174 snprintf(buf
, sizeof(buf
), "r %s()", name
);
176 return alloc_string(buf
);
179 char *get_fnptr_name(struct expression
*expr
)
183 if (expr_is_zero(expr
))
186 expr
= strip_expr(expr
);
188 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
189 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*')
190 expr
= strip_expr(expr
->unop
);
192 name
= get_from__symbol_get(expr
);
196 name
= get_array_ptr(expr
);
200 name
= get_returned_ptr(expr
);
204 name
= get_member_name(expr
);
206 return alloc_string(name
);
208 if (expr
->type
== EXPR_SYMBOL
) {
214 param
= get_param_num_from_sym(expr
->symbol
);
216 snprintf(buf
, sizeof(buf
), "%s param %d", get_function(), param
);
217 return alloc_string(buf
);
220 name
= expr_to_var_sym(expr
, &sym
);
223 type
= get_type(expr
);
224 if (type
&& type
->type
== SYM_PTR
) {
225 snprintf(buf
, sizeof(buf
), "%s %s", ptr_prefix(sym
), name
);
227 return alloc_string(buf
);
231 return expr_to_var(expr
);
234 static int get_arg_count(struct expression
*fn
)
236 struct symbol
*fn_type
;
238 fn_type
= get_type(fn
);
241 if (fn_type
->type
== SYM_PTR
)
242 fn_type
= get_real_base_type(fn_type
);
243 if (fn_type
->type
!= SYM_FN
)
246 return ptr_list_size((struct ptr_list
*)fn_type
->arguments
);
249 static void match_passes_function_pointer(struct expression
*expr
)
251 struct expression
*arg
, *tmp
;
258 cnt
= get_arg_count(expr
->fn
);
261 FOR_EACH_PTR(expr
->args
, arg
) {
267 tmp
= strip_expr(arg
);
268 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&')
269 tmp
= strip_expr(tmp
->unop
);
271 type
= get_type(tmp
);
272 if (type
&& type
->type
== SYM_PTR
)
273 type
= get_real_base_type(type
);
274 if (!type
|| type
->type
!= SYM_FN
)
277 called_name
= expr_to_var(expr
->fn
);
280 fn_name
= get_fnptr_name(tmp
);
284 snprintf(ptr_name
, sizeof(ptr_name
), "%s param %d", called_name
, i
);
285 sql_insert_function_ptr(fn_name
, ptr_name
);
287 free_string(fn_name
);
288 free_string(called_name
);
289 } END_FOR_EACH_PTR(arg
);
292 static int get_row_count(void *_row_count
, int argc
, char **argv
, char **azColName
)
294 int *row_count
= _row_count
;
299 *row_count
= atoi(argv
[0]);
303 static int can_hold_function_ptr(struct expression
*expr
)
307 type
= get_type(expr
);
310 if (type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
) {
311 type
= get_real_base_type(type
);
315 /* pointer to a pointer */
316 if (type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
) {
317 type
= get_real_base_type(type
);
321 if (type
->type
== SYM_FN
)
323 if (type
== &ulong_ctype
&& expr
->type
== EXPR_DEREF
)
325 if (type
== &void_ctype
)
330 static void match_function_assign(struct expression
*expr
)
332 struct expression
*right
;
337 if (__in_fake_assign
)
339 if (is_fake_var_assign(expr
))
342 right
= strip_expr(expr
->right
);
343 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
344 right
= strip_expr(right
->unop
);
346 if (right
->type
!= EXPR_SYMBOL
&&
347 right
->type
!= EXPR_DEREF
&&
348 right
->type
!= EXPR_CALL
)
351 if (!can_hold_function_ptr(right
) ||
352 !can_hold_function_ptr(expr
->left
))
355 fn_name
= get_fnptr_name(right
);
356 ptr_name
= get_fnptr_name(expr
->left
);
357 if (!fn_name
|| !ptr_name
)
359 if (strcmp(fn_name
, ptr_name
) == 0)
363 type
= get_type(right
);
366 if (type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
) {
367 type
= get_real_base_type(type
);
371 if (type
->type
!= SYM_FN
) {
374 /* look it up in function_ptr */
375 run_sql(get_row_count
, &count
,
376 "select count(*) from function_ptr where ptr = '%s'",
382 sql_insert_function_ptr(fn_name
, ptr_name
);
384 free_string(fn_name
);
385 free_string(ptr_name
);
388 static void match_returns_function_pointer(struct expression
*expr
)
397 type
= get_real_base_type(cur_func_sym
);
398 if (!type
|| type
->type
!= SYM_FN
)
400 type
= get_real_base_type(type
);
401 if (!type
|| type
->type
!= SYM_PTR
)
403 type
= get_real_base_type(type
);
404 if (!type
|| type
->type
!= SYM_FN
)
407 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
408 expr
= strip_expr(expr
->unop
);
410 fn_name
= get_fnptr_name(expr
);
413 snprintf(ptr_name
, sizeof(ptr_name
), "r %s()", get_function());
414 sql_insert_function_ptr(fn_name
, ptr_name
);
417 static void print_initializer_list(struct expression_list
*expr_list
,
418 struct symbol
*struct_type
)
420 struct expression
*expr
;
421 struct symbol
*base_type
;
422 char struct_name
[256];
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
);
429 if (expr
->type
!= EXPR_IDENTIFIER
)
431 if (!expr
->expr_ident
)
433 if (!expr
->ident_expression
||
434 expr
->ident_expression
->type
!= EXPR_SYMBOL
||
435 !expr
->ident_expression
->symbol_name
)
437 base_type
= get_type(expr
->ident_expression
);
438 if (!base_type
|| base_type
->type
!= SYM_FN
)
440 snprintf(struct_name
, sizeof(struct_name
), "(struct %s)->%s",
441 struct_type
->ident
->name
, expr
->expr_ident
->name
);
442 sql_insert_function_ptr(expr
->ident_expression
->symbol_name
->name
,
444 } END_FOR_EACH_PTR(expr
);
447 static void global_variable(struct symbol
*sym
)
449 struct symbol
*struct_type
;
453 if (!sym
->initializer
|| sym
->initializer
->type
!= EXPR_INITIALIZER
)
455 struct_type
= get_base_type(sym
);
458 if (struct_type
->type
== SYM_ARRAY
) {
459 struct_type
= get_base_type(struct_type
);
463 if (struct_type
->type
!= SYM_STRUCT
|| !struct_type
->ident
)
465 print_initializer_list(sym
->initializer
->expr_list
, struct_type
);
468 void register_function_ptrs(int id
)
475 add_hook(&global_variable
, BASE_HOOK
);
476 add_hook(&global_variable
, DECLARATION_HOOK
);
477 add_hook(&match_passes_function_pointer
, FUNCTION_CALL_HOOK
);
478 add_hook(&match_returns_function_pointer
, RETURN_HOOK
);
479 add_hook(&match_function_assign
, ASSIGNMENT_HOOK
);
480 add_hook(&match_function_assign
, GLOBAL_ASSIGNMENT_HOOK
);