'Normalize the CFG, making sure that there are no overlapping basic blocks.
Note that this method will not alter transition graphs of each function in self.kb.functions. You may call
normalize() on each Function object to normalize their transition graphs.
:return: None'

def normalize(self):

    graph = self.graph
    smallest_nodes = {}
    end_addresses_to_nodes = defaultdict(set)
    for n in graph.nodes():
        if n.is_simprocedure:
            continue
        end_addr = (n.addr + n.size)
        key = (end_addr, n.callstack_key)
        end_addresses_to_nodes[key].add(n)
    for key in end_addresses_to_nodes.keys():
        if (len(end_addresses_to_nodes[key]) == 1):
            smallest_nodes[key] = next(iter(end_addresses_to_nodes[key]))
            del end_addresses_to_nodes[key]
    while end_addresses_to_nodes:
        key_to_find = (None, None)
        for (tpl, x) in end_addresses_to_nodes.iteritems():
            if (len(x) > 1):
                key_to_find = tpl
                break
        (end_addr, callstack_key) = key_to_find
        all_nodes = end_addresses_to_nodes[key_to_find]
        all_nodes = sorted(all_nodes, key=(lambda node: node.addr), reverse=True)
        smallest_node = all_nodes[0]
        other_nodes = all_nodes[1:]
        self._normalize_core(graph, callstack_key, smallest_node, other_nodes, smallest_nodes, end_addresses_to_nodes)
        del end_addresses_to_nodes[key_to_find]
        smallest_nodes[key_to_find] = smallest_node
        if (not end_addresses_to_nodes):
            sorted_smallest_nodes = defaultdict(list)
            for (k, node) in smallest_nodes.iteritems():
                (_, callstack_key) = k
                sorted_smallest_nodes[callstack_key].append(node)
            for k in sorted_smallest_nodes.iterkeys():
                sorted_smallest_nodes[k] = sorted(sorted_smallest_nodes[k], key=(lambda node: node.addr))
            for (callstack_key, lst) in sorted_smallest_nodes.iteritems():
                lst_len = len(lst)
                for (i, node) in enumerate(lst):
                    if (i == (lst_len - 1)):
                        break
                    next_node = lst[(i + 1)]
                    if (node.addr <= next_node.addr < (node.addr + node.size)):
                        nodekey_a = ((node.addr + node.size), callstack_key)
                        nodekey_b = ((next_node.addr + next_node.size), callstack_key)
                        if ((nodekey_a in smallest_nodes) and (nodekey_b in smallest_nodes)):
                            end_addresses_to_nodes[((node.addr + node.size), callstack_key)].add(node)
                            end_addresses_to_nodes[((node.addr + node.size), callstack_key)].add(next_node)
                        smallest_nodes.pop(nodekey_a, None)
                        smallest_nodes.pop(nodekey_b, None)
    self._normalized = True
