Check in some scripts I use for callgraph analysis.

This commit is contained in:
Nick Mathewson 2015-07-30 12:23:28 -04:00
parent beac91cf08
commit 26c9691186
3 changed files with 94 additions and 0 deletions

View 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)

View 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)

View 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