Advertisement
joxeankoret

Script to show nodes, edges, complexity, loops and switchs.

Feb 1st, 2019
911
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.73 KB | None | 0 0
  1. """
  2. Script to calculate the Cyclomatic Complexity of every function.
  3.  
  4. Joxean Koret, 2019
  5. Public Domain
  6. """
  7.  
  8. import idaapi
  9.  
  10. from tarjan_sort import strongly_connected_components
  11.  
  12. #-------------------------------------------------------------------------------
  13. class CCFGDataChooser(idaapi.Choose2):
  14.   def __init__(self, title, items):
  15.     idaapi.Choose2.__init__(self,
  16.                      title,
  17.                      [ ["Address", 8], ["Name", 50], ["Nodes", 8],
  18.                      ["Edges", 8], ["CC", 8], ["Loops", 8], ["Switchs", 8]])
  19.     self.items = []
  20.     for item in items:
  21.       element = ["0x%08x" % item[0], item[1],
  22.                  "%04d" % item[2], "%04d" % item[3], "%04d" % item[4],
  23.                  "%04d" % item[5], "%03d" % item[6]]
  24.       self.items.append(element)
  25.  
  26.   def OnSelectLine(self, n):
  27.     ea = int(self.items[n][0], 16)
  28.     jumpto(ea)
  29.  
  30.   def OnGetLine(self, n):
  31.     return self.items[n]
  32.  
  33.   def OnGetSize(self):
  34.     return len(self.items)
  35.  
  36. #-------------------------------------------------------------------------------
  37. def analyze_function(ea):
  38.   nodes = 0
  39.   edges = 0
  40.   cc = 0
  41.   g = {}
  42.   switches = set()
  43.  
  44.   func = idaapi.get_func(ea)
  45.   if func is not None:
  46.     nodes = 0
  47.     edges = 0
  48.     flow = idaapi.FlowChart(func)
  49.     for block in flow:
  50.       nodes += 1
  51.       g[block.startEA] = []
  52.       for succ in block.succs():
  53.         edges += 1
  54.         g[block.startEA].append(succ.startEA)
  55.  
  56.       for pred in block.preds():
  57.         edges += 1
  58.         try:
  59.           g[pred.startEA].append(block.startEA)
  60.         except KeyError:
  61.           g[pred.startEA] = [block.startEA]
  62.  
  63.       if block.startEA == 0:
  64.         continue
  65.  
  66.       for head in Heads(block.startEA, block.endEA):
  67.         switch = idaapi.get_switch_info_ex(head)
  68.         if switch:
  69.           switches.add(switch.startea)
  70.  
  71.   cc = edges - nodes + 2
  72.   return nodes, edges, cc, g, len(switches)
  73.  
  74. #-------------------------------------------------------------------------------
  75. def main():
  76.   vals = []
  77.   items = []
  78.   for ea in Functions():
  79.     nodes, edges, cc, graph, switches = analyze_function(ea)
  80.     try:
  81.       scc = strongly_connected_components(graph)
  82.       loops = 0
  83.       for item in scc:
  84.         val = len(item)
  85.         if val > 1:
  86.           loops += 1
  87.     except:
  88.       loops = -1
  89.  
  90.     name = GetFunctionName(ea)
  91.     tmp = Demangle(name, INF_SHORT_DN)
  92.     if tmp != "" and tmp is not None:
  93.       name = tmp
  94.     items.append([ea, name, nodes, edges, cc, loops, switches])
  95.     vals.append(cc)
  96.  
  97.   line = "Cyclomatic complexity: Max %d, Avg %d"
  98.   print(line % (max(vals), sum(vals)/len(vals)))
  99.  
  100.   ch = CCFGDataChooser("Control Flow Graphs Data", items)
  101.   ch.Show()
  102.  
  103. if __name__ == "__main__":
  104.   main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement