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_data/db/smdb.py
+++ new/usr/src/tools/smatch/src/smatch_data/db/smdb.py
1 1 #!/usr/bin/python
2 2
3 3 # Copyright (C) 2013 Oracle.
4 4 #
5 5 # Licensed under the Open Software License version 1.1
6 6
7 7 import sqlite3
8 8 import sys
9 9 import re
10 10 import subprocess
11 11
12 12 try:
13 13 con = sqlite3.connect('smatch_db.sqlite')
14 14 except sqlite3.Error, e:
15 15 print "Error %s:" % e.args[0]
16 16 sys.exit(1)
17 17
18 18 def usage():
19 19 print "%s" %(sys.argv[0])
20 20 print "<function> - how a function is called"
21 21 print "info <type> - how a function is called, filtered by type"
22 22 print "return_states <function> - what a function returns"
23 23 print "call_tree <function> - show the call tree"
24 24 print "where <struct_type> <member> - where a struct member is set"
25 25 print "type_size <struct_type> <member> - how a struct member is allocated"
26 26 print "data_info <struct_type> <member> - information about a given data type"
27 27 print "function_ptr <function> - which function pointers point to this"
28 28 print "trace_param <function> <param> - trace where a parameter came from"
29 29 print "find_tagged <function> <param> - find the source of a tagged value (arm64)"
30 30 print "parse_warns_tagged <smatch_warns.txt> - parse warns file for summary of tagged issues (arm64)"
31 31 print "locals <file> - print the local values in a file."
32 32 sys.exit(1)
33 33
34 34 function_ptrs = []
35 35 searched_ptrs = []
36 36 def get_function_pointers_helper(func):
37 37 cur = con.cursor()
38 38 cur.execute("select distinct ptr from function_ptr where function = '%s';" %(func))
39 39 for row in cur:
40 40 ptr = row[0]
41 41 if ptr in function_ptrs:
42 42 continue
43 43 function_ptrs.append(ptr)
44 44 if not ptr in searched_ptrs:
45 45 searched_ptrs.append(ptr)
46 46 get_function_pointers_helper(ptr)
47 47
48 48 def get_function_pointers(func):
49 49 global function_ptrs
50 50 global searched_ptrs
51 51 function_ptrs = [func]
52 52 searched_ptrs = [func]
53 53 get_function_pointers_helper(func)
54 54 return function_ptrs
55 55
56 56 db_types = { 0: "INTERNAL",
57 57 101: "PARAM_CLEARED",
58 58 103: "PARAM_LIMIT",
59 59 104: "PARAM_FILTER",
60 60 1001: "PARAM_VALUE",
61 61 1002: "BUF_SIZE",
62 62 1004: "CAPPED_DATA",
63 63 1005: "RETURN_VALUE",
64 64 1006: "DEREFERENCE",
65 65 1007: "RANGE_CAP",
66 66 1008: "LOCK_HELD",
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
67 67 1009: "LOCK_RELEASED",
68 68 1010: "ABSOLUTE_LIMITS",
69 69 1012: "PARAM_ADD",
70 70 1013: "PARAM_FREED",
71 71 1014: "DATA_SOURCE",
72 72 1015: "FUZZY_MAX",
73 73 1016: "STR_LEN",
74 74 1017: "ARRAY_LEN",
75 75 1018: "CAPABLE",
76 76 1019: "NS_CAPABLE",
77 + 1020: "CONTAINER",
77 78 1022: "TYPE_LINK",
78 79 1023: "UNTRACKED_PARAM",
79 80 1024: "CULL_PATH",
80 81 1025: "PARAM_SET",
81 82 1026: "PARAM_USED",
82 83 1027: "BYTE_UNITS",
83 84 1028: "COMPARE_LIMIT",
84 85 1029: "PARAM_COMPARE",
85 86 1030: "EXPECTS_TYPE",
86 87 1031: "CONSTRAINT",
87 88 1032: "PASSES_TYPE",
88 89 1033: "CONSTRAINT_REQUIRED",
89 90 1034: "BIT_INFO",
90 91 1035: "NOSPEC",
91 92 1036: "NOSPEC_WB",
92 93 1037: "STMT_CNT",
93 94 1038: "TERMINATED",
94 95 1039: "SLEEP",
95 - 1040: "NO_SLEEP_CNT",
96 + 1040: "PREEMPT_CNT",
96 97 1041: "SMALLISH",
97 98 1042: "FRESH_MTAG",
98 99
99 100 8017: "USER_DATA",
100 101 9017: "USER_DATA_SET",
101 102 8018: "NO_OVERFLOW",
102 103 8019: "NO_OVERFLOW_SIMPLE",
103 104 8020: "LOCKED",
104 105 8021: "UNLOCKED",
106 + 9022: "HALF_LOCKED",
107 + 9023: "LOCK_RESTORED",
108 + 9024: "KNOWN_LOCKED",
109 + 9025: "KNOWN_UNLOCKED",
105 110 8023: "ATOMIC_INC",
106 111 8024: "ATOMIC_DEC",
107 112 };
108 113
109 114 def add_range(rl, min_val, max_val):
110 115 check_next = 0
111 116 done = 0
112 117 ret = []
113 118 idx = 0
114 119
115 120 if len(rl) == 0:
116 121 return [[min_val, max_val]]
117 122
118 123 for idx in range(len(rl)):
119 124 cur_min = rl[idx][0]
120 125 cur_max = rl[idx][1]
121 126
122 127 # we already merged the new range but we might need to change later
123 128 # ranges if they over lap with more than one
124 129 if check_next:
125 130 # join with added range
126 131 if max_val + 1 == cur_min:
127 132 ret[len(ret) - 1][1] = cur_max
128 133 done = 1
129 134 break
130 135 # don't overlap
131 136 if max_val < cur_min:
132 137 ret.append([cur_min, cur_max])
133 138 done = 1
134 139 break
135 140 # partially overlap
136 141 if max_val < cur_max:
137 142 ret[len(ret) - 1][1] = cur_max
138 143 done = 1
139 144 break
140 145 # completely overlap
141 146 continue
142 147
143 148 # join 2 ranges into one
144 149 if max_val + 1 == cur_min:
145 150 ret.append([min_val, cur_max])
146 151 done = 1
147 152 break
148 153 # range is entirely below
149 154 if max_val < cur_min:
150 155 ret.append([min_val, max_val])
151 156 ret.append([cur_min, cur_max])
152 157 done = 1
153 158 break
154 159 # range is partially below
155 160 if min_val < cur_min:
156 161 if max_val <= cur_max:
157 162 ret.append([min_val, cur_max])
158 163 done = 1
159 164 break
160 165 else:
161 166 ret.append([min_val, max_val])
162 167 check_next = 1
163 168 continue
164 169 # range already included
165 170 if max_val <= cur_max:
166 171 ret.append([cur_min, cur_max])
167 172 done = 1
168 173 break;
169 174 # range partially above
170 175 if min_val <= cur_max:
171 176 ret.append([cur_min, max_val])
172 177 check_next = 1
173 178 continue
174 179 # join 2 ranges on the other side
175 180 if min_val - 1 == cur_max:
176 181 ret.append([cur_min, max_val])
177 182 check_next = 1
178 183 continue
179 184 # range is above
180 185 ret.append([cur_min, cur_max])
181 186
182 187 if idx + 1 < len(rl): # we hit a break statement
183 188 ret = ret + rl[idx + 1:]
184 189 elif done: # we hit a break on the last iteration
185 190 pass
186 191 elif not check_next: # it's past the end of the rl
187 192 ret.append([min_val, max_val])
188 193
189 194 return ret;
190 195
191 196 def rl_union(rl1, rl2):
192 197 ret = []
193 198 for r in rl1:
194 199 ret = add_range(ret, r[0], r[1])
195 200 for r in rl2:
196 201 ret = add_range(ret, r[0], r[1])
197 202
198 203 if (rl1 or rl2) and not ret:
199 204 print "bug: merging %s + %s gives empty" %(rl1, rl2)
200 205
201 206 return ret
202 207
203 208 def txt_to_val(txt):
204 209 if txt == "s64min":
205 210 return -(2**63)
206 211 elif txt == "s32min":
207 212 return -(2**31)
208 213 elif txt == "s16min":
209 214 return -(2**15)
210 215 elif txt == "s64max":
211 216 return 2**63 - 1
212 217 elif txt == "s32max":
213 218 return 2**31 - 1
214 219 elif txt == "s16max":
215 220 return 2**15 - 1
216 221 elif txt == "u64max":
217 222 return 2**64 - 1
218 223 elif txt == "ptr_max":
219 224 return 2**64 - 1
220 225 elif txt == "u32max":
221 226 return 2**32 - 1
222 227 elif txt == "u16max":
223 228 return 2**16 - 1
224 229 else:
225 230 try:
226 231 return int(txt)
227 232 except ValueError:
228 233 return 0
229 234
230 235 def val_to_txt(val):
231 236 if val == -(2**63):
232 237 return "s64min"
233 238 elif val == -(2**31):
234 239 return "s32min"
235 240 elif val == -(2**15):
236 241 return "s16min"
237 242 elif val == 2**63 - 1:
238 243 return "s64max"
239 244 elif val == 2**31 - 1:
240 245 return "s32max"
241 246 elif val == 2**15 - 1:
242 247 return "s16max"
243 248 elif val == 2**64 - 1:
244 249 return "u64max"
245 250 elif val == 2**32 - 1:
246 251 return "u32max"
247 252 elif val == 2**16 - 1:
248 253 return "u16max"
249 254 elif val < 0:
250 255 return "(%d)" %(val)
251 256 else:
252 257 return "%d" %(val)
253 258
254 259 def get_next_str(txt):
255 260 val = ""
256 261 parsed = 0
257 262
258 263 if txt[0] == '(':
259 264 parsed += 1
260 265 for char in txt[1:]:
261 266 if char == ')':
262 267 break
263 268 parsed += 1
264 269 val = txt[1:parsed]
265 270 parsed += 1
266 271 elif txt[0] == 's' or txt[0] == 'u':
267 272 parsed += 6
268 273 val = txt[:parsed]
269 274 else:
270 275 if txt[0] == '-':
271 276 parsed += 1
272 277 for char in txt[parsed:]:
273 278 if char == '-' or char == '[':
274 279 break
275 280 parsed += 1
276 281 val = txt[:parsed]
277 282 return [parsed, val]
278 283
279 284 def txt_to_rl(txt):
280 285 if len(txt) == 0:
281 286 return []
282 287
283 288 ret = []
284 289 pairs = txt.split(",")
285 290 for pair in pairs:
286 291 cnt, min_str = get_next_str(pair)
287 292 if cnt == len(pair):
288 293 max_str = min_str
289 294 else:
290 295 cnt, max_str = get_next_str(pair[cnt + 1:])
291 296 min_val = txt_to_val(min_str)
292 297 max_val = txt_to_val(max_str)
293 298 ret.append([min_val, max_val])
294 299
295 300 # Hm... Smatch won't call INT_MAX s32max if the variable is unsigned.
296 301 # if txt != rl_to_txt(ret):
297 302 # print "bug: converting: text = %s rl = %s internal = %s" %(txt, rl_to_txt(ret), ret)
298 303
299 304 return ret
300 305
301 306 def rl_to_txt(rl):
302 307 ret = ""
303 308 for idx in range(len(rl)):
304 309 cur_min = rl[idx][0]
305 310 cur_max = rl[idx][1]
306 311
307 312 if idx != 0:
308 313 ret += ","
309 314
310 315 if cur_min == cur_max:
311 316 ret += val_to_txt(cur_min)
312 317 else:
313 318 ret += val_to_txt(cur_min)
314 319 ret += "-"
315 320 ret += val_to_txt(cur_max)
316 321 return ret
317 322
318 323 def type_to_str(type_int):
319 324
320 325 t = int(type_int)
321 326 if db_types.has_key(t):
322 327 return db_types[t]
323 328 return type_int
324 329
325 330 def type_to_int(type_string):
326 331 for k in db_types.keys():
327 332 if db_types[k] == type_string:
328 333 return k
329 334 return -1
330 335
331 336 def display_caller_info(printed, cur, param_names):
332 337 for txt in cur:
333 338 if not printed:
334 339 print "file | caller | function | type | parameter | key | value |"
335 340 printed = 1
336 341
337 342 parameter = int(txt[6])
338 343 key = txt[7]
339 344 if len(param_names) and parameter in param_names:
340 345 key = key.replace("$", param_names[parameter])
341 346
342 347 print "%20s | %20s | %20s |" %(txt[0], txt[1], txt[2]),
343 348 print " %10s |" %(type_to_str(txt[5])),
344 349 print " %d | %s | %s" %(parameter, key, txt[8])
345 350 return printed
346 351
347 352 def get_caller_info(filename, ptrs, my_type):
348 353 cur = con.cursor()
349 354 param_names = get_param_names(filename, func)
350 355 printed = 0
351 356 type_filter = ""
352 357 if my_type != "":
353 358 type_filter = "and type = %d" %(type_to_int(my_type))
354 359 for ptr in ptrs:
355 360 cur.execute("select * from caller_info where function = '%s' %s;" %(ptr, type_filter))
356 361 printed = display_caller_info(printed, cur, param_names)
357 362
358 363 def print_caller_info(filename, func, my_type = ""):
359 364 ptrs = get_function_pointers(func)
360 365 get_caller_info(filename, ptrs, my_type)
361 366
362 367 def merge_values(param_names, vals, cur):
363 368 for txt in cur:
364 369 parameter = int(txt[0])
365 370 name = txt[1]
366 371 rl = txt_to_rl(txt[2])
367 372 if parameter in param_names:
368 373 name = name.replace("$", param_names[parameter])
369 374
370 375 if not parameter in vals:
371 376 vals[parameter] = {}
372 377
373 378 # the first item on the list is the number of rows. it's incremented
374 379 # every time we call merge_values().
375 380 if name in vals[parameter]:
376 381 vals[parameter][name] = [vals[parameter][name][0] + 1, rl_union(vals[parameter][name][1], rl)]
377 382 else:
378 383 vals[parameter][name] = [1, rl]
379 384
380 385 def get_param_names(filename, func):
381 386 cur = con.cursor()
382 387 param_names = {}
383 388 cur.execute("select parameter, value from parameter_name where file = '%s' and function = '%s';" %(filename, func))
384 389 for txt in cur:
385 390 parameter = int(txt[0])
386 391 name = txt[1]
387 392 param_names[parameter] = name
388 393 if len(param_names):
389 394 return param_names
390 395
391 396 cur.execute("select parameter, value from parameter_name where function = '%s';" %(func))
392 397 for txt in cur:
393 398 parameter = int(txt[0])
394 399 name = txt[1]
395 400 param_names[parameter] = name
396 401 return param_names
397 402
398 403 def get_caller_count(ptrs):
399 404 cur = con.cursor()
400 405 count = 0
401 406 for ptr in ptrs:
402 407 cur.execute("select count(distinct(call_id)) from caller_info where function = '%s';" %(ptr))
403 408 for txt in cur:
404 409 count += int(txt[0])
405 410 return count
406 411
407 412 def print_merged_caller_values(filename, func, ptrs, param_names, call_cnt):
408 413 cur = con.cursor()
409 414 vals = {}
410 415 for ptr in ptrs:
411 416 cur.execute("select parameter, key, value from caller_info where function = '%s' and type = %d;" %(ptr, type_to_int("PARAM_VALUE")))
412 417 merge_values(param_names, vals, cur);
413 418
414 419 for param in sorted(vals):
415 420 for name in sorted(vals[param]):
416 421 if vals[param][name][0] != call_cnt:
417 422 continue
418 423 print "%d %s -> %s" %(param, name, rl_to_txt(vals[param][name][1]))
419 424
420 425
421 426 def print_unmerged_caller_values(filename, func, ptrs, param_names):
422 427 cur = con.cursor()
423 428 for ptr in ptrs:
424 429 prev = -1
425 430 cur.execute("select file, caller, call_id, parameter, key, value from caller_info where function = '%s' and type = %d;" %(ptr, type_to_int("PARAM_VALUE")))
426 431 for filename, caller, call_id, parameter, name, value in cur:
427 432 if prev != int(call_id):
428 433 prev = int(call_id)
429 434
430 435 parameter = int(parameter)
431 436 if parameter < len(param_names):
432 437 name = name.replace("$", param_names[parameter])
433 438 else:
434 439 name = name.replace("$", "$%d" %(parameter))
435 440
436 441 print "%s | %s | %s | %s" %(filename, caller, name, value)
437 442 print "=========================="
438 443
439 444 def print_caller_values(filename, func, ptrs):
440 445 param_names = get_param_names(filename, func)
441 446 call_cnt = get_caller_count(ptrs)
442 447
443 448 print_merged_caller_values(filename, func, ptrs, param_names, call_cnt)
444 449 print "=========================="
445 450 print_unmerged_caller_values(filename, func, ptrs, param_names)
446 451
447 452 def caller_info_values(filename, func):
448 453 ptrs = get_function_pointers(func)
449 454 print_caller_values(filename, func, ptrs)
450 455
451 456 def print_return_states(func):
452 457 cur = con.cursor()
453 458 cur.execute("select * from return_states where function = '%s';" %(func))
454 459 count = 0
455 460 for txt in cur:
456 461 printed = 1
457 462 if count == 0:
458 463 print "file | function | return_id | return_value | type | param | key | value |"
459 464 count += 1
460 465 print "%s | %s | %2s | %13s" %(txt[0], txt[1], txt[3], txt[4]),
461 466 print "| %13s |" %(type_to_str(txt[6])),
462 467 print " %2d | %20s | %20s |" %(txt[7], txt[8], txt[9])
463 468
464 469 def print_return_implies(func):
465 470 cur = con.cursor()
466 471 cur.execute("select * from return_implies where function = '%s';" %(func))
467 472 count = 0
468 473 for txt in cur:
469 474 if not count:
470 475 print "file | function | type | param | key | value |"
471 476 count += 1
472 477 print "%15s | %15s" %(txt[0], txt[1]),
473 478 print "| %15s" %(type_to_str(txt[4])),
474 479 print "| %3d | %s | %15s |" %(txt[5], txt[6], txt[7])
475 480
476 481 def print_type_size(struct_type, member):
477 482 cur = con.cursor()
478 483 cur.execute("select * from type_size where type like '(struct %s)->%s';" %(struct_type, member))
479 484 print "type | size"
480 485 for txt in cur:
481 486 print "%-15s | %s" %(txt[0], txt[1])
482 487
483 488 cur.execute("select * from function_type_size where type like '(struct %s)->%s';" %(struct_type, member))
484 489 print "file | function | type | size"
485 490 for txt in cur:
486 491 print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], txt[2], txt[3])
487 492
488 493 def print_data_info(struct_type, member):
489 494 cur = con.cursor()
490 495 cur.execute("select * from data_info where data like '(struct %s)->%s';" %(struct_type, member))
491 496 print "file | data | type | value"
492 497 for txt in cur:
493 498 print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], type_to_str(txt[2]), txt[3])
494 499
495 500 def print_fn_ptrs(func):
496 501 ptrs = get_function_pointers(func)
497 502 if not ptrs:
498 503 return
499 504 print "%s = " %(func),
500 505 print(ptrs)
501 506
502 507 def print_functions(member):
503 508 cur = con.cursor()
504 509 cur.execute("select * from function_ptr where ptr like '%%->%s';" %(member))
505 510 print "File | Pointer | Function | Static"
506 511 for txt in cur:
507 512 print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[2], txt[1], txt[3])
508 513
509 514 def get_callers(func):
510 515 ret = []
511 516 cur = con.cursor()
512 517 ptrs = get_function_pointers(func)
513 518 for ptr in ptrs:
514 519 cur.execute("select distinct caller from caller_info where function = '%s';" %(ptr))
515 520 for row in cur:
516 521 ret.append(row[0])
517 522 return ret
518 523
519 524 printed_funcs = []
520 525 def call_tree_helper(func, indent = 0):
521 526 global printed_funcs
522 527 if func in printed_funcs:
523 528 return
524 529 print "%s%s()" %(" " * indent, func)
525 530 if func == "too common":
526 531 return
527 532 if indent > 6:
528 533 return
529 534 printed_funcs.append(func)
530 535 callers = get_callers(func)
531 536 if len(callers) >= 20:
532 537 print "Over 20 callers for %s()" %(func)
533 538 return
534 539 for caller in callers:
535 540 call_tree_helper(caller, indent + 2)
536 541
537 542 def print_call_tree(func):
538 543 global printed_funcs
539 544 printed_funcs = []
540 545 call_tree_helper(func)
541 546
542 547 def function_type_value(struct_type, member):
543 548 cur = con.cursor()
544 549 cur.execute("select * from function_type_value where type like '(struct %s)->%s';" %(struct_type, member))
545 550 for txt in cur:
546 551 print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
547 552
548 553 def rl_too_big(txt):
549 554 rl = txt_to_rl(txt)
550 555 ret = ""
551 556 for idx in range(len(rl)):
552 557 cur_max = rl[idx][1]
553 558 if (cur_max > 0xFFFFFFFFFFFFFF):
554 559 return 1
555 560
556 561 return 0
557 562
558 563 def rl_has_min_untagged(txt):
559 564 rl = txt_to_rl(txt)
560 565 ret = ""
561 566 for idx in range(len(rl)):
562 567 cur_min = rl[idx][0]
563 568 if (cur_min == 0xff80000000000000):
564 569 return 1
565 570
566 571 return 0
567 572
568 573 def rl_is_tagged(txt):
569 574 if not rl_too_big(txt):
570 575 return 0
571 576
572 577 if rl_has_min_untagged(txt):
573 578 return 0
574 579
575 580 return 1
576 581
577 582 def rl_is_treat_untagged(txt):
578 583 if "[u]" in txt:
579 584 return 1;
580 585
581 586 return 0
582 587
583 588 def parse_warns_tagged(filename):
584 589 proc = subprocess.Popen(['cat %s | grep "potentially tagged" | sort | uniq' %(filename)], shell=True, stdout=subprocess.PIPE)
585 590 while True:
586 591 line = proc.stdout.readline()
587 592 if not line:
588 593 break
589 594
590 595 linepos = re.search("([^\s]+)", line).group(1)
591 596 groupre = re.search("potentially tagged address \(([^,]+), ([^,]+), ([^\)]+)\)", line)
592 597 groupre.group(1)
593 598
594 599 func = groupre.group(1)
595 600 param = int(groupre.group(2))
596 601 var = groupre.group(3)
597 602
598 603 if ("end" in var or "size" in var or "len" in var):
599 604 continue
600 605
601 606 print "\n%s (func: %s, param: %d:%s) may be caused by:" %(linepos, func, param, var)
602 607
603 608 if (param != -1):
604 609 if not find_tagged(func, param, 0, []):
605 610 print " %s (param %d) (can't walk call tree)" % (func, param)
606 611 else:
607 612 print " %s (variable %s (can't walk call tree)" % (func, var)
608 613
609 614 def find_tagged(func, param, caller_call_id, printed):
610 615
611 616 callers = {}
612 617 cur = con.cursor()
613 618 ptrs = get_function_pointers(func)
614 619 found = 0
615 620
616 621 for ptr in ptrs:
617 622 cur.execute("select call_id, value from caller_info where function = '%s' and parameter=%d and type=%d" %(ptr, param, type_to_int("DATA_SOURCE")))
618 623
619 624 for row in cur:
620 625 if (row[1][0] == '$'):
621 626 if row[0] not in callers:
622 627 callers[row[0]] = {}
623 628 callers[row[0]]["param"] = int(row[1][1])
624 629
625 630 for ptr in ptrs:
626 631 cur.execute("select caller, call_id, value from caller_info where function = '%s' and parameter=%d and type=%d" %(ptr, param, type_to_int("USER_DATA")))
627 632
628 633 for row in cur:
629 634 if not rl_is_tagged(row[2]):
630 635 continue
631 636 if rl_is_treat_untagged(row[2]):
632 637 continue
633 638 found = 1
634 639 if row[1] not in callers:
635 640 callers[row[1]] = {}
636 641 if "param" not in callers[row[1]]:
637 642 line = " %s (param ?) -> %s (param %d)" % (row[0], func, param)
638 643 if line not in printed:
639 644 printed.append(line)
640 645 print line
641 646 continue
642 647 if row[0] not in printed:
643 648 printed.append(row[0])
644 649 if not find_tagged(row[0], callers[row[1]]["param"], row[1], printed):
645 650 print " %s (param %d)" % (row[0], param)
646 651
647 652 return found
648 653
649 654 def trace_callers(func, param):
650 655 sources = []
651 656 prev_type = 0
652 657
653 658 cur = con.cursor()
654 659 ptrs = get_function_pointers(func)
655 660 for ptr in ptrs:
656 661 cur.execute("select type, caller, value from caller_info where function = '%s' and (type = 0 or type = 1014 or type = 1028) and (parameter = -1 or parameter = %d);" %(ptr, param))
657 662 for row in cur:
658 663 data_type = int(row[0])
659 664 if data_type == 1014:
660 665 sources.append((row[1], row[2]))
661 666 elif data_type == 1028:
662 667 sources.append(("%", row[2])) # hack...
663 668 elif data_type == 0 and prev_type == 0:
664 669 sources.append((row[1], ""))
665 670 prev_type = data_type
666 671 return sources
667 672
668 673 def trace_param_helper(func, param, indent = 0):
669 674 global printed_funcs
670 675 if func in printed_funcs:
671 676 return
672 677 print "%s%s(param %d)" %(" " * indent, func, param)
673 678 if func == "too common":
674 679 return
675 680 if indent > 20:
676 681 return
677 682 printed_funcs.append(func)
678 683 sources = trace_callers(func, param)
679 684 for path in sources:
680 685
681 686 if len(path[1]) and path[1][0] == '$':
682 687 p = int(re.findall('\d+', path[1][1:])[0])
683 688 trace_param_helper(path[0], p, indent + 2)
684 689 elif len(path[0]) and path[0][0] == '%':
685 690 print " %s%s" %(" " * indent, path[1])
686 691 else:
687 692 print "* %s%s %s" %(" " * (indent - 1), path[0], path[1])
688 693
689 694 def trace_param(func, param):
690 695 global printed_funcs
691 696 printed_funcs = []
692 697 print "tracing %s %d" %(func, param)
693 698 trace_param_helper(func, param)
694 699
695 700 def print_locals(filename):
696 701 cur = con.cursor()
697 702 cur.execute("select file,data,value from data_info where file = '%s' and type = 8029 and value != 0;" %(filename))
698 703 for txt in cur:
699 704 print "%s | %s | %s" %(txt[0], txt[1], txt[2])
700 705
701 706 def constraint(struct_type, member):
702 707 cur = con.cursor()
703 708 cur.execute("select * from constraints_required where data like '(struct %s)->%s' or bound like '(struct %s)->%s';" %(struct_type, member, struct_type, member))
704 709 for txt in cur:
705 710 print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
706 711
707 712 if len(sys.argv) < 2:
708 713 usage()
709 714
710 715 if len(sys.argv) == 2:
711 716 func = sys.argv[1]
712 717 print_caller_info("", func)
713 718 elif sys.argv[1] == "info":
714 719 my_type = ""
715 720 if len(sys.argv) == 4:
716 721 my_type = sys.argv[3]
717 722 func = sys.argv[2]
718 723 print_caller_info("", func, my_type)
719 724 elif sys.argv[1] == "call_info":
720 725 if len(sys.argv) != 4:
721 726 usage()
722 727 filename = sys.argv[2]
723 728 func = sys.argv[3]
724 729 caller_info_values(filename, func)
725 730 print_caller_info(filename, func)
726 731 elif sys.argv[1] == "function_ptr" or sys.argv[1] == "fn_ptr":
727 732 func = sys.argv[2]
728 733 print_fn_ptrs(func)
729 734 elif sys.argv[1] == "return_states":
730 735 func = sys.argv[2]
731 736 print_return_states(func)
732 737 print "================================================"
733 738 print_return_implies(func)
734 739 elif sys.argv[1] == "return_implies":
735 740 func = sys.argv[2]
736 741 print_return_implies(func)
737 742 elif sys.argv[1] == "type_size" or sys.argv[1] == "buf_size":
738 743 struct_type = sys.argv[2]
739 744 member = sys.argv[3]
740 745 print_type_size(struct_type, member)
741 746 elif sys.argv[1] == "data_info":
742 747 struct_type = sys.argv[2]
743 748 member = sys.argv[3]
744 749 print_data_info(struct_type, member)
745 750 elif sys.argv[1] == "call_tree":
746 751 func = sys.argv[2]
747 752 print_call_tree(func)
748 753 elif sys.argv[1] == "find_tagged":
749 754 func = sys.argv[2]
750 755 param = int(sys.argv[3])
751 756 find_tagged(func, param, 0, [])
752 757 elif sys.argv[1] == "parse_warns_tagged":
753 758 filename = sys.argv[2]
754 759 parse_warns_tagged(filename)
755 760 elif sys.argv[1] == "where":
756 761 if len(sys.argv) == 3:
757 762 struct_type = "%"
758 763 member = sys.argv[2]
759 764 elif len(sys.argv) == 4:
760 765 struct_type = sys.argv[2]
761 766 member = sys.argv[3]
762 767 function_type_value(struct_type, member)
763 768 elif sys.argv[1] == "local":
764 769 filename = sys.argv[2]
765 770 variable = ""
766 771 if len(sys.argv) == 4:
767 772 variable = sys.argv[3]
768 773 local_values(filename, variable)
769 774 elif sys.argv[1] == "functions":
770 775 member = sys.argv[2]
771 776 print_functions(member)
772 777 elif sys.argv[1] == "trace_param":
773 778 if len(sys.argv) != 4:
774 779 usage()
775 780 func = sys.argv[2]
776 781 param = int(sys.argv[3])
777 782 trace_param(func, param)
778 783 elif sys.argv[1] == "locals":
779 784 if len(sys.argv) != 3:
780 785 usage()
781 786 filename = sys.argv[2]
782 787 print_locals(filename);
783 788 elif sys.argv[1] == "constraint":
784 789 if len(sys.argv) == 3:
785 790 struct_type = "%"
786 791 member = sys.argv[2]
787 792 elif len(sys.argv) == 4:
788 793 struct_type = sys.argv[2]
789 794 member = sys.argv[3]
790 795 constraint(struct_type, member)
791 796 else:
792 797 usage()
↓ open down ↓ |
678 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX