public ExecutionNode(ExecutionNode other) { op = other.op; children = new ArrayList<>(other.getChildren()); }
@Override public ExecutionNode next() { ExecutionNode result = stack.poll(); stack.addAll(result.getChildren()); return result; }
public List<ExecutionNode> getChildren(int address) { List<ExecutionNode> children = new ArrayList<>(); List<ExecutionNode> nodePile = getNodePile(address); for (ExecutionNode node : nodePile) { children.addAll(node.getChildren()); } return children; }
private static void getGraph(ExecutionNode node, ExecutionGraph graph, StringBuilder sb, List<ExecutionNode> visitedNodes) { if (visitedNodes.contains(node)) { return; } visitedNodes.add(node); StringBuilder nodeState = getNodeState(node, graph); for (ExecutionNode child : node.getChildren()) { sb.append(nodeState).append(" -> ").append(getNodeState(child, graph)).append('\n'); getGraph(child, graph, sb, visitedNodes); } }
private void removeFromNodePile(MethodLocation location) { List<ExecutionNode> nodePile = locationToNodePile.remove(location); Map<MethodLocation, ExecutionNode> locationToChildNodeToRemove = new HashMap<>(); for (ExecutionNode removedNode : nodePile) { ExecutionNode parentNode = removedNode.getParent(); if (parentNode == null) { continue; } parentNode.removeChild(removedNode); recreateLocations.add(parentNode.getOp().getLocation()); // reexecuteLocations.add(parentNode.getOp().getLocation()); for (ExecutionNode childNode : removedNode.getChildren()) { Op childOp = childNode.getOp(); boolean pseudoChild = childOp instanceof FillArrayDataPayloadOp || childOp instanceof SwitchPayloadOp; if (!pseudoChild) { reparentNode(childNode, parentNode); } else { // pseudo child // Implementation was altered such that dexlib removed something, probably nop padding for (ExecutionNode grandChildNode : childNode.getChildren()) { reparentNode(grandChildNode, parentNode); } locationToChildNodeToRemove.put(childOp.getLocation(), childNode); } } } for (Entry<MethodLocation, ExecutionNode> entry : locationToChildNodeToRemove.entrySet()) { List<ExecutionNode> pile = locationToNodePile.get(entry.getKey()); pile.remove(entry.getValue()); } }
if (node.getChildren().size() > 1 && !warnedMultipleExecutionPaths) { warnedMultipleExecutionPaths = true; String children = node.getChildren() .stream() .map(ExecutionNode::toString) stack.addAll(node.getChildren()); checkMaxExecutionTime(endTime, method);
private void reparentNode(@Nonnull ExecutionNode child, @Nonnull ExecutionNode parent) { ExecutionContext newContext = parent.getContext().spawnChild(); child.setContext(newContext); child.setParent(parent); reexecuteLocations.add(child.getOp().getLocation()); for (ExecutionNode grandChild : child.getChildren()) { grandChild.getContext().setShallowParent(newContext); } }
List<ExecutionNode> pile = manipulator.getNodePile(address); for (ExecutionNode node : pile) { children.addAll(node.getChildren()); ExecutionNode child = pile.get(0).getChildren().get(0); boolean isNext = child.getAddress() == original.getLocation().getCodeAddress() + original.getCodeUnits(); peepAddresses.add(address);
stack.addAll(node.getChildren());
List<ExecutionNode> children = current.getChildren(); if (children.size() == 1) { current = children.get(0);
@Test public void testHasExpectedGraph() { ExecutionNode child = buildNode(CHILD_ADDRESS, CHILD_NODE_STR, CHILD_STATE_STR); when(child.getChildren()).thenReturn(new LinkedList<ExecutionNode>()); ExecutionNode root = buildNode(ROOT_ADDRESS, ROOT_NODE_STR, ROOT_STATE_STR); List<ExecutionNode> children = new LinkedList<ExecutionNode>(); children.add(child); when(root.getChildren()).thenReturn(children); VirtualMethod localMethod = mock(VirtualMethod.class); when(localMethod.toString()).thenReturn(METHOD_SIGNATURE); ExecutionGraph graph = mock(ExecutionGraph.class); when(graph.getRoot()).thenReturn(root); when(graph.getMethod()).thenReturn(localMethod); when(graph.getNodeIndex(root)).thenReturn(0); when(graph.getNodeIndex(child)).thenReturn(0); String digraph = ExecutionGrapher.graph(graph); StringBuilder sb = new StringBuilder("digraph {\n"); sb.append("\"@").append(ROOT_ADDRESS).append(".0 :: ").append(ROOT_NODE_STR).append('\n'); sb.append(ROOT_STATE_STR).append("\" -> "); sb.append("\"@").append(CHILD_ADDRESS).append(".0 :: ").append(CHILD_NODE_STR).append('\n'); sb.append(CHILD_STATE_STR).append("\"\n"); sb.append("labelloc=\"t\"\n"); sb.append("label=\"").append(METHOD_SIGNATURE).append("\";"); sb.append("\n}"); String expected = sb.toString(); assertEquals(expected, digraph); }
private static void testHeritage(ExecutionGraphManipulator manipulator, int address) { ExecutionNode template = manipulator.getTemplateNode(address); assertEquals(0, template.getChildren().size()); assertNotNull(template.getOp().getChildren()); ExecutionNode node = manipulator.getNodePile(address).get(0); assertEquals(template.getOp(), node.getOp()); List<ExecutionNode> children = node.getChildren(); assertEquals(1, children.size()); MethodLocation[] childLocations = node.getChildLocations(); assertEquals(1, childLocations.length); ExecutionNode child = node.getChildren().get(0); assertEquals(node, child.getParent()); assertEquals(node.getContext(), child.getContext().getParent()); Op childOp = child.getOp(); assertEquals(childOp.getLocation(), childLocations[0]); assertEquals(childOp.getLocation(), node.getOp().getChildren()[0]); }
private static void test(Object[][] expected, ExecutionGraphManipulator manipulator) { for (Object[] ex : expected) { int address = (Integer) ex[0]; BuilderInstruction actualInstruction = manipulator.getInstruction(address); Opcode expectedOpcode = (Opcode) ex[1]; assertEquals(expectedOpcode, actualInstruction.getOpcode()); Object[][][] exChildren = (Object[][][]) ex[2]; List<ExecutionNode> actualNodePile = manipulator.getNodePile(address); assertEquals(expectedOpcode.name + " @" + address + " node pile size", exChildren.length, actualNodePile.size()); for (int i = 0; i < exChildren.length; i++) { ExecutionNode actualNode = actualNodePile.get(i); List<ExecutionNode> childNodes = actualNode.getChildren(); BuilderInstruction[] children = new BuilderInstruction[childNodes.size()]; for (int j = 0; j < children.length; j++) { children[j] = childNodes.get(j).getOp().getInstruction(); } assertEquals(expectedOpcode.name + " @" + address + " children size", exChildren[i].length, children.length); for (int j = 0; j < exChildren[i].length; j++) { assertEquals(expectedOpcode.name + " @" + address + " child address", (int) exChildren[i][j][0], children[j].getLocation().getCodeAddress()); assertEquals(expectedOpcode.name + " @" + address + " child opcode", exChildren[i][j][1], children[j].getOpcode()); } } } }