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 char *get_array_ptr(struct expression
*expr
)
55 struct expression
*array
;
60 array
= get_array_base(expr
);
63 name
= get_member_name(array
);
68 /* FIXME: is_array() should probably be is_array_element() */
69 type
= get_type(expr
);
70 if (!array
&& type
&& type
->type
== SYM_ARRAY
)
73 name
= expr_to_var(array
);
76 snprintf(buf
, sizeof(buf
), "%s[]", name
);
77 return alloc_string(buf
);
80 expr
= get_assigned_expr(expr
);
81 array
= get_array_base(expr
);
84 name
= expr_to_var(array
);
87 snprintf(buf
, sizeof(buf
), "%s[]", name
);
89 return alloc_string(buf
);
92 static int is_local_symbol(struct symbol
*sym
)
95 !(sym
->ctype
.modifiers
& MOD_TOPLEVEL
))
100 static char *ptr_prefix(struct symbol
*sym
)
102 static char buf
[128];
105 if (is_local_symbol(sym
))
106 snprintf(buf
, sizeof(buf
), "%s ptr", get_function());
107 else if (sym
&& toplevel(sym
->scope
))
108 snprintf(buf
, sizeof(buf
), "%s ptr", get_base_file());
110 snprintf(buf
, sizeof(buf
), "ptr");
115 char *get_returned_ptr(struct expression
*expr
)
121 if (expr
->type
!= EXPR_CALL
)
123 if (!expr
->fn
|| expr
->fn
->type
!= EXPR_SYMBOL
)
126 type
= get_type(expr
);
127 if (type
&& type
->type
== SYM_PTR
)
128 type
= get_real_base_type(type
);
129 if (!type
|| type
->type
!= SYM_FN
)
132 name
= expr_to_var(expr
->fn
);
135 snprintf(buf
, sizeof(buf
), "r %s()", name
);
137 return alloc_string(buf
);
140 char *get_fnptr_name(struct expression
*expr
)
144 expr
= strip_expr(expr
);
146 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
147 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*')
148 expr
= strip_expr(expr
->unop
);
150 name
= get_from__symbol_get(expr
);
154 name
= get_array_ptr(expr
);
158 name
= get_returned_ptr(expr
);
162 name
= get_member_name(expr
);
166 if (expr
->type
== EXPR_SYMBOL
) {
172 param
= get_param_num_from_sym(expr
->symbol
);
174 snprintf(buf
, sizeof(buf
), "%s param %d", get_function(), param
);
175 return alloc_string(buf
);
178 name
= expr_to_var_sym(expr
, &sym
);
181 type
= get_type(expr
);
182 if (type
&& type
->type
== SYM_PTR
) {
183 snprintf(buf
, sizeof(buf
), "%s %s", ptr_prefix(sym
), name
);
185 return alloc_string(buf
);
189 return expr_to_var(expr
);
192 static void match_passes_function_pointer(struct expression
*expr
)
194 struct expression
*arg
, *tmp
;
203 FOR_EACH_PTR(expr
->args
, arg
) {
206 tmp
= strip_expr(arg
);
207 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&')
208 tmp
= strip_expr(tmp
->unop
);
210 type
= get_type(tmp
);
211 if (type
&& type
->type
== SYM_PTR
)
212 type
= get_real_base_type(type
);
213 if (!type
|| type
->type
!= SYM_FN
)
216 called_name
= expr_to_var(expr
->fn
);
219 fn_name
= get_fnptr_name(tmp
);
223 snprintf(ptr_name
, sizeof(ptr_name
), "%s param %d", called_name
, i
);
224 sql_insert_function_ptr(fn_name
, ptr_name
);
226 free_string(fn_name
);
227 free_string(called_name
);
228 } END_FOR_EACH_PTR(arg
);
232 static int get_row_count(void *_row_count
, int argc
, char **argv
, char **azColName
)
234 int *row_count
= _row_count
;
239 *row_count
= atoi(argv
[0]);
243 static int can_hold_function_ptr(struct expression
*expr
)
247 type
= get_type(expr
);
250 if (type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
) {
251 type
= get_real_base_type(type
);
255 if (type
->type
== SYM_FN
)
257 if (type
== &ulong_ctype
&& expr
->type
== EXPR_DEREF
)
259 if (type
== &void_ctype
)
264 static void match_function_assign(struct expression
*expr
)
266 struct expression
*right
;
271 if (__in_fake_assign
)
274 right
= strip_expr(expr
->right
);
275 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
276 right
= strip_expr(right
->unop
);
278 if (right
->type
!= EXPR_SYMBOL
&&
279 right
->type
!= EXPR_DEREF
)
282 if (!can_hold_function_ptr(right
) ||
283 !can_hold_function_ptr(expr
->left
))
286 fn_name
= get_fnptr_name(right
);
287 ptr_name
= get_fnptr_name(expr
->left
);
288 if (!fn_name
|| !ptr_name
)
290 if (strcmp(fn_name
, ptr_name
) == 0)
294 type
= get_type(right
);
297 if (type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
) {
298 type
= get_real_base_type(type
);
302 if (type
->type
!= SYM_FN
) {
305 /* look it up in function_ptr */
306 run_sql(get_row_count
, &count
,
307 "select count(*) from function_ptr where ptr = '%s'",
313 sql_insert_function_ptr(fn_name
, ptr_name
);
315 free_string(fn_name
);
316 free_string(ptr_name
);
319 static void match_returns_function_pointer(struct expression
*expr
)
328 type
= get_real_base_type(cur_func_sym
);
329 if (!type
|| type
->type
!= SYM_FN
)
331 type
= get_real_base_type(type
);
332 if (!type
|| type
->type
!= SYM_PTR
)
334 type
= get_real_base_type(type
);
335 if (!type
|| type
->type
!= SYM_FN
)
338 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
339 expr
= strip_expr(expr
->unop
);
341 fn_name
= get_fnptr_name(expr
);
344 snprintf(ptr_name
, sizeof(ptr_name
), "r %s()", get_function());
345 sql_insert_function_ptr(fn_name
, ptr_name
);
348 void register_function_ptrs(int id
)
355 add_hook(&match_passes_function_pointer
, FUNCTION_CALL_HOOK
);
356 add_hook(&match_returns_function_pointer
, RETURN_HOOK
);
357 add_hook(&match_function_assign
, ASSIGNMENT_HOOK
);
358 add_hook(&match_function_assign
, GLOBAL_ASSIGNMENT_HOOK
);