#! /usr/bin/python import sys,os import re from popen2 import popen2 import string import getopt class Func: def __init__(self, name): self.calls = [] self.name = name def usage(): print "%s [-d depth] [-r root] -i infile" % sys.argv[0] def main(): try: infile = "" depth = 0 root=None uniq = 0 opts=getopt.getopt(sys.argv[1:],"i:r:d:u") for opt, parm in opts[0]: if opt == "-i": infile = parm elif opt == "-r": root = parm elif opt == "-u": uniq = 1 elif opt == "-d": try: depth = int(parm) except ValueError,str: raise getopt.error,(("bad depth: %s" % str), None) if not infile: raise getopt.error, ("missing infile", None) except getopt.error,str: print "Error:", str print usage() sys.exit(0) out,inf=popen2("objdump -d %s" % infile) symb=re.compile("^([0-9a-f]{8}) <(.*)>:$") callfunc=re.compile("^.*call.*<([^+-]*)>$") graph = {} current = None l="a" while l: l=out.readline() m = symb.search(l) if m: sym = m.expand("\\2") current = Func(sym) graph[sym] = current # print sym continue m = callfunc.search(l) if m: call = m.expand("\\1") try: current.calls.index(call) if not uniq: raise ValueError except ValueError: current.calls.append(call) # print "--> ",call continue for r in [root,"main", "init", "_init", ".text", graph.keys()[0]]: if graph.has_key(r): root=r break if depth: Func.selected = 0 global select def select(cur, n, depth=depth, graph=graph): f = graph[cur] if f.selected: return f.selected = 1 if n < depth: for g in f.calls: select(g,n+1) else: f.calls=[] select(root,0) fs=graph.keys()[:] for f in fs: if not graph[f].selected: del(graph[f]) outfile=os.tempnam() f=open(outfile,"w") f.write('digraph "%s" {\n' % outfile.split("/")[-1]) for k in graph.keys(): f.write('"%s" [ label="%s" ];\n' % (k,k)) for k in graph.keys(): for l in graph[k].calls: f.write('"%s" -> "%s";\n' % (k,l)) f.write("}\n") f.close() os.system("dotty %s" % outfile) try: main() except: import pdb (type, value, tb) = sys.exc_info() raise type,value,tb pdb.post_mortem(tb)