20789228ba323efd76b02be6a4c3f67b2cebb173
[smatch.git] / smatch_data / db / smdb.py
blob20789228ba323efd76b02be6a4c3f67b2cebb173
1 #!/usr/bin/python
3 # Copyright (C) 2013 Oracle.
5 # Licensed under the Open Software License version 1.1
7 import sqlite3
8 import sys
9 import re
11 try:
12 con = sqlite3.connect('smatch_db.sqlite')
13 except sqlite3.Error, e:
14 print "Error %s:" % e.args[0]
15 sys.exit(1)
17 def usage():
18 print "%s <function> [table] [type] [parameter]" %(sys.argv[0])
19 sys.exit(1)
21 function_ptrs = []
22 searched_ptrs = []
23 def get_function_pointers_helper(func):
24 cur = con.cursor()
25 cur.execute("select distinct ptr from function_ptr where function = '%s';" %(func))
26 for row in cur:
27 ptr = row[0]
28 if ptr in function_ptrs:
29 continue
30 function_ptrs.append(ptr)
31 if not ptr in searched_ptrs:
32 searched_ptrs.append(ptr)
33 get_function_pointers_helper(ptr)
35 def get_function_pointers(func):
36 global function_ptrs
37 global searched_ptrs
38 function_ptrs = [func]
39 searched_ptrs = [func]
40 get_function_pointers_helper(func)
41 return function_ptrs
43 db_types = { 0: "INTERNAL",
44 101: "PARAM_CLEARED",
45 102: "FILTER_VALUE",
46 1001: "PARAM_VALUE",
47 1002: "BUF_SIZE",
48 1003: "USER_DATA",
49 1004: "CAPPED_DATA",
50 1005: "RETURN_VALUE",
51 1006: "DEREFERENCE",
52 1007: "RANGE_CAP",
53 1008: "LOCK_HELD",
54 1009: "LOCK_RELEASED",
55 1010: "ABSOLUTE_LIMITS",
56 1011: "LIMITED_VALUE",
57 1012: "ADDED_VALUE",
58 1013: "PARAM_FREED",
59 1014: "DATA_SOURCE",
60 1015: "FUZZY_MAX",
61 1016: "STR_LEN",
64 def type_to_str(type_int):
66 t = int(type_int)
67 if db_types[t]:
68 return db_types[t]
69 return type_int
71 def type_to_int(type_string):
72 for k in db_types.keys():
73 if db_types[k] == type_string:
74 return k
75 return -1
77 def display_caller_info(printed, cur):
78 for txt in cur:
79 if not printed:
80 print "file | caller | function | type | parameter | key | value |"
81 printed = 1
82 print "%20s | %20s | %20s |" %(txt[0], txt[1], txt[2]),
83 print " %10s |" %(type_to_str(txt[5])),
84 print " %d | %s | %s" %(txt[6], txt[7], txt[8])
85 return printed
87 def get_caller_info(ptrs, my_type):
88 cur = con.cursor()
89 printed = 0
90 type_filter = ""
91 if my_type != "":
92 type_filter = "and type = %d" %(type_to_int(my_type))
93 for ptr in ptrs:
94 cur.execute("select * from caller_info where function = '%s' %s;" %(ptr, type_filter))
95 printed = display_caller_info(printed, cur)
97 def print_caller_info(func, my_type = ""):
98 ptrs = get_function_pointers(func)
99 get_caller_info(ptrs, my_type)
101 def print_return_states(func):
102 cur = con.cursor()
103 cur.execute("select * from return_states where function = '%s';" %(func))
104 count = 0
105 for txt in cur:
106 printed = 1
107 if count == 0:
108 print "file | function | return_id | return_value | type | param | key | value |"
109 count += 1
110 print "%s | %s | %2s | %13s" %(txt[0], txt[1], txt[3], txt[4]),
111 print "| %13s |" %(type_to_str(txt[6])),
112 print " %2d | %20s | %20s |" %(txt[7], txt[8], txt[9])
114 def print_call_implies(func):
115 cur = con.cursor()
116 cur.execute("select * from call_implies where function = '%s';" %(func))
117 count = 0
118 for txt in cur:
119 if not count:
120 print "file | function | type | param | key | value |"
121 count += 1
122 print "%15s | %15s" %(txt[0], txt[1]),
123 print "| %15s" %(type_to_str(txt[4])),
124 print "| %3d | %15s |" %(txt[5], txt[6])
126 def print_type_size(struct_type, member):
127 cur = con.cursor()
128 cur.execute("select * from function_type_size where type = '(struct %s)->%s';" %(struct_type, member))
129 print "file | function | type | size"
130 for txt in cur:
131 printed = 1
132 print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], txt[2], txt[3])
134 def print_fn_ptrs(func):
135 ptrs = get_function_pointers(func)
136 if not ptrs:
137 return
138 print "%s = " %(func),
139 i = 0
140 for p in ptrs:
141 if i > 0:
142 print ",",
143 i = i + 1
144 print "'%s'" %(p),
145 print ""
147 def get_callers(func):
148 ret = []
149 cur = con.cursor()
150 ptrs = get_function_pointers(func)
151 for ptr in ptrs:
152 cur.execute("select distinct caller from caller_info where function = '%s';" %(ptr))
153 for row in cur:
154 ret.append(row[0])
155 return ret
157 printed_funcs = []
158 def call_tree_helper(func, indent = 0):
159 global printed_funcs
160 if func in printed_funcs:
161 return
162 print "%s%s()" %(" " * indent, func)
163 if func == "too common":
164 return
165 if indent > 6:
166 return
167 printed_funcs.append(func)
168 callers = get_callers(func)
169 if len(callers) >= 20:
170 print "Over 20 callers for %s()" %(func)
171 return
172 for caller in callers:
173 call_tree_helper(caller, indent + 2)
175 def print_call_tree(func):
176 global printed_funcs
177 printed_funcs = []
178 call_tree_helper(func)
180 def function_type_value(struct_type, member):
181 cur = con.cursor()
182 cur.execute("select * from function_type_value where type = '(struct %s)->%s';" %(struct_type, member))
183 for txt in cur:
184 print "%s | %s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
186 if len(sys.argv) < 2:
187 usage()
189 if len(sys.argv) == 2:
190 func = sys.argv[1]
191 print_caller_info(func)
192 elif sys.argv[1] == "user_data":
193 func = sys.argv[2]
194 print_caller_info(func, "USER_DATA")
195 elif sys.argv[1] == "param_value":
196 func = sys.argv[2]
197 print_caller_info(func, "PARAM_VALUE")
198 elif sys.argv[1] == "function_ptr" or sys.argv[1] == "fn_ptr":
199 func = sys.argv[2]
200 print_fn_ptrs(func)
201 elif sys.argv[1] == "return_states":
202 func = sys.argv[2]
203 print_return_states(func)
204 elif sys.argv[1] == "call_implies":
205 func = sys.argv[2]
206 print_call_implies(func)
207 elif sys.argv[1] == "type_size" or sys.argv[1] == "buf_size":
208 struct_type = sys.argv[2]
209 member = sys.argv[3]
210 print_type_size(struct_type, member)
211 elif sys.argv[1] == "call_tree":
212 func = sys.argv[2]
213 print_call_tree(func)
214 elif sys.argv[1] == "where":
215 struct_type = sys.argv[2]
216 member = sys.argv[3]
217 function_type_value(struct_type, member)
218 else:
219 usage()