private void rebuildGraph() { // This seems like overkill until you realize implementation may change from under us. // Multiple new instructions may be added from adding or removing a single instruction. Set<MethodLocation> staleLocations = locationToNodePile.keySet(); Set<MethodLocation> implementationLocations = implementation.getInstructions().stream().map(BuilderInstruction::getLocation) .collect(Collectors.toSet()); Set<MethodLocation> addedLocations = new HashSet<>(implementationLocations); addedLocations.removeAll(staleLocations); for (MethodLocation location : addedLocations) { addToNodePile(location); } Set<MethodLocation> removedLocations = new HashSet<>(staleLocations); removedLocations.removeAll(implementationLocations); removedLocations.forEach(this::removeFromNodePile); TIntObjectMap<MethodLocation> newAddressToLocation = buildAddressToLocation(implementation); addressToLocation.clear(); addressToLocation.putAll(newAddressToLocation); recreateAndExecute(); }
public void addInstruction(MethodLocation location, BuilderInstruction instruction) { int index = location.getIndex(); implementation.addInstruction(index, instruction); MethodLocation newLocation = instruction.getLocation(); MethodLocation oldLocation = implementation.getInstructions().get(index + 1).getLocation(); try { java.lang.reflect.Method m = MethodLocation.class.getDeclaredMethod("mergeInto", MethodLocation.class); m.setAccessible(true); m.invoke(oldLocation, newLocation); } catch (Exception e) { log.error("Error invoking MethodLocation.mergeInto(). Wrong dexlib version?", e); } rebuildGraph(); }
protected static TIntObjectMap<MethodLocation> buildAddressToLocation(MutableMethodImplementation implementation) { List<BuilderInstruction> instructions = implementation.getInstructions(); TIntObjectMap<MethodLocation> addressToLocation = new TIntObjectHashMap<>(instructions.size()); for (BuilderInstruction instruction : instructions) { MethodLocation location = instruction.getLocation(); int address = location.getCodeAddress(); addressToLocation.put(address, location); } return addressToLocation; }
private void fixInstructions(@Nonnull MutableMethodImplementation methodImplementation) { List<? extends Instruction> instructions = methodImplementation.getInstructions(); for (int i=0; i<instructions.size(); i++) { Instruction instruction = instructions.get(i); if (instruction.getOpcode() == Opcode.CONST_STRING) { if (stringSection.getItemIndex( (StringRef)((ReferenceInstruction)instruction).getReference()) >= 65536) { methodImplementation.replaceInstruction(i, new BuilderInstruction31c(Opcode.CONST_STRING_JUMBO, ((OneRegisterInstruction)instruction).getRegisterA(), ((ReferenceInstruction)instruction).getReference())); } } } }
public ExecutionGraph(VirtualMachine vm, VirtualMethod method) { this.method = method; MutableMethodImplementation implementation = method.getImplementation(); addressToLocation = buildAddressToLocation(implementation); locationToNodePile = buildLocationToNodePile(vm, addressToLocation); List<BuilderInstruction> instructions = implementation.getInstructions(); terminatingAddresses = buildTerminatingAddresses(instructions); this.vm = vm; }
fixInstructions(mutableMethodImplementation); instructions = mutableMethodImplementation.getInstructions(); tryBlocks = mutableMethodImplementation.getTryBlocks(); debugItems = mutableMethodImplementation.getDebugItems();
private void fixInstructions(@Nonnull MutableMethodImplementation methodImplementation) { List<? extends Instruction> instructions = methodImplementation.getInstructions(); for (int i=0; i<instructions.size(); i++) { Instruction instruction = instructions.get(i); if (instruction.getOpcode() == Opcode.CONST_STRING) { if (stringSection.getItemIndex( (StringRef)((ReferenceInstruction)instruction).getReference()) >= 65536) { methodImplementation.replaceInstruction(i, new BuilderInstruction31c(Opcode.CONST_STRING_JUMBO, ((OneRegisterInstruction)instruction).getRegisterA(), ((ReferenceInstruction)instruction).getReference())); } } } }
private void fixInstructions(@Nonnull MutableMethodImplementation methodImplementation) { List<? extends Instruction> instructions = methodImplementation.getInstructions(); for (int i=0; i<instructions.size(); i++) { Instruction instruction = instructions.get(i); if (instruction.getOpcode() == Opcode.CONST_STRING) { if (stringSection.getItemIndex( (StringRef)((ReferenceInstruction)instruction).getReference()) >= 65536) { methodImplementation.replaceInstruction(i, new BuilderInstruction31c(Opcode.CONST_STRING_JUMBO, ((OneRegisterInstruction)instruction).getRegisterA(), ((ReferenceInstruction)instruction).getReference())); } } } }
private static MethodImplementation modifyMethodAndFix(@Nonnull MethodImplementation implementation, Method method) { MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation); System.out.println(mutableImplementation.getRegisterCount()); List<BuilderInstruction> instructions = mutableImplementation.getInstructions(); mutableImplementation.addInstruction(0, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("AndFix:" + method.getDefiningClass().replace("/", ".")))); mutableImplementation.addInstruction(1, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I"))); return mutableImplementation; }
private static MethodImplementation modifyMethodTpatch(@Nonnull MethodImplementation implementation, Method method) { MutableMethodImplementation mutableImplementation = new MutableMethodImplementation(implementation); System.out.println(mutableImplementation.getRegisterCount()); List<BuilderInstruction> instructions = mutableImplementation.getInstructions(); boolean isModified = false; for (int i = 0; i < instructions.size(); i++) { isModified = false; if (instructions.get(i).getOpcode() == Opcode.INVOKE_DIRECT) { if (!isModified) { mutableImplementation.addInstruction(i++, new BuilderInstruction21c(Opcode.CONST_STRING, 0, new ImmutableStringReference("tpatch:" + method.getDefiningClass().replace("/", ".")))); mutableImplementation.addInstruction(i++, new BuilderInstruction35c(Opcode.INVOKE_STATIC, 1, 0, 0, 0, 0, 0, new ImmutableMethodReference("Landroid/util/Log;", "e", Lists.newArrayList("Ljava/lang/String;", "Ljava/lang/String;"), "I"))); isModified = true; break; } } // mutableImplementation.addInstruction(instructions.get(i)); } return mutableImplementation; }
fixInstructions(mutableMethodImplementation); instructions = mutableMethodImplementation.getInstructions(); tryBlocks = mutableMethodImplementation.getTryBlocks(); debugItems = mutableMethodImplementation.getDebugItems();
fixInstructions(mutableMethodImplementation); instructions = mutableMethodImplementation.getInstructions(); tryBlocks = mutableMethodImplementation.getTryBlocks(); debugItems = mutableMethodImplementation.getDebugItems();