Print this page
11506 smatch resync
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_function_hooks.c
+++ new/usr/src/tools/smatch/src/smatch_function_hooks.c
1 1 /*
2 2 * Copyright (C) 2009 Dan Carpenter.
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 * There are several types of function hooks:
20 20 * add_function_hook() - For any time a function is called.
21 21 * add_function_assign_hook() - foo = the_function().
22 22 * add_implied_return_hook() - Calculates the implied return value.
23 23 * add_macro_assign_hook() - foo = the_macro().
24 24 * return_implies_state() - For when a return value of 1 implies locked
25 25 * and 0 implies unlocked. etc. etc.
26 26 *
27 27 */
28 28
29 29 #include <stdlib.h>
30 30 #include <stdio.h>
31 31 #include "smatch.h"
32 32 #include "smatch_slist.h"
33 33 #include "smatch_extra.h"
34 34 #include "smatch_function_hashtable.h"
35 35
36 36 struct fcall_back {
37 37 int type;
38 38 struct data_range *range;
39 39 union {
40 40 func_hook *call_back;
41 41 implication_hook *ranged;
42 42 implied_return_hook *implied_return;
43 43 } u;
44 44 void *info;
45 45 };
46 46
47 47 ALLOCATOR(fcall_back, "call backs");
48 48 DECLARE_PTR_LIST(call_back_list, struct fcall_back);
49 49
50 50 DEFINE_FUNCTION_HASHTABLE_STATIC(callback, struct fcall_back, struct call_back_list);
51 51 static struct hashtable *func_hash;
52 52
53 53 int __in_fake_parameter_assign;
54 54
55 55 #define REGULAR_CALL 0
56 56 #define RANGED_CALL 1
57 57 #define ASSIGN_CALL 2
58 58 #define IMPLIED_RETURN 3
59 59 #define MACRO_ASSIGN 4
60 60 #define MACRO_ASSIGN_EXTRA 5
61 61
62 62 struct return_implies_callback {
63 63 int type;
64 64 return_implies_hook *callback;
65 65 };
66 66 ALLOCATOR(return_implies_callback, "return_implies callbacks");
67 67 DECLARE_PTR_LIST(db_implies_list, struct return_implies_callback);
68 68 static struct db_implies_list *db_return_states_list;
69 69
70 70 typedef void (void_fn)(void);
71 71 DECLARE_PTR_LIST(void_fn_list, void_fn *);
72 72 static struct void_fn_list *return_states_before;
73 73 static struct void_fn_list *return_states_after;
74 74
75 75 static struct fcall_back *alloc_fcall_back(int type, void *call_back,
76 76 void *info)
77 77 {
78 78 struct fcall_back *cb;
79 79
80 80 cb = __alloc_fcall_back(0);
81 81 cb->type = type;
82 82 cb->u.call_back = call_back;
83 83 cb->info = info;
84 84 return cb;
85 85 }
86 86
87 87 void add_function_hook(const char *look_for, func_hook *call_back, void *info)
88 88 {
89 89 struct fcall_back *cb;
90 90
91 91 cb = alloc_fcall_back(REGULAR_CALL, call_back, info);
92 92 add_callback(func_hash, look_for, cb);
93 93 }
94 94
95 95 void add_function_assign_hook(const char *look_for, func_hook *call_back,
96 96 void *info)
97 97 {
98 98 struct fcall_back *cb;
99 99
100 100 cb = alloc_fcall_back(ASSIGN_CALL, call_back, info);
101 101 add_callback(func_hash, look_for, cb);
102 102 }
103 103
104 104 void add_implied_return_hook(const char *look_for,
105 105 implied_return_hook *call_back,
106 106 void *info)
107 107 {
108 108 struct fcall_back *cb;
109 109
110 110 cb = alloc_fcall_back(IMPLIED_RETURN, call_back, info);
111 111 add_callback(func_hash, look_for, cb);
112 112 }
113 113
114 114 void add_macro_assign_hook(const char *look_for, func_hook *call_back,
115 115 void *info)
116 116 {
117 117 struct fcall_back *cb;
118 118
119 119 cb = alloc_fcall_back(MACRO_ASSIGN, call_back, info);
120 120 add_callback(func_hash, look_for, cb);
121 121 }
122 122
123 123 void add_macro_assign_hook_extra(const char *look_for, func_hook *call_back,
124 124 void *info)
125 125 {
126 126 struct fcall_back *cb;
127 127
128 128 cb = alloc_fcall_back(MACRO_ASSIGN_EXTRA, call_back, info);
129 129 add_callback(func_hash, look_for, cb);
130 130 }
131 131
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
132 132 void return_implies_state(const char *look_for, long long start, long long end,
133 133 implication_hook *call_back, void *info)
134 134 {
135 135 struct fcall_back *cb;
136 136
137 137 cb = alloc_fcall_back(RANGED_CALL, call_back, info);
138 138 cb->range = alloc_range_perm(ll_to_sval(start), ll_to_sval(end));
139 139 add_callback(func_hash, look_for, cb);
140 140 }
141 141
142 +void return_implies_state_sval(const char *look_for, sval_t start, sval_t end,
143 + implication_hook *call_back, void *info)
144 +{
145 + struct fcall_back *cb;
146 +
147 + cb = alloc_fcall_back(RANGED_CALL, call_back, info);
148 + cb->range = alloc_range_perm(start, end);
149 + add_callback(func_hash, look_for, cb);
150 +}
151 +
142 152 void select_return_states_hook(int type, return_implies_hook *callback)
143 153 {
144 154 struct return_implies_callback *cb = __alloc_return_implies_callback(0);
145 155
146 156 cb->type = type;
147 157 cb->callback = callback;
148 158 add_ptr_list(&db_return_states_list, cb);
149 159 }
150 160
151 161 void select_return_states_before(void_fn *fn)
152 162 {
153 163 void_fn **p = malloc(sizeof(void_fn *));
154 164 *p = fn;
155 165 add_ptr_list(&return_states_before, p);
156 166 }
157 167
158 168 void select_return_states_after(void_fn *fn)
159 169 {
160 170 void_fn **p = malloc(sizeof(void_fn *));
161 171 *p = fn;
162 172 add_ptr_list(&return_states_after, p);
163 173 }
164 174
165 175 static void call_return_states_before_hooks(void)
166 176 {
167 177 void_fn **fn;
168 178
169 179 FOR_EACH_PTR(return_states_before, fn) {
170 180 (*fn)();
171 181 } END_FOR_EACH_PTR(fn);
172 182 }
173 183
174 184 static void call_return_states_after_hooks(struct expression *expr)
175 185 {
176 186 void_fn **fn;
177 187
178 188 FOR_EACH_PTR(return_states_after, fn) {
179 189 (*fn)();
180 190 } END_FOR_EACH_PTR(fn);
181 191 __pass_to_client(expr, FUNCTION_CALL_HOOK_AFTER_DB);
182 192 }
183 193
184 194 static int call_call_backs(struct call_back_list *list, int type,
185 195 const char *fn, struct expression *expr)
186 196 {
187 197 struct fcall_back *tmp;
188 198 int handled = 0;
189 199
190 200 FOR_EACH_PTR(list, tmp) {
191 201 if (tmp->type == type) {
192 202 (tmp->u.call_back)(fn, expr, tmp->info);
193 203 handled = 1;
194 204 }
195 205 } END_FOR_EACH_PTR(tmp);
196 206
197 207 return handled;
198 208 }
199 209
200 210 static void call_ranged_call_backs(struct call_back_list *list,
201 211 const char *fn, struct expression *call_expr,
202 212 struct expression *assign_expr)
203 213 {
204 214 struct fcall_back *tmp;
205 215
206 216 FOR_EACH_PTR(list, tmp) {
207 217 (tmp->u.ranged)(fn, call_expr, assign_expr, tmp->info);
208 218 } END_FOR_EACH_PTR(tmp);
209 219 }
210 220
211 221 static struct call_back_list *get_same_ranged_call_backs(struct call_back_list *list,
212 222 struct data_range *drange)
213 223 {
214 224 struct call_back_list *ret = NULL;
215 225 struct fcall_back *tmp;
216 226
217 227 FOR_EACH_PTR(list, tmp) {
218 228 if (tmp->type != RANGED_CALL)
219 229 continue;
220 230 if (ranges_equiv(tmp->range, drange))
221 231 add_ptr_list(&ret, tmp);
222 232 } END_FOR_EACH_PTR(tmp);
223 233 return ret;
224 234 }
225 235
226 236 static int in_list_exact_sval(struct range_list *list, struct data_range *drange)
227 237 {
228 238 struct data_range *tmp;
229 239
230 240 FOR_EACH_PTR(list, tmp) {
231 241 if (ranges_equiv(tmp, drange))
232 242 return 1;
233 243 } END_FOR_EACH_PTR(tmp);
234 244 return 0;
235 245 }
236 246
237 247 static int assign_ranged_funcs(const char *fn, struct expression *expr,
238 248 struct call_back_list *call_backs)
↓ open down ↓ |
87 lines elided |
↑ open up ↑ |
239 249 {
240 250 struct fcall_back *tmp;
241 251 struct sm_state *sm;
242 252 char *var_name;
243 253 struct symbol *sym;
244 254 struct smatch_state *estate;
245 255 struct stree *tmp_stree;
246 256 struct stree *final_states = NULL;
247 257 struct range_list *handled_ranges = NULL;
248 258 struct call_back_list *same_range_call_backs = NULL;
259 + struct range_list *rl;
249 260 int handled = 0;
250 261
251 262 if (!call_backs)
252 263 return 0;
253 264
254 265 var_name = expr_to_var_sym(expr->left, &sym);
255 266 if (!var_name || !sym)
256 267 goto free;
257 268
258 269 FOR_EACH_PTR(call_backs, tmp) {
259 270 if (tmp->type != RANGED_CALL)
260 271 continue;
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
261 272
262 273 if (in_list_exact_sval(handled_ranges, tmp->range))
263 274 continue;
264 275 __push_fake_cur_stree();
265 276 tack_on(&handled_ranges, tmp->range);
266 277
267 278 same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range);
268 279 call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
269 280 __free_ptr_list((struct ptr_list **)&same_range_call_backs);
270 281
271 - estate = alloc_estate_range(tmp->range->min, tmp->range->max);
282 + rl = alloc_rl(tmp->range->min, tmp->range->max);
283 + rl = cast_rl(get_type(expr->left), rl);
284 + estate = alloc_estate_rl(rl);
272 285 set_extra_mod(var_name, sym, expr->left, estate);
273 286
274 287 tmp_stree = __pop_fake_cur_stree();
275 288 merge_fake_stree(&final_states, tmp_stree);
276 289 free_stree(&tmp_stree);
277 290 handled = 1;
278 291 } END_FOR_EACH_PTR(tmp);
279 292
280 293 FOR_EACH_SM(final_states, sm) {
281 294 __set_sm(sm);
282 295 } END_FOR_EACH_SM(sm);
283 296
284 297 free_stree(&final_states);
285 298 free:
286 299 free_string(var_name);
287 300 return handled;
288 301 }
289 302
290 303 static void call_implies_callbacks(int comparison, struct expression *expr, sval_t sval, int left, struct stree **implied_true, struct stree **implied_false)
291 304 {
292 305 struct call_back_list *call_backs;
293 306 struct fcall_back *tmp;
294 307 const char *fn;
295 308 struct data_range *value_range;
296 309 struct stree *true_states = NULL;
297 310 struct stree *false_states = NULL;
298 311 struct stree *tmp_stree;
299 312
300 313 *implied_true = NULL;
301 314 *implied_false = NULL;
302 315 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
303 316 return;
304 317 fn = expr->fn->symbol->ident->name;
305 318 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
306 319 if (!call_backs)
307 320 return;
308 321 value_range = alloc_range(sval, sval);
309 322
310 323 /* set true states */
311 324 __push_fake_cur_stree();
312 325 FOR_EACH_PTR(call_backs, tmp) {
313 326 if (tmp->type != RANGED_CALL)
314 327 continue;
315 328 if (!true_comparison_range_LR(comparison, tmp->range, value_range, left))
316 329 continue;
317 330 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
318 331 } END_FOR_EACH_PTR(tmp);
319 332 tmp_stree = __pop_fake_cur_stree();
320 333 merge_fake_stree(&true_states, tmp_stree);
321 334 free_stree(&tmp_stree);
322 335
323 336 /* set false states */
324 337 __push_fake_cur_stree();
325 338 FOR_EACH_PTR(call_backs, tmp) {
326 339 if (tmp->type != RANGED_CALL)
327 340 continue;
328 341 if (!false_comparison_range_LR(comparison, tmp->range, value_range, left))
329 342 continue;
330 343 (tmp->u.ranged)(fn, expr, NULL, tmp->info);
331 344 } END_FOR_EACH_PTR(tmp);
332 345 tmp_stree = __pop_fake_cur_stree();
333 346 merge_fake_stree(&false_states, tmp_stree);
334 347 free_stree(&tmp_stree);
335 348
336 349 *implied_true = true_states;
337 350 *implied_false = false_states;
338 351 }
339 352
340 353 struct db_callback_info {
341 354 int true_side;
342 355 int comparison;
343 356 struct expression *expr;
344 357 struct range_list *rl;
345 358 int left;
346 359 struct stree *stree;
347 360 struct db_implies_list *callbacks;
348 361 int prev_return_id;
349 362 int cull;
350 363 int has_states;
351 364 char *ret_str;
352 365 struct smatch_state *ret_state;
353 366 struct expression *var_expr;
354 367 int handled;
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
355 368 };
356 369
357 370 static void store_return_state(struct db_callback_info *db_info, const char *ret_str, struct smatch_state *state)
358 371 {
359 372 db_info->ret_str = alloc_sname(ret_str),
360 373 db_info->ret_state = state;
361 374 }
362 375
363 376 static bool fake_a_param_assignment(struct expression *expr, const char *return_str)
364 377 {
365 - struct expression *arg, *left, *right, *fake_assign;
378 + struct expression *arg, *left, *right, *tmp, *fake_assign;
366 379 char *p;
367 380 int param;
368 381 char buf[256];
369 382 char *str;
370 383
371 384 if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
372 385 return false;
373 386 left = expr->left;
374 387 right = expr->right;
375 388
376 389 while (right->type == EXPR_ASSIGNMENT)
377 390 right = strip_expr(right->right);
378 391 if (!right || right->type != EXPR_CALL)
379 392 return false;
380 393
381 394 p = strchr(return_str, '[');
382 395 if (!p)
383 396 return false;
384 397
385 398 p++;
386 399 if (p[0] == '=' && p[1] == '=')
387 400 p += 2;
388 401 if (p[0] != '$')
389 402 return false;
390 403
391 404 snprintf(buf, sizeof(buf), "%s", p);
392 405
393 406 p = buf;
394 407 p += 1;
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
395 408 param = strtol(p, &p, 10);
396 409
397 410 p = strchr(p, ']');
398 411 if (!p || *p != ']')
399 412 return false;
400 413 *p = '\0';
401 414
402 415 arg = get_argument_from_call_expr(right->args, param);
403 416 if (!arg)
404 417 return false;
418 +
419 + /* There should be a get_other_name() function which returns an expr */
420 + tmp = get_assigned_expr(arg);
421 + if (tmp)
422 + arg = tmp;
423 +
405 424 /*
406 425 * This is a sanity check to prevent side effects from evaluating stuff
407 426 * twice.
408 427 */
409 428 str = expr_to_chunk_sym_vsl(arg, NULL, NULL);
410 429 if (!str)
411 430 return false;
412 431 free_string(str);
413 432
414 433 right = gen_expression_from_key(arg, buf);
415 434 if (!right) /* Mostly fails for binops like [$0 + 4032] */
416 435 return false;
417 436 fake_assign = assign_expression(left, '=', right);
418 437 __in_fake_parameter_assign++;
419 438 __split_expr(fake_assign);
420 439 __in_fake_parameter_assign--;
421 440 return true;
422 441 }
423 442
424 -static void set_return_state(struct expression *expr, struct db_callback_info *db_info)
443 +static void set_return_assign_state(struct db_callback_info *db_info)
425 444 {
445 + struct expression *expr = db_info->expr->left;
426 446 struct smatch_state *state;
427 447
428 448 if (!db_info->ret_state)
429 449 return;
430 450
431 451 state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
432 452 set_extra_expr_mod(expr, state);
433 453 db_info->ret_state = NULL;
434 454 fake_a_param_assignment(db_info->expr, db_info->ret_str);
435 455 db_info->ret_str = NULL;
436 456 }
437 457
458 +static void set_other_side_state(struct db_callback_info *db_info)
459 +{
460 + struct expression *expr = db_info->var_expr;
461 + struct smatch_state *state;
462 +
463 + if (!db_info->ret_state)
464 + return;
465 +
466 + state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
467 + set_extra_expr_nomod(expr, state);
468 + db_info->ret_state = NULL;
469 + db_info->ret_str = NULL;
470 +}
471 +
438 472 static void handle_ret_equals_param(char *ret_string, struct range_list *rl, struct expression *call)
439 473 {
440 474 char *str;
441 475 long long param;
442 476 struct expression *arg;
443 477 struct range_list *orig;
444 478
445 479 str = strstr(ret_string, "==$");
446 480 if (!str)
447 481 return;
448 482 str += 3;
449 483 param = strtoll(str, NULL, 10);
450 484 arg = get_argument_from_call_expr(call->args, param);
451 485 if (!arg)
452 486 return;
453 487 get_absolute_rl(arg, &orig);
454 488 rl = rl_intersection(orig, rl);
455 489 if (!rl)
456 490 return;
457 491 set_extra_expr_nomod(arg, alloc_estate_rl(rl));
458 492 }
459 493
460 494 static int impossible_limit(struct expression *expr, int param, char *key, char *value)
461 495 {
462 496 struct expression *arg;
463 497 struct smatch_state *state;
464 498 struct range_list *passed;
465 499 struct range_list *limit;
466 500 struct symbol *compare_type;
467 501
468 502 while (expr->type == EXPR_ASSIGNMENT)
469 503 expr = strip_expr(expr->right);
470 504 if (expr->type != EXPR_CALL)
471 505 return 0;
472 506
473 507 arg = get_argument_from_call_expr(expr->args, param);
474 508 if (!arg)
475 509 return 0;
476 510
477 511 if (strcmp(key, "$") == 0) {
478 512 if (!get_implied_rl(arg, &passed))
479 513 return 0;
480 514
481 515 compare_type = get_arg_type(expr->fn, param);
482 516 } else {
483 517 char *name;
484 518 struct symbol *sym;
485 519
486 520 name = get_variable_from_key(arg, key, &sym);
487 521 if (!name || !sym)
488 522 return 0;
489 523
490 524 state = get_state(SMATCH_EXTRA, name, sym);
491 525 if (!state) {
492 526 free_string(name);
493 527 return 0;
494 528 }
495 529 passed = estate_rl(state);
496 530 if (!passed || is_whole_rl(passed)) {
497 531 free_string(name);
498 532 return 0;
499 533 }
500 534
501 535 compare_type = get_member_type_from_key(arg, key);
502 536 }
503 537
504 538 passed = cast_rl(compare_type, passed);
505 539 call_results_to_rl(expr, compare_type, value, &limit);
506 540 if (!limit || is_whole_rl(limit))
507 541 return 0;
508 542 if (possibly_true_rl(passed, SPECIAL_EQUAL, limit))
509 543 return 0;
510 544 if (option_debug || local_debug)
511 545 sm_msg("impossible: %d '%s' limit '%s' == '%s'", param, key, show_rl(passed), value);
512 546 return 1;
513 547 }
514 548
515 549 static int is_impossible_data(int type, struct expression *expr, int param, char *key, char *value)
516 550 {
517 551 if (type == PARAM_LIMIT && impossible_limit(expr, param, key, value))
518 552 return 1;
519 553 if (type == COMPARE_LIMIT && param_compare_limit_is_impossible(expr, param, key, value)) {
520 554 if (local_debug)
521 555 sm_msg("param_compare_limit_is_impossible: %d %s %s", param, key, value);
522 556 return 1;
523 557 }
524 558 return 0;
525 559 }
526 560
527 561 static int func_type_mismatch(struct expression *expr, const char *value)
528 562 {
529 563 struct symbol *type;
530 564
531 565 /* This makes faking returns easier */
532 566 if (!value || value[0] == '\0')
533 567 return 0;
534 568
535 569 while (expr->type == EXPR_ASSIGNMENT)
536 570 expr = strip_expr(expr->right);
537 571
538 572 /*
539 573 * Short cut: We only care about function pointers that are struct
540 574 * members.
541 575 *
542 576 */
543 577 if (expr->fn->type == EXPR_SYMBOL)
544 578 return 0;
545 579
546 580 type = get_type(expr->fn);
547 581 if (!type)
548 582 return 0;
549 583 if (type->type == SYM_PTR)
550 584 type = get_real_base_type(type);
551 585
552 586 if (strcmp(type_to_str(type), value) == 0)
553 587 return 0;
↓ open down ↓ |
106 lines elided |
↑ open up ↑ |
554 588
555 589 return 1;
556 590 }
557 591
558 592 static int db_compare_callback(void *_info, int argc, char **argv, char **azColName)
559 593 {
560 594 struct db_callback_info *db_info = _info;
561 595 struct range_list *var_rl = db_info->rl;
562 596 struct range_list *ret_range;
563 597 int type, param;
564 - char *key, *value;
598 + char *ret_str, *key, *value;
565 599 struct return_implies_callback *tmp;
566 600 struct stree *stree;
567 601 int return_id;
568 602 int comparison;
569 603
570 604 if (argc != 6)
571 605 return 0;
572 606
573 607 return_id = atoi(argv[0]);
608 + ret_str = argv[1];
574 609 type = atoi(argv[2]);
575 610 param = atoi(argv[3]);
576 611 key = argv[4];
577 612 value = argv[5];
578 613
579 614 db_info->has_states = 1;
580 615 if (db_info->prev_return_id != -1 && type == INTERNAL) {
581 - set_return_state(db_info->var_expr, db_info);
616 + set_other_side_state(db_info);
582 617 stree = __pop_fake_cur_stree();
583 618
584 619 if (!db_info->cull)
585 620 merge_fake_stree(&db_info->stree, stree);
586 621 free_stree(&stree);
587 622 __push_fake_cur_stree();
588 623 db_info->cull = 0;
589 624 }
590 625 db_info->prev_return_id = return_id;
591 626
592 627 if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
593 628 db_info->cull = 1;
594 629 if (db_info->cull)
595 630 return 0;
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
596 631 if (type == CULL_PATH) {
597 632 db_info->cull = 1;
598 633 return 0;
599 634 }
600 635
601 636 if (is_impossible_data(type, db_info->expr, param, key, value)) {
602 637 db_info->cull = 1;
603 638 return 0;
604 639 }
605 640
606 - call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
641 + call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
607 642 ret_range = cast_rl(get_type(db_info->expr), ret_range);
608 643 if (!ret_range)
609 644 ret_range = alloc_whole_rl(get_type(db_info->expr));
610 645
611 646 comparison = db_info->comparison;
612 647 if (db_info->left)
613 648 comparison = flip_comparison(comparison);
614 649
615 650 if (db_info->true_side) {
616 651 if (!possibly_true_rl(var_rl, comparison, ret_range))
617 652 return 0;
618 653 if (type == PARAM_LIMIT)
619 654 param_limit_implications(db_info->expr, param, key, value);
620 655 filter_by_comparison(&var_rl, comparison, ret_range);
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
621 656 filter_by_comparison(&ret_range, flip_comparison(comparison), var_rl);
622 657 } else {
623 658 if (!possibly_false_rl(var_rl, comparison, ret_range))
624 659 return 0;
625 660 if (type == PARAM_LIMIT)
626 661 param_limit_implications(db_info->expr, param, key, value);
627 662 filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
628 663 filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
629 664 }
630 665
631 - handle_ret_equals_param(argv[1], ret_range, db_info->expr);
666 + handle_ret_equals_param(ret_str, ret_range, db_info->expr);
632 667
633 668 if (type == INTERNAL) {
634 669 set_state(-1, "unnull_path", NULL, &true_state);
635 - __add_return_comparison(strip_expr(db_info->expr), argv[1]);
636 - __add_return_to_param_mapping(db_info->expr, argv[1]);
637 - store_return_state(db_info, argv[1], alloc_estate_rl(clone_rl(var_rl)));
670 + __add_return_comparison(strip_expr(db_info->expr), ret_str);
671 + __add_return_to_param_mapping(db_info->expr, ret_str);
672 + store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
638 673 }
639 674
640 675 FOR_EACH_PTR(db_info->callbacks, tmp) {
641 676 if (tmp->type == type)
642 677 tmp->callback(db_info->expr, param, key, value);
643 678 } END_FOR_EACH_PTR(tmp);
644 679
645 680 return 0;
646 681 }
647 682
648 683 static void compare_db_return_states_callbacks(struct expression *left, int comparison, struct expression *right, struct stree *implied_true, struct stree *implied_false)
649 684 {
650 685 struct stree *orig_states;
651 686 struct stree *stree;
652 687 struct stree *true_states;
653 688 struct stree *false_states;
654 689 struct sm_state *sm;
655 690 struct db_callback_info db_info = {};
656 691 struct expression *var_expr;
657 692 struct expression *call_expr;
658 693 struct range_list *rl;
659 694 int call_on_left;
660 695
661 696 orig_states = clone_stree(__get_cur_stree());
662 697
663 698 /* legacy cruft. need to fix call_implies_callbacks(). */
664 699 call_on_left = 1;
665 700 call_expr = left;
666 701 var_expr = right;
667 702 if (left->type != EXPR_CALL) {
668 703 call_on_left = 0;
669 704 call_expr = right;
670 705 var_expr = left;
671 706 }
672 707
673 708 get_absolute_rl(var_expr, &rl);
674 709
675 710 db_info.comparison = comparison;
676 711 db_info.expr = call_expr;
677 712 db_info.rl = rl;
678 713 db_info.left = call_on_left;
679 714 db_info.callbacks = db_return_states_list;
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
680 715 db_info.var_expr = var_expr;
681 716
682 717 call_return_states_before_hooks();
683 718
684 719 db_info.true_side = 1;
685 720 db_info.stree = NULL;
686 721 db_info.prev_return_id = -1;
687 722 __push_fake_cur_stree();
688 723 sql_select_return_states("return_id, return, type, parameter, key, value",
689 724 call_expr, db_compare_callback, &db_info);
690 - set_return_state(db_info.var_expr, &db_info);
725 + set_other_side_state(&db_info);
691 726 stree = __pop_fake_cur_stree();
692 - if (!db_info.cull) {
693 - set_return_state(db_info.var_expr, &db_info);
727 + if (!db_info.cull)
694 728 merge_fake_stree(&db_info.stree, stree);
695 - }
696 729 free_stree(&stree);
697 730 true_states = db_info.stree;
698 731 if (!true_states && db_info.has_states) {
699 732 __push_fake_cur_stree();
700 733 set_path_impossible();
701 734 true_states = __pop_fake_cur_stree();
702 735 }
703 736
704 737 nullify_path();
705 738 __unnullify_path();
706 739 FOR_EACH_SM(orig_states, sm) {
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
707 740 __set_sm_cur_stree(sm);
708 741 } END_FOR_EACH_SM(sm);
709 742
710 743 db_info.true_side = 0;
711 744 db_info.stree = NULL;
712 745 db_info.prev_return_id = -1;
713 746 db_info.cull = 0;
714 747 __push_fake_cur_stree();
715 748 sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
716 749 db_compare_callback, &db_info);
750 + set_other_side_state(&db_info);
717 751 stree = __pop_fake_cur_stree();
718 - if (!db_info.cull) {
719 - set_return_state(db_info.var_expr, &db_info);
752 + if (!db_info.cull)
720 753 merge_fake_stree(&db_info.stree, stree);
721 - }
722 754 free_stree(&stree);
723 755 false_states = db_info.stree;
724 756 if (!false_states && db_info.has_states) {
725 757 __push_fake_cur_stree();
726 758 set_path_impossible();
727 759 false_states = __pop_fake_cur_stree();
728 760 }
729 761
730 762 nullify_path();
731 763 __unnullify_path();
732 764 FOR_EACH_SM(orig_states, sm) {
733 765 __set_sm_cur_stree(sm);
734 766 } END_FOR_EACH_SM(sm);
735 767
736 768 free_stree(&orig_states);
737 769
738 770 FOR_EACH_SM(true_states, sm) {
739 771 __set_true_false_sm(sm, NULL);
740 772 } END_FOR_EACH_SM(sm);
741 773 FOR_EACH_SM(false_states, sm) {
742 774 __set_true_false_sm(NULL, sm);
743 775 } END_FOR_EACH_SM(sm);
744 776
745 777 free_stree(&true_states);
746 778 free_stree(&false_states);
747 779
748 780 call_return_states_after_hooks(call_expr);
749 781
750 782 FOR_EACH_SM(implied_true, sm) {
751 783 __set_true_false_sm(sm, NULL);
752 784 } END_FOR_EACH_SM(sm);
753 785 FOR_EACH_SM(implied_false, sm) {
754 786 __set_true_false_sm(NULL, sm);
755 787 } END_FOR_EACH_SM(sm);
756 788 }
757 789
758 790 void function_comparison(struct expression *left, int comparison, struct expression *right)
759 791 {
760 792 struct expression *var_expr;
761 793 struct expression *call_expr;
762 794 struct stree *implied_true = NULL;
763 795 struct stree *implied_false = NULL;
764 796 struct range_list *rl;
765 797 sval_t sval;
766 798 int call_on_left;
767 799
768 800 if (unreachable())
769 801 return;
770 802
771 803 /* legacy cruft. need to fix call_implies_callbacks(). */
772 804 call_on_left = 1;
773 805 call_expr = left;
774 806 var_expr = right;
775 807 if (left->type != EXPR_CALL) {
776 808 call_on_left = 0;
777 809 call_expr = right;
778 810 var_expr = left;
779 811 }
780 812
781 813 get_absolute_rl(var_expr, &rl);
782 814
783 815 if (rl_to_sval(rl, &sval))
784 816 call_implies_callbacks(comparison, call_expr, sval, call_on_left, &implied_true, &implied_false);
785 817
786 818 compare_db_return_states_callbacks(left, comparison, right, implied_true, implied_false);
787 819 free_stree(&implied_true);
788 820 free_stree(&implied_false);
789 821 }
790 822
791 823 static void call_ranged_return_hooks(struct db_callback_info *db_info)
792 824 {
793 825 struct call_back_list *call_backs;
794 826 struct expression *expr;
795 827 struct fcall_back *tmp;
796 828 char *fn;
797 829
798 830 expr = strip_expr(db_info->expr);
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
799 831 while (expr->type == EXPR_ASSIGNMENT)
800 832 expr = strip_expr(expr->right);
801 833 if (expr->type != EXPR_CALL ||
802 834 expr->fn->type != EXPR_SYMBOL)
803 835 return;
804 836
805 837 fn = expr->fn->symbol_name->name;
806 838
807 839 call_backs = search_callback(func_hash, fn);
808 840 FOR_EACH_PTR(call_backs, tmp) {
809 - struct range_list *range_rl = NULL;
841 + struct range_list *range_rl;
810 842
811 843 if (tmp->type != RANGED_CALL)
812 844 continue;
813 - add_range(&range_rl, tmp->range->min, tmp->range->max);
845 + range_rl = alloc_rl(tmp->range->min, tmp->range->max);
814 846 range_rl = cast_rl(estate_type(db_info->ret_state), range_rl);
815 - if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state))) {
816 - if (!possibly_true_rl(rl_invert(range_rl), SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
817 - (tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
818 - else
819 - db_info->handled = -1;
820 - }
847 + if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
848 + (tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
821 849 } END_FOR_EACH_PTR(tmp);
822 850 }
823 851
824 852 static int db_assign_return_states_callback(void *_info, int argc, char **argv, char **azColName)
825 853 {
826 854 struct db_callback_info *db_info = _info;
827 855 struct range_list *ret_range;
828 856 int type, param;
829 - char *key, *value;
857 + char *ret_str, *key, *value;
830 858 struct return_implies_callback *tmp;
831 859 struct stree *stree;
832 860 int return_id;
833 861
834 862 if (argc != 6)
835 863 return 0;
836 864
837 865 return_id = atoi(argv[0]);
866 + ret_str = argv[1];
838 867 type = atoi(argv[2]);
839 868 param = atoi(argv[3]);
840 869 key = argv[4];
841 870 value = argv[5];
842 871
843 872 if (db_info->prev_return_id != -1 && type == INTERNAL) {
844 873 call_ranged_return_hooks(db_info);
845 - set_return_state(db_info->expr->left, db_info);
874 + set_return_assign_state(db_info);
846 875 stree = __pop_fake_cur_stree();
847 876 if (!db_info->cull)
848 877 merge_fake_stree(&db_info->stree, stree);
849 878 free_stree(&stree);
850 879 __push_fake_cur_stree();
851 880 db_info->cull = 0;
852 881 }
853 882 db_info->prev_return_id = return_id;
854 883
855 884 if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
856 885 db_info->cull = 1;
857 886 if (db_info->cull)
858 887 return 0;
859 888 if (type == CULL_PATH) {
860 889 db_info->cull = 1;
861 890 return 0;
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
862 891 }
863 892 if (is_impossible_data(type, db_info->expr, param, key, value)) {
864 893 db_info->cull = 1;
865 894 return 0;
866 895 }
867 896
868 897 if (type == PARAM_LIMIT)
869 898 param_limit_implications(db_info->expr, param, key, value);
870 899
871 900 db_info->handled = 1;
872 - call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), argv[1], &ret_range);
901 + call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
873 902 if (!ret_range)
874 903 ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
875 904 ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
876 905
877 906 if (type == INTERNAL) {
878 907 set_state(-1, "unnull_path", NULL, &true_state);
879 - __add_return_comparison(strip_expr(db_info->expr->right), argv[1]);
880 - __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), argv[1]);
881 - __add_return_to_param_mapping(db_info->expr, argv[1]);
882 - store_return_state(db_info, argv[1], alloc_estate_rl(ret_range));
908 + __add_return_comparison(strip_expr(db_info->expr->right), ret_str);
909 + __add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
910 + __add_return_to_param_mapping(db_info->expr, ret_str);
911 + store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));
883 912 }
884 913
885 914 FOR_EACH_PTR(db_return_states_list, tmp) {
886 915 if (tmp->type == type)
887 916 tmp->callback(db_info->expr, param, key, value);
888 917 } END_FOR_EACH_PTR(tmp);
889 918
890 919 return 0;
891 920 }
892 921
893 922 static int db_return_states_assign(struct expression *expr)
894 923 {
895 924 struct expression *right;
896 925 struct sm_state *sm;
897 926 struct stree *stree;
898 927 struct db_callback_info db_info = {};
899 928
900 929 right = strip_expr(expr->right);
901 930
902 931 db_info.prev_return_id = -1;
903 932 db_info.expr = expr;
904 933 db_info.stree = NULL;
905 934 db_info.handled = 0;
906 935
907 936 call_return_states_before_hooks();
908 937
909 938 __push_fake_cur_stree();
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
910 939 sql_select_return_states("return_id, return, type, parameter, key, value",
911 940 right, db_assign_return_states_callback, &db_info);
912 941 if (option_debug) {
913 942 sm_msg("%s return_id %d return_ranges %s",
914 943 db_info.cull ? "culled" : "merging",
915 944 db_info.prev_return_id,
916 945 db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
917 946 }
918 947 if (db_info.handled)
919 948 call_ranged_return_hooks(&db_info);
920 - set_return_state(db_info.expr->left, &db_info);
949 + set_return_assign_state(&db_info);
921 950 stree = __pop_fake_cur_stree();
922 951 if (!db_info.cull)
923 952 merge_fake_stree(&db_info.stree, stree);
924 953 free_stree(&stree);
925 954
926 955 if (!db_info.stree && db_info.cull) { /* this means we culled everything */
927 956 set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left)));
928 957 set_path_impossible();
929 958 }
930 959 FOR_EACH_SM(db_info.stree, sm) {
931 960 __set_sm(sm);
932 961 } END_FOR_EACH_SM(sm);
933 962
934 963 free_stree(&db_info.stree);
935 964 call_return_states_after_hooks(right);
936 965
937 966 return db_info.handled;
938 967 }
939 968
940 969 static int handle_implied_return(struct expression *expr)
941 970 {
942 971 struct range_list *rl;
943 972
944 973 if (!get_implied_return(expr->right, &rl))
945 974 return 0;
946 975 rl = cast_rl(get_type(expr->left), rl);
947 976 set_extra_expr_mod(expr->left, alloc_estate_rl(rl));
948 977 return 1;
949 978 }
950 979
951 980 static void match_assign_call(struct expression *expr)
952 981 {
953 982 struct call_back_list *call_backs;
954 983 const char *fn;
955 984 struct expression *right;
956 985 int handled = 0;
957 986 struct range_list *rl;
958 987
959 988 if (expr->op != '=')
960 989 return;
961 990
962 991 right = strip_expr(expr->right);
963 992 if (right->fn->type != EXPR_SYMBOL || !right->fn->symbol) {
964 993 handled |= db_return_states_assign(expr);
965 994 if (!handled)
966 995 goto assigned_unknown;
967 996 return;
968 997 }
969 998 if (is_fake_call(right)) {
970 999 set_extra_expr_mod(expr->left, alloc_estate_whole(get_type(expr->left)));
971 1000 return;
972 1001 }
973 1002
974 1003 fn = right->fn->symbol->ident->name;
975 1004 call_backs = search_callback(func_hash, (char *)fn);
976 1005
977 1006 /*
978 1007 * The ordering here is sort of important.
979 1008 * One example, of how this matters is that when we do:
980 1009 *
981 1010 * len = strlen(str);
982 1011 *
983 1012 * That is handled by smatch_common_functions.c and smatch_strlen.c.
984 1013 * They use implied_return and function_assign_hook respectively.
985 1014 * We want to get the implied return first before we do the function
986 1015 * assignment hook otherwise we end up writing the wrong thing for len
987 1016 * in smatch_extra.c because we assume that it already holds the
988 1017 * strlen() when we haven't set it yet.
989 1018 */
990 1019
991 1020 if (db_return_states_assign(expr) == 1)
992 1021 handled = 1;
993 1022 else
994 1023 handled = assign_ranged_funcs(fn, expr, call_backs);
995 1024 handled |= handle_implied_return(expr);
996 1025
997 1026
998 1027 call_call_backs(call_backs, ASSIGN_CALL, fn, expr);
999 1028
1000 1029 if (handled)
1001 1030 return;
1002 1031
1003 1032 assigned_unknown:
↓ open down ↓ |
73 lines elided |
↑ open up ↑ |
1004 1033 get_absolute_rl(expr->right, &rl);
1005 1034 rl = cast_rl(get_type(expr->left), rl);
1006 1035 set_extra_expr_mod(expr->left, alloc_estate_rl(rl));
1007 1036 }
1008 1037
1009 1038 static int db_return_states_callback(void *_info, int argc, char **argv, char **azColName)
1010 1039 {
1011 1040 struct db_callback_info *db_info = _info;
1012 1041 struct range_list *ret_range;
1013 1042 int type, param;
1014 - char *key, *value;
1043 + char *ret_str, *key, *value;
1015 1044 struct return_implies_callback *tmp;
1016 1045 struct stree *stree;
1017 1046 int return_id;
1018 1047 char buf[64];
1019 1048
1020 1049 if (argc != 6)
1021 1050 return 0;
1022 1051
1023 1052 return_id = atoi(argv[0]);
1053 + ret_str = argv[1];
1024 1054 type = atoi(argv[2]);
1025 1055 param = atoi(argv[3]);
1026 1056 key = argv[4];
1027 1057 value = argv[5];
1028 1058
1029 1059 if (db_info->prev_return_id != -1 && type == INTERNAL) {
1030 1060 stree = __pop_fake_cur_stree();
1031 1061 if (!db_info->cull)
1032 1062 merge_fake_stree(&db_info->stree, stree);
1033 1063 free_stree(&stree);
1034 1064 __push_fake_cur_stree();
1035 1065 __unnullify_path();
1036 1066 db_info->cull = 0;
1037 1067 }
1038 1068 db_info->prev_return_id = return_id;
1039 1069
1040 1070 if (type == INTERNAL && func_type_mismatch(db_info->expr, value))
1041 1071 db_info->cull = 1;
1042 1072 if (db_info->cull)
1043 1073 return 0;
1044 1074 if (type == CULL_PATH) {
1045 1075 db_info->cull = 1;
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1046 1076 return 0;
1047 1077 }
1048 1078 if (is_impossible_data(type, db_info->expr, param, key, value)) {
1049 1079 db_info->cull = 1;
1050 1080 return 0;
1051 1081 }
1052 1082
1053 1083 if (type == PARAM_LIMIT)
1054 1084 param_limit_implications(db_info->expr, param, key, value);
1055 1085
1056 - call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
1086 + call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
1057 1087 ret_range = cast_rl(get_type(db_info->expr), ret_range);
1058 1088
1059 1089 if (type == INTERNAL) {
1060 1090 set_state(-1, "unnull_path", NULL, &true_state);
1061 - __add_return_comparison(strip_expr(db_info->expr), argv[1]);
1062 - __add_return_to_param_mapping(db_info->expr, argv[1]);
1091 + __add_return_comparison(strip_expr(db_info->expr), ret_str);
1092 + __add_return_to_param_mapping(db_info->expr, ret_str);
1063 1093 }
1064 1094
1065 1095
1066 1096 FOR_EACH_PTR(db_return_states_list, tmp) {
1067 1097 if (tmp->type == type)
1068 1098 tmp->callback(db_info->expr, param, key, value);
1069 1099 } END_FOR_EACH_PTR(tmp);
1070 1100
1071 1101 /*
1072 1102 * We want to store the return values so that we can split the strees
1073 1103 * in smatch_db.c. This uses set_state() directly because it's not a
1074 1104 * real smatch_extra state.
1075 1105 */
1076 1106 snprintf(buf, sizeof(buf), "return %p", db_info->expr);
1077 1107 set_state(SMATCH_EXTRA, buf, NULL, alloc_estate_rl(ret_range));
1078 1108
1079 1109 return 0;
1080 1110 }
1081 1111
1082 1112 static void db_return_states(struct expression *expr)
1083 1113 {
1084 1114 struct sm_state *sm;
1085 1115 struct stree *stree;
1086 1116 struct db_callback_info db_info = {};
1087 1117
1088 1118 if (!__get_cur_stree()) /* no return functions */
1089 1119 return;
1090 1120
1091 1121 db_info.prev_return_id = -1;
1092 1122 db_info.expr = expr;
1093 1123 db_info.stree = NULL;
1094 1124
1095 1125 call_return_states_before_hooks();
1096 1126
1097 1127 __push_fake_cur_stree();
1098 1128 __unnullify_path();
1099 1129 sql_select_return_states("return_id, return, type, parameter, key, value",
1100 1130 expr, db_return_states_callback, &db_info);
1101 1131 stree = __pop_fake_cur_stree();
1102 1132 if (!db_info.cull)
1103 1133 merge_fake_stree(&db_info.stree, stree);
1104 1134 free_stree(&stree);
1105 1135
1106 1136 FOR_EACH_SM(db_info.stree, sm) {
1107 1137 __set_sm(sm);
1108 1138 } END_FOR_EACH_SM(sm);
1109 1139
1110 1140 free_stree(&db_info.stree);
1111 1141 call_return_states_after_hooks(expr);
1112 1142 }
1113 1143
1114 1144 static int is_condition_call(struct expression *expr)
1115 1145 {
1116 1146 struct expression *tmp;
1117 1147
1118 1148 FOR_EACH_PTR_REVERSE(big_condition_stack, tmp) {
1119 1149 if (expr == tmp || expr_get_parent_expr(expr) == tmp)
1120 1150 return 1;
1121 1151 if (tmp->pos.line < expr->pos.line)
1122 1152 return 0;
1123 1153 } END_FOR_EACH_PTR_REVERSE(tmp);
1124 1154
1125 1155 return 0;
1126 1156 }
1127 1157
1128 1158 static void db_return_states_call(struct expression *expr)
1129 1159 {
1130 1160 if (unreachable())
1131 1161 return;
1132 1162
1133 1163 if (is_assigned_call(expr))
1134 1164 return;
1135 1165 if (is_condition_call(expr))
1136 1166 return;
1137 1167 db_return_states(expr);
1138 1168 }
1139 1169
1140 1170 static void match_function_call(struct expression *expr)
1141 1171 {
1142 1172 struct call_back_list *call_backs;
1143 1173
1144 1174 if (expr->fn->type == EXPR_SYMBOL && expr->fn->symbol) {
1145 1175 call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
1146 1176 if (call_backs)
1147 1177 call_call_backs(call_backs, REGULAR_CALL,
1148 1178 expr->fn->symbol->ident->name, expr);
1149 1179 }
1150 1180 db_return_states_call(expr);
1151 1181 }
1152 1182
1153 1183 static void match_macro_assign(struct expression *expr)
1154 1184 {
1155 1185 struct call_back_list *call_backs;
1156 1186 const char *macro;
1157 1187 struct expression *right;
1158 1188
1159 1189 right = strip_expr(expr->right);
1160 1190 macro = get_macro_name(right->pos);
1161 1191 call_backs = search_callback(func_hash, (char *)macro);
1162 1192 if (!call_backs)
1163 1193 return;
1164 1194 call_call_backs(call_backs, MACRO_ASSIGN, macro, expr);
1165 1195 call_call_backs(call_backs, MACRO_ASSIGN_EXTRA, macro, expr);
1166 1196 }
1167 1197
1168 1198 int get_implied_return(struct expression *expr, struct range_list **rl)
1169 1199 {
1170 1200 struct call_back_list *call_backs;
1171 1201 struct fcall_back *tmp;
1172 1202 int handled = 0;
1173 1203 char *fn;
1174 1204
1175 1205 *rl = NULL;
1176 1206
1177 1207 expr = strip_expr(expr);
1178 1208 fn = expr_to_var(expr->fn);
1179 1209 if (!fn)
1180 1210 goto out;
1181 1211
1182 1212 call_backs = search_callback(func_hash, fn);
1183 1213
1184 1214 FOR_EACH_PTR(call_backs, tmp) {
1185 1215 if (tmp->type == IMPLIED_RETURN) {
1186 1216 (tmp->u.implied_return)(expr, tmp->info, rl);
1187 1217 handled = 1;
1188 1218 }
1189 1219 } END_FOR_EACH_PTR(tmp);
1190 1220
1191 1221 out:
1192 1222 free_string(fn);
1193 1223 return handled;
1194 1224 }
1195 1225
1196 1226 void create_function_hook_hash(void)
1197 1227 {
1198 1228 func_hash = create_function_hashtable(5000);
1199 1229 }
1200 1230
1201 1231 void register_function_hooks(int id)
1202 1232 {
1203 1233 add_hook(&match_function_call, CALL_HOOK_AFTER_INLINE);
1204 1234 add_hook(&match_assign_call, CALL_ASSIGNMENT_HOOK);
1205 1235 add_hook(&match_macro_assign, MACRO_ASSIGNMENT_HOOK);
1206 1236 }
↓ open down ↓ |
134 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX