Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_function_ptrs.c
+++ new/usr/src/tools/smatch/src/smatch_function_ptrs.c
1 1 /*
2 2 * Copyright (C) 2013 Oracle.
3 3 *
4 4 * This program is free software; you can redistribute it and/or
5 5 * modify it under the terms of the GNU General Public License
6 6 * as published by the Free Software Foundation; either version 2
7 7 * of the License, or (at your option) any later version.
8 8 *
9 9 * This program is distributed in the hope that it will be useful,
10 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 * GNU General Public License for more details.
13 13 *
14 14 * You should have received a copy of the GNU General Public License
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 /*
19 19 * Track how functions are saved as various struct members or passed as
20 20 * parameters.
21 21 *
22 22 */
23 23
24 24 #include "scope.h"
25 25 #include "smatch.h"
26 26 #include "smatch_slist.h"
27 27
28 28 static int my_id;
29 29
30 30 static char *get_from__symbol_get(struct expression *expr)
31 31 {
32 32 struct expression *arg;
33 33
34 34 /*
35 35 * typeof(&dib0070_attach) __a =
36 36 * ((((typeof(&dib0070_attach)) (__symbol_get("dib0070_attach")))) ?:
37 37 * (__request_module(true, "symbol:" "dib0070_attach"), (((typeof(&dib0070_attach))(__symbol_get("dib0070_attach"))))));
38 38 */
39 39
40 40 expr = strip_expr(expr);
41 41
42 42 if (expr->type != EXPR_CALL)
43 43 return NULL;
44 44 if (!sym_name_is("__symbol_get", expr->fn))
45 45 return NULL;
46 46 arg = get_argument_from_call_expr(expr->args, 0);
47 47 if (!arg || arg->type != EXPR_STRING)
48 48 return NULL;
49 49
50 50 return alloc_string(arg->string->data);
51 51 }
52 52
53 53 static char *get_array_ptr(struct expression *expr)
54 54 {
55 55 struct expression *array;
56 56 struct symbol *type;
57 57 char *name;
58 58 char buf[256];
59 59
60 60 array = get_array_base(expr);
61 61
62 62 if (array) {
63 63 name = get_member_name(array);
64 64 if (name)
65 65 return name;
66 66 }
67 67
68 68 /* FIXME: is_array() should probably be is_array_element() */
69 69 type = get_type(expr);
70 70 if (!array && type && type->type == SYM_ARRAY)
71 71 array = expr;
72 72 if (array) {
73 73 name = expr_to_var(array);
74 74 if (!name)
75 75 return NULL;
76 76 snprintf(buf, sizeof(buf), "%s[]", name);
77 77 return alloc_string(buf);
78 78 }
79 79
80 80 expr = get_assigned_expr(expr);
81 81 array = get_array_base(expr);
82 82 if (!array)
83 83 return NULL;
84 84 name = expr_to_var(array);
85 85 if (!name)
86 86 return NULL;
87 87 snprintf(buf, sizeof(buf), "%s[]", name);
88 88 free_string(name);
89 89 return alloc_string(buf);
90 90 }
91 91
92 92 static int is_local_symbol(struct symbol *sym)
93 93 {
94 94 if (!sym ||
95 95 !(sym->ctype.modifiers & MOD_TOPLEVEL))
96 96 return 1;
97 97 return 0;
98 98 }
99 99
100 100 static char *ptr_prefix(struct symbol *sym)
101 101 {
102 102 static char buf[128];
103 103
104 104
105 105 if (is_local_symbol(sym))
106 106 snprintf(buf, sizeof(buf), "%s ptr", get_function());
107 107 else if (sym && toplevel(sym->scope))
108 108 snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
109 109 else
110 110 snprintf(buf, sizeof(buf), "ptr");
111 111
112 112 return buf;
113 113 }
114 114
115 115 char *get_returned_ptr(struct expression *expr)
116 116 {
117 117 struct symbol *type;
118 118 char *name;
119 119 char buf[256];
120 120
121 121 if (expr->type != EXPR_CALL)
122 122 return NULL;
123 123 if (!expr->fn || expr->fn->type != EXPR_SYMBOL)
124 124 return NULL;
125 125
126 126 type = get_type(expr);
127 127 if (type && type->type == SYM_PTR)
128 128 type = get_real_base_type(type);
129 129 if (!type || type->type != SYM_FN)
130 130 return NULL;
131 131
132 132 name = expr_to_var(expr->fn);
133 133 if (!name)
↓ open down ↓ |
133 lines elided |
↑ open up ↑ |
134 134 return NULL;
135 135 snprintf(buf, sizeof(buf), "r %s()", name);
136 136 free_string(name);
137 137 return alloc_string(buf);
138 138 }
139 139
140 140 char *get_fnptr_name(struct expression *expr)
141 141 {
142 142 char *name;
143 143
144 + if (is_zero(expr))
145 + return NULL;
146 +
144 147 expr = strip_expr(expr);
145 148
146 149 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
147 150 if (expr->type == EXPR_PREOP && expr->op == '*')
148 151 expr = strip_expr(expr->unop);
149 152
150 153 name = get_from__symbol_get(expr);
151 154 if (name)
152 155 return name;
153 156
154 157 name = get_array_ptr(expr);
155 158 if (name)
156 159 return name;
157 160
158 161 name = get_returned_ptr(expr);
159 162 if (name)
160 163 return name;
161 164
162 165 name = get_member_name(expr);
163 166 if (name)
164 167 return name;
165 168
166 169 if (expr->type == EXPR_SYMBOL) {
167 170 int param;
168 171 char buf[256];
169 172 struct symbol *sym;
170 173 struct symbol *type;
171 174
172 175 param = get_param_num_from_sym(expr->symbol);
173 176 if (param >= 0) {
174 177 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
175 178 return alloc_string(buf);
176 179 }
177 180
178 181 name = expr_to_var_sym(expr, &sym);
179 182 if (!name)
180 183 return NULL;
181 184 type = get_type(expr);
182 185 if (type && type->type == SYM_PTR) {
183 186 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
184 187 free_string(name);
185 188 return alloc_string(buf);
186 189 }
187 190 return name;
188 191 }
189 192 return expr_to_var(expr);
190 193 }
191 194
192 195 static void match_passes_function_pointer(struct expression *expr)
193 196 {
194 197 struct expression *arg, *tmp;
195 198 struct symbol *type;
196 199 char *called_name;
197 200 char *fn_name;
198 201 char ptr_name[256];
199 202 int i;
200 203
201 204
202 205 i = -1;
203 206 FOR_EACH_PTR(expr->args, arg) {
204 207 i++;
205 208
206 209 tmp = strip_expr(arg);
207 210 if (tmp->type == EXPR_PREOP && tmp->op == '&')
208 211 tmp = strip_expr(tmp->unop);
209 212
210 213 type = get_type(tmp);
211 214 if (type && type->type == SYM_PTR)
212 215 type = get_real_base_type(type);
213 216 if (!type || type->type != SYM_FN)
214 217 continue;
215 218
216 219 called_name = expr_to_var(expr->fn);
217 220 if (!called_name)
218 221 return;
219 222 fn_name = get_fnptr_name(tmp);
220 223 if (!fn_name)
221 224 goto free;
222 225
223 226 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
224 227 sql_insert_function_ptr(fn_name, ptr_name);
225 228 free:
226 229 free_string(fn_name);
227 230 free_string(called_name);
228 231 } END_FOR_EACH_PTR(arg);
229 232
230 233 }
231 234
232 235 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
233 236 {
234 237 int *row_count = _row_count;
235 238
236 239 *row_count = 0;
237 240 if (argc != 1)
238 241 return 0;
239 242 *row_count = atoi(argv[0]);
240 243 return 0;
241 244 }
242 245
243 246 static int can_hold_function_ptr(struct expression *expr)
244 247 {
245 248 struct symbol *type;
246 249
247 250 type = get_type(expr);
248 251 if (!type)
249 252 return 0;
250 253 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
251 254 type = get_real_base_type(type);
252 255 if (!type)
253 256 return 0;
254 257 }
255 258 if (type->type == SYM_FN)
256 259 return 1;
257 260 if (type == &ulong_ctype && expr->type == EXPR_DEREF)
258 261 return 1;
259 262 if (type == &void_ctype)
260 263 return 1;
261 264 return 0;
262 265 }
263 266
264 267 static void match_function_assign(struct expression *expr)
265 268 {
266 269 struct expression *right;
267 270 struct symbol *type;
268 271 char *fn_name;
269 272 char *ptr_name;
270 273
271 274 if (__in_fake_assign)
272 275 return;
273 276
274 277 right = strip_expr(expr->right);
275 278 if (right->type == EXPR_PREOP && right->op == '&')
276 279 right = strip_expr(right->unop);
277 280
278 281 if (right->type != EXPR_SYMBOL &&
279 282 right->type != EXPR_DEREF)
280 283 return;
281 284
282 285 if (!can_hold_function_ptr(right) ||
283 286 !can_hold_function_ptr(expr->left))
284 287 return;
285 288
286 289 fn_name = get_fnptr_name(right);
287 290 ptr_name = get_fnptr_name(expr->left);
288 291 if (!fn_name || !ptr_name)
289 292 goto free;
290 293 if (strcmp(fn_name, ptr_name) == 0)
291 294 goto free;
292 295
293 296
294 297 type = get_type(right);
295 298 if (!type)
296 299 return;
297 300 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
298 301 type = get_real_base_type(type);
299 302 if (!type)
300 303 return;
301 304 }
302 305 if (type->type != SYM_FN) {
303 306 int count = 0;
304 307
305 308 /* look it up in function_ptr */
306 309 run_sql(get_row_count, &count,
307 310 "select count(*) from function_ptr where ptr = '%s'",
308 311 fn_name);
309 312 if (count == 0)
310 313 goto free;
311 314 }
312 315
313 316 sql_insert_function_ptr(fn_name, ptr_name);
314 317 free:
315 318 free_string(fn_name);
316 319 free_string(ptr_name);
317 320 }
318 321
319 322 static void match_returns_function_pointer(struct expression *expr)
320 323 {
321 324 struct symbol *type;
322 325 char *fn_name;
323 326 char ptr_name[256];
324 327
325 328 if (__inline_fn)
326 329 return;
327 330
328 331 type = get_real_base_type(cur_func_sym);
329 332 if (!type || type->type != SYM_FN)
330 333 return;
331 334 type = get_real_base_type(type);
332 335 if (!type || type->type != SYM_PTR)
333 336 return;
334 337 type = get_real_base_type(type);
335 338 if (!type || type->type != SYM_FN)
336 339 return;
337 340
↓ open down ↓ |
184 lines elided |
↑ open up ↑ |
338 341 if (expr->type == EXPR_PREOP && expr->op == '&')
339 342 expr = strip_expr(expr->unop);
340 343
341 344 fn_name = get_fnptr_name(expr);
342 345 if (!fn_name)
343 346 return;
344 347 snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function());
345 348 sql_insert_function_ptr(fn_name, ptr_name);
346 349 }
347 350
351 +static void print_initializer_list(struct expression_list *expr_list,
352 + struct symbol *struct_type)
353 +{
354 + struct expression *expr;
355 + struct symbol *base_type;
356 + char struct_name[256];
357 +
358 + FOR_EACH_PTR(expr_list, expr) {
359 + if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
360 + print_initializer_list(expr->idx_expression->expr_list, struct_type);
361 + continue;
362 + }
363 + if (expr->type != EXPR_IDENTIFIER)
364 + continue;
365 + if (!expr->expr_ident)
366 + continue;
367 + if (!expr->ident_expression ||
368 + expr->ident_expression->type != EXPR_SYMBOL ||
369 + !expr->ident_expression->symbol_name)
370 + continue;
371 + base_type = get_type(expr->ident_expression);
372 + if (!base_type || base_type->type != SYM_FN)
373 + continue;
374 + snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
375 + struct_type->ident->name, expr->expr_ident->name);
376 + sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
377 + struct_name);
378 + } END_FOR_EACH_PTR(expr);
379 +}
380 +
381 +static void global_variable(struct symbol *sym)
382 +{
383 + struct symbol *struct_type;
384 +
385 + if (!sym->ident)
386 + return;
387 + if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
388 + return;
389 + struct_type = get_base_type(sym);
390 + if (!struct_type)
391 + return;
392 + if (struct_type->type == SYM_ARRAY) {
393 + struct_type = get_base_type(struct_type);
394 + if (!struct_type)
395 + return;
396 + }
397 + if (struct_type->type != SYM_STRUCT || !struct_type->ident)
398 + return;
399 + print_initializer_list(sym->initializer->expr_list, struct_type);
400 +}
401 +
348 402 void register_function_ptrs(int id)
349 403 {
350 404 my_id = id;
351 405
352 406 if (!option_info)
353 407 return;
354 408
409 + add_hook(&global_variable, BASE_HOOK);
410 + add_hook(&global_variable, DECLARATION_HOOK);
355 411 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
356 412 add_hook(&match_returns_function_pointer, RETURN_HOOK);
357 413 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
358 414 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);
359 415 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX