6This script generates a call tree for a function from its disassembly
7information. This script is ony a proof of concept. Use testIDEA to
8generate scripts, which produce more readable call graphs.
12import isystem.connect
as ic
13import subprocess
as sp
22def createGraphImage(graphFileName):
23 print(
'Creating call graph image ...')
24 cmd =
'dot -Tpng -O ' + graphFileName
26 sp.check_call(cmd, shell=
True)
27 except Exception
as ex:
28 print(
"\nERROR: Can not run the graphviz 'dot' utility. Command: ", cmd,
29 '\n\n' + str(ex), file=sys.stderr)
31 return graphFileName +
".png"
34def writeGraphFile(outFileName, graphStr):
35 print(
'Writing graph calls to file: ', outFileName)
36 with open(outFileName,
'w')
as outf:
43def printFunction(cmgr, functionName):
46 print(
"Printing: " + functionName)
48 graph +=
"\"" + functionName +
"\" " + \
49 "[shape=circle, style=bold, label=\"" + \
50 str(functionName) +
"\"];\n"
52 debugCtrl = ic.CDebugFacade(cmgr)
54 functionInfo = debugCtrl.getSymbolInfo(ic.IConnectDebug.fCacheCode | ic.IConnectDebug.fRealTime | ic.IConnectDebug.gafFunctions, functionName)
56 print(
"Not a known function")
59 dataCtrl2 = ic.CDataController2(cmgr)
60 disassembly = dataCtrl2.getDisassembly(0,
61 functionInfo.getMemArea(),
62 functionInfo.getAddress(),
63 functionInfo.getSizeMAUs())
65 daLines = disassembly.Lines()
67 numLines = daLines.size()
69 for idx
in range(numLines):
71 disassemblyLine = daLines.at(idx)
73 if disassemblyLine.IsCall():
74 symbolName: str = debugCtrl.getSymbolAtAddress(ic.IConnectDebug.sFunctions,
75 functionInfo.getMemArea(),
76 disassemblyLine.BranchTarget())
79 symbolName = hex(disassemblyLine.BranchTarget())
83 symbolName = symbolName.replace(
'"',
"'")
85 graph +=
"\"" + str(functionName) +
"\" -> \"" + str(symbolName) +
"\"\n"
87 if symbolName
not in vertex:
88 vertex.add(symbolName)
89 printFunction(cmgr, symbolName)
92 dataCtrl2.release(disassembly)
95def analyzeFunction(cmgr, functionName):
98 graph +=
"digraph {\n"
99 graph +=
"graph [rank=max]\n"
101 printFunction(cmgr, functionName)
111 if len(sys.argv) != 2:
112 print(
"Usage: ", sys.argv[0],
" <function>")
113 print(
'defaulting to "main"')
116 function = sys.argv[1]
119 cmgr = ic.ConnectionMgr()
120 cmgr.connect(ic.CConnectionConfig().instanceId(winidea_id))
122 graph = analyzeFunction(cmgr, function)
123 graphFileName = writeGraphFile(str(function) +
".tree.dot", graph)
124 imageFileName = createGraphImage(graphFileName)
127 sp.check_call(
'start ' + imageFileName, shell=
True)
130 sp.check_call(
'gwenview ' + imageFileName, shell=
True)
132 except Exception
as ex:
133 print(str(ex), file=sys.stderr)
136if __name__ ==
"__main__":