gdb/contrib/exsummary.py - gdb
Global variables defined
Functions defined
Source code
- import sys
- import glob
- class Function:
- def __init__(self, name):
- self.name = name
- self.location = None
- self.callers = []
- self.can_throw = False
- self.marked_nothrow = False
- self.reason = None
- def log(self, message):
- print "%s: note: %s" % (self.location, message)
- def set_location(self, location):
- self.location = location
-
- def add_caller(self, caller):
-
- self.callers.append(caller)
-
- def consistency_check(self):
- if self.marked_nothrow and self.can_throw:
- print ("%s: error: %s marked as both 'throw' and 'nothrow'"
- % (self.location, self.name))
- def declare_nothrow(self):
- self.marked_nothrow = True
- self.consistency_check()
- def declare_throw(self):
- result = not self.can_throw
- self.can_throw = True
- self.consistency_check()
- return result
- def print_stack(self, is_indirect):
- if is_indirect:
- print ("%s: error: function %s is marked nothrow but is assumed to throw due to indirect call"
- % (self.location, self.name))
- else:
- print ("%s: error: function %s is marked nothrow but can throw"
- % (self.location, self.name))
- edge = self.reason
- while edge is not None:
- print ("%s: info: via call to %s"
- % (edge.location, edge.to_fn.name))
- edge = edge.to_fn.reason
- def mark_throw(self, edge, work_list, is_indirect):
- if not self.can_throw:
-
- self.can_throw = True
- self.reason = edge
- if self.marked_nothrow:
- self.print_stack(is_indirect)
- else:
-
-
- work_list.append(self)
- class Edge:
- def __init__(self, from_fn, to_fn, location):
- self.from_fn = from_fn
- self.to_fn = to_fn
- self.location = location
- work_list = []
- function_map = {}
- indirect_functions = []
- process_cleanups = False
- process_indirect = False
- def declare(fn_name):
- global function_map
- if fn_name not in function_map:
- function_map[fn_name] = Function(fn_name)
- return function_map[fn_name]
- def define_function(fn_name, location):
- fn = declare(fn_name)
- fn.set_location(location)
- def declare_throw(fn_name):
- global work_list
- fn = declare(fn_name)
- if fn.declare_throw():
- work_list.append(fn)
- def declare_nothrow(fn_name):
- fn = declare(fn_name)
- fn.declare_nothrow()
- def declare_cleanup(fn_name):
- global process_cleanups
- fn = declare(fn_name)
- if process_cleanups:
- fn.declare_nothrow()
- def function_call(to, frm, location):
- to_fn = declare(to)
- frm_fn = declare(frm)
- to_fn.add_caller(Edge(frm_fn, to_fn, location))
- def has_indirect_call(fn_name, location):
- global indirect_functions
- fn = declare(fn_name)
- phony = Function("<indirect call>")
- phony.add_caller(Edge(fn, phony, location))
- indirect_functions.append(phony)
- def mark_functions(worklist, is_indirect):
- for callee in worklist:
- for edge in callee.callers:
- edge.from_fn.mark_throw(edge, worklist, is_indirect)
- def help_and_exit():
- print "Usage: exsummary [OPTION]..."
- print ""
- print "Read the .py files from the exception checker plugin and"
- print "generate an error summary."
- print ""
- print " --cleanups Include invalid behavior in cleanups"
- print " --indirect Include assumed errors due to indirect function calls"
- sys.exit(0)
- def main():
- global work_list
- global indirect_functions
- global process_cleanups
- global process_indirect
- for arg in sys.argv:
- if arg == '--cleanups':
- process_cleanups = True
- elif arg == '--indirect':
- process_indirect = True
- elif arg == '--help':
- help_and_exit()
- for fname in sorted(glob.glob('*.c.gdb_exc.py')):
- execfile(fname)
- print "================"
- print "= Ordinary marking"
- print "================"
- mark_functions(work_list, False)
- if process_indirect:
- print "================"
- print "= Indirect marking"
- print "================"
- mark_functions(indirect_functions, True)
- return 0
- if __name__ == '__main__':
- status = main()
- sys.exit(status)