Print this page
12166 resync smatch to 0.6.1-rc1-il-3
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/smatch_container_of.c
+++ new/usr/src/tools/smatch/src/smatch_container_of.c
1 1 /*
2 2 * Copyright (C) 2017 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
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16 16 */
17 17
18 18 #include "smatch.h"
19 19 #include "smatch_slist.h"
20 20 #include "smatch_extra.h"
21 21
22 22 static int my_id;
23 23 static int param_id;
24 24
25 -static struct stree *used_stree;
26 -static struct stree_stack *saved_stack;
27 -
28 -STATE(used);
29 -
30 25 int get_param_from_container_of(struct expression *expr)
31 26 {
32 27 struct expression *param_expr;
33 28 struct symbol *type;
34 29 sval_t sval;
35 30 int param;
36 31
37 32
38 33 type = get_type(expr);
39 34 if (!type || type->type != SYM_PTR)
40 35 return -1;
41 36
42 37 expr = strip_expr(expr);
43 38 if (expr->type != EXPR_BINOP || expr->op != '-')
44 39 return -1;
45 40
46 41 if (!get_value(expr->right, &sval))
47 42 return -1;
48 43 if (sval.value < 0 || sval.value > 4096)
49 44 return -1;
50 45
51 46 param_expr = get_assigned_expr(expr->left);
52 47 if (!param_expr)
53 48 return -1;
54 49 param = get_param_num(param_expr);
55 50 if (param < 0)
56 51 return -1;
57 52
58 53 return param;
59 54 }
60 55
61 56 int get_offset_from_container_of(struct expression *expr)
62 57 {
63 58 struct expression *param_expr;
64 59 struct symbol *type;
65 60 sval_t sval;
66 61
67 62 type = get_type(expr);
68 63 if (!type || type->type != SYM_PTR)
69 64 return -1;
70 65
71 66 expr = strip_expr(expr);
72 67 if (expr->type != EXPR_BINOP || expr->op != '-')
73 68 return -1;
74 69
75 70 if (!get_value(expr->right, &sval))
76 71 return -1;
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
77 72 if (sval.value < 0 || sval.value > 4096)
78 73 return -1;
79 74
80 75 param_expr = get_assigned_expr(expr->left);
81 76 if (!param_expr)
82 77 return -1;
83 78
84 79 return sval.value;
85 80 }
86 81
87 -static int get_container_arg(struct symbol *sym)
88 -{
89 - struct expression *__mptr;
90 - int param;
91 -
92 - if (!sym || !sym->ident)
93 - return -1;
94 -
95 - __mptr = get_assigned_expr_name_sym(sym->ident->name, sym);
96 - param = get_param_from_container_of(__mptr);
97 -
98 - return param;
99 -}
100 -
101 -static int get_container_offset(struct symbol *sym)
102 -{
103 - struct expression *__mptr;
104 - int offset;
105 -
106 - if (!sym || !sym->ident)
107 - return -1;
108 -
109 - __mptr = get_assigned_expr_name_sym(sym->ident->name, sym);
110 - offset = get_offset_from_container_of(__mptr);
111 -
112 - return offset;
113 -}
114 -
115 -static char *get_container_name_sm(struct sm_state *sm, int offset)
116 -{
117 - static char buf[256];
118 - const char *name;
119 -
120 - name = get_param_name(sm);
121 - if (!name)
122 - return NULL;
123 -
124 - if (name[0] == '$')
125 - snprintf(buf, sizeof(buf), "$(-%d)%s", offset, name + 1);
126 - else if (name[0] == '*' || name[1] == '$')
127 - snprintf(buf, sizeof(buf), "*$(-%d)%s", offset, name + 2);
128 - else
129 - return NULL;
130 -
131 - return buf;
132 -}
133 -
134 -static void get_state_hook(int owner, const char *name, struct symbol *sym)
135 -{
136 - int arg;
137 -
138 - if (!option_info)
139 - return;
140 - if (__in_fake_assign)
141 - return;
142 -
143 - arg = get_container_arg(sym);
144 - if (arg >= 0)
145 - set_state_stree(&used_stree, my_id, name, sym, &used);
146 -}
147 -
148 -static void set_param_used(struct expression *call, struct expression *arg, char *key, char *unused)
149 -{
150 - struct symbol *sym;
151 - char *name;
152 - int arg_nr;
153 -
154 - name = get_variable_from_key(arg, key, &sym);
155 - if (!name || !sym)
156 - goto free;
157 -
158 - arg_nr = get_container_arg(sym);
159 - if (arg_nr >= 0)
160 - set_state(my_id, name, sym, &used);
161 -free:
162 - free_string(name);
163 -}
164 -
165 -static void process_states(void)
166 -{
167 - struct sm_state *tmp;
168 - int arg, offset;
169 - const char *name;
170 -
171 - FOR_EACH_SM(used_stree, tmp) {
172 - arg = get_container_arg(tmp->sym);
173 - offset = get_container_offset(tmp->sym);
174 - if (arg < 0 || offset < 0)
175 - continue;
176 - name = get_container_name_sm(tmp, offset);
177 - if (!name)
178 - continue;
179 - sql_insert_return_implies(CONTAINER, arg, name, "");
180 - } END_FOR_EACH_SM(tmp);
181 -
182 - free_stree(&used_stree);
183 -}
184 -
185 -static void match_function_def(struct symbol *sym)
186 -{
187 - free_stree(&used_stree);
188 -}
189 -
190 -static void match_save_states(struct expression *expr)
191 -{
192 - push_stree(&saved_stack, used_stree);
193 - used_stree = NULL;
194 -}
195 -
196 -static void match_restore_states(struct expression *expr)
197 -{
198 - free_stree(&used_stree);
199 - used_stree = pop_stree(&saved_stack);
200 -}
201 -
202 82 static void print_returns_container_of(int return_id, char *return_ranges, struct expression *expr)
203 83 {
204 84 int offset;
205 85 int param;
206 86 char key[64];
207 87 char value[64];
208 88
209 89 param = get_param_from_container_of(expr);
210 90 if (param < 0)
211 91 return;
212 92 offset = get_offset_from_container_of(expr);
213 93 if (offset < 0)
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
214 94 return;
215 95
216 96 snprintf(key, sizeof(key), "%d", param);
217 97 snprintf(value, sizeof(value), "-%d", offset);
218 98
219 99 /* no need to add it to return_implies because it's not really param_used */
220 100 sql_insert_return_states(return_id, return_ranges, CONTAINER, -1,
221 101 key, value);
222 102 }
223 103
224 -static void returns_container_of(struct expression *expr, int param, char *key, char *value)
225 -{
226 - struct expression *call, *arg;
227 - int offset;
228 - char buf[64];
229 -
230 - if (expr->type != EXPR_ASSIGNMENT || expr->op != '=')
231 - return;
232 - call = strip_expr(expr->right);
233 - if (call->type != EXPR_CALL)
234 - return;
235 - if (param != -1)
236 - return;
237 - param = atoi(key);
238 - offset = atoi(value);
239 -
240 - arg = get_argument_from_call_expr(call->args, param);
241 - if (!arg)
242 - return;
243 - if (arg->type != EXPR_SYMBOL)
244 - return;
245 - param = get_param_num(arg);
246 - if (param < 0)
247 - return;
248 - snprintf(buf, sizeof(buf), "$(%d)", offset);
249 - sql_insert_return_implies(CONTAINER, param, buf, "");
250 -}
251 -
252 104 static int get_deref_count(struct expression *expr)
253 105 {
254 106 int cnt = 0;
255 107
256 108 while (expr && expr->type == EXPR_DEREF) {
257 109 expr = expr->deref;
258 110 if (expr->type == EXPR_PREOP && expr->op == '*')
259 111 expr = expr->unop;
260 112 cnt++;
261 113 if (cnt > 100)
262 114 return -1;
263 115 }
264 116 return cnt;
265 117 }
266 118
267 119 static struct expression *get_partial_deref(struct expression *expr, int cnt)
268 120 {
269 121 while (--cnt >= 0) {
270 122 if (!expr || expr->type != EXPR_DEREF)
271 123 return expr;
272 124 expr = expr->deref;
273 125 if (expr->type == EXPR_PREOP && expr->op == '*')
274 126 expr = expr->unop;
275 127 }
276 128 return expr;
277 129 }
278 130
279 131 static int partial_deref_to_offset_str(struct expression *expr, int cnt, char op, char *buf, int size)
280 132 {
281 133 int n, offset;
282 134
283 135 if (cnt == 0)
284 136 return snprintf(buf, size, "%c0", op);
285 137
286 138 n = 0;
287 139 while (--cnt >= 0) {
288 140 offset = get_member_offset_from_deref(expr);
289 141 if (offset < 0)
290 142 return -1;
291 143 n += snprintf(buf + n, size - n, "%c%d", op, offset);
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
292 144 if (expr->type != EXPR_DEREF)
293 145 return -1;
294 146 expr = expr->deref;
295 147 if (expr->type == EXPR_PREOP && expr->op == '*')
296 148 expr = expr->unop;
297 149 }
298 150
299 151 return n;
300 152 }
301 153
302 -static char *get_shared_str(struct expression *container, struct expression *expr)
154 +static char *get_shared_str(struct expression *expr, struct expression *container)
303 155 {
304 156 struct expression *one, *two;
305 - int cont, exp, min, ret, n;
157 + int exp, cont, min, ret, n;
306 158 static char buf[48];
307 159
308 - cont = get_deref_count(container);
309 160 exp = get_deref_count(expr);
310 - if (cont < 0 || exp < 0)
161 + cont = get_deref_count(container);
162 + if (exp < 0 || cont < 0)
311 163 return NULL;
312 164
313 - min = (cont < exp) ? cont : exp;
165 + min = (exp < cont) ? exp : cont;
314 166 while (min >= 0) {
315 - one = get_partial_deref(container, cont - min);
316 - two = get_partial_deref(expr, exp - min);
167 + one = get_partial_deref(expr, exp - min);
168 + two = get_partial_deref(container, cont - min);
317 169 if (expr_equiv(one, two))
318 170 goto found;
319 171 min--;
320 172 }
321 173
322 174 return NULL;
323 175
324 176 found:
325 - ret = partial_deref_to_offset_str(container, cont - min, '-', buf, sizeof(buf));
177 + ret = partial_deref_to_offset_str(expr, exp - min, '-', buf, sizeof(buf));
326 178 if (ret < 0)
327 179 return NULL;
328 180 n = ret;
329 - ret = partial_deref_to_offset_str(expr, exp - min, '+', buf + ret, sizeof(buf) - ret);
181 + ret = partial_deref_to_offset_str(container, cont - min, '+', buf + ret, sizeof(buf) - ret);
330 182 if (ret < 0)
331 183 return NULL;
332 184 n += ret;
333 185 if (n >= sizeof(buf))
334 186 return NULL;
335 187
336 188 return buf;
337 189 }
338 190
191 +static char *get_stored_container_name(struct expression *container,
192 + struct expression *expr)
193 +{
194 + struct smatch_state *state;
195 + static char buf[64];
196 + char *p;
197 + int param;
198 +
199 + if (!container || container->type != EXPR_SYMBOL)
200 + return NULL;
201 + if (!expr || expr->type != EXPR_SYMBOL)
202 + return NULL;
203 + state = get_state_expr(param_id, expr);
204 + if (!state)
205 + return NULL;
206 +
207 + snprintf(buf, sizeof(buf), "%s", state->name);
208 + p = strchr(buf, '|');
209 + if (!p)
210 + return NULL;
211 + *p = '\0';
212 + param = atoi(p + 2);
213 + if (get_param_sym_from_num(param) == container->symbol)
214 + return buf;
215 + return NULL;
216 +}
217 +
339 218 char *get_container_name(struct expression *container, struct expression *expr)
340 219 {
341 220 struct symbol *container_sym, *sym;
342 221 struct expression *tmp;
343 222 static char buf[64];
344 - char *shared;
223 + char *ret, *shared;
345 224 bool star;
346 225 int cnt;
347 226
348 - container_sym = expr_to_sym(container);
227 + expr = strip_expr(expr);
228 + container = strip_expr(container);
229 +
230 + ret = get_stored_container_name(container, expr);
231 + if (ret)
232 + return ret;
233 +
349 234 sym = expr_to_sym(expr);
350 - if (container_sym && container_sym == sym)
235 + container_sym = expr_to_sym(container);
236 + if (sym && sym == container_sym)
351 237 goto found;
352 238
353 239 cnt = 0;
354 - while ((tmp = get_assigned_expr(expr))) {
355 - expr = tmp;
240 + while ((tmp = get_assigned_expr(container))) {
241 + container = strip_expr(tmp);
356 242 if (cnt++ > 3)
357 243 break;
358 244 }
359 245
360 246 cnt = 0;
361 - while ((tmp = get_assigned_expr(container))) {
362 - container = tmp;
247 + while ((tmp = get_assigned_expr(expr))) {
248 + expr = strip_expr(tmp);
363 249 if (cnt++ > 3)
364 250 break;
365 251 }
366 252
367 253 found:
368 - expr = strip_expr(expr);
369 - star = true;
370 - if (expr->type == EXPR_PREOP && expr->op == '&') {
371 - expr = strip_expr(expr->unop);
254 +
255 + if (container->type == EXPR_DEREF)
256 + star = true;
257 + else
372 258 star = false;
373 - }
374 259
375 - container_sym = expr_to_sym(container);
376 - if (!container_sym)
377 - return NULL;
260 + if (container->type == EXPR_PREOP && container->op == '&')
261 + container = strip_expr(container->unop);
262 + if (expr->type == EXPR_PREOP && expr->op == '&')
263 + expr = strip_expr(expr->unop);
264 +
378 265 sym = expr_to_sym(expr);
379 - if (!sym || container_sym != sym)
266 + if (!sym)
380 267 return NULL;
268 + container_sym = expr_to_sym(container);
269 + if (!container_sym || sym != container_sym)
270 + return NULL;
381 271
382 - shared = get_shared_str(container, expr);
272 + shared = get_shared_str(expr, container);
273 + if (!shared)
274 + return NULL;
383 275 if (star)
384 276 snprintf(buf, sizeof(buf), "*(%s)", shared);
385 277 else
386 278 snprintf(buf, sizeof(buf), "%s", shared);
387 279
388 280 return buf;
389 281 }
390 282
283 +static bool is_fn_ptr(struct expression *expr)
284 +{
285 + struct symbol *type;
286 +
287 + if (!expr)
288 + return false;
289 + if (expr->type != EXPR_SYMBOL && expr->type != EXPR_DEREF)
290 + return false;
291 +
292 + type = get_type(expr);
293 + if (!type || type->type != SYM_PTR)
294 + return false;
295 + type = get_real_base_type(type);
296 + if (!type || type->type != SYM_FN)
297 + return false;
298 + return true;
299 +}
300 +
391 301 static void match_call(struct expression *call)
392 302 {
393 - struct expression *fn, *arg;
303 + struct expression *fn, *arg, *tmp;
304 + bool found = false;
305 + int fn_param, param;
306 + char buf[32];
394 307 char *name;
395 - int param;
396 308
397 309 /*
398 310 * We're trying to link the function with the parameter. There are a
399 311 * couple ways this can be passed:
400 312 * foo->func(foo, ...);
401 313 * foo->func(foo->x, ...);
402 314 * foo->bar.func(&foo->bar, ...);
403 315 * foo->bar->baz->func(foo, ...);
404 316 *
405 317 * So the method is basically to subtract the offsets until we get to
406 318 * the common bit, then add the member offsets to get the parameter.
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
407 319 *
408 320 * If we're taking an address then the offset math is not stared,
409 321 * otherwise it is. Starred means dereferenced.
410 322 */
411 323 fn = strip_expr(call->fn);
412 324
413 325 param = -1;
414 326 FOR_EACH_PTR(call->args, arg) {
415 327 param++;
416 328
417 - name = get_container_name(fn, arg);
329 + name = get_container_name(arg, fn);
418 330 if (!name)
419 331 continue;
420 332
333 + found = true;
421 334 sql_insert_caller_info(call, CONTAINER, param, name, "$(-1)");
422 335 } END_FOR_EACH_PTR(arg);
336 +
337 + if (found)
338 + return;
339 +
340 + fn_param = -1;
341 + FOR_EACH_PTR(call->args, arg) {
342 + fn_param++;
343 + if (!is_fn_ptr(arg))
344 + continue;
345 + param = -1;
346 + FOR_EACH_PTR(call->args, tmp) {
347 + param++;
348 +
349 + /* the function isn't it's own container */
350 + if (arg == tmp)
351 + continue;
352 +
353 + name = get_container_name(tmp, arg);
354 + if (!name)
355 + continue;
356 +
357 + snprintf(buf, sizeof(buf), "$%d", param);
358 + sql_insert_caller_info(call, CONTAINER, fn_param, name, buf);
359 + return;
360 + } END_FOR_EACH_PTR(tmp);
361 + } END_FOR_EACH_PTR(arg);
423 362 }
424 363
425 364 static void db_passed_container(const char *name, struct symbol *sym, char *key, char *value)
426 365 {
427 - set_state(param_id, name, sym, alloc_state_str(key));
366 + char buf[64];
367 +
368 + snprintf(buf, sizeof(buf), "%s|%s", key, value);
369 + set_state(param_id, name, sym, alloc_state_str(buf));
428 370 }
429 371
430 372 struct db_info {
431 373 struct symbol *arg;
432 374 int prev_offset;
433 375 struct range_list *rl;
434 376 int star;
435 377 struct stree *stree;
436 378 };
437 379
438 380 static struct symbol *get_member_from_offset(struct symbol *sym, int offset)
439 381 {
440 382 struct symbol *type, *tmp;
441 383 int cur;
442 384
443 385 type = get_real_base_type(sym);
444 386 if (!type || type->type != SYM_PTR)
445 387 return NULL;
446 388 type = get_real_base_type(type);
447 389 if (!type || type->type != SYM_STRUCT)
448 390 return NULL;
449 391
450 392 cur = 0;
451 393 FOR_EACH_PTR(type->symbol_list, tmp) {
452 394 cur = ALIGN(cur, tmp->ctype.alignment);
453 395 if (offset == cur)
454 396 return tmp;
455 397 cur += type_bytes(tmp);
456 398 } END_FOR_EACH_PTR(tmp);
457 399 return NULL;
458 400 }
459 401
460 402 static struct symbol *get_member_type_from_offset(struct symbol *sym, int offset)
461 403 {
462 404 struct symbol *base_type;
463 405 struct symbol *member;
464 406
465 407 base_type = get_real_base_type(sym);
466 408 if (base_type && base_type->type == SYM_PTR)
467 409 base_type = get_real_base_type(base_type);
468 410 if (offset == 0 && base_type && base_type->type == SYM_BASETYPE)
469 411 return base_type;
470 412
471 413 member = get_member_from_offset(sym, offset);
472 414 if (!member)
473 415 return NULL;
474 416 return get_real_base_type(member);
475 417 }
476 418
477 419 static const char *get_name_from_offset(struct symbol *arg, int offset)
478 420 {
479 421 struct symbol *member, *type;
480 422 const char *name;
481 423 static char fullname[256];
482 424
483 425 name = arg->ident->name;
484 426
485 427 type = get_real_base_type(arg);
486 428 if (!type || type->type != SYM_PTR)
487 429 return name;
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
488 430
489 431 type = get_real_base_type(type);
490 432 if (!type)
491 433 return NULL;
492 434 if (type->type != SYM_STRUCT) {
493 435 snprintf(fullname, sizeof(fullname), "*%s", name);
494 436 return fullname;
495 437 }
496 438
497 439 member = get_member_from_offset(arg, offset);
498 - if (!member)
440 + if (!member || !member->ident)
499 441 return NULL;
500 442
501 443 snprintf(fullname, sizeof(fullname), "%s->%s", name, member->ident->name);
502 444 return fullname;
503 445 }
504 446
505 447 static void set_param_value(struct stree **stree, struct symbol *arg, int offset, struct range_list *rl)
506 448 {
507 449 const char *name;
508 450
509 451 name = get_name_from_offset(arg, offset);
510 452 if (!name)
511 453 return;
512 454 set_state_stree(stree, SMATCH_EXTRA, name, arg, alloc_estate_rl(rl));
513 455 }
514 456
515 457 static int save_vals(void *_db_info, int argc, char **argv, char **azColName)
516 458 {
517 459 struct db_info *db_info = _db_info;
518 460 struct symbol *type;
519 461 struct range_list *rl;
520 462 int offset = 0;
521 463 const char *value;
522 464
523 465 if (argc == 2) {
524 466 offset = atoi(argv[0]);
525 467 value = argv[1];
526 468 } else {
527 469 value = argv[0];
528 470 }
529 471
530 472 if (db_info->prev_offset != -1 &&
531 473 db_info->prev_offset != offset) {
532 474 set_param_value(&db_info->stree, db_info->arg, db_info->prev_offset, db_info->rl);
533 475 db_info->rl = NULL;
534 476 }
535 477
536 478 db_info->prev_offset = offset;
537 479
538 480 type = get_real_base_type(db_info->arg);
539 481 if (db_info->star)
540 482 goto found_type;
541 483 if (type->type != SYM_PTR)
542 484 return 0;
543 485 type = get_real_base_type(type);
544 486 if (type->type == SYM_BASETYPE)
545 487 goto found_type;
546 488 type = get_member_type_from_offset(db_info->arg, offset);
547 489 found_type:
548 490 str_to_rl(type, (char *)value, &rl);
549 491 if (db_info->rl)
550 492 db_info->rl = rl_union(db_info->rl, rl);
551 493 else
552 494 db_info->rl = rl;
553 495
554 496 return 0;
555 497 }
556 498
557 499 static struct stree *load_tag_info_sym(mtag_t tag, struct symbol *arg, int arg_offset, int star)
558 500 {
559 501 struct db_info db_info = {
560 502 .arg = arg,
561 503 .prev_offset = -1,
562 504 .star = star,
563 505 };
564 506 struct symbol *type;
565 507
566 508 if (!tag || !arg->ident)
567 509 return NULL;
568 510
569 511 type = get_real_base_type(arg);
570 512 if (!type)
571 513 return NULL;
572 514 if (!star) {
573 515 if (type->type != SYM_PTR)
574 516 return NULL;
575 517 type = get_real_base_type(type);
576 518 if (!type)
577 519 return NULL;
578 520 }
579 521
580 522 if (star || type->type == SYM_BASETYPE) {
581 523 run_sql(save_vals, &db_info,
582 524 "select value from mtag_data where tag = %lld and offset = %d and type = %d;",
583 525 tag, arg_offset, DATA_VALUE);
584 526 } else { /* presumably the parameter is a struct pointer */
585 527 run_sql(save_vals, &db_info,
586 528 "select offset, value from mtag_data where tag = %lld and type = %d;",
587 529 tag, DATA_VALUE);
588 530 }
589 531
590 532 if (db_info.prev_offset != -1)
591 533 set_param_value(&db_info.stree, arg, db_info.prev_offset, db_info.rl);
592 534
593 535 // FIXME: handle an offset correctly
594 536 if (!star && !arg_offset) {
595 537 sval_t sval;
596 538
597 539 sval.type = get_real_base_type(arg);
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
598 540 sval.uvalue = tag;
599 541 set_state_stree(&db_info.stree, SMATCH_EXTRA, arg->ident->name, arg, alloc_estate_sval(sval));
600 542 }
601 543 return db_info.stree;
602 544 }
603 545
604 546 static void load_container_data(struct symbol *arg, const char *info)
605 547 {
606 548 mtag_t cur_tag, container_tag, arg_tag;
607 549 int container_offset, arg_offset;
608 - char *p = (char *)info;
609 550 struct sm_state *sm;
610 551 struct stree *stree;
552 + char *p, *cont;
553 + char copy[64];
611 554 bool star = 0;
612 555
556 + snprintf(copy, sizeof(copy), "%s", info);
557 + p = strchr(copy, '|');
558 + if (!p)
559 + return;
560 + *p = '\0';
561 + cont = p + 1;
562 + p = copy;
613 563 if (p[0] == '*') {
614 564 star = 1;
615 565 p += 2;
616 566 }
617 567
568 + if (strcmp(cont, "$(-1)") != 0)
569 + return;
570 +
618 571 if (!get_toplevel_mtag(cur_func_sym, &cur_tag))
619 572 return;
620 573
621 574 while (true) {
622 575 container_offset = strtoul(p, &p, 0);
623 576 if (local_debug)
624 577 sm_msg("%s: cur_tag = %llu container_offset = %d",
625 578 __func__, cur_tag, container_offset);
626 579 if (!mtag_map_select_container(cur_tag, container_offset, &container_tag))
627 580 return;
628 581 cur_tag = container_tag;
629 582 if (local_debug)
630 583 sm_msg("%s: container_tag = %llu p = '%s'",
631 584 __func__, container_tag, p);
632 585 if (!p)
633 586 return;
634 587 if (p[0] != '-')
635 588 break;
636 589 p++;
637 590 }
638 591
639 592 if (p[0] != '+')
640 593 return;
641 594
642 595 p++;
643 596 arg_offset = strtoul(p, &p, 0);
644 597 if (p && *p && *p != ')')
645 598 return;
646 599
647 600 if (!arg_offset || star) {
648 601 arg_tag = container_tag;
649 602 } else {
650 603 if (!mtag_map_select_tag(container_tag, -arg_offset, &arg_tag))
651 604 return;
652 605 }
653 606
654 607 stree = load_tag_info_sym(arg_tag, arg, arg_offset, star);
655 608 FOR_EACH_SM(stree, sm) {
656 609 set_state(sm->owner, sm->name, sm->sym, sm->state);
657 610 } END_FOR_EACH_SM(sm);
658 611 free_stree(&stree);
659 612 }
660 613
661 614 static void handle_passed_container(struct symbol *sym)
662 615 {
663 616 struct symbol *arg;
664 617 struct smatch_state *state;
665 618
666 619 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
667 620 state = get_state(param_id, arg->ident->name, arg);
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
668 621 if (!state || state == &merged)
669 622 continue;
670 623 load_container_data(arg, state->name);
671 624 } END_FOR_EACH_PTR(arg);
672 625 }
673 626
674 627 void register_container_of(int id)
675 628 {
676 629 my_id = id;
677 630
678 - add_hook(&match_function_def, FUNC_DEF_HOOK);
679 -
680 - add_get_state_hook(&get_state_hook);
681 -
682 - add_hook(&match_save_states, INLINE_FN_START);
683 - add_hook(&match_restore_states, INLINE_FN_END);
684 -
685 - select_return_implies_hook(CONTAINER, &set_param_used);
686 - all_return_states_hook(&process_states);
687 -
688 631 add_split_return_callback(&print_returns_container_of);
689 - select_return_states_hook(CONTAINER, &returns_container_of);
690 -
691 632 add_hook(&match_call, FUNCTION_CALL_HOOK);
692 633 }
693 634
694 635 void register_container_of2(int id)
695 636 {
696 637 param_id = id;
697 638
698 639 set_dynamic_states(param_id);
699 640 select_caller_info_hook(db_passed_container, CONTAINER);
700 641 add_merge_hook(param_id, &merge_str_state);
701 642 add_hook(&handle_passed_container, AFTER_DEF_HOOK);
702 643 }
703 644
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX