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_db.c
+++ new/usr/src/tools/smatch/src/smatch_db.c
1 1 /*
2 2 * Copyright (C) 2010 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 #include <string.h>
19 19 #include <errno.h>
20 20 #include <unistd.h>
21 21 #include <ctype.h>
22 22 #include "smatch.h"
23 23 #include "smatch_slist.h"
24 24 #include "smatch_extra.h"
25 25
26 26 struct sqlite3 *smatch_db;
27 27 struct sqlite3 *mem_db;
28 28 struct sqlite3 *cache_db;
29 29
30 30 int debug_db;
31 31
32 32 static int return_id;
33 33
34 34 static void call_return_state_hooks(struct expression *expr);
35 35
36 36 #define SQLITE_CACHE_PAGES 1000
37 37
38 38 struct def_callback {
39 39 int hook_type;
40 40 void (*callback)(const char *name, struct symbol *sym, char *key, char *value);
41 41 };
42 42 ALLOCATOR(def_callback, "definition db hook callbacks");
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
43 43 DECLARE_PTR_LIST(callback_list, struct def_callback);
44 44 static struct callback_list *select_caller_info_callbacks;
45 45
46 46 struct member_info_callback {
47 47 int owner;
48 48 void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm);
49 49 };
50 50 ALLOCATOR(member_info_callback, "caller_info callbacks");
51 51 DECLARE_PTR_LIST(member_info_cb_list, struct member_info_callback);
52 52 static struct member_info_cb_list *member_callbacks;
53 +static struct member_info_cb_list *member_callbacks_new;
53 54
54 55 struct returned_state_callback {
55 56 void (*callback)(int return_id, char *return_ranges, struct expression *return_expr);
56 57 };
57 58 ALLOCATOR(returned_state_callback, "returned state callbacks");
58 59 DECLARE_PTR_LIST(returned_state_cb_list, struct returned_state_callback);
59 60 static struct returned_state_cb_list *returned_state_callbacks;
60 61
61 62 struct returned_member_callback {
62 63 int owner;
63 64 void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state);
64 65 };
65 66 ALLOCATOR(returned_member_callback, "returned member callbacks");
66 67 DECLARE_PTR_LIST(returned_member_cb_list, struct returned_member_callback);
67 68 static struct returned_member_cb_list *returned_member_callbacks;
68 69
69 70 struct db_implies_callback {
70 71 int type;
71 72 void (*callback)(struct expression *call, struct expression *arg, char *key, char *value);
72 73 };
73 74 ALLOCATOR(db_implies_callback, "return_implies callbacks");
74 75 DECLARE_PTR_LIST(db_implies_cb_list, struct db_implies_callback);
75 76 static struct db_implies_cb_list *return_implies_cb_list;
76 77 static struct db_implies_cb_list *call_implies_cb_list;
77 78
78 79 /* silently truncates if needed. */
79 80 char *escape_newlines(const char *str)
80 81 {
81 82 char buf[1024] = "";
82 83 bool found = false;
83 84 int i, j;
84 85
85 86 for (i = 0, j = 0; str[i] != '\0' && j != sizeof(buf); i++, j++) {
86 87 if (str[i] != '\r' && str[i] != '\n') {
87 88 buf[j] = str[i];
88 89 continue;
89 90 }
90 91
91 92 found = true;
92 93 buf[j++] = '\\';
93 94 if (j == sizeof(buf))
94 95 break;
95 96 buf[j] = 'n';
96 97 }
97 98
98 99 if (!found)
99 100 return alloc_sname(str);
100 101
101 102 if (j == sizeof(buf))
102 103 buf[j - 1] = '\0';
103 104 return alloc_sname(buf);
104 105 }
105 106
106 107 static int print_sql_output(void *unused, int argc, char **argv, char **azColName)
107 108 {
108 109 int i;
109 110
110 111 for (i = 0; i < argc; i++) {
111 112 if (i != 0)
112 113 sm_printf(", ");
113 114 sm_printf("%s", argv[i]);
114 115 }
115 116 sm_printf("\n");
116 117 return 0;
117 118 }
118 119
119 120 void sql_exec(struct sqlite3 *db, int (*callback)(void*, int, char**, char**), void *data, const char *sql)
120 121 {
121 122 char *err = NULL;
122 123 int rc;
123 124
124 125 if (!db)
125 126 return;
126 127
127 128 if (option_debug || debug_db) {
128 129 sm_msg("%s", sql);
129 130 if (strncasecmp(sql, "select", strlen("select")) == 0)
130 131 sqlite3_exec(db, sql, print_sql_output, NULL, NULL);
131 132 }
132 133
133 134 rc = sqlite3_exec(db, sql, callback, data, &err);
134 135 if (rc != SQLITE_OK && !parse_error) {
135 136 sm_ierror("%s:%d SQL error #2: %s\n", get_filename(), get_lineno(), err);
136 137 sm_ierror("%s:%d SQL: '%s'\n", get_filename(), get_lineno(), sql);
137 138 parse_error = 1;
138 139 }
139 140 }
140 141
141 142 static int replace_count;
142 143 static char **replace_table;
143 144 static const char *replace_return_ranges(const char *return_ranges)
144 145 {
145 146 int i;
146 147
147 148 if (!get_function()) {
148 149 /* I have no idea why EXPORT_SYMBOL() is here */
149 150 return return_ranges;
150 151 }
151 152 for (i = 0; i < replace_count; i += 3) {
152 153 if (strcmp(replace_table[i + 0], get_function()) == 0) {
153 154 if (strcmp(replace_table[i + 1], return_ranges) == 0)
154 155 return replace_table[i + 2];
155 156 }
156 157 }
157 158 return return_ranges;
158 159 }
159 160
160 161
161 162 static char *use_states;
162 163 static int get_db_state_count(void)
163 164 {
164 165 struct sm_state *sm;
165 166 int count = 0;
166 167
167 168 FOR_EACH_SM(__get_cur_stree(), sm) {
168 169 if (sm->owner == USHRT_MAX)
169 170 continue;
170 171 if (use_states[sm->owner])
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
171 172 count++;
172 173 } END_FOR_EACH_SM(sm);
173 174 return count;
174 175 }
175 176
176 177 void db_ignore_states(int id)
177 178 {
178 179 use_states[id] = 0;
179 180 }
180 181
182 +unsigned long long __fn_mtag;
183 +static void set_fn_mtag(struct symbol *sym)
184 +{
185 + char buf[128];
186 +
187 + if (cur_func_sym->ctype.modifiers & MOD_STATIC)
188 + snprintf(buf, sizeof(buf), "%s %s", get_base_file(), get_function());
189 + else
190 + snprintf(buf, sizeof(buf), "extern %s", get_function());
191 +
192 + __fn_mtag = str_to_mtag(buf);
193 +}
194 +
181 195 void sql_insert_return_states(int return_id, const char *return_ranges,
182 196 int type, int param, const char *key, const char *value)
183 197 {
198 + unsigned long long id;
199 +
200 +
184 201 if (key && strlen(key) >= 80)
185 202 return;
203 + if (__inline_fn)
204 + id = (unsigned long)__inline_fn;
205 + else
206 + id = __fn_mtag;
207 +
186 208 return_ranges = replace_return_ranges(return_ranges);
187 - sql_insert(return_states, "'%s', '%s', %lu, %d, '%s', %d, %d, %d, '%s', '%s'",
188 - get_base_file(), get_function(), (unsigned long)__inline_fn,
189 - return_id, return_ranges, fn_static(), type, param, key, value);
209 + sql_insert(return_states, "'%s', '%s', %llu, %d, '%s', %d, %d, %d, '%s', '%s'",
210 + get_base_file(), get_function(), id, return_id,
211 + return_ranges, fn_static(), type, param, key, value);
190 212 }
191 213
192 214 static struct string_list *common_funcs;
193 215 static int is_common_function(const char *fn)
194 216 {
195 217 char *tmp;
196 218
197 219 if (!fn)
198 220 return 0;
199 221
200 222 if (strncmp(fn, "__builtin_", 10) == 0)
201 223 return 1;
202 224
203 225 FOR_EACH_PTR(common_funcs, tmp) {
204 226 if (strcmp(tmp, fn) == 0)
205 227 return 1;
206 228 } END_FOR_EACH_PTR(tmp);
207 229
208 230 return 0;
209 231 }
210 232
211 233 static char *function_signature(void)
212 234 {
213 235 return type_to_str(get_real_base_type(cur_func_sym));
214 236 }
215 237
216 238 void sql_insert_caller_info(struct expression *call, int type,
217 239 int param, const char *key, const char *value)
218 240 {
219 241 FILE *tmp_fd = sm_outfd;
220 242 char *fn;
221 243
222 244 if (!option_info && !__inline_call)
223 245 return;
224 246
225 247 if (key && strlen(key) >= 80)
226 248 return;
227 249
228 250 fn = get_fnptr_name(call->fn);
229 251 if (!fn)
230 252 return;
231 253
232 254 if (__inline_call) {
233 255 mem_sql(NULL, NULL,
234 256 "insert into caller_info values ('%s', '%s', '%s', %lu, %d, %d, %d, '%s', '%s');",
235 257 get_base_file(), get_function(), fn, (unsigned long)call,
236 258 is_static(call->fn), type, param, key, value);
237 259 }
238 260
239 261 if (!option_info)
240 262 return;
241 263
242 264 if (strncmp(fn, "__builtin_", 10) == 0)
243 265 return;
244 266 if (type != INTERNAL && is_common_function(fn))
245 267 return;
246 268
247 269 sm_outfd = caller_info_fd;
248 270 sm_msg("SQL_caller_info: insert into caller_info values ("
249 271 "'%s', '%s', '%s', %%CALL_ID%%, %d, %d, %d, '%s', '%s');",
250 272 get_base_file(), get_function(), fn, is_static(call->fn),
251 273 type, param, key, value);
252 274 sm_outfd = tmp_fd;
253 275
254 276 free_string(fn);
255 277 }
256 278
257 279 void sql_insert_function_ptr(const char *fn, const char *struct_name)
258 280 {
259 281 sql_insert_or_ignore(function_ptr, "'%s', '%s', '%s', 0",
260 282 get_base_file(), fn, struct_name);
261 283 }
262 284
263 285 void sql_insert_return_implies(int type, int param, const char *key, const char *value)
264 286 {
265 287 sql_insert_or_ignore(return_implies, "'%s', '%s', %lu, %d, %d, %d, '%s', '%s'",
266 288 get_base_file(), get_function(), (unsigned long)__inline_fn,
267 289 fn_static(), type, param, key, value);
268 290 }
269 291
270 292 void sql_insert_call_implies(int type, int param, const char *key, const char *value)
271 293 {
272 294 sql_insert_or_ignore(call_implies, "'%s', '%s', %lu, %d, %d, %d, '%s', '%s'",
273 295 get_base_file(), get_function(), (unsigned long)__inline_fn,
274 296 fn_static(), type, param, key, value);
275 297 }
276 298
277 299 void sql_insert_function_type_size(const char *member, const char *ranges)
278 300 {
279 301 sql_insert(function_type_size, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), member, ranges);
280 302 }
281 303
282 304 void sql_insert_function_type_info(int type, const char *struct_type, const char *member, const char *value)
283 305 {
284 306 sql_insert(function_type_info, "'%s', '%s', %d, '%s', '%s', '%s'", get_base_file(), get_function(), type, struct_type, member, value);
285 307 }
286 308
287 309 void sql_insert_type_info(int type, const char *member, const char *value)
288 310 {
289 311 sql_insert_cache(type_info, "'%s', %d, '%s', '%s'", get_base_file(), type, member, value);
290 312 }
291 313
292 314 void sql_insert_local_values(const char *name, const char *value)
293 315 {
294 316 sql_insert(local_values, "'%s', '%s', '%s'", get_base_file(), name, value);
295 317 }
296 318
297 319 void sql_insert_function_type_value(const char *type, const char *value)
298 320 {
299 321 sql_insert(function_type_value, "'%s', '%s', '%s', '%s'", get_base_file(), get_function(), type, value);
300 322 }
301 323
302 324 void sql_insert_function_type(int param, const char *value)
303 325 {
304 326 sql_insert(function_type, "'%s', '%s', %d, %d, '%s'",
305 327 get_base_file(), get_function(), fn_static(), param, value);
306 328 }
307 329
308 330 void sql_insert_parameter_name(int param, const char *value)
309 331 {
310 332 sql_insert(parameter_name, "'%s', '%s', %d, %d, '%s'",
311 333 get_base_file(), get_function(), fn_static(), param, value);
312 334 }
313 335
314 336 void sql_insert_data_info(struct expression *data, int type, const char *value)
315 337 {
316 338 char *data_name;
317 339
318 340 data_name = get_data_info_name(data);
319 341 if (!data_name)
320 342 return;
321 343 sql_insert(data_info, "'%s', '%s', %d, '%s'",
322 344 is_static(data) ? get_base_file() : "extern",
323 345 data_name, type, value);
324 346 }
325 347
326 348 void sql_insert_data_info_var_sym(const char *var, struct symbol *sym, int type, const char *value)
327 349 {
328 350 sql_insert(data_info, "'%s', '%s', %d, '%s'",
329 351 (sym->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
330 352 var, type, value);
331 353 }
332 354
333 355 void sql_save_constraint(const char *con)
334 356 {
335 357 if (!option_info)
336 358 return;
337 359
338 360 sm_msg("SQL: insert or ignore into constraints (str) values('%s');", escape_newlines(con));
339 361 }
340 362
341 363 void sql_save_constraint_required(const char *data, int op, const char *limit)
342 364 {
343 365 sql_insert_or_ignore(constraints_required, "'%s', '%s', '%s'", data, show_special(op), limit);
344 366 }
345 367
346 368 void sql_copy_constraint_required(const char *new_limit, const char *old_limit)
347 369 {
348 370 if (!option_info)
349 371 return;
350 372
351 373 sm_msg("SQL_late: insert or ignore into constraints_required (data, op, bound) "
352 374 "select constraints_required.data, constraints_required.op, '%s' from "
353 375 "constraints_required where bound = '%s';", new_limit, old_limit);
354 376 }
355 377
356 378 void sql_insert_fn_ptr_data_link(const char *ptr, const char *data)
357 379 {
358 380 sql_insert_or_ignore(fn_ptr_data_link, "'%s', '%s'", ptr, data);
359 381 }
360 382
361 383 void sql_insert_fn_data_link(struct expression *fn, int type, int param, const char *key, const char *value)
362 384 {
363 385 if (fn->type != EXPR_SYMBOL || !fn->symbol->ident)
364 386 return;
↓ open down ↓ |
165 lines elided |
↑ open up ↑ |
365 387
366 388 sql_insert(fn_data_link, "'%s', '%s', %d, %d, %d, '%s', '%s'",
367 389 (fn->symbol->ctype.modifiers & MOD_STATIC) ? get_base_file() : "extern",
368 390 fn->symbol->ident->name,
369 391 !!(fn->symbol->ctype.modifiers & MOD_STATIC),
370 392 type, param, key, value);
371 393 }
372 394
373 395 void sql_insert_mtag_about(mtag_t tag, const char *left_name, const char *right_name)
374 396 {
375 - sql_insert(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
376 - tag, get_filename(), get_function(), get_lineno(), left_name, right_name);
397 + sql_insert_cache(mtag_about, "%lld, '%s', '%s', %d, '%s', '%s'",
398 + tag, get_filename(), get_function(), get_lineno(),
399 + left_name, right_name);
377 400 }
378 401
379 -void sql_insert_mtag_map(mtag_t tag, int offset, mtag_t container)
402 +void sql_insert_mtag_info(mtag_t tag, int type, const char *value)
380 403 {
381 - sql_insert(mtag_map, "%lld, %d, %lld", tag, offset, container);
404 + sql_insert_cache(mtag_info, "'%s', %lld, %d, '%s'", get_filename(), tag, type, value);
382 405 }
383 406
407 +void sql_insert_mtag_map(mtag_t container, int container_offset, mtag_t tag, int tag_offset)
408 +{
409 + sql_insert(mtag_map, "%lld, %d, %lld, %d", container, container_offset, tag, tag_offset);
410 +}
411 +
384 412 void sql_insert_mtag_alias(mtag_t orig, mtag_t alias)
385 413 {
386 414 sql_insert(mtag_alias, "%lld, %lld", orig, alias);
387 415 }
388 416
389 417 static int save_mtag(void *_tag, int argc, char **argv, char **azColName)
390 418 {
391 419 mtag_t *saved_tag = _tag;
392 420 mtag_t new_tag;
393 421
394 422 new_tag = strtoll(argv[0], NULL, 10);
395 423
396 424 if (!*saved_tag)
397 425 *saved_tag = new_tag;
398 426 else if (*saved_tag != new_tag)
399 427 *saved_tag = -1ULL;
400 428
401 429 return 0;
402 430 }
403 431
404 -int mtag_map_select_container(mtag_t tag, int offset, mtag_t *container)
432 +int mtag_map_select_container(mtag_t tag, int container_offset, mtag_t *container)
405 433 {
406 434 mtag_t tmp = 0;
407 435
408 436 run_sql(save_mtag, &tmp,
409 - "select container from mtag_map where tag = %lld and offset = %d;",
410 - tag, offset);
437 + "select container from mtag_map where tag = %lld and container_offset = %d and tag_offset = 0;",
438 + tag, container_offset);
411 439
412 440 if (tmp == 0 || tmp == -1ULL)
413 441 return 0;
414 442 *container = tmp;
415 443 return 1;
416 444 }
417 445
418 446 int mtag_map_select_tag(mtag_t container, int offset, mtag_t *tag)
419 447 {
420 448 mtag_t tmp = 0;
421 449
422 450 run_sql(save_mtag, &tmp,
423 - "select tag from mtag_map where container = %lld and offset = %d;",
451 + "select tag from mtag_map where container = %lld and container_offset = %d;",
424 452 container, offset);
425 453
426 454 if (tmp == 0 || tmp == -1ULL)
427 455 return 0;
428 456 *tag = tmp;
429 457 return 1;
430 458 }
431 459
432 460 char *get_static_filter(struct symbol *sym)
433 461 {
434 462 static char sql_filter[1024];
435 463
436 464 /* This can only happen on buggy code. Return invalid SQL. */
437 465 if (!sym) {
438 466 sql_filter[0] = '\0';
439 467 return sql_filter;
440 468 }
441 469
442 470 if (sym->ctype.modifiers & MOD_STATIC) {
443 471 snprintf(sql_filter, sizeof(sql_filter),
444 472 "file = '%s' and function = '%s' and static = '1'",
445 473 get_base_file(), sym->ident->name);
446 474 } else {
447 475 snprintf(sql_filter, sizeof(sql_filter),
448 476 "function = '%s' and static = '0'", sym->ident->name);
449 477 }
450 478
451 479 return sql_filter;
452 480 }
453 481
454 482 static int get_row_count(void *_row_count, int argc, char **argv, char **azColName)
455 483 {
456 484 int *row_count = _row_count;
457 485
458 486 *row_count = 0;
459 487 if (argc != 1)
460 488 return 0;
461 489 *row_count = atoi(argv[0]);
462 490 return 0;
463 491 }
464 492
465 493 static void mark_call_params_untracked(struct expression *call)
466 494 {
467 495 struct expression *arg;
468 496 int i = 0;
469 497
470 498 FOR_EACH_PTR(call->args, arg) {
471 499 mark_untracked(call, i++, "$", NULL);
472 500 } END_FOR_EACH_PTR(arg);
473 501 }
474 502
475 503 static void sql_select_return_states_pointer(const char *cols,
476 504 struct expression *call, int (*callback)(void*, int, char**, char**), void *info)
477 505 {
478 506 char *ptr;
479 507 int return_count = 0;
480 508
481 509 ptr = get_fnptr_name(call->fn);
482 510 if (!ptr)
483 511 return;
484 512
485 513 run_sql(get_row_count, &return_count,
486 514 "select count(*) from return_states join function_ptr "
487 515 "where return_states.function == function_ptr.function and "
488 516 "ptr = '%s' and searchable = 1 and type = %d;", ptr, INTERNAL);
489 517 /* The magic number 100 is just from testing on the kernel. */
490 518 if (return_count > 100) {
491 519 mark_call_params_untracked(call);
492 520 return;
493 521 }
494 522
495 523 run_sql(callback, info,
496 524 "select %s from return_states join function_ptr where "
497 525 "return_states.function == function_ptr.function and ptr = '%s' "
498 526 "and searchable = 1 "
499 527 "order by function_ptr.file, return_states.file, return_id, type;",
500 528 cols, ptr);
501 529 }
502 530
503 531 static int is_local_symbol(struct expression *expr)
504 532 {
505 533 if (expr->type != EXPR_SYMBOL)
506 534 return 0;
507 535 if (expr->symbol->ctype.modifiers & (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))
508 536 return 0;
509 537 return 1;
510 538 }
511 539
512 540 void sql_select_return_states(const char *cols, struct expression *call,
513 541 int (*callback)(void*, int, char**, char**), void *info)
514 542 {
515 543 struct expression *fn;
516 544 int row_count = 0;
517 545
518 546 if (is_fake_call(call))
519 547 return;
520 548
521 549 fn = strip_expr(call->fn);
522 550 if (fn->type != EXPR_SYMBOL || !fn->symbol || is_local_symbol(fn)) {
523 551 sql_select_return_states_pointer(cols, call, callback, info);
524 552 return;
525 553 }
526 554
527 555 if (inlinable(fn)) {
528 556 mem_sql(callback, info,
529 557 "select %s from return_states where call_id = '%lu' order by return_id, type;",
530 558 cols, (unsigned long)call);
531 559 return;
532 560 }
533 561
534 562 run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
535 563 get_static_filter(fn->symbol));
536 564 if (row_count > 3000)
537 565 return;
538 566
539 567 run_sql(callback, info, "select %s from return_states where %s order by file, return_id, type;",
540 568 cols, get_static_filter(fn->symbol));
541 569 }
542 570
543 571 #define CALL_IMPLIES 0
544 572 #define RETURN_IMPLIES 1
545 573
546 574 struct implies_info {
547 575 int type;
548 576 struct db_implies_cb_list *cb_list;
549 577 struct expression *expr;
550 578 struct symbol *sym;
551 579 };
552 580
553 581 void sql_select_implies(const char *cols, struct implies_info *info,
554 582 int (*callback)(void*, int, char**, char**))
555 583 {
556 584 if (info->type == RETURN_IMPLIES && inlinable(info->expr->fn)) {
557 585 mem_sql(callback, info,
558 586 "select %s from return_implies where call_id = '%lu';",
559 587 cols, (unsigned long)info->expr);
560 588 return;
561 589 }
562 590
563 591 run_sql(callback, info, "select %s from %s_implies where %s;",
564 592 cols,
565 593 info->type == CALL_IMPLIES ? "call" : "return",
566 594 get_static_filter(info->sym));
567 595 }
568 596
569 597 struct select_caller_info_data {
570 598 struct stree *final_states;
571 599 struct timeval start_time;
572 600 int prev_func_id;
573 601 int ignore;
574 602 int results;
575 603 };
576 604
577 605 static int caller_info_callback(void *_data, int argc, char **argv, char **azColName);
578 606
579 607 static void sql_select_caller_info(struct select_caller_info_data *data,
580 608 const char *cols, struct symbol *sym)
581 609 {
582 610 if (__inline_fn) {
583 611 mem_sql(caller_info_callback, data,
584 612 "select %s from caller_info where call_id = %lu;",
585 613 cols, (unsigned long)__inline_fn);
586 614 return;
587 615 }
588 616
589 617 if (sym->ident->name && is_common_function(sym->ident->name))
590 618 return;
591 619 run_sql(caller_info_callback, data,
592 620 "select %s from common_caller_info where %s order by call_id;",
593 621 cols, get_static_filter(sym));
594 622 if (data->results)
595 623 return;
596 624
597 625 run_sql(caller_info_callback, data,
598 626 "select %s from caller_info where %s order by call_id;",
599 627 cols, get_static_filter(sym));
600 628 }
601 629
602 630 void select_caller_info_hook(void (*callback)(const char *name, struct symbol *sym, char *key, char *value), int type)
603 631 {
604 632 struct def_callback *def_callback = __alloc_def_callback(0);
605 633
606 634 def_callback->hook_type = type;
607 635 def_callback->callback = callback;
608 636 add_ptr_list(&select_caller_info_callbacks, def_callback);
609 637 }
610 638
611 639 /*
612 640 * These call backs are used when the --info option is turned on to print struct
613 641 * member information. For example foo->bar could have a state in
614 642 * smatch_extra.c and also check_user.c.
↓ open down ↓ |
181 lines elided |
↑ open up ↑ |
615 643 */
616 644 void add_member_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
617 645 {
618 646 struct member_info_callback *member_callback = __alloc_member_info_callback(0);
619 647
620 648 member_callback->owner = owner;
621 649 member_callback->callback = callback;
622 650 add_ptr_list(&member_callbacks, member_callback);
623 651 }
624 652
653 +void add_caller_info_callback(int owner, void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
654 +{
655 + struct member_info_callback *member_callback = __alloc_member_info_callback(0);
656 +
657 + member_callback->owner = owner;
658 + member_callback->callback = callback;
659 + add_ptr_list(&member_callbacks_new, member_callback);
660 +}
661 +
625 662 void add_split_return_callback(void (*fn)(int return_id, char *return_ranges, struct expression *returned_expr))
626 663 {
627 664 struct returned_state_callback *callback = __alloc_returned_state_callback(0);
628 665
629 666 callback->callback = fn;
630 667 add_ptr_list(&returned_state_callbacks, callback);
631 668 }
632 669
633 670 void add_returned_member_callback(int owner, void (*callback)(int return_id, char *return_ranges, struct expression *expr, char *printed_name, struct smatch_state *state))
634 671 {
635 672 struct returned_member_callback *member_callback = __alloc_returned_member_callback(0);
636 673
637 674 member_callback->owner = owner;
638 675 member_callback->callback = callback;
639 676 add_ptr_list(&returned_member_callbacks, member_callback);
640 677 }
641 678
642 679 void select_call_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
643 680 {
644 681 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
645 682
646 683 cb->type = type;
647 684 cb->callback = callback;
648 685 add_ptr_list(&call_implies_cb_list, cb);
649 686 }
650 687
651 688 void select_return_implies_hook(int type, void (*callback)(struct expression *call, struct expression *arg, char *key, char *value))
652 689 {
653 690 struct db_implies_callback *cb = __alloc_db_implies_callback(0);
654 691
655 692 cb->type = type;
656 693 cb->callback = callback;
657 694 add_ptr_list(&return_implies_cb_list, cb);
658 695 }
659 696
660 697 struct return_info {
661 698 struct expression *static_returns_call;
662 699 struct symbol *return_type;
663 700 struct range_list *return_range_list;
664 701 };
665 702
666 703 static int db_return_callback(void *_ret_info, int argc, char **argv, char **azColName)
667 704 {
668 705 struct return_info *ret_info = _ret_info;
669 706 struct range_list *rl;
670 707 struct expression *call_expr = ret_info->static_returns_call;
671 708
672 709 if (argc != 1)
673 710 return 0;
674 711 call_results_to_rl(call_expr, ret_info->return_type, argv[0], &rl);
675 712 ret_info->return_range_list = rl_union(ret_info->return_range_list, rl);
676 713 return 0;
677 714 }
678 715
679 716 struct range_list *db_return_vals(struct expression *expr)
680 717 {
681 718 struct return_info ret_info = {};
682 719 char buf[64];
683 720 struct sm_state *sm;
684 721
685 722 if (is_fake_call(expr))
686 723 return NULL;
687 724
688 725 snprintf(buf, sizeof(buf), "return %p", expr);
689 726 sm = get_sm_state(SMATCH_EXTRA, buf, NULL);
690 727 if (sm)
691 728 return clone_rl(estate_rl(sm->state));
692 729 ret_info.static_returns_call = expr;
693 730 ret_info.return_type = get_type(expr);
694 731 if (!ret_info.return_type)
695 732 return NULL;
696 733
697 734 if (expr->fn->type != EXPR_SYMBOL || !expr->fn->symbol)
698 735 return NULL;
699 736
700 737 ret_info.return_range_list = NULL;
701 738 if (inlinable(expr->fn)) {
702 739 mem_sql(db_return_callback, &ret_info,
703 740 "select distinct return from return_states where call_id = '%lu';",
704 741 (unsigned long)expr);
705 742 } else {
706 743 run_sql(db_return_callback, &ret_info,
707 744 "select distinct return from return_states where %s;",
708 745 get_static_filter(expr->fn->symbol));
709 746 }
710 747 return ret_info.return_range_list;
711 748 }
712 749
713 750 struct range_list *db_return_vals_from_str(const char *fn_name)
714 751 {
715 752 struct return_info ret_info;
716 753
717 754 ret_info.static_returns_call = NULL;
718 755 ret_info.return_type = &llong_ctype;
719 756 ret_info.return_range_list = NULL;
720 757
721 758 run_sql(db_return_callback, &ret_info,
722 759 "select distinct return from return_states where function = '%s';",
723 760 fn_name);
724 761 return ret_info.return_range_list;
725 762 }
726 763
727 764 /*
728 765 * This is used when we have a function that takes a function pointer as a
729 766 * parameter. "frob(blah, blah, my_function);" We know that the return values
730 767 * from frob() come from my_funcion() so we want to find the possible returns
731 768 * of my_function(), but we don't know which arguments are passed to it.
732 769 *
733 770 */
734 771 struct range_list *db_return_vals_no_args(struct expression *expr)
735 772 {
736 773 struct return_info ret_info = {};
737 774
738 775 if (!expr || expr->type != EXPR_SYMBOL)
739 776 return NULL;
740 777
741 778 ret_info.static_returns_call = expr;
742 779 ret_info.return_type = get_type(expr);
743 780 ret_info.return_type = get_real_base_type(ret_info.return_type);
744 781 if (!ret_info.return_type)
745 782 return NULL;
746 783
747 784 run_sql(db_return_callback, &ret_info,
748 785 "select distinct return from return_states where %s;",
749 786 get_static_filter(expr->symbol));
750 787
751 788 return ret_info.return_range_list;
752 789 }
753 790
754 791 static void match_call_marker(struct expression *expr)
755 792 {
756 793 struct symbol *type;
757 794
758 795 type = get_type(expr->fn);
759 796 if (type && type->type == SYM_PTR)
760 797 type = get_real_base_type(type);
761 798
762 799 /*
763 800 * we just want to record something in the database so that if we have
764 801 * two calls like: frob(4); frob(some_unkown); then on the receiving
765 802 * side we know that sometimes frob is called with unknown parameters.
766 803 */
767 804
768 805 sql_insert_caller_info(expr, INTERNAL, -1, "%call_marker%", type_to_str(type));
769 806 }
770 807
771 808 int is_recursive_member(const char *name)
772 809 {
773 810 char buf[256];
774 811 const char *p, *next;
775 812 int size;
776 813
777 814 p = strchr(name, '>');
778 815 if (!p)
779 816 return 0;
780 817 p++;
781 818 while (true) {
782 819 next = strchr(p, '>');
783 820 if (!next)
784 821 return 0;
785 822 next++;
786 823
787 824 size = next - p;
788 825 if (size >= sizeof(buf))
789 826 return 0;
790 827 memcpy(buf, p, size);
791 828 buf[size] = '\0';
792 829 if (strstr(next, buf))
793 830 return 1;
794 831 p = next;
795 832 }
796 833 }
797 834
798 835 char *sm_to_arg_name(struct expression *expr, struct sm_state *sm)
799 836 {
800 837 struct symbol *sym;
801 838 const char *sm_name;
802 839 char *name;
803 840 bool is_address = false;
804 841 bool add_star = false;
805 842 char buf[256];
806 843 char *ret = NULL;
807 844 int len;
808 845
809 846 expr = strip_expr(expr);
810 847 if (!expr)
811 848 return NULL;
812 849
813 850 if (expr->type == EXPR_PREOP && expr->op == '&') {
814 851 expr = strip_expr(expr->unop);
815 852 is_address = true;
816 853 }
817 854
818 855 name = expr_to_var_sym(expr, &sym);
819 856 if (!name || !sym)
820 857 goto free;
821 858 if (sym != sm->sym)
822 859 goto free;
823 860
824 861 sm_name = sm->name;
825 862 add_star = false;
826 863 if (sm_name[0] == '*') {
827 864 add_star = true;
828 865 sm_name++;
829 866 }
830 867
831 868 len = strlen(name);
832 869 if (strncmp(name, sm_name, len) != 0)
833 870 goto free;
834 871 if (sm_name[len] == '\0') {
835 872 snprintf(buf, sizeof(buf), "%s%s$",
836 873 add_star ? "*" : "", is_address ? "*" : "");
837 874 } else {
838 875 if (sm_name[len] != '.' && sm_name[len] != '-')
839 876 goto free;
840 877 if (sm_name[len] == '-')
841 878 len++;
842 879 // FIXME does is_address really imply that sm_name[len] == '-'
843 880 snprintf(buf, sizeof(buf), "%s$->%s", add_star ? "*" : "",
↓ open down ↓ |
209 lines elided |
↑ open up ↑ |
844 881 sm_name + len);
845 882 }
846 883
847 884 ret = alloc_sname(buf);
848 885 free:
849 886 free_string(name);
850 887 return ret;
851 888 }
852 889
853 890 static void print_struct_members(struct expression *call, struct expression *expr, int param, struct stree *stree,
854 - void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm))
891 + void (*callback)(struct expression *call, int param, char *printed_name, struct sm_state *sm),
892 + bool new)
855 893 {
856 894 struct sm_state *sm;
857 895 const char *sm_name;
858 896 char *name;
859 897 struct symbol *sym;
860 898 int len;
861 899 char printed_name[256];
862 900 int is_address = 0;
863 901 bool add_star;
864 902 struct symbol *type;
865 903
866 904 expr = strip_expr(expr);
867 905 if (!expr)
868 906 return;
869 907 type = get_type(expr);
870 908 if (type && type_bits(type) < type_bits(&ulong_ctype))
871 909 return;
872 910
873 911 if (expr->type == EXPR_PREOP && expr->op == '&') {
874 912 expr = strip_expr(expr->unop);
875 913 is_address = 1;
876 914 }
877 915
878 916 name = expr_to_var_sym(expr, &sym);
879 917 if (!name || !sym)
880 918 goto free;
881 919
882 920 len = strlen(name);
883 921 FOR_EACH_SM(stree, sm) {
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
884 922 if (sm->sym != sym)
885 923 continue;
886 924 sm_name = sm->name;
887 925 add_star = false;
888 926 if (sm_name[0] == '*') {
889 927 add_star = true;
890 928 sm_name++;
891 929 }
892 930 // FIXME: simplify?
893 931 if (!add_star && strcmp(name, sm_name) == 0) {
894 - if (is_address)
932 + if (is_address) {
895 933 snprintf(printed_name, sizeof(printed_name), "*$");
896 - else /* these are already handled. fixme: handle them here */
897 - continue;
934 + } else {
935 + if (new)
936 + snprintf(printed_name, sizeof(printed_name), "$");
937 + else
938 + continue;
939 + }
898 940 } else if (add_star && strcmp(name, sm_name) == 0) {
899 941 snprintf(printed_name, sizeof(printed_name), "%s*$",
900 942 is_address ? "*" : "");
901 943 } else if (strncmp(name, sm_name, len) == 0) {
902 944 if (sm_name[len] != '.' && sm_name[len] != '-')
903 945 continue;
904 - if (is_address)
946 + if (is_address && sm_name[len] == '.') {
905 947 snprintf(printed_name, sizeof(printed_name),
906 948 "%s$->%s", add_star ? "*" : "",
907 949 sm_name + len + 1);
908 - else
950 + } else if (is_address && sm_name[len] == '-') {
909 951 snprintf(printed_name, sizeof(printed_name),
952 + "%s(*$)%s", add_star ? "*" : "",
953 + sm_name + len);
954 + } else {
955 + snprintf(printed_name, sizeof(printed_name),
910 956 "%s$%s", add_star ? "*" : "",
911 957 sm_name + len);
958 + }
912 959 } else {
913 960 continue;
914 961 }
915 962 if (is_recursive_member(printed_name))
916 963 continue;
917 964 callback(call, param, printed_name, sm);
918 965 } END_FOR_EACH_SM(sm);
919 966 free:
920 967 free_string(name);
921 968 }
922 969
923 970 static void match_call_info(struct expression *call)
924 971 {
925 972 struct member_info_callback *cb;
926 973 struct expression *arg;
927 974 struct stree *stree;
928 975 char *name;
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
929 976 int i;
930 977
931 978 name = get_fnptr_name(call->fn);
932 979 if (!name)
933 980 return;
934 981
935 982 FOR_EACH_PTR(member_callbacks, cb) {
936 983 stree = get_all_states_stree(cb->owner);
937 984 i = 0;
938 985 FOR_EACH_PTR(call->args, arg) {
939 - print_struct_members(call, arg, i, stree, cb->callback);
986 + print_struct_members(call, arg, i, stree, cb->callback, 0);
940 987 i++;
941 988 } END_FOR_EACH_PTR(arg);
942 989 free_stree(&stree);
943 990 } END_FOR_EACH_PTR(cb);
944 991
945 992 free_string(name);
946 993 }
947 994
995 +static void match_call_info_new(struct expression *call)
996 +{
997 + struct member_info_callback *cb;
998 + struct expression *arg;
999 + struct stree *stree;
1000 + char *name;
1001 + int i;
1002 +
1003 + name = get_fnptr_name(call->fn);
1004 + if (!name)
1005 + return;
1006 +
1007 + FOR_EACH_PTR(member_callbacks_new, cb) {
1008 + stree = get_all_states_stree(cb->owner);
1009 + i = 0;
1010 + FOR_EACH_PTR(call->args, arg) {
1011 + print_struct_members(call, arg, i, stree, cb->callback, 1);
1012 + i++;
1013 + } END_FOR_EACH_PTR(arg);
1014 + free_stree(&stree);
1015 + } END_FOR_EACH_PTR(cb);
1016 +
1017 + free_string(name);
1018 +}
1019 +
948 1020 static int get_param(int param, char **name, struct symbol **sym)
949 1021 {
950 1022 struct symbol *arg;
951 1023 int i;
952 1024
953 1025 i = 0;
954 1026 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, arg) {
955 1027 /*
956 1028 * this is a temporary hack to work around a bug (I think in sparse?)
957 1029 * 2.6.37-rc1:fs/reiserfs/journal.o
958 1030 * If there is a function definition without parameter name found
959 1031 * after a function implementation then it causes a crash.
960 1032 * int foo() {}
961 1033 * int bar(char *);
962 1034 */
963 1035 if (arg->ident->name < (char *)100)
964 1036 continue;
965 1037 if (i == param) {
966 1038 *name = arg->ident->name;
967 1039 *sym = arg;
968 1040 return TRUE;
969 1041 }
970 1042 i++;
971 1043 } END_FOR_EACH_PTR(arg);
972 1044
973 1045 return FALSE;
974 1046 }
975 1047
976 1048 static int function_signature_matches(const char *sig)
977 1049 {
978 1050 char *my_sig;
979 1051
980 1052 my_sig = function_signature();
981 1053 if (!sig || !my_sig)
982 1054 return 1; /* default to matching */
983 1055 if (strcmp(my_sig, sig) == 0)
984 1056 return 1;
985 1057 return 0;
986 1058 }
987 1059
988 1060 static int caller_info_callback(void *_data, int argc, char **argv, char **azColName)
989 1061 {
990 1062 struct select_caller_info_data *data = _data;
991 1063 int func_id;
992 1064 long type;
993 1065 long param;
994 1066 char *key;
995 1067 char *value;
996 1068 char *name = NULL;
997 1069 struct symbol *sym = NULL;
998 1070 struct def_callback *def_callback;
999 1071 struct stree *stree;
1000 1072 struct timeval cur_time;
1001 1073
1002 1074 data->results = 1;
1003 1075
1004 1076 if (argc != 5)
1005 1077 return 0;
1006 1078
1007 1079 gettimeofday(&cur_time, NULL);
1008 1080 if (cur_time.tv_sec - data->start_time.tv_sec > 10)
1009 1081 return 0;
1010 1082
1011 1083 func_id = atoi(argv[0]);
1012 1084 errno = 0;
1013 1085 type = strtol(argv[1], NULL, 10);
1014 1086 param = strtol(argv[2], NULL, 10);
1015 1087 if (errno)
1016 1088 return 0;
1017 1089 key = argv[3];
1018 1090 value = argv[4];
1019 1091
1020 1092 if (data->prev_func_id == -1)
1021 1093 data->prev_func_id = func_id;
1022 1094 if (func_id != data->prev_func_id) {
1023 1095 stree = __pop_fake_cur_stree();
1024 1096 if (!data->ignore)
1025 1097 merge_stree(&data->final_states, stree);
1026 1098 free_stree(&stree);
1027 1099 __push_fake_cur_stree();
1028 1100 __unnullify_path();
1029 1101 data->prev_func_id = func_id;
1030 1102 data->ignore = 0;
1031 1103 }
1032 1104
1033 1105 if (data->ignore)
1034 1106 return 0;
1035 1107 if (type == INTERNAL &&
1036 1108 !function_signature_matches(value)) {
1037 1109 data->ignore = 1;
1038 1110 return 0;
1039 1111 }
1040 1112
1041 1113 if (param >= 0 && !get_param(param, &name, &sym))
1042 1114 return 0;
1043 1115
1044 1116 FOR_EACH_PTR(select_caller_info_callbacks, def_callback) {
1045 1117 if (def_callback->hook_type == type)
1046 1118 def_callback->callback(name, sym, key, value);
1047 1119 } END_FOR_EACH_PTR(def_callback);
1048 1120
1049 1121 return 0;
1050 1122 }
1051 1123
1052 1124 static struct string_list *ptr_names_done;
1053 1125 static struct string_list *ptr_names;
1054 1126
1055 1127 static int get_ptr_name(void *unused, int argc, char **argv, char **azColName)
1056 1128 {
1057 1129 insert_string(&ptr_names, alloc_string(argv[0]));
1058 1130 return 0;
1059 1131 }
1060 1132
1061 1133 static char *get_next_ptr_name(void)
1062 1134 {
1063 1135 char *ptr;
1064 1136
1065 1137 FOR_EACH_PTR(ptr_names, ptr) {
1066 1138 if (!insert_string(&ptr_names_done, ptr))
1067 1139 continue;
1068 1140 return ptr;
1069 1141 } END_FOR_EACH_PTR(ptr);
1070 1142 return NULL;
1071 1143 }
1072 1144
1073 1145 static void get_ptr_names(const char *file, const char *name)
1074 1146 {
1075 1147 char sql_filter[1024];
1076 1148 int before, after;
1077 1149
1078 1150 if (file) {
1079 1151 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
1080 1152 file, name);
1081 1153 } else {
1082 1154 snprintf(sql_filter, 1024, "function = '%s';", name);
1083 1155 }
1084 1156
1085 1157 before = ptr_list_size((struct ptr_list *)ptr_names);
1086 1158
1087 1159 run_sql(get_ptr_name, NULL,
1088 1160 "select distinct ptr from function_ptr where %s",
1089 1161 sql_filter);
1090 1162
1091 1163 after = ptr_list_size((struct ptr_list *)ptr_names);
1092 1164 if (before == after)
1093 1165 return;
1094 1166
1095 1167 while ((name = get_next_ptr_name()))
1096 1168 get_ptr_names(NULL, name);
1097 1169 }
1098 1170
↓ open down ↓ |
141 lines elided |
↑ open up ↑ |
1099 1171 static void match_data_from_db(struct symbol *sym)
1100 1172 {
1101 1173 struct select_caller_info_data data = { .prev_func_id = -1 };
1102 1174 struct sm_state *sm;
1103 1175 struct stree *stree;
1104 1176 struct timeval end_time;
1105 1177
1106 1178 if (!sym || !sym->ident)
1107 1179 return;
1108 1180
1181 + set_fn_mtag(sym);
1109 1182 gettimeofday(&data.start_time, NULL);
1110 1183
1111 1184 __push_fake_cur_stree();
1112 1185 __unnullify_path();
1113 1186
1114 1187 if (!__inline_fn) {
1115 1188 char *ptr;
1116 1189
1117 1190 if (sym->ctype.modifiers & MOD_STATIC)
1118 1191 get_ptr_names(get_base_file(), sym->ident->name);
1119 1192 else
1120 1193 get_ptr_names(NULL, sym->ident->name);
1121 1194
1122 1195 if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
1123 1196 __free_ptr_list((struct ptr_list **)&ptr_names);
1124 1197 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1125 1198 __free_fake_cur_stree();
1126 1199 return;
1127 1200 }
1128 1201
1129 1202 sql_select_caller_info(&data,
1130 1203 "call_id, type, parameter, key, value",
1131 1204 sym);
1132 1205
1133 1206
1134 1207 stree = __pop_fake_cur_stree();
1135 1208 if (!data.ignore)
1136 1209 merge_stree(&data.final_states, stree);
1137 1210 free_stree(&stree);
1138 1211 __push_fake_cur_stree();
1139 1212 __unnullify_path();
1140 1213 data.prev_func_id = -1;
1141 1214 data.ignore = 0;
1142 1215 data.results = 0;
1143 1216
1144 1217 FOR_EACH_PTR(ptr_names, ptr) {
1145 1218 run_sql(caller_info_callback, &data,
1146 1219 "select call_id, type, parameter, key, value"
1147 1220 " from common_caller_info where function = '%s' order by call_id",
1148 1221 ptr);
1149 1222 } END_FOR_EACH_PTR(ptr);
1150 1223
1151 1224 if (data.results) {
1152 1225 FOR_EACH_PTR(ptr_names, ptr) {
1153 1226 free_string(ptr);
1154 1227 } END_FOR_EACH_PTR(ptr);
1155 1228 goto free_ptr_names;
1156 1229 }
1157 1230
1158 1231 FOR_EACH_PTR(ptr_names, ptr) {
1159 1232 run_sql(caller_info_callback, &data,
1160 1233 "select call_id, type, parameter, key, value"
1161 1234 " from caller_info where function = '%s' order by call_id",
1162 1235 ptr);
1163 1236 free_string(ptr);
1164 1237 } END_FOR_EACH_PTR(ptr);
1165 1238
1166 1239 free_ptr_names:
1167 1240 __free_ptr_list((struct ptr_list **)&ptr_names);
1168 1241 __free_ptr_list((struct ptr_list **)&ptr_names_done);
1169 1242 } else {
1170 1243 sql_select_caller_info(&data,
1171 1244 "call_id, type, parameter, key, value",
1172 1245 sym);
1173 1246 }
1174 1247
1175 1248 stree = __pop_fake_cur_stree();
1176 1249 if (!data.ignore)
1177 1250 merge_stree(&data.final_states, stree);
1178 1251 free_stree(&stree);
1179 1252
1180 1253 gettimeofday(&end_time, NULL);
1181 1254 if (end_time.tv_sec - data.start_time.tv_sec <= 10) {
1182 1255 FOR_EACH_SM(data.final_states, sm) {
1183 1256 __set_sm(sm);
1184 1257 } END_FOR_EACH_SM(sm);
1185 1258 }
1186 1259
1187 1260 free_stree(&data.final_states);
1188 1261 }
1189 1262
1190 1263 static int return_implies_callbacks(void *_info, int argc, char **argv, char **azColName)
1191 1264 {
1192 1265 struct implies_info *info = _info;
1193 1266 struct db_implies_callback *cb;
1194 1267 struct expression *arg = NULL;
1195 1268 int type;
1196 1269 int param;
1197 1270
1198 1271 if (argc != 5)
1199 1272 return 0;
1200 1273
1201 1274 type = atoi(argv[1]);
1202 1275 param = atoi(argv[2]);
1203 1276
1204 1277 FOR_EACH_PTR(info->cb_list, cb) {
1205 1278 if (cb->type != type)
1206 1279 continue;
1207 1280 if (param != -1) {
1208 1281 arg = get_argument_from_call_expr(info->expr->args, param);
1209 1282 if (!arg)
1210 1283 continue;
1211 1284 }
1212 1285 cb->callback(info->expr, arg, argv[3], argv[4]);
1213 1286 } END_FOR_EACH_PTR(cb);
1214 1287
1215 1288 return 0;
1216 1289 }
1217 1290
1218 1291 static int call_implies_callbacks(void *_info, int argc, char **argv, char **azColName)
1219 1292 {
1220 1293 struct implies_info *info = _info;
1221 1294 struct db_implies_callback *cb;
1222 1295 struct expression *arg;
1223 1296 struct symbol *sym;
1224 1297 char *name;
1225 1298 int type;
1226 1299 int param;
1227 1300
1228 1301 if (argc != 5)
1229 1302 return 0;
1230 1303
1231 1304 type = atoi(argv[1]);
1232 1305 param = atoi(argv[2]);
1233 1306
1234 1307 if (!get_param(param, &name, &sym))
1235 1308 return 0;
1236 1309 arg = symbol_expression(sym);
1237 1310 if (!arg)
1238 1311 return 0;
1239 1312
1240 1313 FOR_EACH_PTR(info->cb_list, cb) {
1241 1314 if (cb->type != type)
1242 1315 continue;
1243 1316 cb->callback(info->expr, arg, argv[3], argv[4]);
1244 1317 } END_FOR_EACH_PTR(cb);
1245 1318
1246 1319 return 0;
1247 1320 }
1248 1321
1249 1322 static void match_return_implies(struct expression *expr)
1250 1323 {
1251 1324 struct implies_info info = {
1252 1325 .type = RETURN_IMPLIES,
1253 1326 .cb_list = return_implies_cb_list,
1254 1327 };
1255 1328
1256 1329 if (expr->fn->type != EXPR_SYMBOL ||
1257 1330 !expr->fn->symbol)
1258 1331 return;
1259 1332 info.expr = expr;
1260 1333 info.sym = expr->fn->symbol;
1261 1334 sql_select_implies("function, type, parameter, key, value", &info,
1262 1335 return_implies_callbacks);
1263 1336 }
1264 1337
1265 1338 static void match_call_implies(struct symbol *sym)
1266 1339 {
1267 1340 struct implies_info info = {
1268 1341 .type = CALL_IMPLIES,
1269 1342 .cb_list = call_implies_cb_list,
1270 1343 };
1271 1344
1272 1345 if (!sym || !sym->ident)
1273 1346 return;
1274 1347
1275 1348 info.sym = sym;
1276 1349 sql_select_implies("function, type, parameter, key, value", &info,
1277 1350 call_implies_callbacks);
1278 1351 }
1279 1352
1280 1353 static char *get_fn_param_str(struct expression *expr)
1281 1354 {
1282 1355 struct expression *tmp;
1283 1356 int param;
1284 1357 char buf[32];
1285 1358
1286 1359 tmp = get_assigned_expr(expr);
1287 1360 if (tmp)
1288 1361 expr = tmp;
1289 1362 expr = strip_expr(expr);
1290 1363 if (!expr || expr->type != EXPR_CALL)
1291 1364 return NULL;
1292 1365 expr = strip_expr(expr->fn);
1293 1366 if (!expr || expr->type != EXPR_SYMBOL)
1294 1367 return NULL;
1295 1368 param = get_param_num(expr);
1296 1369 if (param < 0)
1297 1370 return NULL;
1298 1371
1299 1372 snprintf(buf, sizeof(buf), "[r $%d]", param);
1300 1373 return alloc_sname(buf);
1301 1374 }
1302 1375
1303 1376 static char *get_return_compare_is_param(struct expression *expr)
1304 1377 {
1305 1378 char *var;
1306 1379 char buf[256];
1307 1380 int comparison;
1308 1381 int param;
1309 1382
1310 1383 param = get_param_num(expr);
1311 1384 if (param < 0)
1312 1385 return NULL;
1313 1386
1314 1387 var = expr_to_var(expr);
1315 1388 if (!var)
1316 1389 return NULL;
1317 1390 snprintf(buf, sizeof(buf), "%s orig", var);
1318 1391 comparison = get_comparison_strings(var, buf);
1319 1392 free_string(var);
1320 1393
1321 1394 if (!comparison)
1322 1395 return NULL;
1323 1396
1324 1397 snprintf(buf, sizeof(buf), "[%s$%d]", show_special(comparison), param);
1325 1398 return alloc_sname(buf);
1326 1399 }
1327 1400
1328 1401 static char *get_return_compare_str(struct expression *expr)
1329 1402 {
1330 1403 char *compare_str;
1331 1404
1332 1405 compare_str = get_return_compare_is_param(expr);
1333 1406 if (compare_str)
1334 1407 return compare_str;
1335 1408
1336 1409 compare_str = expr_lte_to_param(expr, -1);
1337 1410 if (compare_str)
1338 1411 return compare_str;
1339 1412
1340 1413 return expr_param_comparison(expr, -1);
1341 1414 }
1342 1415
1343 1416 static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
1344 1417 {
1345 1418 struct range_list *rl;
1346 1419 char *return_ranges;
1347 1420 sval_t sval;
1348 1421 char *fn_param_str;
1349 1422 char *compare_str;
1350 1423 char *math_str;
1351 1424 char buf[128];
1352 1425
1353 1426 *rl_p = NULL;
1354 1427
1355 1428 if (!expr)
1356 1429 return alloc_sname("");
1357 1430
1358 1431 if (get_implied_value(expr, &sval)) {
1359 1432 sval = sval_cast(cur_func_return_type(), sval);
1360 1433 *rl_p = alloc_rl(sval, sval);
1361 1434 return sval_to_str_or_err_ptr(sval);
1362 1435 }
1363 1436
1364 1437 fn_param_str = get_fn_param_str(expr);
1365 1438 compare_str = expr_equal_to_param(expr, -1);
1366 1439 math_str = get_value_in_terms_of_parameter_math(expr);
1367 1440
1368 1441 if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
1369 1442 rl = cast_rl(cur_func_return_type(), rl);
1370 1443 return_ranges = show_rl(rl);
1371 1444 } else if (get_imaginary_absolute(expr, &rl)){
1372 1445 rl = cast_rl(cur_func_return_type(), rl);
1373 1446 return alloc_sname(show_rl(rl));
1374 1447 } else {
1375 1448 get_absolute_rl(expr, &rl);
1376 1449 rl = cast_rl(cur_func_return_type(), rl);
1377 1450 return_ranges = show_rl(rl);
1378 1451 }
1379 1452 *rl_p = rl;
1380 1453
1381 1454 if (fn_param_str) {
1382 1455 snprintf(buf, sizeof(buf), "%s%s", return_ranges, fn_param_str);
1383 1456 return alloc_sname(buf);
1384 1457 }
1385 1458 if (compare_str) {
1386 1459 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1387 1460 return alloc_sname(buf);
1388 1461 }
1389 1462 if (math_str) {
1390 1463 snprintf(buf, sizeof(buf), "%s[%s]", return_ranges, math_str);
1391 1464 return alloc_sname(buf);
1392 1465 }
1393 1466 compare_str = get_return_compare_str(expr);
1394 1467 if (compare_str) {
1395 1468 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1396 1469 return alloc_sname(buf);
1397 1470 }
1398 1471
1399 1472 return return_ranges;
1400 1473 }
1401 1474
1402 1475 static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
1403 1476 {
1404 1477 sql_insert_return_states(return_id, return_ranges, INTERNAL, -1, "", function_signature());
1405 1478 }
1406 1479
1407 1480 static bool call_return_state_hooks_conditional(struct expression *expr)
1408 1481 {
1409 1482 int final_pass_orig = final_pass;
1410 1483 static int recurse;
1411 1484
1412 1485 if (recurse >= 2)
1413 1486 return false;
1414 1487 if (!expr ||
1415 1488 (expr->type != EXPR_CONDITIONAL && expr->type != EXPR_SELECT))
1416 1489 return false;
1417 1490
1418 1491 recurse++;
1419 1492
1420 1493 __push_fake_cur_stree();
1421 1494
1422 1495 final_pass = 0;
1423 1496 __split_whole_condition(expr->conditional);
1424 1497 final_pass = final_pass_orig;
1425 1498
1426 1499 call_return_state_hooks(expr->cond_true ?: expr->conditional);
1427 1500
1428 1501 __push_true_states();
1429 1502 __use_false_states();
1430 1503
1431 1504 call_return_state_hooks(expr->cond_false);
1432 1505
1433 1506 __merge_true_states();
1434 1507 __free_fake_cur_stree();
1435 1508
1436 1509 recurse--;
1437 1510 return true;
1438 1511 }
1439 1512
1440 1513 static void call_return_state_hooks_compare(struct expression *expr)
1441 1514 {
1442 1515 struct returned_state_callback *cb;
1443 1516 char *return_ranges;
1444 1517 int final_pass_orig = final_pass;
1445 1518 sval_t sval = { .type = &int_ctype };
1446 1519 sval_t ret;
1447 1520
1448 1521 if (!get_implied_value(expr, &ret))
1449 1522 ret.value = -1;
1450 1523
1451 1524 __push_fake_cur_stree();
1452 1525
1453 1526 final_pass = 0;
1454 1527 __split_whole_condition(expr);
1455 1528 final_pass = final_pass_orig;
1456 1529
1457 1530 if (ret.value != 0) {
1458 1531 return_ranges = alloc_sname("1");
1459 1532 sval.value = 1;
1460 1533 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_sval(sval));
1461 1534
1462 1535 return_id++;
1463 1536 FOR_EACH_PTR(returned_state_callbacks, cb) {
1464 1537 cb->callback(return_id, return_ranges, expr);
1465 1538 } END_FOR_EACH_PTR(cb);
1466 1539 }
1467 1540
1468 1541 __push_true_states();
1469 1542 __use_false_states();
1470 1543
1471 1544 if (ret.value != 1) {
1472 1545 return_ranges = alloc_sname("0");
1473 1546 sval.value = 0;
1474 1547 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_sval(sval));
1475 1548
1476 1549 return_id++;
1477 1550 FOR_EACH_PTR(returned_state_callbacks, cb) {
1478 1551 cb->callback(return_id, return_ranges, expr);
1479 1552 } END_FOR_EACH_PTR(cb);
1480 1553 }
1481 1554
1482 1555 __merge_true_states();
1483 1556 __free_fake_cur_stree();
1484 1557 }
1485 1558
1486 1559 static int ptr_in_list(struct sm_state *sm, struct state_list *slist)
1487 1560 {
1488 1561 struct sm_state *tmp;
1489 1562
1490 1563 FOR_EACH_PTR(slist, tmp) {
1491 1564 if (strcmp(tmp->state->name, sm->state->name) == 0)
1492 1565 return 1;
1493 1566 } END_FOR_EACH_PTR(tmp);
1494 1567
1495 1568 return 0;
1496 1569 }
1497 1570
1498 1571 static int split_possible_helper(struct sm_state *sm, struct expression *expr)
1499 1572 {
1500 1573 struct returned_state_callback *cb;
1501 1574 struct range_list *rl;
1502 1575 char *return_ranges;
1503 1576 struct sm_state *tmp;
1504 1577 int ret = 0;
1505 1578 int nr_possible, nr_states;
1506 1579 char *compare_str;
1507 1580 char buf[128];
1508 1581 struct state_list *already_handled = NULL;
1509 1582 sval_t sval;
1510 1583
1511 1584 if (!sm || !sm->merged)
1512 1585 return 0;
1513 1586
1514 1587 if (too_many_possible(sm))
1515 1588 return 0;
1516 1589
1517 1590 /* bail if it gets too complicated */
1518 1591 nr_possible = 0;
1519 1592 FOR_EACH_PTR(sm->possible, tmp) {
1520 1593 if (tmp->merged)
1521 1594 continue;
1522 1595 if (ptr_in_list(tmp, already_handled))
1523 1596 continue;
1524 1597 add_ptr_list(&already_handled, tmp);
1525 1598 nr_possible++;
1526 1599 } END_FOR_EACH_PTR(tmp);
1527 1600 free_slist(&already_handled);
1528 1601 nr_states = get_db_state_count();
1529 1602 if (nr_states * nr_possible >= 2000)
1530 1603 return 0;
1531 1604
1532 1605 FOR_EACH_PTR(sm->possible, tmp) {
1533 1606 if (tmp->merged)
1534 1607 continue;
1535 1608 if (ptr_in_list(tmp, already_handled))
1536 1609 continue;
1537 1610 add_ptr_list(&already_handled, tmp);
1538 1611
1539 1612 ret = 1;
1540 1613 __push_fake_cur_stree();
1541 1614
1542 1615 overwrite_states_using_pool(sm, tmp);
1543 1616
1544 1617 rl = cast_rl(cur_func_return_type(), estate_rl(tmp->state));
1545 1618 return_ranges = show_rl(rl);
1546 1619 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(clone_rl(rl)));
1547 1620 if (!rl_to_sval(rl, &sval)) {
1548 1621 compare_str = get_return_compare_str(expr);
1549 1622 if (compare_str) {
1550 1623 snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
1551 1624 return_ranges = alloc_sname(buf);
1552 1625 }
1553 1626 }
1554 1627
1555 1628 return_id++;
1556 1629 FOR_EACH_PTR(returned_state_callbacks, cb) {
1557 1630 cb->callback(return_id, return_ranges, expr);
1558 1631 } END_FOR_EACH_PTR(cb);
1559 1632
1560 1633 __free_fake_cur_stree();
1561 1634 } END_FOR_EACH_PTR(tmp);
↓ open down ↓ |
443 lines elided |
↑ open up ↑ |
1562 1635
1563 1636 free_slist(&already_handled);
1564 1637
1565 1638 return ret;
1566 1639 }
1567 1640
1568 1641 static int call_return_state_hooks_split_possible(struct expression *expr)
1569 1642 {
1570 1643 struct sm_state *sm;
1571 1644
1572 - if (!expr || expr_equal_to_param(expr, -1))
1645 + if (!expr)
1573 1646 return 0;
1574 1647
1575 1648 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1576 1649 return split_possible_helper(sm, expr);
1577 1650 }
1578 1651
1579 1652 static bool has_possible_negative(struct sm_state *sm)
1580 1653 {
1581 1654 struct sm_state *tmp;
1582 1655
1583 1656 if (!type_signed(estate_type(sm->state)))
1584 1657 return false;
1585 1658
1586 1659 FOR_EACH_PTR(sm->possible, tmp) {
1587 1660 if (!estate_rl(tmp->state))
1588 1661 continue;
1589 1662 if (sval_is_negative(estate_min(tmp->state)) &&
1590 1663 sval_is_negative(estate_max(tmp->state)))
1591 1664 return true;
1592 1665 } END_FOR_EACH_PTR(tmp);
1593 1666
1594 1667 return false;
1595 1668 }
1596 1669
1597 1670 static bool has_separate_zero_null(struct sm_state *sm)
1598 1671 {
1599 1672 struct sm_state *tmp;
1600 1673 sval_t sval;
1601 1674
1602 1675 FOR_EACH_PTR(sm->possible, tmp) {
1603 1676 if (!estate_get_single_value(tmp->state, &sval))
1604 1677 continue;
1605 1678 if (sval.value == 0)
1606 1679 return true;
1607 1680 } END_FOR_EACH_PTR(tmp);
1608 1681
1609 1682 return false;
1610 1683 }
1611 1684
1612 1685 static int split_positive_from_negative(struct expression *expr)
1613 1686 {
1614 1687 struct sm_state *sm;
1615 1688 struct returned_state_callback *cb;
1616 1689 struct range_list *rl;
1617 1690 const char *return_ranges;
1618 1691 struct range_list *ret_rl;
1619 1692 bool separate_zero;
1620 1693 int undo;
1621 1694
1622 1695 /* We're going to print the states 3 times */
1623 1696 if (get_db_state_count() > 10000 / 3)
1624 1697 return 0;
1625 1698
1626 1699 if (!get_implied_rl(expr, &rl) || !rl)
1627 1700 return 0;
1628 1701 /* Forget about INT_MAX and larger */
1629 1702 if (rl_max(rl).value <= 0)
1630 1703 return 0;
1631 1704 if (!sval_is_negative(rl_min(rl)))
1632 1705 return 0;
1633 1706
1634 1707 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1635 1708 if (!sm)
1636 1709 return 0;
1637 1710 if (!has_possible_negative(sm))
1638 1711 return 0;
1639 1712 separate_zero = has_separate_zero_null(sm);
1640 1713
1641 1714 if (!assume(compare_expression(expr, separate_zero ? '>' : SPECIAL_GTE, zero_expr())))
1642 1715 return 0;
1643 1716
1644 1717 return_id++;
1645 1718 return_ranges = get_return_ranges_str(expr, &ret_rl);
1646 1719 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1647 1720 FOR_EACH_PTR(returned_state_callbacks, cb) {
1648 1721 cb->callback(return_id, (char *)return_ranges, expr);
1649 1722 } END_FOR_EACH_PTR(cb);
1650 1723
1651 1724 end_assume();
1652 1725
1653 1726 if (separate_zero) {
1654 1727 undo = assume(compare_expression(expr, SPECIAL_EQUAL, zero_expr()));
1655 1728
1656 1729 return_id++;
1657 1730 return_ranges = get_return_ranges_str(expr, &ret_rl);
1658 1731 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1659 1732 FOR_EACH_PTR(returned_state_callbacks, cb) {
1660 1733 cb->callback(return_id, (char *)return_ranges, expr);
1661 1734 } END_FOR_EACH_PTR(cb);
1662 1735
1663 1736 if (undo)
1664 1737 end_assume();
1665 1738 }
1666 1739
1667 1740 undo = assume(compare_expression(expr, '<', zero_expr()));
1668 1741
1669 1742 return_id++;
1670 1743 return_ranges = get_return_ranges_str(expr, &ret_rl);
1671 1744 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1672 1745 FOR_EACH_PTR(returned_state_callbacks, cb) {
1673 1746 cb->callback(return_id, (char *)return_ranges, expr);
1674 1747 } END_FOR_EACH_PTR(cb);
1675 1748
1676 1749 if (undo)
1677 1750 end_assume();
1678 1751
1679 1752 return 1;
1680 1753 }
1681 1754
1682 1755 static int call_return_state_hooks_split_null_non_null_zero(struct expression *expr)
1683 1756 {
1684 1757 struct returned_state_callback *cb;
1685 1758 struct range_list *rl;
1686 1759 struct range_list *nonnull_rl;
1687 1760 sval_t null_sval;
1688 1761 struct range_list *null_rl = NULL;
1689 1762 char *return_ranges;
1690 1763 struct sm_state *sm;
1691 1764 struct smatch_state *state;
1692 1765 int nr_states;
1693 1766 int final_pass_orig = final_pass;
1694 1767
1695 1768 if (!expr || expr_equal_to_param(expr, -1))
1696 1769 return 0;
1697 1770 if (expr->type == EXPR_CALL)
1698 1771 return 0;
1699 1772
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
1700 1773 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1701 1774 if (!sm)
1702 1775 return 0;
1703 1776 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1704 1777 return 0;
1705 1778 state = sm->state;
1706 1779 if (!estate_rl(state))
1707 1780 return 0;
1708 1781 if (estate_min(state).value == 0 && estate_max(state).value == 0)
1709 1782 return 0;
1783 + if (has_possible_negative(sm))
1784 + return 0;
1710 1785 if (!has_separate_zero_null(sm))
1711 1786 return 0;
1712 1787
1713 1788 nr_states = get_db_state_count();
1714 1789 if (option_info && nr_states >= 1500)
1715 1790 return 0;
1716 1791
1717 1792 rl = estate_rl(state);
1718 1793
1719 1794 __push_fake_cur_stree();
1720 1795
1721 1796 final_pass = 0;
1722 1797 __split_whole_condition(expr);
1723 1798 final_pass = final_pass_orig;
1724 1799
1725 1800 nonnull_rl = rl_filter(rl, rl_zero());
1726 1801 return_ranges = show_rl(nonnull_rl);
1727 1802 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonnull_rl));
1728 1803
1729 1804 return_id++;
1730 1805 FOR_EACH_PTR(returned_state_callbacks, cb) {
1731 1806 cb->callback(return_id, return_ranges, expr);
1732 1807 } END_FOR_EACH_PTR(cb);
1733 1808
1734 1809 __push_true_states();
1735 1810 __use_false_states();
1736 1811
1737 1812 return_ranges = alloc_sname("0");
1738 1813 null_sval = sval_type_val(rl_type(rl), 0);
1739 1814 add_range(&null_rl, null_sval, null_sval);
1740 1815 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(null_rl));
1741 1816 return_id++;
1742 1817 FOR_EACH_PTR(returned_state_callbacks, cb) {
1743 1818 cb->callback(return_id, return_ranges, expr);
1744 1819 } END_FOR_EACH_PTR(cb);
1745 1820
1746 1821 __merge_true_states();
1747 1822 __free_fake_cur_stree();
1748 1823
1749 1824 return 1;
1750 1825 }
1751 1826
1752 1827 static bool is_kernel_success_fail(struct sm_state *sm)
1753 1828 {
1754 1829 struct sm_state *tmp;
1755 1830 struct range_list *rl;
1756 1831 bool has_zero = false;
1757 1832 bool has_neg = false;
1758 1833
1759 1834 if (!type_signed(estate_type(sm->state)))
1760 1835 return false;
1761 1836
1762 1837 FOR_EACH_PTR(sm->possible, tmp) {
1763 1838 rl = estate_rl(tmp->state);
1764 1839 if (!rl)
1765 1840 return false;
1766 1841 if (rl_min(rl).value == 0 && rl_max(rl).value == 0) {
1767 1842 has_zero = true;
1768 1843 continue;
1769 1844 }
1770 1845 has_neg = true;
1771 1846 if (rl_min(rl).value >= -4095 && rl_max(rl).value < 0)
1772 1847 continue;
1773 1848 if (strcmp(tmp->state->name, "s32min-(-1)") == 0)
1774 1849 continue;
1775 1850 if (strcmp(tmp->state->name, "s32min-(-1),1-s32max") == 0)
1776 1851 continue;
1777 1852 return false;
1778 1853 } END_FOR_EACH_PTR(tmp);
1779 1854
1780 1855 return has_zero && has_neg;
1781 1856 }
1782 1857
1783 1858 static int call_return_state_hooks_split_success_fail(struct expression *expr)
1784 1859 {
1785 1860 struct sm_state *sm;
1786 1861 struct range_list *rl;
1787 1862 struct range_list *nonzero_rl;
1788 1863 sval_t zero_sval;
1789 1864 struct range_list *zero_rl = NULL;
1790 1865 int nr_states;
1791 1866 struct returned_state_callback *cb;
1792 1867 char *return_ranges;
1793 1868 int final_pass_orig = final_pass;
1794 1869
1795 1870 if (option_project != PROJ_KERNEL)
1796 1871 return 0;
1797 1872
1798 1873 nr_states = get_db_state_count();
1799 1874 if (nr_states > 2000)
1800 1875 return 0;
1801 1876
1802 1877 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
1803 1878 if (!sm)
1804 1879 return 0;
1805 1880 if (ptr_list_size((struct ptr_list *)sm->possible) == 1)
1806 1881 return 0;
1807 1882 if (!is_kernel_success_fail(sm))
1808 1883 return 0;
1809 1884
1810 1885 rl = estate_rl(sm->state);
1811 1886 if (!rl)
1812 1887 return 0;
1813 1888
1814 1889 __push_fake_cur_stree();
1815 1890
1816 1891 final_pass = 0;
1817 1892 __split_whole_condition(expr);
1818 1893 final_pass = final_pass_orig;
1819 1894
1820 1895 nonzero_rl = rl_filter(rl, rl_zero());
1821 1896 nonzero_rl = cast_rl(cur_func_return_type(), nonzero_rl);
1822 1897 return_ranges = show_rl(nonzero_rl);
1823 1898 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(nonzero_rl));
1824 1899
1825 1900 return_id++;
1826 1901 FOR_EACH_PTR(returned_state_callbacks, cb) {
1827 1902 cb->callback(return_id, return_ranges, expr);
1828 1903 } END_FOR_EACH_PTR(cb);
1829 1904
1830 1905 __push_true_states();
1831 1906 __use_false_states();
1832 1907
1833 1908 return_ranges = alloc_sname("0");
1834 1909 zero_sval = sval_type_val(rl_type(rl), 0);
1835 1910 add_range(&zero_rl, zero_sval, zero_sval);
1836 1911 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(zero_rl));
1837 1912 return_id++;
1838 1913 FOR_EACH_PTR(returned_state_callbacks, cb) {
1839 1914 cb->callback(return_id, return_ranges, expr);
1840 1915 } END_FOR_EACH_PTR(cb);
1841 1916
1842 1917 __merge_true_states();
1843 1918 __free_fake_cur_stree();
1844 1919
1845 1920 return 1;
1846 1921 }
1847 1922
1848 1923 static int is_boolean(struct expression *expr)
1849 1924 {
1850 1925 struct range_list *rl;
1851 1926
1852 1927 if (!get_implied_rl(expr, &rl))
1853 1928 return 0;
1854 1929 if (rl_min(rl).value == 0 && rl_max(rl).value == 1)
1855 1930 return 1;
1856 1931 return 0;
1857 1932 }
1858 1933
1859 1934 static int splitable_function_call(struct expression *expr)
1860 1935 {
1861 1936 struct sm_state *sm;
1862 1937 char buf[64];
1863 1938
1864 1939 if (!expr || expr->type != EXPR_CALL)
1865 1940 return 0;
1866 1941 snprintf(buf, sizeof(buf), "return %p", expr);
1867 1942 sm = get_sm_state(SMATCH_EXTRA, buf, NULL);
1868 1943 return split_possible_helper(sm, expr);
1869 1944 }
1870 1945
1871 1946 static struct sm_state *find_bool_param(void)
1872 1947 {
1873 1948 struct stree *start_states;
1874 1949 struct symbol *arg;
1875 1950 struct sm_state *sm, *tmp;
1876 1951 sval_t sval;
1877 1952
1878 1953 start_states = get_start_states();
1879 1954
1880 1955 FOR_EACH_PTR_REVERSE(cur_func_sym->ctype.base_type->arguments, arg) {
1881 1956 if (!arg->ident)
1882 1957 continue;
1883 1958 sm = get_sm_state_stree(start_states, SMATCH_EXTRA, arg->ident->name, arg);
1884 1959 if (!sm)
1885 1960 continue;
1886 1961 if (rl_min(estate_rl(sm->state)).value != 0 ||
1887 1962 rl_max(estate_rl(sm->state)).value != 1)
1888 1963 continue;
1889 1964 goto found;
1890 1965 } END_FOR_EACH_PTR_REVERSE(arg);
1891 1966
1892 1967 return NULL;
1893 1968
1894 1969 found:
1895 1970 /*
1896 1971 * Check if it's splitable. If not, then splitting it up is likely not
1897 1972 * useful for the callers.
1898 1973 */
1899 1974 FOR_EACH_PTR(sm->possible, tmp) {
1900 1975 if (is_merged(tmp))
1901 1976 continue;
1902 1977 if (!estate_get_single_value(tmp->state, &sval))
1903 1978 return NULL;
1904 1979 } END_FOR_EACH_PTR(tmp);
1905 1980
1906 1981 return sm;
1907 1982 }
1908 1983
1909 1984 static int split_on_bool_sm(struct sm_state *sm, struct expression *expr)
1910 1985 {
1911 1986 struct returned_state_callback *cb;
1912 1987 struct range_list *ret_rl;
1913 1988 const char *return_ranges;
1914 1989 struct sm_state *tmp;
1915 1990 int ret = 0;
1916 1991 struct state_list *already_handled = NULL;
1917 1992
1918 1993 if (!sm || !sm->merged)
1919 1994 return 0;
1920 1995
1921 1996 if (too_many_possible(sm))
1922 1997 return 0;
1923 1998
1924 1999 FOR_EACH_PTR(sm->possible, tmp) {
1925 2000 if (tmp->merged)
1926 2001 continue;
1927 2002 if (ptr_in_list(tmp, already_handled))
1928 2003 continue;
1929 2004 add_ptr_list(&already_handled, tmp);
1930 2005
1931 2006 ret = 1;
1932 2007 __push_fake_cur_stree();
1933 2008
1934 2009 overwrite_states_using_pool(sm, tmp);
1935 2010
1936 2011 return_ranges = get_return_ranges_str(expr, &ret_rl);
1937 2012 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
1938 2013 return_id++;
1939 2014 FOR_EACH_PTR(returned_state_callbacks, cb) {
1940 2015 cb->callback(return_id, (char *)return_ranges, expr);
1941 2016 } END_FOR_EACH_PTR(cb);
1942 2017
1943 2018 __free_fake_cur_stree();
1944 2019 } END_FOR_EACH_PTR(tmp);
1945 2020
1946 2021 free_slist(&already_handled);
1947 2022
1948 2023 return ret;
1949 2024 }
1950 2025
1951 2026 static int split_by_bool_param(struct expression *expr)
1952 2027 {
1953 2028 struct sm_state *start_sm, *sm;
1954 2029 sval_t sval;
1955 2030
1956 2031 start_sm = find_bool_param();
1957 2032 if (!start_sm)
1958 2033 return 0;
1959 2034 sm = get_sm_state(SMATCH_EXTRA, start_sm->name, start_sm->sym);
1960 2035 if (!sm || estate_get_single_value(sm->state, &sval))
1961 2036 return 0;
1962 2037
1963 2038 if (get_db_state_count() * 2 >= 2000)
1964 2039 return 0;
1965 2040
1966 2041 return split_on_bool_sm(sm, expr);
1967 2042 }
1968 2043
1969 2044 static int split_by_null_nonnull_param(struct expression *expr)
1970 2045 {
1971 2046 struct symbol *arg;
1972 2047 struct sm_state *sm;
1973 2048 int nr_possible;
1974 2049
1975 2050 /* function must only take one pointer */
1976 2051 if (ptr_list_size((struct ptr_list *)cur_func_sym->ctype.base_type->arguments) != 1)
1977 2052 return 0;
1978 2053 arg = first_ptr_list((struct ptr_list *)cur_func_sym->ctype.base_type->arguments);
1979 2054 if (!arg->ident)
1980 2055 return 0;
1981 2056 if (get_real_base_type(arg)->type != SYM_PTR)
1982 2057 return 0;
1983 2058
1984 2059 if (param_was_set_var_sym(arg->ident->name, arg))
1985 2060 return 0;
1986 2061 sm = get_sm_state(SMATCH_EXTRA, arg->ident->name, arg);
1987 2062 if (!sm)
1988 2063 return 0;
1989 2064
1990 2065 if (!has_separate_zero_null(sm))
1991 2066 return 0;
1992 2067
1993 2068 nr_possible = ptr_list_size((struct ptr_list *)sm->possible);
1994 2069 if (get_db_state_count() * nr_possible >= 2000)
1995 2070 return 0;
1996 2071
1997 2072 return split_on_bool_sm(sm, expr);
1998 2073 }
1999 2074
2000 2075 struct expression *strip_expr_statement(struct expression *expr)
2001 2076 {
2002 2077 struct expression *orig = expr;
2003 2078 struct statement *stmt, *last_stmt;
2004 2079
2005 2080 if (!expr)
2006 2081 return NULL;
2007 2082 if (expr->type == EXPR_PREOP && expr->op == '(')
2008 2083 expr = expr->unop;
2009 2084 if (expr->type != EXPR_STATEMENT)
2010 2085 return orig;
2011 2086 stmt = expr->statement;
2012 2087 if (!stmt || stmt->type != STMT_COMPOUND)
↓ open down ↓ |
293 lines elided |
↑ open up ↑ |
2013 2088 return orig;
2014 2089
2015 2090 last_stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
2016 2091 if (!last_stmt || last_stmt->type == STMT_LABEL)
2017 2092 last_stmt = last_stmt->label_statement;
2018 2093 if (!last_stmt || last_stmt->type != STMT_EXPRESSION)
2019 2094 return orig;
2020 2095 return strip_expr(last_stmt->expression);
2021 2096 }
2022 2097
2098 +static bool is_kernel_error_path(struct expression *expr)
2099 +{
2100 + struct range_list *rl;
2101 +
2102 + /*
2103 + * Splitting up returns requires resources. It also requires resources
2104 + * for the caller. It doesn't seem worth it to split anything up.
2105 + */
2106 + if (!get_implied_rl(expr, &rl))
2107 + return false;
2108 + if (rl_type(rl) != &int_ctype)
2109 + return false;
2110 + if (rl_min(rl).value >= -4095 &&
2111 + rl_max(rl).value < 0)
2112 + return true;
2113 + return false;
2114 +}
2115 +
2023 2116 static void call_return_state_hooks(struct expression *expr)
2024 2117 {
2025 2118 struct returned_state_callback *cb;
2026 2119 struct range_list *ret_rl;
2027 2120 const char *return_ranges;
2028 2121 int nr_states;
2029 2122 sval_t sval;
2030 2123
2031 2124 if (__path_is_null())
2032 2125 return;
2033 2126
2034 2127 expr = strip_expr(expr);
2035 2128 expr = strip_expr_statement(expr);
2036 2129
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
2037 2130 if (is_impossible_path())
2038 2131 goto vanilla;
2039 2132
2040 2133 if (expr && (expr->type == EXPR_COMPARE ||
2041 2134 !get_implied_value(expr, &sval)) &&
2042 2135 (is_condition(expr) || is_boolean(expr))) {
2043 2136 call_return_state_hooks_compare(expr);
2044 2137 return;
2045 2138 } else if (call_return_state_hooks_conditional(expr)) {
2046 2139 return;
2140 + } else if (is_kernel_error_path(expr)) {
2141 + goto vanilla;
2047 2142 } else if (call_return_state_hooks_split_possible(expr)) {
2048 2143 return;
2049 2144 } else if (split_positive_from_negative(expr)) {
2050 2145 return;
2051 2146 } else if (call_return_state_hooks_split_null_non_null_zero(expr)) {
2052 2147 return;
2053 2148 } else if (call_return_state_hooks_split_success_fail(expr)) {
2054 2149 return;
2055 2150 } else if (splitable_function_call(expr)) {
2056 2151 return;
2057 2152 } else if (split_by_bool_param(expr)) {
2058 2153 } else if (split_by_null_nonnull_param(expr)) {
2059 2154 return;
2060 2155 }
2061 2156
2062 2157 vanilla:
2063 2158 return_ranges = get_return_ranges_str(expr, &ret_rl);
2064 2159 set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
2065 2160
2066 2161 return_id++;
2067 2162 nr_states = get_db_state_count();
2068 2163 if (nr_states >= 10000) {
2069 2164 match_return_info(return_id, (char *)return_ranges, expr);
2070 2165 print_limited_param_set(return_id, (char *)return_ranges, expr);
2071 2166 mark_all_params_untracked(return_id, (char *)return_ranges, expr);
2072 2167 return;
2073 2168 }
2074 2169 FOR_EACH_PTR(returned_state_callbacks, cb) {
2075 2170 cb->callback(return_id, (char *)return_ranges, expr);
2076 2171 } END_FOR_EACH_PTR(cb);
2077 2172 }
2078 2173
2079 2174 static void print_returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
2080 2175 {
2081 2176 struct returned_member_callback *cb;
2082 2177 struct stree *stree;
2083 2178 struct sm_state *sm;
2084 2179 struct symbol *type;
2085 2180 char *name;
2086 2181 char member_name[256];
2087 2182 int len;
2088 2183
2089 2184 type = get_type(expr);
2090 2185 if (!type || type->type != SYM_PTR)
2091 2186 return;
2092 2187 name = expr_to_var(expr);
2093 2188 if (!name)
2094 2189 return;
2095 2190
2096 2191 member_name[sizeof(member_name) - 1] = '\0';
2097 2192 strcpy(member_name, "$");
2098 2193
2099 2194 len = strlen(name);
2100 2195 FOR_EACH_PTR(returned_member_callbacks, cb) {
2101 2196 stree = __get_cur_stree();
2102 2197 FOR_EACH_MY_SM(cb->owner, stree, sm) {
2103 2198 if (sm->name[0] == '*' && strcmp(sm->name + 1, name) == 0) {
2104 2199 strcpy(member_name, "*$");
2105 2200 cb->callback(return_id, return_ranges, expr, member_name, sm->state);
2106 2201 continue;
2107 2202 }
2108 2203 if (strncmp(sm->name, name, len) != 0)
2109 2204 continue;
2110 2205 if (strncmp(sm->name + len, "->", 2) != 0)
2111 2206 continue;
2112 2207 snprintf(member_name, sizeof(member_name), "$%s", sm->name + len);
2113 2208 cb->callback(return_id, return_ranges, expr, member_name, sm->state);
2114 2209 } END_FOR_EACH_SM(sm);
2115 2210 } END_FOR_EACH_PTR(cb);
2116 2211
2117 2212 free_string(name);
2118 2213 }
2119 2214
2120 2215 static void reset_memdb(struct symbol *sym)
2121 2216 {
2122 2217 mem_sql(NULL, NULL, "delete from caller_info;");
2123 2218 mem_sql(NULL, NULL, "delete from return_states;");
2124 2219 mem_sql(NULL, NULL, "delete from call_implies;");
2125 2220 mem_sql(NULL, NULL, "delete from return_implies;");
2126 2221 }
2127 2222
2128 2223 static void match_end_func_info(struct symbol *sym)
2129 2224 {
2130 2225 if (__path_is_null())
2131 2226 return;
2132 2227 call_return_state_hooks(NULL);
2133 2228 }
2134 2229
2135 2230 static void match_after_func(struct symbol *sym)
2136 2231 {
2137 2232 if (!__inline_fn)
2138 2233 reset_memdb(sym);
2139 2234 }
2140 2235
2141 2236 static void init_memdb(void)
2142 2237 {
2143 2238 char *err = NULL;
2144 2239 int rc;
2145 2240 const char *schema_files[] = {
2146 2241 "db/db.schema",
2147 2242 "db/caller_info.schema",
2148 2243 "db/common_caller_info.schema",
2149 2244 "db/return_states.schema",
2150 2245 "db/function_type_size.schema",
2151 2246 "db/type_size.schema",
2152 2247 "db/function_type_info.schema",
2153 2248 "db/type_info.schema",
2154 2249 "db/call_implies.schema",
2155 2250 "db/return_implies.schema",
2156 2251 "db/function_ptr.schema",
2157 2252 "db/local_values.schema",
↓ open down ↓ |
101 lines elided |
↑ open up ↑ |
2158 2253 "db/function_type_value.schema",
2159 2254 "db/type_value.schema",
2160 2255 "db/function_type.schema",
2161 2256 "db/data_info.schema",
2162 2257 "db/parameter_name.schema",
2163 2258 "db/constraints.schema",
2164 2259 "db/constraints_required.schema",
2165 2260 "db/fn_ptr_data_link.schema",
2166 2261 "db/fn_data_link.schema",
2167 2262 "db/mtag_about.schema",
2263 + "db/mtag_info.schema",
2168 2264 "db/mtag_map.schema",
2169 2265 "db/mtag_data.schema",
2170 2266 "db/mtag_alias.schema",
2171 2267 };
2172 2268 static char buf[4096];
2173 2269 int fd;
2174 2270 int ret;
2175 2271 int i;
2176 2272
2177 2273 rc = sqlite3_open(":memory:", &mem_db);
2178 2274 if (rc != SQLITE_OK) {
2179 2275 sm_ierror("starting In-Memory database.");
2180 2276 return;
2181 2277 }
2182 2278
2183 2279 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2184 2280 fd = open_schema_file(schema_files[i]);
2185 2281 if (fd < 0)
2186 2282 continue;
2187 2283 ret = read(fd, buf, sizeof(buf));
2188 2284 if (ret < 0) {
2189 2285 sm_ierror("failed to read: %s", schema_files[i]);
2190 2286 continue;
2191 2287 }
2192 2288 close(fd);
2193 2289 if (ret == sizeof(buf)) {
2194 2290 sm_ierror("Schema file too large: %s (limit %zd bytes)",
2195 2291 schema_files[i], sizeof(buf));
2196 2292 continue;
2197 2293 }
2198 2294 buf[ret] = '\0';
2199 2295 rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
2200 2296 if (rc != SQLITE_OK) {
2201 2297 sm_ierror("SQL error #2: %s", err);
2202 2298 sm_ierror("%s", buf);
2203 2299 }
2204 2300 }
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
2205 2301 }
2206 2302
2207 2303 static void init_cachedb(void)
2208 2304 {
2209 2305 char *err = NULL;
2210 2306 int rc;
2211 2307 const char *schema_files[] = {
2212 2308 "db/call_implies.schema",
2213 2309 "db/return_implies.schema",
2214 2310 "db/type_info.schema",
2311 + "db/mtag_about.schema",
2215 2312 "db/mtag_data.schema",
2313 + "db/mtag_info.schema",
2216 2314 "db/sink_info.schema",
2217 2315 };
2218 2316 static char buf[4096];
2219 2317 int fd;
2220 2318 int ret;
2221 2319 int i;
2222 2320
2223 2321 rc = sqlite3_open(":memory:", &cache_db);
2224 2322 if (rc != SQLITE_OK) {
2225 2323 sm_ierror("starting In-Memory database.");
2226 2324 return;
2227 2325 }
2228 2326
2229 2327 for (i = 0; i < ARRAY_SIZE(schema_files); i++) {
2230 2328 fd = open_schema_file(schema_files[i]);
2231 2329 if (fd < 0)
2232 2330 continue;
2233 2331 ret = read(fd, buf, sizeof(buf));
2234 2332 if (ret < 0) {
2235 2333 sm_ierror("failed to read: %s", schema_files[i]);
2236 2334 continue;
2237 2335 }
2238 2336 close(fd);
2239 2337 if (ret == sizeof(buf)) {
2240 2338 sm_ierror("Schema file too large: %s (limit %zd bytes)",
2241 2339 schema_files[i], sizeof(buf));
2242 2340 continue;
2243 2341 }
2244 2342 buf[ret] = '\0';
2245 2343 rc = sqlite3_exec(cache_db, buf, NULL, NULL, &err);
2246 2344 if (rc != SQLITE_OK) {
2247 2345 sm_ierror("SQL error #2: %s", err);
2248 2346 sm_ierror("%s", buf);
2249 2347 }
2250 2348 }
2251 2349 }
2252 2350
2253 2351 static int save_cache_data(void *_table, int argc, char **argv, char **azColName)
2254 2352 {
2255 2353 static char buf[4096];
2256 2354 char tmp[256];
2257 2355 char *p = buf;
2258 2356 char *table = _table;
2259 2357 int i;
2260 2358
2261 2359
2262 2360 p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table);
2263 2361 for (i = 0; i < argc; i++) {
2264 2362 if (i)
2265 2363 p += snprintf(p, 4096 - (p - buf), ", ");
2266 2364 sqlite3_snprintf(sizeof(tmp), tmp, "%q", escape_newlines(argv[i]));
2267 2365 p += snprintf(p, 4096 - (p - buf), "'%s'", tmp);
2268 2366
2269 2367 }
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
2270 2368 p += snprintf(p, 4096 - (p - buf), ");");
2271 2369 if (p - buf > 4096)
2272 2370 return 0;
2273 2371
2274 2372 sm_msg("SQL: %s", buf);
2275 2373 return 0;
2276 2374 }
2277 2375
2278 2376 static void dump_cache(struct symbol_list *sym_list)
2279 2377 {
2378 + const char *cache_tables[] = {
2379 + "type_info", "return_implies", "call_implies", "mtag_data",
2380 + "mtag_info", "mtag_about", "sink_info",
2381 + };
2382 + char buf[64];
2383 + int i;
2384 +
2280 2385 if (!option_info)
2281 2386 return;
2282 - cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;");
2283 - cache_sql(&save_cache_data, (char *)"return_implies", "select * from return_implies;");
2284 - cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;");
2285 - cache_sql(&save_cache_data, (char *)"mtag_data", "select * from mtag_data;");
2286 - cache_sql(&save_cache_data, (char *)"sink_info", "select * from sink_info;");
2387 +
2388 + for (i = 0; i < ARRAY_SIZE(cache_tables); i++) {
2389 + snprintf(buf, sizeof(buf), "select * from %s;", cache_tables[i]);
2390 + cache_sql(&save_cache_data, (char *)cache_tables[i], buf);
2391 + }
2287 2392 }
2288 2393
2289 2394 void open_smatch_db(char *db_file)
2290 2395 {
2291 2396 int rc;
2292 2397
2293 2398 if (option_no_db)
2294 2399 return;
2295 2400
2296 2401 use_states = malloc(num_checks + 1);
2297 2402 memset(use_states, 0xff, num_checks + 1);
2298 2403
2299 2404 init_memdb();
2300 2405 init_cachedb();
2301 2406
2302 2407 rc = sqlite3_open_v2(db_file, &smatch_db, SQLITE_OPEN_READONLY, NULL);
2303 2408 if (rc != SQLITE_OK) {
2304 2409 option_no_db = 1;
2305 2410 return;
2306 2411 }
2307 2412 run_sql(NULL, NULL,
2308 2413 "PRAGMA cache_size = %d;", SQLITE_CACHE_PAGES);
2309 2414 return;
2310 2415 }
2311 2416
2312 2417 static void register_common_funcs(void)
2313 2418 {
2314 2419 struct token *token;
2315 2420 char *func;
2316 2421 char filename[256];
2317 2422
2318 2423 if (option_project == PROJ_NONE)
2319 2424 strcpy(filename, "common_functions");
2320 2425 else
2321 2426 snprintf(filename, 256, "%s.common_functions", option_project_str);
2322 2427
2323 2428 token = get_tokens_file(filename);
2324 2429 if (!token)
2325 2430 return;
2326 2431 if (token_type(token) != TOKEN_STREAMBEGIN)
2327 2432 return;
2328 2433 token = token->next;
2329 2434 while (token_type(token) != TOKEN_STREAMEND) {
2330 2435 if (token_type(token) != TOKEN_IDENT)
2331 2436 return;
2332 2437 func = alloc_string(show_ident(token->ident));
2333 2438 add_ptr_list(&common_funcs, func);
2334 2439 token = token->next;
2335 2440 }
2336 2441 clear_token_alloc();
2337 2442 }
2338 2443
2339 2444 static char *get_next_string(char **str)
2340 2445 {
2341 2446 static char string[256];
2342 2447 char *start;
2343 2448 char *p = *str;
2344 2449 int len, i, j;
2345 2450
2346 2451 if (*p == '\0')
2347 2452 return NULL;
2348 2453 start = p;
2349 2454
2350 2455 while (*p != '\0' && *p != '\n') {
2351 2456 if (*p == '\\' && *(p + 1) == ' ') {
2352 2457 p += 2;
2353 2458 continue;
2354 2459 }
2355 2460 if (*p == ' ')
2356 2461 break;
2357 2462 p++;
2358 2463 }
2359 2464
2360 2465 len = p - start;
2361 2466 if (len >= sizeof(string)) {
2362 2467 memcpy(string, start, sizeof(string));
2363 2468 string[sizeof(string) - 1] = '\0';
2364 2469 sm_ierror("return_fix: '%s' too long", string);
2365 2470 **str = '\0';
2366 2471 return NULL;
2367 2472 }
2368 2473 memcpy(string, start, len);
2369 2474 string[len] = '\0';
2370 2475 for (i = 0; i < sizeof(string) - 1; i++) {
2371 2476 if (string[i] == '\\' && string[i + 1] == ' ') {
2372 2477 for (j = i; string[j] != '\0'; j++)
2373 2478 string[j] = string[j + 1];
2374 2479 }
2375 2480 }
2376 2481 if (*p != '\0')
2377 2482 p++;
2378 2483 *str = p;
2379 2484 return string;
2380 2485 }
2381 2486
2382 2487 static void register_return_replacements(void)
2383 2488 {
2384 2489 char *func, *orig, *new;
2385 2490 char filename[256];
2386 2491 char buf[4096];
2387 2492 int fd, ret, i;
2388 2493 char *p;
2389 2494
2390 2495 snprintf(filename, 256, "db/%s.return_fixes", option_project_str);
2391 2496 fd = open_schema_file(filename);
2392 2497 if (fd < 0)
2393 2498 return;
2394 2499 ret = read(fd, buf, sizeof(buf));
2395 2500 close(fd);
2396 2501 if (ret < 0)
2397 2502 return;
2398 2503 if (ret == sizeof(buf)) {
2399 2504 sm_ierror("file too large: %s (limit %zd bytes)",
2400 2505 filename, sizeof(buf));
2401 2506 return;
2402 2507 }
2403 2508 buf[ret] = '\0';
2404 2509
2405 2510 p = buf;
2406 2511 while (*p) {
2407 2512 get_next_string(&p);
2408 2513 replace_count++;
2409 2514 }
2410 2515 if (replace_count == 0 || replace_count % 3 != 0) {
2411 2516 replace_count = 0;
2412 2517 return;
2413 2518 }
2414 2519 replace_table = malloc(replace_count * sizeof(char *));
2415 2520
2416 2521 p = buf;
2417 2522 i = 0;
2418 2523 while (*p) {
2419 2524 func = alloc_string(get_next_string(&p));
2420 2525 orig = alloc_string(get_next_string(&p));
2421 2526 new = alloc_string(get_next_string(&p));
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
2422 2527
2423 2528 replace_table[i++] = func;
2424 2529 replace_table[i++] = orig;
2425 2530 replace_table[i++] = new;
2426 2531 }
2427 2532 }
2428 2533
2429 2534 void register_definition_db_callbacks(int id)
2430 2535 {
2431 2536 add_hook(&match_call_info, FUNCTION_CALL_HOOK);
2537 + add_hook(&match_call_info_new, FUNCTION_CALL_HOOK);
2432 2538 add_split_return_callback(match_return_info);
2433 2539 add_split_return_callback(print_returned_struct_members);
2434 2540 add_hook(&call_return_state_hooks, RETURN_HOOK);
2435 2541 add_hook(&match_end_func_info, END_FUNC_HOOK);
2436 2542 add_hook(&match_after_func, AFTER_FUNC_HOOK);
2437 2543
2438 2544 add_hook(&match_data_from_db, FUNC_DEF_HOOK);
2439 2545 add_hook(&match_call_implies, FUNC_DEF_HOOK);
2440 2546 add_hook(&match_return_implies, CALL_HOOK_AFTER_INLINE);
2441 2547
2442 2548 register_common_funcs();
2443 2549 register_return_replacements();
2444 2550
2445 2551 add_hook(&dump_cache, END_FILE_HOOK);
2446 2552 }
2447 2553
2448 2554 void register_db_call_marker(int id)
2449 2555 {
2450 2556 add_hook(&match_call_marker, FUNCTION_CALL_HOOK);
2451 2557 }
2452 2558
2453 2559 char *return_state_to_var_sym(struct expression *expr, int param, const char *key, struct symbol **sym)
2454 2560 {
2455 2561 struct expression *arg;
2456 2562 char *name = NULL;
2457 2563 char member_name[256];
2458 2564
2459 2565 *sym = NULL;
2460 2566
2461 2567 if (param == -1) {
2462 2568 const char *star = "";
2463 2569
2464 2570 if (expr->type != EXPR_ASSIGNMENT)
2465 2571 return NULL;
2466 2572 if (get_type(expr->left) == &int_ctype && strcmp(key, "$") != 0)
2467 2573 return NULL;
2468 2574 name = expr_to_var_sym(expr->left, sym);
2469 2575 if (!name)
2470 2576 return NULL;
2471 2577 if (key[0] == '*') {
2472 2578 star = "*";
2473 2579 key++;
2474 2580 }
2475 2581 if (strncmp(key, "$", 1) != 0)
2476 2582 return name;
2477 2583 snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 1);
2478 2584 free_string(name);
2479 2585 return alloc_string(member_name);
2480 2586 }
2481 2587
2482 2588 while (expr->type == EXPR_ASSIGNMENT)
2483 2589 expr = strip_expr(expr->right);
2484 2590 if (expr->type != EXPR_CALL)
2485 2591 return NULL;
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
2486 2592
2487 2593 arg = get_argument_from_call_expr(expr->args, param);
2488 2594 if (!arg)
2489 2595 return NULL;
2490 2596
2491 2597 return get_variable_from_key(arg, key, sym);
2492 2598 }
2493 2599
2494 2600 char *get_variable_from_key(struct expression *arg, const char *key, struct symbol **sym)
2495 2601 {
2602 + struct symbol *type;
2496 2603 char buf[256];
2497 2604 char *tmp;
2498 2605 int star_cnt = 0;
2606 + bool add_dot = false;
2499 2607
2500 2608 if (!arg)
2501 2609 return NULL;
2502 2610
2503 2611 arg = strip_expr(arg);
2504 2612
2505 2613 if (strcmp(key, "$") == 0)
2506 2614 return expr_to_var_sym(arg, sym);
2507 2615
2508 2616 if (strcmp(key, "*$") == 0) {
2509 2617 if (arg->type == EXPR_PREOP && arg->op == '&') {
2510 2618 arg = strip_expr(arg->unop);
2511 2619 return expr_to_var_sym(arg, sym);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
2512 2620 } else {
2513 2621 tmp = expr_to_var_sym(arg, sym);
2514 2622 if (!tmp)
2515 2623 return NULL;
2516 2624 snprintf(buf, sizeof(buf), "*%s", tmp);
2517 2625 free_string(tmp);
2518 2626 return alloc_string(buf);
2519 2627 }
2520 2628 }
2521 2629
2630 + if (strncmp(key, "(*$)", 4) == 0) {
2631 + char buf[64];
2632 +
2633 + if (arg->type == EXPR_PREOP && arg->op == '&') {
2634 + arg = strip_expr(arg->unop);
2635 + snprintf(buf, sizeof(buf), "$%s", key + 4);
2636 + return get_variable_from_key(arg, buf, sym);
2637 + } else {
2638 + tmp = expr_to_var_sym(arg, sym);
2639 + if (!tmp)
2640 + return NULL;
2641 + snprintf(buf, sizeof(buf), "(*%s)%s", tmp, key + 4);
2642 + free_string(tmp);
2643 + return alloc_string(buf);
2644 + }
2645 + }
2646 +
2522 2647 while (key[0] == '*') {
2523 2648 star_cnt++;
2524 2649 key++;
2525 2650 }
2526 2651
2527 - if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt) {
2652 + /*
2653 + * FIXME: This is a hack.
2654 + * We should be able to parse expressions like (*$)->foo and *$->foo.
2655 + */
2656 + type = get_type(arg);
2657 + if (is_struct_ptr(type))
2658 + add_dot = true;
2659 +
2660 + if (arg->type == EXPR_PREOP && arg->op == '&' && star_cnt && !add_dot) {
2528 2661 arg = strip_expr(arg->unop);
2529 2662 star_cnt--;
2530 2663 }
2531 2664
2532 2665 if (arg->type == EXPR_PREOP && arg->op == '&') {
2533 2666 arg = strip_expr(arg->unop);
2534 2667 tmp = expr_to_var_sym(arg, sym);
2535 2668 if (!tmp)
2536 2669 return NULL;
2537 2670 snprintf(buf, sizeof(buf), "%.*s%s.%s",
2538 2671 star_cnt, "**********", tmp, key + 3);
2539 2672 return alloc_string(buf);
2540 2673 }
2541 2674
2542 2675 tmp = expr_to_var_sym(arg, sym);
2543 2676 if (!tmp)
2544 2677 return NULL;
2545 2678 snprintf(buf, sizeof(buf), "%.*s%s%s", star_cnt, "**********", tmp, key + 1);
2546 2679 free_string(tmp);
2547 2680 return alloc_string(buf);
2548 2681 }
2549 2682
2550 2683 char *get_chunk_from_key(struct expression *arg, char *key, struct symbol **sym, struct var_sym_list **vsl)
2551 2684 {
2552 2685 *vsl = NULL;
2553 2686
2554 2687 if (strcmp("$", key) == 0)
2555 2688 return expr_to_chunk_sym_vsl(arg, sym, vsl);
2556 2689 return get_variable_from_key(arg, key, sym);
2557 2690 }
2558 2691
2559 2692 const char *state_name_to_param_name(const char *state_name, const char *param_name)
2560 2693 {
2561 2694 int star_cnt = 0;
2562 2695 int name_len;
2563 2696 char buf[256];
2564 2697
2565 2698 name_len = strlen(param_name);
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
2566 2699
2567 2700 while (state_name[0] == '*') {
2568 2701 star_cnt++;
2569 2702 state_name++;
2570 2703 }
2571 2704
2572 2705 /* ten out of ten stars! */
2573 2706 if (star_cnt > 10)
2574 2707 return NULL;
2575 2708
2709 + if (strncmp(state_name, "(*", 2) == 0 &&
2710 + strncmp(state_name + 2, param_name, name_len) == 0 &&
2711 + state_name[name_len + 2] == ')') {
2712 + snprintf(buf, sizeof(buf), "%.*s(*$)%s", star_cnt, "**********",
2713 + state_name + name_len + 3);
2714 + return alloc_sname(buf);
2715 + }
2716 +
2576 2717 if (strcmp(state_name, param_name) == 0) {
2577 2718 snprintf(buf, sizeof(buf), "%.*s$", star_cnt, "**********");
2578 2719 return alloc_sname(buf);
2579 2720 }
2580 2721
2581 2722 if (state_name[name_len] == '-' && /* check for '-' from "->" */
2582 2723 strncmp(state_name, param_name, name_len) == 0) {
2583 2724 snprintf(buf, sizeof(buf), "%.*s$%s", star_cnt, "**********", state_name + name_len);
2584 2725 return alloc_sname(buf);
2585 2726 }
2586 2727 return NULL;
2587 2728 }
2588 2729
2589 2730 const char *get_param_name_var_sym(const char *name, struct symbol *sym)
2590 2731 {
2591 2732 if (!sym || !sym->ident)
2592 2733 return NULL;
2593 2734
2594 2735 return state_name_to_param_name(name, sym->ident->name);
2595 2736 }
2596 2737
2597 2738 const char *get_mtag_name_var_sym(const char *state_name, struct symbol *sym)
2598 2739 {
2599 2740 struct symbol *type;
2600 2741 const char *sym_name;
2601 2742 int name_len;
2602 2743 static char buf[256];
2603 2744
2604 2745 /*
2605 2746 * mtag_name is different from param_name because mtags can be a struct
2606 2747 * instead of a struct pointer. But we want to treat it like a pointer
2607 2748 * because really an mtag is a pointer. Or in other words, if you pass
2608 2749 * a struct foo then you want to talk about foo.bar but with an mtag
2609 2750 * you want to refer to it as foo->bar.
2610 2751 *
2611 2752 */
2612 2753
2613 2754 if (!sym || !sym->ident)
2614 2755 return NULL;
2615 2756
2616 2757 type = get_real_base_type(sym);
2617 2758 if (type && type->type == SYM_BASETYPE)
2618 2759 return "*$";
2619 2760
2620 2761 sym_name = sym->ident->name;
2621 2762 name_len = strlen(sym_name);
2622 2763
2623 2764 if (state_name[name_len] == '.' && /* check for '-' from "->" */
2624 2765 strncmp(state_name, sym_name, name_len) == 0) {
2625 2766 snprintf(buf, sizeof(buf), "$->%s", state_name + name_len + 1);
2626 2767 return buf;
2627 2768 }
2628 2769
2629 2770 return state_name_to_param_name(state_name, sym_name);
2630 2771 }
2631 2772
2632 2773 const char *get_mtag_name_expr(struct expression *expr)
2633 2774 {
2634 2775 char *name;
2635 2776 struct symbol *sym;
2636 2777 const char *ret = NULL;
2637 2778
2638 2779 name = expr_to_var_sym(expr, &sym);
2639 2780 if (!name || !sym)
2640 2781 goto free;
2641 2782
2642 2783 ret = get_mtag_name_var_sym(name, sym);
2643 2784 free:
2644 2785 free_string(name);
2645 2786 return ret;
2646 2787 }
2647 2788
2648 2789 const char *get_param_name(struct sm_state *sm)
2649 2790 {
2650 2791 return get_param_name_var_sym(sm->name, sm->sym);
2651 2792 }
2652 2793
2653 2794 char *get_data_info_name(struct expression *expr)
2654 2795 {
2655 2796 struct symbol *sym;
2656 2797 char *name;
2657 2798 char buf[256];
2658 2799 char *ret = NULL;
2659 2800
2660 2801 expr = strip_expr(expr);
2661 2802 name = get_member_name(expr);
2662 2803 if (name)
2663 2804 return name;
2664 2805 name = expr_to_var_sym(expr, &sym);
2665 2806 if (!name || !sym)
2666 2807 goto free;
2667 2808 if (!(sym->ctype.modifiers & MOD_TOPLEVEL))
2668 2809 goto free;
2669 2810 if (sym->ctype.modifiers & MOD_STATIC)
2670 2811 snprintf(buf, sizeof(buf), "static %s", name);
2671 2812 else
2672 2813 snprintf(buf, sizeof(buf), "global %s", name);
2673 2814 ret = alloc_sname(buf);
2674 2815 free:
2675 2816 free_string(name);
2676 2817 return ret;
2677 2818 }
↓ open down ↓ |
92 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX