diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-07-30 12:23:28 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-07-30 12:23:28 -0400 |
commit | 26c96911862f80ad228ec2655f8390c011705946 (patch) | |
tree | 65bac1d01d3759066c965b7b3bab0604582c42c7 /scripts/maint/analyze_callgraph.py | |
parent | beac91cf086de0178ef628778a90f3cec7e51e84 (diff) | |
download | tor-26c96911862f80ad228ec2655f8390c011705946.tar.gz tor-26c96911862f80ad228ec2655f8390c011705946.zip |
Check in some scripts I use for callgraph analysis.
Diffstat (limited to 'scripts/maint/analyze_callgraph.py')
-rwxr-xr-x | scripts/maint/analyze_callgraph.py | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/scripts/maint/analyze_callgraph.py b/scripts/maint/analyze_callgraph.py new file mode 100755 index 0000000000..afafe1430b --- /dev/null +++ b/scripts/maint/analyze_callgraph.py @@ -0,0 +1,72 @@ +#!/usr/bin/python + +import re +import sys +import copy +import cPickle +import os + +class Parser: + def __init__(self): + self.calls = {} + + def enter_func(self, name): + if self.infunc and not self.extern: + self.calls.setdefault(self.infunc, set()).update( self.calledfns ) + + self.calledfns = set() + self.infunc = name + self.extern = False + + def parse_callgraph_file(self, inp): + self.infunc = None + self.extern = False + self.calledfns = set() + for line in inp: + m = re.match(r"Call graph node for function: '([^']+)'", line) + if m: + self.enter_func(m.group(1)) + continue + m = re.match(r" CS<[^>]+> calls external node", line) + if m: + self.extern = True + m = re.match(r" CS<[^>]+> calls function '([^']+)'", line) + if m: + self.calledfns.add(m.group(1)) + self.enter_func(None) + + def extract_callgraph(self): + c = self.calls + self.calls = {} + return c + + +def transitive_closure(g): + changed = True + g = copy.deepcopy(g) + while changed: + changed = False + print "X" + for k in g.keys(): + newset = g[k].copy() + for fn in g[k]: + newset.update(g.get(fn, set())) + if len(newset) != len(g[k]): + g[k].update( newset ) + changed = True + return g + +if __name__ == '__main__': + p = Parser() + for fname in sys.argv[1:]: + with open(fname, 'r') as f: + p.parse_callgraph_file(f) + callgraph = p.extract_callgraph() + + closure = transitive_closure(callgraph) + + with open('callgraph.cp', 'w') as f: + cPickle.dump(callgraph, f) + + with open('callgraph_closure.cp', 'w') as f: + cPickle.dump(closure, f) |