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