def make_node(graph, block, block_to_node, vmap, gen_ret): node = block_to_node.get(block) if node is None: node = build_node_from_block(block, vmap, gen_ret) block_to_node[block] = node if block.exception_analysis: for _type, _, exception_target in block.exception_analysis.exceptions: exception_node = block_to_node.get(exception_target) if exception_node is None: exception_node = build_node_from_block(exception_target, vmap, gen_ret, _type) exception_node.set_catch_type(_type) exception_node.in_catch = True block_to_node[exception_target] = exception_node graph.add_catch_edge(node, exception_node) for _, _, child_block in block.childs: child_node = block_to_node.get(child_block) if child_node is None: child_node = build_node_from_block(child_block, vmap, gen_ret) block_to_node[child_block] = child_node graph.add_edge(node, child_node) if node.type.is_switch: node.add_case(child_node) if node.type.is_cond: if_target = ((block.end // 2) - (block.last_length // 2) + node.off_last_ins) child_addr = child_block.start // 2 if if_target == child_addr: node.true = child_node else: node.false = child_node # Check that both branch of the if point to something # It may happen that both branch point to the same node, in this case # the false branch will be None. So we set it to the right node. # TODO: In this situation, we should transform the condition node into # a statement node if node.type.is_cond and node.false is None: node.false = node.true return node
def make_node(graph, block, block_to_node, vmap, gen_ret): node = block_to_node.get(block) if node is None: node = build_node_from_block(block, vmap, gen_ret) block_to_node[block] = node if block.exception_analysis: for _type, _, exception_target in block.exception_analysis.exceptions: exception_node = block_to_node.get(exception_target) if exception_node is None: exception_node = build_node_from_block(exception_target, vmap, gen_ret, _type) exception_node.set_catch_type(_type) exception_node.in_catch = True block_to_node[exception_target] = exception_node graph.add_catch_edge(node, exception_node) for _, _, child_block in block.childs: child_node = block_to_node.get(child_block) if child_node is None: child_node = build_node_from_block(child_block, vmap, gen_ret) block_to_node[child_block] = child_node graph.add_edge(node, child_node) if node.type.is_switch: node.add_case(child_node) if node.type.is_cond: if_target = ((block.end / 2) - (block.last_length / 2) + node.off_last_ins) child_addr = child_block.start / 2 if if_target == child_addr: node.true = child_node else: node.false = child_node # Check that both branch of the if point to something # It may happen that both branch point to the same node, in this case # the false branch will be None. So we set it to the right node. # TODO: In this situation, we should transform the condition node into # a statement node if node.type.is_cond and node.false is None: node.false = node.true return node
def construct(start_block, vmap, exceptions): # Exceptions are not yet handled. An exception block has no parent, so # we can skip them by doing a BFS on the basic blocks. bfs_blocks = bfs(start_block) graph = Graph() gen_ret = GenInvokeRetName() # Construction of a mapping of basic blocks into Nodes block_to_node = {} for block in bfs_blocks: node = block_to_node.get(block) if node is None: node = build_node_from_block(block, vmap, gen_ret) block_to_node[block] = node for _, _, child_block in block.childs: child_node = block_to_node.get(child_block) if child_node is None: child_node = build_node_from_block(child_block, vmap, gen_ret) block_to_node[child_block] = child_node graph.add_edge(node, child_node) if node.type.is_switch: node.add_case(child_node) if node.type.is_cond: if_target = ((block.end / 2) - (block.last_length / 2) + node.off_last_ins) child_addr = child_block.start / 2 if if_target == child_addr: node.true = child_node else: node.false = child_node # Check that both branch of the if point to something # It may happen that both branch point to the same node, in this case # the false branch will be None. So we set it to the right node. # TODO: In this situation, we should transform the condition node into # a statement node if node.type.is_cond and node.false is None: node.false = node.true graph.add_node(node) graph.entry = block_to_node[start_block] del block_to_node, bfs_blocks graph.compute_rpo() graph.number_ins() # Create a list of Node which are 'return' node # There should be one and only one node of this type # If this is not the case, try to continue anyway by setting the exit node # to the one which has the greatest RPO number (not necessarily the case) lexit_nodes = [node for node in graph if node.type.is_return] if len(lexit_nodes) > 1: # Not sure that this case is possible... logger.error('Multiple exit nodes found !') graph.exit = graph.rpo[-1] elif len(lexit_nodes) < 1: # A method can have no return if it has throw statement(s) or if its # body is a while(1) whitout break/return. logger.debug('No exit node found !') else: graph.exit = lexit_nodes[0] return graph
def construct(start_block, vmap, exceptions): # Exceptions are not yet handled. An exception block has no parent, so # we can skip them by doing a BFS on the basic blocks. bfs_blocks = bfs(start_block) graph = Graph() gen_ret = GenInvokeRetName() # Construction of a mapping of basic blocks into Nodes block_to_node = {} for block in bfs_blocks: node = block_to_node.get(block) if node is None: node = build_node_from_block(block, vmap, gen_ret) block_to_node[block] = node for _, _, child_block in block.childs: child_node = block_to_node.get(child_block) if child_node is None: child_node = build_node_from_block(child_block, vmap, gen_ret) block_to_node[child_block] = child_node graph.add_edge(node, child_node) if node.type.is_switch: node.add_case(child_node) if node.type.is_cond: if_target = ((block.end / 2) - (block.last_length / 2) + node.off_last_ins) child_addr = child_block.start / 2 if if_target == child_addr: node.true = child_node else: node.false = child_node # Check that both branch of the if point to something # It may happen that both branch point to the same node, in this case # the false branch will be None. So we set it to the right node. # TODO: In this situation, we should transform the condition node into # a statement node if node.type.is_cond and node.false is None: node.false = node.true graph.add_node(node) graph.entry = block_to_node[start_block] del block_to_node, bfs_blocks graph.compute_rpo() graph.number_ins() # Create a list of Node which are 'return' node # There should be one and only one node of this type # If this is not the case, try to continue anyway by setting the exit node # to the one which has the greatest RPO number (not necessarily the case) lexit_nodes = [node for node in graph if node.type.is_return] if len(lexit_nodes) > 1: # Not sure that this case is possible... logger.error('Multiple exit nodes found !') graph.exit = graph.rpo[-1] elif len(lexit_nodes) < 1: # A method can have no return if it has throw statement(s) or if its # body is a while(1) whitout break/return. logger.debug('No exit node found !') else: graph.exit = lexit_nodes[0] return graph