joxeankoret icon

Python script to show the cyclomatic complexity of each func

joxeankoret | PRO | 01/11/19 09:47:50 AM UTC | 0 ⭐ | 882 👁️ | Never ⏰ | []
Python |

1.88 KB

|

None

|

0 👍

/

0 👎

"""
Script to calculate the Cyclomatic Complexity of every function.
 
Joxean Koret, 2019
Public Domain
"""
 
import idaapi
 
#-------------------------------------------------------------------------------
class CCyclomaticComplexityChooser(idaapi.Choose2):
  def __init__(self, title, items):
    idaapi.Choose2.__init__(self,
                     title,
                     [ ["Address", 8], ["Name", 50], ["Nodes", 8],
                     ["Edges", 8], ["CC", 8], ])
    self.items = []
    for item in items:
      element = ["0x%08x" % item[0], item[1],
                 "%04d" % item[2], "%04d" % item[3], "%04d" % item[4]]
      self.items.append(element)
 
  def OnSelectLine(self, n):
    ea = int(self.items[n][0], 16)
    jumpto(ea)
 
  def OnGetLine(self, n):
    return self.items[n]
 
  def OnGetSize(self):
    return len(self.items)
 
#-------------------------------------------------------------------------------
def calc_cc(ea):
  func = idaapi.get_func(ea)
  if func is not None:
  
    nodes = 0
    edges = 0
    flow = idaapi.FlowChart(func)
    for block in flow:
      nodes += 1
      for succ in block.succs():
        edges += 1
      
      for pred in block.preds():
        edges += 1
  
  cc = edges - nodes + 2
  return nodes, edges, cc
 
#-------------------------------------------------------------------------------
def main():
  vals = []
  items = []
  for ea in Functions():
    nodes, edges, cc = calc_cc(ea)
    name = GetFunctionName(ea)
    tmp = Demangle(name, INF_SHORT_DN)
    if tmp != "" and tmp is not None:
      name = tmp
    items.append([ea, name, nodes, edges, cc])
    vals.append(cc)
 
  line = "Cyclomatic complexity: Max %d, Avg %d"
  print(line % (max(vals), sum(vals)/len(vals)))
  
  ch = CCyclomaticComplexityChooser("Cyclomatic Complexity", items)
  ch.Show()
 
if __name__ == "__main__":
  main()

Comments