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