Search in sources :

Example 1 with CInliningResult

use of com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult in project binnavi by google.

the class ViewGraphHelpers method inlineFunctionCall.

// ! Inlines a function call into a code node.
/**
 * Inserts the code nodes of a function into a view and splits an existing code node (if
 * necessary) to call the function.
 *
 * @param view The view where the inlining operation takes place.
 * @param codeNode The code node that is split.
 * @param instruction The sub-function call instruction.
 * @param function The function to be inlined.
 *
 * @return Gives information about the inlining process.
 */
public static InliningResult inlineFunctionCall(final View view, final CodeNode codeNode, final Instruction instruction, final Function function) {
    Preconditions.checkNotNull(view, "Error: View argument can not be null");
    Preconditions.checkNotNull(codeNode, "Error: Code node argument can not be null");
    Preconditions.checkNotNull(instruction, "Error: Instruction argument can not be null");
    Preconditions.checkNotNull(function, "Error: Function argument can not be null");
    final CInliningResult result = CInliningHelper.inlineCodeNode(view.getNative(), codeNode.getNative(), instruction.getNative(), function.getNative());
    final CodeNode firstNode = (CodeNode) ObjectFinders.getObject(result.getFirstNode(), view.getGraph().getNodes());
    final CodeNode secondNode = (CodeNode) (result.getSecondNode() == null ? null : ObjectFinders.getObject(result.getSecondNode(), view.getGraph().getNodes()));
    return new InliningResult(firstNode, secondNode);
}
Also used : CInliningResult(com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult) CInliningResult(com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult)

Example 2 with CInliningResult

use of com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult in project binnavi by google.

the class CInliningHelper method inlineCodeNode.

/**
 * Inlines the basic blocks of a function into a code node.
 *
 * @param view The view where the inlining operation takes place.
 * @param originalNode The node where the inlining operation takes place.
 * @param inlineInstruction The function call instruction after which the function is inlined.
 * @param functionToInline The function to be inlined.
 *
 * @return Contains information about the inlining result.
 */
