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);
}
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);
}
Aggregations