3 # Copyright (C) 2013 Oracle.
5 # Licensed under the Open Software License version 1.1
12 con
= sqlite3
.connect('smatch_db.sqlite')
13 except sqlite3
.Error
, e
:
14 print "Error %s:" % e
.args
[0]
18 print "%s" %(sys
.argv
[0])
19 print "<function> - how a function is called"
20 print "return_states <function> - what a function returns"
21 print "call_tree <function> - show the call tree"
22 print "where <struct_type> <member> - where a struct member is set"
23 print "type_size <struct_type> <member> - how a struct member is allocated"
24 print "data_info <struct_type> <member> - information about a given data type"
25 print "function_ptr <function> - which function pointers point to this"
26 print "trace_param <function> <param> - trace where a parameter came from"
27 print "locals <file> - print the local values in a file."
32 def get_function_pointers_helper(func
):
34 cur
.execute("select distinct ptr from function_ptr where function = '%s';" %(func))
37 if ptr
in function_ptrs
:
39 function_ptrs
.append(ptr
)
40 if not ptr
in searched_ptrs
:
41 searched_ptrs
.append(ptr
)
42 get_function_pointers_helper(ptr
)
44 def get_function_pointers(func
):
47 function_ptrs
= [func
]
48 searched_ptrs
= [func
]
49 get_function_pointers_helper(func
)
52 db_types
= { 0: "INTERNAL",
64 1009: "LOCK_RELEASED",
65 1010: "ABSOLUTE_LIMITS",
75 1023: "UNTRACKED_PARAM",
80 1028: "COMPARE_LIMIT",
81 1029: "PARAM_COMPARE",
84 8019: "NO_OVERFLOW_SIMPLE",
91 def add_range(rl
, min_val
, max_val
):
98 return [[min_val
, max_val
]]
100 for idx
in range(len(rl
)):
104 # we already merged the new range but we might need to change later
105 # ranges if they over lap with more than one
107 # join with added range
108 if max_val
+ 1 == cur_min
:
109 ret
[len(ret
) - 1][1] = cur_max
113 if max_val
< cur_min
:
114 ret
.append([cur_min
, cur_max
])
118 if max_val
< cur_max
:
119 ret
[len(ret
) - 1][1] = cur_max
125 # join 2 ranges into one
126 if max_val
+ 1 == cur_min
:
127 ret
.append([min_val
, cur_max
])
130 # range is entirely below
131 if max_val
< cur_min
:
132 ret
.append([min_val
, max_val
])
133 ret
.append([cur_min
, cur_max
])
136 # range is partially below
137 if min_val
< cur_min
:
138 if max_val
<= cur_max
:
139 ret
.append([min_val
, cur_max
])
143 ret
.append([min_val
, max_val
])
146 # range already included
147 if max_val
<= cur_max
:
148 ret
.append([cur_min
, cur_max
])
151 # range partially above
152 if min_val
<= cur_max
:
153 ret
.append([cur_min
, max_val
])
156 # join 2 ranges on the other side
157 if min_val
- 1 == cur_max
:
158 ret
.append([cur_min
, max_val
])
162 ret
.append([cur_min
, cur_max
])
164 if idx
+ 1 < len(rl
): # we hit a break statement
165 ret
= ret
+ rl
[idx
+ 1:]
166 elif done
: # we hit a break on the last iteration
168 elif not check_next
: # it's past the end of the rl
169 ret
.append([min_val
, max_val
])
173 def rl_union(rl1
, rl2
):
176 ret
= add_range(ret
, r
[0], r
[1])
178 ret
= add_range(ret
, r
[0], r
[1])
180 if (rl1
or rl2
) and not ret
:
181 print "bug: merging %s + %s gives empty" %(rl1
, rl2
)
188 elif txt
== "s32min":
190 elif txt
== "s16min":
192 elif txt
== "s64max":
194 elif txt
== "s32max":
196 elif txt
== "s16max":
198 elif txt
== "u64max":
200 elif txt
== "u32max":
202 elif txt
== "u16max":
213 elif val
== -(2**31):
215 elif val
== -(2**15):
217 elif val
== 2**63 - 1:
219 elif val
== 2**31 - 1:
221 elif val
== 2**15 - 1:
223 elif val
== 2**64 - 1:
225 elif val
== 2**32 - 1:
227 elif val
== 2**16 - 1:
234 def get_next_str(txt
):
246 elif txt
[0] == 's' or txt
[0] == 'u':
252 for char
in txt
[parsed
:]:
264 pairs
= txt
.split(",")
266 cnt
, min_str
= get_next_str(pair
)
270 cnt
, max_str
= get_next_str(pair
[cnt
+ 1:])
271 min_val
= txt_to_val(min_str
)
272 max_val
= txt_to_val(max_str
)
273 ret
.append([min_val
, max_val
])
275 # Hm... Smatch won't call INT_MAX s32max if the variable is unsigned.
276 # if txt != rl_to_txt(ret):
277 # print "bug: converting: text = %s rl = %s internal = %s" %(txt, rl_to_txt(ret), ret)
283 for idx
in range(len(rl
)):
290 if cur_min
== cur_max
:
291 ret
+= val_to_txt(cur_min
)
293 ret
+= val_to_txt(cur_min
)
295 ret
+= val_to_txt(cur_max
)
298 def type_to_str(type_int
):
301 if db_types
.has_key(t
):
305 def type_to_int(type_string
):
306 for k
in db_types
.keys():
307 if db_types
[k
] == type_string
:
311 def display_caller_info(printed
, cur
, param_names
):
314 print "file | caller | function | type | parameter | key | value |"
317 parameter
= int(txt
[6])
319 if len(param_names
) and parameter
in param_names
:
320 key
= key
.replace("$", param_names
[parameter
])
322 print "%20s | %20s | %20s |" %(txt
[0], txt
[1], txt
[2]),
323 print " %10s |" %(type_to_str(txt
[5])),
324 print " %d | %s | %s" %(parameter
, key
, txt
[8])
327 def get_caller_info(filename
, ptrs
, my_type
):
329 param_names
= get_param_names(filename
, func
)
333 type_filter
= "and type = %d" %(type_to_int(my_type
))
335 cur
.execute("select * from caller_info where function = '%s' %s;" %(ptr
, type_filter
))
336 printed
= display_caller_info(printed
, cur
, param_names
)
338 def print_caller_info(filename
, func
, my_type
= ""):
339 ptrs
= get_function_pointers(func
)
340 get_caller_info(filename
, ptrs
, my_type
)
342 def merge_values(param_names
, vals
, cur
):
344 parameter
= int(txt
[0])
346 rl
= txt_to_rl(txt
[2])
347 if parameter
in param_names
:
348 name
= name
.replace("$", param_names
[parameter
])
350 if not parameter
in vals
:
353 # the first item on the list is the number of rows. it's incremented
354 # every time we call merge_values().
355 if name
in vals
[parameter
]:
356 vals
[parameter
][name
] = [vals
[parameter
][name
][0] + 1, rl_union(vals
[parameter
][name
][1], rl
)]
358 vals
[parameter
][name
] = [1, rl
]
360 def get_param_names(filename
, func
):
363 cur
.execute("select parameter, value from parameter_name where file = '%s' and function = '%s';" %(filename
, func
))
365 parameter
= int(txt
[0])
367 param_names
[parameter
] = name
371 cur
.execute("select parameter, value from parameter_name where function = '%s';" %(func))
373 parameter
= int(txt
[0])
375 param_names
[parameter
] = name
378 def get_caller_count(ptrs
):
382 cur
.execute("select count(distinct(call_id)) from caller_info where function = '%s';" %(ptr))
387 def print_merged_caller_values(filename
, func
, ptrs
, param_names
, call_cnt
):
391 cur
.execute("select parameter, key, value from caller_info where function = '%s' and type = %d;" %(ptr
, type_to_int("PARAM_VALUE")))
392 merge_values(param_names
, vals
, cur
);
394 for param
in sorted(vals
):
395 for name
in sorted(vals
[param
]):
396 if vals
[param
][name
][0] != call_cnt
:
398 print "%d %s -> %s" %(param
, name
, rl_to_txt(vals
[param
][name
][1]))
401 def print_unmerged_caller_values(filename
, func
, ptrs
, param_names
):
405 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")))
406 for filename
, caller
, call_id
, parameter
, name
, value
in cur
:
407 if prev
!= int(call_id
):
410 parameter
= int(parameter
)
411 if parameter
< len(param_names
):
412 name
= name
.replace("$", param_names
[parameter
])
414 name
= name
.replace("$", "$%d" %(parameter))
416 print "%s | %s | %s | %s" %(filename
, caller
, name
, value
)
417 print "=========================="
419 def print_caller_values(filename
, func
, ptrs
):
420 param_names
= get_param_names(filename
, func
)
421 call_cnt
= get_caller_count(ptrs
)
423 print_merged_caller_values(filename
, func
, ptrs
, param_names
, call_cnt
)
424 print "=========================="
425 print_unmerged_caller_values(filename
, func
, ptrs
, param_names
)
427 def caller_info_values(filename
, func
):
428 ptrs
= get_function_pointers(func
)
429 print_caller_values(filename
, func
, ptrs
)
431 def print_return_states(func
):
433 cur
.execute("select * from return_states where function = '%s';" %(func))
438 print "file | function | return_id | return_value | type | param | key | value |"
440 print "%s | %s | %2s | %13s" %(txt
[0], txt
[1], txt
[3], txt
[4]),
441 print "| %13s |" %(type_to_str(txt
[6])),
442 print " %2d | %20s | %20s |" %(txt
[7], txt
[8], txt
[9])
444 def print_return_implies(func
):
446 cur
.execute("select * from return_implies where function = '%s';" %(func))
450 print "file | function | type | param | key | value |"
452 print "%15s | %15s" %(txt
[0], txt
[1]),
453 print "| %15s" %(type_to_str(txt
[4])),
454 print "| %3d | %s | %15s |" %(txt
[5], txt
[6], txt
[7])
456 def print_type_size(struct_type
, member
):
458 cur
.execute("select * from type_size where type like '(struct %s)->%s';" %(struct_type
, member
))
461 print "%-15s | %s" %(txt
[0], txt
[1])
463 cur
.execute("select * from function_type_size where type like '(struct %s)->%s';" %(struct_type
, member
))
464 print "file | function | type | size"
466 print "%-15s | %-15s | %-15s | %s" %(txt
[0], txt
[1], txt
[2], txt
[3])
468 def print_data_info(struct_type
, member
):
470 cur
.execute("select * from data_info where data like '(struct %s)->%s';" %(struct_type
, member
))
471 print "file | data | type | value"
473 print "%-15s | %-15s | %-15s | %s" %(txt
[0], txt
[1], type_to_str(txt
[2]), txt
[3])
475 def print_fn_ptrs(func
):
476 ptrs
= get_function_pointers(func
)
479 print "%s = " %(func),
482 def print_functions(member
):
484 cur
.execute("select * from function_ptr where ptr like '%%->%s';" %(member))
485 print "File | Pointer | Function | Static"
487 print "%-15s | %-15s | %-15s | %s" %(txt
[0], txt
[2], txt
[1], txt
[3])
489 def get_callers(func
):
492 ptrs
= get_function_pointers(func
)
494 cur
.execute("select distinct caller from caller_info where function = '%s';" %(ptr))
500 def call_tree_helper(func
, indent
= 0):
502 if func
in printed_funcs
:
504 print "%s%s()" %(" " * indent
, func
)
505 if func
== "too common":
509 printed_funcs
.append(func
)
510 callers
= get_callers(func
)
511 if len(callers
) >= 20:
512 print "Over 20 callers for %s()" %(func)
514 for caller
in callers
:
515 call_tree_helper(caller
, indent
+ 2)
517 def print_call_tree(func
):
520 call_tree_helper(func
)
522 def function_type_value(struct_type
, member
):
524 cur
.execute("select * from function_type_value where type like '(struct %s)->%s';" %(struct_type
, member
))
526 print "%-30s | %-30s | %s | %s" %(txt
[0], txt
[1], txt
[2], txt
[3])
528 def trace_callers(func
, param
):
533 ptrs
= get_function_pointers(func
)
535 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
))
537 data_type
= int(row
[0])
538 if data_type
== 1014:
539 sources
.append((row
[1], row
[2]))
540 elif data_type
== 1028:
541 sources
.append(("%", row
[2])) # hack...
542 elif data_type
== 0 and prev_type
== 0:
543 sources
.append((row
[1], ""))
544 prev_type
= data_type
547 def trace_param_helper(func
, param
, indent
= 0):
549 if func
in printed_funcs
:
551 print "%s%s(param %d)" %(" " * indent
, func
, param
)
552 if func
== "too common":
556 printed_funcs
.append(func
)
557 sources
= trace_callers(func
, param
)
560 if len(path
[1]) and path
[1][0] == 'p' and path
[1][1] == ' ':
562 trace_param_helper(path
[0], p
, indent
+ 2)
563 elif len(path
[0]) and path
[0][0] == '%':
564 print " %s%s" %(" " * indent
, path
[1])
566 print "* %s%s %s" %(" " * (indent
- 1), path
[0], path
[1])
568 def trace_param(func
, param
):
571 print "tracing %s %d" %(func
, param
)
572 trace_param_helper(func
, param
)
574 def print_locals(filename
):
576 cur
.execute("select file,data,value from data_info where file = '%s' and type = 8029 and value != 0;" %(filename))
578 print "%s | %s | %s" %(txt
[0], txt
[1], txt
[2])
580 def constraint(struct_type
, member
):
582 cur
.execute("select * from constraints_required where data like '(struct %s)->%s' or bound like '(struct %s)->%s';" %(struct_type
, member
, struct_type
, member
))
584 print "%-30s | %-30s | %s | %s" %(txt
[0], txt
[1], txt
[2], txt
[3])
586 if len(sys
.argv
) < 2:
589 if len(sys
.argv
) == 2:
591 print_caller_info("", func
)
592 elif sys
.argv
[1] == "call_info":
593 if len(sys
.argv
) != 4:
595 filename
= sys
.argv
[2]
597 caller_info_values(filename
, func
)
598 print_caller_info(filename
, func
)
599 elif sys
.argv
[1] == "user_data":
601 print_caller_info(filename
, func
, "USER_DATA")
602 elif sys
.argv
[1] == "param_value":
604 print_caller_info(filename
, func
, "PARAM_VALUE")
605 elif sys
.argv
[1] == "function_ptr" or sys
.argv
[1] == "fn_ptr":
608 elif sys
.argv
[1] == "return_states":
610 print_return_states(func
)
611 print "================================================"
612 print_return_implies(func
)
613 elif sys
.argv
[1] == "return_implies":
615 print_return_implies(func
)
616 elif sys
.argv
[1] == "type_size" or sys
.argv
[1] == "buf_size":
617 struct_type
= sys
.argv
[2]
619 print_type_size(struct_type
, member
)
620 elif sys
.argv
[1] == "data_info":
621 struct_type
= sys
.argv
[2]
623 print_data_info(struct_type
, member
)
624 elif sys
.argv
[1] == "call_tree":
626 print_call_tree(func
)
627 elif sys
.argv
[1] == "where":
628 if len(sys
.argv
) == 3:
631 elif len(sys
.argv
) == 4:
632 struct_type
= sys
.argv
[2]
634 function_type_value(struct_type
, member
)
635 elif sys
.argv
[1] == "local":
636 filename
= sys
.argv
[2]
638 if len(sys
.argv
) == 4:
639 variable
= sys
.argv
[3]
640 local_values(filename
, variable
)
641 elif sys
.argv
[1] == "functions":
643 print_functions(member
)
644 elif sys
.argv
[1] == "trace_param":
645 if len(sys
.argv
) != 4:
648 param
= int(sys
.argv
[3])
649 trace_param(func
, param
)
650 elif sys
.argv
[1] == "locals":
651 if len(sys
.argv
) != 3:
653 filename
= sys
.argv
[2]
654 print_locals(filename
);
655 elif sys
.argv
[1] == "constraint":
656 if len(sys
.argv
) == 3:
659 elif len(sys
.argv
) == 4:
660 struct_type
= sys
.argv
[2]
662 constraint(struct_type
, member
)
663 elif sys
.argv
[1] == "test":
664 filename
= sys
.argv
[2]
666 caller_info_values(filename
, func
)