Print this page
12724 update smatch to 0.6.1-rc1-il-5
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 int xxx_is_array(struct expression *expr)
54 54 {
55 55 struct symbol *type;
56 56
57 57 expr = strip_expr(expr);
58 58 if (!expr)
59 59 return 0;
60 60
61 61 if (expr->type == EXPR_PREOP && expr->op == '*') {
62 62 expr = strip_expr(expr->unop);
63 63 if (!expr)
64 64 return 0;
65 65 if (expr->type == EXPR_BINOP && expr->op == '+')
66 66 return 1;
67 67 }
68 68
69 69 if (expr->type != EXPR_BINOP || expr->op != '+')
70 70 return 0;
71 71
72 72 type = get_type(expr->left);
73 73 if (!type)
74 74 return 0;
75 75 if (type->type != SYM_ARRAY && type->type != SYM_PTR)
76 76 return 0;
77 77
78 78 return 1;
79 79 }
80 80
81 81 static struct expression *xxx_get_array_base(struct expression *expr)
82 82 {
83 83 if (!xxx_is_array(expr))
84 84 return NULL;
85 85 expr = strip_expr(expr);
86 86 if (expr->type == EXPR_PREOP && expr->op == '*')
87 87 expr = strip_expr(expr->unop);
88 88 if (expr->type != EXPR_BINOP || expr->op != '+')
89 89 return NULL;
90 90 return strip_parens(expr->left);
91 91 }
92 92
93 93 static char *get_array_ptr(struct expression *expr)
94 94 {
95 95 struct expression *array;
96 96 struct symbol *type;
97 97 char *name;
98 98 char buf[256];
99 99
100 100 array = xxx_get_array_base(expr);
101 101
102 102 if (array) {
103 103 name = get_member_name(array);
104 104 if (name)
105 105 return name;
106 106 }
107 107
108 108 /* FIXME: is_array() should probably be is_array_element() */
109 109 type = get_type(expr);
110 110 if (!array && type && type->type == SYM_ARRAY)
111 111 array = expr;
112 112 if (array) {
113 113 name = expr_to_var(array);
114 114 if (!name)
115 115 return NULL;
116 116 snprintf(buf, sizeof(buf), "%s[]", name);
117 117 return alloc_string(buf);
118 118 }
119 119
120 120 expr = get_assigned_expr(expr);
121 121 array = xxx_get_array_base(expr);
122 122 if (!array)
123 123 return NULL;
124 124 name = expr_to_var(array);
125 125 if (!name)
126 126 return NULL;
127 127 snprintf(buf, sizeof(buf), "%s[]", name);
128 128 free_string(name);
129 129 return alloc_string(buf);
130 130 }
131 131
132 132 static int is_local_symbol(struct symbol *sym)
133 133 {
134 134 if (!sym ||
135 135 !(sym->ctype.modifiers & MOD_TOPLEVEL))
136 136 return 1;
137 137 return 0;
138 138 }
139 139
140 140 static char *ptr_prefix(struct symbol *sym)
141 141 {
142 142 static char buf[128];
143 143
144 144
145 145 if (is_local_symbol(sym))
146 146 snprintf(buf, sizeof(buf), "%s ptr", get_function());
147 147 else if (sym && toplevel(sym->scope))
148 148 snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
149 149 else
150 150 snprintf(buf, sizeof(buf), "ptr");
151 151
152 152 return buf;
153 153 }
154 154
155 155 char *get_returned_ptr(struct expression *expr)
156 156 {
157 157 struct symbol *type;
158 158 char *name;
159 159 char buf[256];
160 160
161 161 if (expr->type != EXPR_CALL)
162 162 return NULL;
163 163 if (!expr->fn || expr->fn->type != EXPR_SYMBOL)
164 164 return NULL;
165 165
166 166 type = get_type(expr);
167 167 if (type && type->type == SYM_PTR)
168 168 type = get_real_base_type(type);
169 169 if (!type || type->type != SYM_FN)
170 170 return NULL;
171 171
172 172 name = expr_to_var(expr->fn);
173 173 if (!name)
174 174 return NULL;
175 175 snprintf(buf, sizeof(buf), "r %s()", name);
176 176 free_string(name);
177 177 return alloc_string(buf);
178 178 }
179 179
180 180 char *get_fnptr_name(struct expression *expr)
181 181 {
182 182 char *name;
183 183
184 184 if (expr_is_zero(expr))
185 185 return NULL;
186 186
187 187 expr = strip_expr(expr);
188 188
189 189 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
190 190 if (expr->type == EXPR_PREOP && expr->op == '*')
191 191 expr = strip_expr(expr->unop);
192 192
193 193 name = get_from__symbol_get(expr);
194 194 if (name)
195 195 return name;
196 196
197 197 name = get_array_ptr(expr);
198 198 if (name)
199 199 return name;
200 200
201 201 name = get_returned_ptr(expr);
202 202 if (name)
203 203 return name;
204 204
205 205 name = get_member_name(expr);
206 206 if (name)
207 207 return name;
208 208
209 209 if (expr->type == EXPR_SYMBOL) {
210 210 int param;
↓ open down ↓ |
210 lines elided |
↑ open up ↑ |
211 211 char buf[256];
212 212 struct symbol *sym;
213 213 struct symbol *type;
214 214
215 215 param = get_param_num_from_sym(expr->symbol);
216 216 if (param >= 0) {
217 217 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
218 218 return alloc_string(buf);
219 219 }
220 220
221 - name = expr_to_var_sym(expr, &sym);
221 + name = expr_to_var_sym(expr, &sym);
222 222 if (!name)
223 223 return NULL;
224 224 type = get_type(expr);
225 225 if (type && type->type == SYM_PTR) {
226 226 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
227 227 free_string(name);
228 228 return alloc_string(buf);
229 229 }
230 230 return name;
231 231 }
232 232 return expr_to_var(expr);
233 233 }
234 234
235 235 static void match_passes_function_pointer(struct expression *expr)
236 236 {
237 237 struct expression *arg, *tmp;
238 238 struct symbol *type;
239 239 char *called_name;
240 240 char *fn_name;
241 241 char ptr_name[256];
242 242 int i;
243 243
244 244
245 245 i = -1;
246 246 FOR_EACH_PTR(expr->args, arg) {
247 247 i++;
248 248
249 249 tmp = strip_expr(arg);
250 250 if (tmp->type == EXPR_PREOP && tmp->op == '&')
251 251 tmp = strip_expr(tmp->unop);
252 252
253 253 type = get_type(tmp);
254 254 if (type && type->type == SYM_PTR)
255 255 type = get_real_base_type(type);
256 256 if (!type || type->type != SYM_FN)
257 257 continue;
258 258
259 259 called_name = expr_to_var(expr->fn);
260 260 if (!called_name)
261 261 return;
262 262 fn_name = get_fnptr_name(tmp);
263 263 if (!fn_name)
264 264 goto free;
265 265
266 266 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
267 267 sql_insert_function_ptr(fn_name, ptr_name);
268 268 free:
269 269 free_string(fn_name);
270 270 free_string(called_name);
271 271 } END_FOR_EACH_PTR(arg);
272 272
273 273 }
274 274
275 275 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
276 276 {
277 277 int *row_count = _row_count;
278 278
279 279 *row_count = 0;
280 280 if (argc != 1)
281 281 return 0;
282 282 *row_count = atoi(argv[0]);
283 283 return 0;
284 284 }
285 285
286 286 static int can_hold_function_ptr(struct expression *expr)
287 287 {
288 288 struct symbol *type;
289 289
290 290 type = get_type(expr);
291 291 if (!type)
292 292 return 0;
293 293 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
294 294 type = get_real_base_type(type);
295 295 if (!type)
296 296 return 0;
297 297 }
298 298 /* pointer to a pointer */
299 299 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
300 300 type = get_real_base_type(type);
301 301 if (!type)
302 302 return 0;
303 303 }
304 304 if (type->type == SYM_FN)
305 305 return 1;
306 306 if (type == &ulong_ctype && expr->type == EXPR_DEREF)
307 307 return 1;
308 308 if (type == &void_ctype)
309 309 return 1;
310 310 return 0;
311 311 }
312 312
313 313 static void match_function_assign(struct expression *expr)
314 314 {
315 315 struct expression *right;
316 316 struct symbol *type;
317 317 char *fn_name;
318 318 char *ptr_name;
319 319
320 320 if (__in_fake_assign)
321 321 return;
322 322
323 323 right = strip_expr(expr->right);
324 324 if (right->type == EXPR_PREOP && right->op == '&')
325 325 right = strip_expr(right->unop);
326 326
327 327 if (right->type != EXPR_SYMBOL &&
328 328 right->type != EXPR_DEREF &&
329 329 right->type != EXPR_CALL)
330 330 return;
331 331
332 332 if (!can_hold_function_ptr(right) ||
333 333 !can_hold_function_ptr(expr->left))
334 334 return;
335 335
336 336 fn_name = get_fnptr_name(right);
337 337 ptr_name = get_fnptr_name(expr->left);
338 338 if (!fn_name || !ptr_name)
339 339 goto free;
340 340 if (strcmp(fn_name, ptr_name) == 0)
341 341 goto free;
342 342
343 343
344 344 type = get_type(right);
345 345 if (!type)
346 346 return;
347 347 if (type->type == SYM_PTR || type->type == SYM_ARRAY) {
348 348 type = get_real_base_type(type);
349 349 if (!type)
350 350 return;
351 351 }
352 352 if (type->type != SYM_FN) {
353 353 int count = 0;
354 354
355 355 /* look it up in function_ptr */
356 356 run_sql(get_row_count, &count,
357 357 "select count(*) from function_ptr where ptr = '%s'",
358 358 fn_name);
359 359 if (count == 0)
360 360 goto free;
361 361 }
362 362
363 363 sql_insert_function_ptr(fn_name, ptr_name);
364 364 free:
365 365 free_string(fn_name);
366 366 free_string(ptr_name);
367 367 }
368 368
369 369 static void match_returns_function_pointer(struct expression *expr)
370 370 {
371 371 struct symbol *type;
372 372 char *fn_name;
373 373 char ptr_name[256];
374 374
375 375 if (__inline_fn)
376 376 return;
377 377
378 378 type = get_real_base_type(cur_func_sym);
379 379 if (!type || type->type != SYM_FN)
380 380 return;
381 381 type = get_real_base_type(type);
382 382 if (!type || type->type != SYM_PTR)
383 383 return;
384 384 type = get_real_base_type(type);
385 385 if (!type || type->type != SYM_FN)
386 386 return;
387 387
388 388 if (expr->type == EXPR_PREOP && expr->op == '&')
389 389 expr = strip_expr(expr->unop);
390 390
391 391 fn_name = get_fnptr_name(expr);
392 392 if (!fn_name)
393 393 return;
394 394 snprintf(ptr_name, sizeof(ptr_name), "r %s()", get_function());
395 395 sql_insert_function_ptr(fn_name, ptr_name);
396 396 }
397 397
398 398 static void print_initializer_list(struct expression_list *expr_list,
399 399 struct symbol *struct_type)
400 400 {
401 401 struct expression *expr;
402 402 struct symbol *base_type;
403 403 char struct_name[256];
404 404
405 405 FOR_EACH_PTR(expr_list, expr) {
406 406 if (expr->type == EXPR_INDEX && expr->idx_expression && expr->idx_expression->type == EXPR_INITIALIZER) {
407 407 print_initializer_list(expr->idx_expression->expr_list, struct_type);
408 408 continue;
409 409 }
410 410 if (expr->type != EXPR_IDENTIFIER)
411 411 continue;
412 412 if (!expr->expr_ident)
413 413 continue;
414 414 if (!expr->ident_expression ||
415 415 expr->ident_expression->type != EXPR_SYMBOL ||
416 416 !expr->ident_expression->symbol_name)
417 417 continue;
418 418 base_type = get_type(expr->ident_expression);
419 419 if (!base_type || base_type->type != SYM_FN)
420 420 continue;
421 421 snprintf(struct_name, sizeof(struct_name), "(struct %s)->%s",
422 422 struct_type->ident->name, expr->expr_ident->name);
423 423 sql_insert_function_ptr(expr->ident_expression->symbol_name->name,
424 424 struct_name);
425 425 } END_FOR_EACH_PTR(expr);
426 426 }
427 427
428 428 static void global_variable(struct symbol *sym)
429 429 {
430 430 struct symbol *struct_type;
431 431
432 432 if (!sym->ident)
433 433 return;
434 434 if (!sym->initializer || sym->initializer->type != EXPR_INITIALIZER)
435 435 return;
436 436 struct_type = get_base_type(sym);
437 437 if (!struct_type)
438 438 return;
439 439 if (struct_type->type == SYM_ARRAY) {
440 440 struct_type = get_base_type(struct_type);
441 441 if (!struct_type)
442 442 return;
443 443 }
444 444 if (struct_type->type != SYM_STRUCT || !struct_type->ident)
445 445 return;
446 446 print_initializer_list(sym->initializer->expr_list, struct_type);
447 447 }
448 448
449 449 void register_function_ptrs(int id)
450 450 {
451 451 my_id = id;
452 452
453 453 if (!option_info)
454 454 return;
455 455
456 456 add_hook(&global_variable, BASE_HOOK);
457 457 add_hook(&global_variable, DECLARATION_HOOK);
458 458 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
459 459 add_hook(&match_returns_function_pointer, RETURN_HOOK);
460 460 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
461 461 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);
462 462 }
↓ open down ↓ |
231 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX