43 'make_cleanup_dtor': 1,
44 'make_final_cleanup': 1,
45 'make_my_cleanup2': 1,
52 'exceptions_state_mc': 1,
59 'do_final_cleanups': 1
65 non_passthrough_functions = {
67 'add_internal_function': 1
71 def type_is_pythonic(t):
72 if isinstance(t, gcc.ArrayType):
74 if not isinstance(t, gcc.RecordType):
77 return str(t).find(
'struct Py') == 0
81 def examine_struct_fields(initializer):
83 for idx2, value2
in initializer.elements:
84 if isinstance(idx2, gcc.Declaration):
85 if isinstance(value2, gcc.AddrExpr):
86 value2 = value2.operand
87 if isinstance(value2, gcc.FunctionDecl):
88 output_file.write(
"declare_nothrow(%s)\n" 89 % repr(str(value2.name)))
93 def examine_globals():
95 vars = gcc.get_variables()
97 if not isinstance(var.decl, gcc.VarDecl):
99 output_file.write(
"################\n")
100 output_file.write(
"# Analysis for %s\n" % var.decl.name)
101 if not var.decl.initial:
103 if not type_is_pythonic(var.decl.type):
106 if isinstance(var.decl.type, gcc.ArrayType):
107 for idx, value
in var.decl.initial.elements:
108 examine_struct_fields(value)
110 gccutils.check_isinstance(var.decl.type, gcc.RecordType)
111 examine_struct_fields(var.decl.initial)
115 def close_output(*args):
125 class GdbExceptionChecker(gcc.GimplePass):
126 def __init__(self, output_file):
127 gcc.GimplePass.__init__(self,
'gdb_exception_checker')
128 self.output_file = output_file
131 self.output_file.write(
"# %s\n" % str(obj))
135 def fn_is_python_ignorable(self, fn):
136 if not isinstance(fn, gcc.SsaName):
139 if not isinstance(stmt, gcc.GimpleAssign):
141 if stmt.exprcode
is not gcc.ComponentRef:
144 if not isinstance(rhs, gcc.ComponentRef):
146 if not isinstance(rhs.field, gcc.FieldDecl):
148 return rhs.field.name ==
'tp_dealloc' or rhs.field.name ==
'tp_free' 155 def handle_one_fndecl(self, this_fun, fndecl, loc):
157 if isinstance(fndecl, gcc.AddrExpr):
158 fndecl = fndecl.operand
159 if isinstance(fndecl, gcc.FunctionDecl):
161 callee_name = str(fndecl.name)
162 self.output_file.write(
"function_call(%s, %s, %s)\n" 163 % (repr(callee_name),
164 repr(this_fun.decl.name),
166 elif self.fn_is_python_ignorable(fndecl):
169 elif (isinstance(fndecl, gcc.SsaName)
170 and isinstance(fndecl.var, gcc.ParmDecl)):
177 self.output_file.write(
"has_indirect_call(%s, %s)\n" 178 % (repr(this_fun.decl.name),
187 def examine_one_bb_inner(self, this_fun, bb):
191 for stmt
in bb.gimple:
194 loc = this_fun.decl.location
195 if not isinstance(stmt, gcc.GimpleCall):
197 callee_name = self.handle_one_fndecl(this_fun, stmt.fn, loc)
199 if callee_name ==
'exceptions_state_mc_action_iter':
202 global non_passthrough_functions
203 if callee_name
in non_passthrough_functions:
211 for arg
in stmt.args:
214 if isinstance(t, gcc.PointerType):
216 if not isinstance(t, gcc.FunctionType):
219 if isinstance(arg, gcc.AddrExpr):
222 global cleanup_functions
223 if callee_name
in cleanup_functions:
224 if not isinstance(arg, gcc.FunctionDecl):
225 gcc.inform(loc,
'cleanup argument not a DECL: %s' % repr(arg))
228 self.output_file.write(
"declare_cleanup(%s)\n" 229 % repr(str(arg.name)))
235 self.handle_one_fndecl(this_fun, arg, loc)
247 def examine_one_bb(self, this_fun, bb, bb_worklist, seen_bbs):
248 try_catch = self.examine_one_bb_inner(this_fun, bb)
249 for edge
in bb.succs:
250 if edge.dest
in seen_bbs:
252 seen_bbs[edge.dest] = 1
257 bb_worklist.append(edge.dest)
259 bb_worklist.append(edge.dest)
262 def iterate_bbs(self, this_fun):
265 bb_worklist = [this_fun.cfg.entry]
267 seen_bbs[this_fun.cfg.entry] = 1
268 for bb
in bb_worklist:
269 self.examine_one_bb(this_fun, bb, bb_worklist, seen_bbs)
271 def execute(self, fun):
272 if fun
and fun.cfg
and fun.decl:
273 self.output_file.write(
"################\n")
274 self.output_file.write(
"# Analysis for %s\n" % fun.decl.name)
275 self.output_file.write(
"define_function(%s, %s)\n" 276 % (repr(fun.decl.name),
277 repr(str(fun.decl.location))))
279 global ignore_functions
280 if fun.decl.name
not in ignore_functions:
281 self.iterate_bbs(fun)
285 output_file = open(gcc.get_dump_base_name() +
'.gdb_exc.py',
'w')
288 output_file.write(
'declare_throw("throw_exception")\n')
289 output_file.write(
'declare_throw("throw_verror")\n')
290 output_file.write(
'declare_throw("throw_vfatal")\n')
291 output_file.write(
'declare_throw("throw_error")\n')
292 gcc.register_callback(gcc.PLUGIN_FINISH_UNIT, close_output)
293 ps = GdbExceptionChecker(output_file)
294 ps.register_after(
'ssa')