Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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