|
| 1 | +import ida_gdl |
| 2 | +import ida_funcs |
| 3 | + |
| 4 | + |
| 5 | +class BasicBlocks(object): |
| 6 | + def __init__(self, offset): |
| 7 | + self.func = ida_funcs.get_func(offset) |
| 8 | + |
| 9 | + self.nodes = filter(self.node_contained, ida_gdl.FlowChart(self.func)) |
| 10 | + self.node_ids = map(lambda n: n.id, self.nodes) |
| 11 | + |
| 12 | + self.seen_nodes = set() |
| 13 | + |
| 14 | + # Assuming node #0 is the root node |
| 15 | + print(self.add_node(self.nodes[0])) |
| 16 | + |
| 17 | + def add_node(self, node): |
| 18 | + if node.id in self.seen_nodes: |
| 19 | + return [self.token(node)] |
| 20 | + |
| 21 | + self.seen_nodes.add(node.id) |
| 22 | + print("{:x}: {}".format(node.startEA, self.token(node))) |
| 23 | + |
| 24 | + # get successive nodes ordered by thier own sizes |
| 25 | + sorted_succs = self.sort_nodes(node.succs()) |
| 26 | + # get successive node sub-graphs ordered |
| 27 | + succ_values = map(self.add_node, sorted_succs) |
| 28 | + # merge all nodes together by order |
| 29 | + return sum(succ_values, [self.token(node)]) |
| 30 | + |
| 31 | + def sort_nodes(self, nodes): |
| 32 | + return sorted(nodes, key=self.sort_key) |
| 33 | + |
| 34 | + @staticmethod |
| 35 | + def token(node): |
| 36 | + # alternatives: offset from start of function |
| 37 | + return node.endEA - node.startEA |
| 38 | + |
| 39 | + sort_ket = token |
| 40 | + |
| 41 | + def node_contained(self, node): |
| 42 | + # make sure only nodes inside the function are accounted for |
| 43 | + # this solves cascaded functions (when multiple functions share same ends) |
| 44 | + return (ida_funcs.func_contains(self.func, node.startEA) and |
| 45 | + ida_funcs.func_contains(self.func, node.endEA - 1)) |
0 commit comments