public static CInliningResult inlineCodeNode(final INaviView view, final INaviCodeNode originalNode, final INaviInstruction inlineInstruction, final INaviFunction functionToInline) {
    Preconditions.checkNotNull(view, "IE00108: View argument can not be null");
    Preconditions.checkNotNull(originalNode, "IE00109: Node argument can not be null");
    Preconditions.checkNotNull(inlineInstruction, "IE00110: Instruction argument can not be null");
    Preconditions.checkArgument(originalNode.hasInstruction(inlineInstruction), "IE00111: Instruction is not part of the code node");
    Preconditions.checkNotNull(functionToInline, "IE00112: Function argument can not be null");
    Preconditions.checkArgument(view.isLoaded(), "IE00113: View must be loaded before it can be inlined");
    Preconditions.checkArgument(view.getGraph().getNodes().contains(originalNode), "IE00114: Code node does not belong to the view");
    Preconditions.checkArgument(functionToInline.isLoaded(), "IE00115: Function must be loaded before it can be inlined");
    Preconditions.checkArgument(functionToInline.getBasicBlockCount() != 0, "IE00116: Functions with 0 blocks can not be inlined");
    final INaviGroupNode parentGroup = originalNode.getParentGroup();
    GroupHelpers.expandParents(originalNode);
    final List<INaviEdge> oldIncomingEdges = originalNode.getIncomingEdges();
    final List<INaviEdge> oldOutgoingEdges = originalNode.getOutgoingEdges();
    // At first we find out which instructions will be part of the new first block
    // and which instructions will be part of the new second block.
    final List<INaviInstruction> upperInstructions = new ArrayList<INaviInstruction>();
    final List<INaviInstruction> lowerInstructions = new ArrayList<INaviInstruction>();
    List<INaviInstruction> currentBlock = upperInstructions;
    for (final INaviInstruction currentInstruction : originalNode.getInstructions()) {
        currentBlock.add(currentInstruction);
        if (currentInstruction == inlineInstruction) {
            currentBlock = lowerInstructions;
        }
    }
    // Now we create the new nodes from the instructions blocks
    INaviCodeNode firstNode;
    final List<INaviViewNode> continueNodes = new ArrayList<INaviViewNode>();
    final boolean keepOriginalBlock = lowerInstructions.isEmpty();
    CCodeNode returnNode = null;
    if (keepOriginalBlock) {
        // There are no instructions in the second block => therefore the call instruction
        // is the last instruction of the block => therefore no splitting is necessary =>
        // therefore we can just reuse the original block.
        firstNode = originalNode;
        for (final INaviEdge edge : originalNode.getOutgoingEdges()) {
            continueNodes.add(edge.getTarget());
            view.getContent().deleteEdge(edge);
        }
    } else {
        // The second block is not empty => the call instruction is somewhere in the middle =>
        // the block must be split => the original block becomes useless and must be replaced by
        // two new blocks.
        final boolean recolor = (originalNode.getIncomingEdges().size() == 1) && (originalNode.getIncomingEdges().get(0).getType() == EdgeType.ENTER_INLINED_FUNCTION) && (originalNode.getOutgoingEdges().size() == 1) && (originalNode.getOutgoingEdges().get(0).getType() == EdgeType.LEAVE_INLINED_FUNCTION);
        view.getContent().deleteNode(originalNode);
        try {
            firstNode = view.getContent().createCodeNode(originalNode.getParentFunction(), upperInstructions);
        } catch (final MaybeNullException exception) {
            firstNode = view.getContent().createCodeNode(null, upperInstructions);
        }
        firstNode.setColor(originalNode.getColor());
        firstNode.setBorderColor(originalNode.getBorderColor());
        try {
            returnNode = view.getContent().createCodeNode(originalNode.getParentFunction(), lowerInstructions);
        } catch (final MaybeNullException e1) {
            returnNode = view.getContent().createCodeNode(null, lowerInstructions);
        }
        returnNode.setColor(originalNode.getColor());
        if (recolor) {
            firstNode.setBorderColor(new Color(-16736256));
            returnNode.setBorderColor(new Color(-6291456));
        }
        if (parentGroup != null) {
            parentGroup.addElement(firstNode);
            parentGroup.addElement(returnNode);
        }
        // Copy the tags of the original node too
        final Iterator<CTag> it = originalNode.getTagsIterator();
        while (it.hasNext()) {
            final CTag tag = it.next();
            try {
                firstNode.tagNode(tag);
                returnNode.tagNode(tag);
            } catch (final CouldntSaveDataException e) {
                CUtilityFunctions.logException(e);
            }
        }
        continueNodes.add(returnNode);
    }
    // Insert the nodes and edges from the loaded function
    final Triple<CCodeNode, List<CCodeNode>, ArrayList<CCodeNode>> nodes = insertNodes(view, functionToInline, parentGroup);
    final INaviCodeNode entryNode = nodes.first();
    final List<CCodeNode> exitNodes = nodes.second();
    if (!keepOriginalBlock) {
        for (final INaviEdge incomingEdge : oldIncomingEdges) {
            if (incomingEdge.getSource() == originalNode) {
                final EdgeType edgeType = incomingEdge.getType();
                view.getContent().createEdge(returnNode, firstNode, edgeType);
            } else {
                final EdgeType edgeType = incomingEdge.getType();
                view.getContent().createEdge(incomingEdge.getSource(), firstNode, edgeType);
            }
        }
    }
    // Create an edge from the upper part of the split block to the entry node
    // of the inlined function.
    view.getContent().createEdge(firstNode, entryNode, EdgeType.ENTER_INLINED_FUNCTION);
    // of the original function where control flow continues.
    for (final INaviCodeNode exitNode : exitNodes) {
        for (final INaviViewNode continueNode : continueNodes) {
            view.getContent().createEdge(exitNode, continueNode, EdgeType.LEAVE_INLINED_FUNCTION);
        }
    }
    if (!keepOriginalBlock) {
        for (final INaviEdge oldChild : oldOutgoingEdges) {
            for (final INaviViewNode continueNode : continueNodes) {
                if (oldChild.getTarget() != originalNode) {
                    view.getContent().createEdge(continueNode, oldChild.getTarget(), oldChild.getType());
                }
            }
        }
    }
    return new CInliningResult(firstNode, returnNode);
}
Also used : MaybeNullException(com.google.security.zynamics.binnavi.Exceptions.MaybeNullException) CouldntSaveDataException(com.google.security.zynamics.binnavi.Database.Exceptions.CouldntSaveDataException) Color(java.awt.Color) ArrayList(java.util.ArrayList) CTag(com.google.security.zynamics.binnavi.Tagging.CTag) EdgeType(com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType) ArrayList(java.util.ArrayList) List(java.util.List) CInliningResult(com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult)

Aggregations

CInliningResult (com.google.security.zynamics.binnavi.disassembly.algorithms.CInliningResult)2 CouldntSaveDataException (com.google.security.zynamics.binnavi.Database.Exceptions.CouldntSaveDataException)1 MaybeNullException (com.google.security.zynamics.binnavi.Exceptions.MaybeNullException)1 CTag (com.google.security.zynamics.binnavi.Tagging.CTag)1 EdgeType (com.google.security.zynamics.zylib.gui.zygraph.edges.EdgeType)1 Color (java.awt.Color)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1