mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Check in some scripts I use for callgraph analysis.
This commit is contained in:
parent
beac91cf08
commit
26c9691186
72
scripts/maint/analyze_callgraph.py
Executable file
72
scripts/maint/analyze_callgraph.py
Executable file
@ -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)
|
9
scripts/maint/display_callgraph.py
Executable file
9
scripts/maint/display_callgraph.py
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import cPickle
|
||||
|
||||
callgraph = cPickle.load(open("callgraph.cp"))
|
||||
closure = cPickle.load(open("callgraph_closure.cp"))
|
||||
|
||||
for n_reachable, fn in sorted(list((len(r), fn) for fn, r in closure.iteritems())):
|
||||
print "%s can reach %s other functions." %(fn, n_reachable)
|
13
scripts/maint/generate_callgraph.sh
Executable file
13
scripts/maint/generate_callgraph.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
C_FILES=`echo src/common/*.c src/or/*.c src/tools/*.c`
|
||||
CFLAGS="-Isrc/ext/trunnel -Isrc/trunnel -I. -Isrc/ext -Isrc/common -DLOCALSTATEDIR=\"\" -DSHARE_DATADIR=\"\" -Dinline="
|
||||
|
||||
mkdir -p callgraph/src/common
|
||||
mkdir -p callgraph/src/or
|
||||
mkdir -p callgraph/src/tools
|
||||
|
||||
for fn in $C_FILES; do
|
||||
clang $CFLAGS -S -emit-llvm -fno-inline -o - $fn | \
|
||||
opt -analyze -print-callgraph 2> "callgraph/${fn}allgraph"
|
||||
done
|
Loading…
Reference in New Issue
Block a user