smdb.py: fix test for if a datatype is known
[smatch.git] / smatch_data / db / smdb.py
blobda1dfe28e5a7f47ae46a3a51ac2de49fafe9a930
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.has_key(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 type_size where type like '(struct %s)->%s';" %(struct_type, member))
129 print "type | size"
130 for txt in cur:
131 print "%-15s | %s" %(txt[0], txt[1])
133 cur.execute("select * from function_type_size where type like '(struct %s)->%s';" %(struct_type, member))
134 print "file | function | type | size"
135 for txt in cur:
136 print "%-15s | %-15s | %-15s | %s" %(txt[0], txt[1], txt[2], txt[3])
138 def print_fn_ptrs(func):
139 ptrs = get_function_pointers(func)
140 if not ptrs:
141 return
142 print "%s = " %(func),
143 i = 0
144 for p in ptrs:
145 if i > 0:
146 print ",",
147 i = i + 1
148 print "'%s'" %(p),
149 print ""
151 def get_callers(func):
152 ret = []
153 cur = con.cursor()
154 ptrs = get_function_pointers(func)
155 for ptr in ptrs:
156 cur.execute("select distinct caller from caller_info where function = '%s';" %(ptr))
157 for row in cur:
158 ret.append(row[0])
159 return ret
161 printed_funcs = []
162 def call_tree_helper(func, indent = 0):
163 global printed_funcs
164 if func in printed_funcs:
165 return
166 print "%s%s()" %(" " * indent, func)
167 if func == "too common":
168 return
169 if indent > 6:
170 return
171 printed_funcs.append(func)
172 callers = get_callers(func)
173 if len(callers) >= 20:
174 print "Over 20 callers for %s()" %(func)
175 return
176 for caller in callers:
177 call_tree_helper(caller, indent + 2)
179 def print_call_tree(func):
180 global printed_funcs
181 printed_funcs = []
182 call_tree_helper(func)
184 def function_type_value(struct_type, member):
185 cur = con.cursor()
186 cur.execute("select * from function_type_value where type like '(struct %s)->%s';" %(struct_type, member))
187 for txt in cur:
188 print "%-30s | %-30s | %s | %s" %(txt[0], txt[1], txt[2], txt[3])
190 if len(sys.argv) < 2:
191 usage()
193 if len(sys.argv) == 2:
194 func = sys.argv[1]
195 print_caller_info(func)
196 elif sys.argv[1] == "user_data":
197 func = sys.argv[2]
198 print_caller_info(func, "USER_DATA")
199 elif sys.argv[1] == "param_value":
200 func = sys.argv[2]
201 print_caller_info(func, "PARAM_VALUE")
202 elif sys.argv[1] == "function_ptr" or sys.argv[1] == "fn_ptr":
203 func = sys.argv[2]
204 print_fn_ptrs(func)
205 elif sys.argv[1] == "return_states":
206 func = sys.argv[2]
207 print_return_states(func)
208 elif sys.argv[1] == "call_implies":
209 func = sys.argv[2]
210 print_call_implies(func)
211 elif sys.argv[1] == "type_size" or sys.argv[1] == "buf_size":
212 struct_type = sys.argv[2]
213 member = sys.argv[3]
214 print_type_size(struct_type, member)
215 elif sys.argv[1] == "call_tree":
216 func = sys.argv[2]
217 print_call_tree(func)
218 elif sys.argv[1] == "where":
219 if len(sys.argv) == 3:
220 struct_type = "%"
221 member = sys.argv[2]
222 elif len(sys.argv) == 4:
223 struct_type = sys.argv[2]
224 member = sys.argv[3]
225 function_type_value(struct_type, member)
226 elif sys.argv[1] == "local":
227 filename = sys.argv[2]
228 variable = ""
229 if len(sys.argv) == 4:
230 variable = sys.argv[3]
231 local_values(filename, variable)
232 else:
233 usage()