private static String buildFrameworkCache(String resPath) throws Exception { List<File> resFiles = new LinkedList<>(); try { URL url = FrameworkJarBuilder.class.getResource(resPath); File file = new File(url.toURI()); resFiles.addAll(Utils.getFilesWithSmaliExtension(file)); } catch (URISyntaxException e) { e.printStackTrace(); } DexBuilder dexBuilder = new DexBuilder(Opcodes.getDefault()); StringBuilder sb = new StringBuilder(); for (File resFile : resFiles) { String absPath = resFile.getAbsolutePath(); String path = absPath.substring(absPath.lastIndexOf(FRAMEWORK_ROOT)); InputStream is = FrameworkJarBuilder.class.getResourceAsStream(path); BuilderClassDef classDef = SmaliParser.parse(path, is, dexBuilder); sb.append(ReferenceUtil.getReferenceString(classDef)); sb.append(':').append(path.substring(1)).append('\n'); } return sb.toString(); }
@Override public void run() { if (help || inputList == null || inputList.isEmpty()) { usage(); return; } if (inputList.size() > 1) { System.err.println("Too many files specified"); usage(); return; } String input = inputList.get(0); loadDexFile(input); for (Reference reference: dexFile.getReferences(referenceType)) { System.out.println(ReferenceUtil.getReferenceString(reference)); } } }
boolean canReplaceMethodInvoke(int address) { Op op = manipulator.getOp(address); if (!(op instanceof InvokeOp)) { return false; } BuilderInstruction instruction = manipulator.getInstruction(address); ReferenceInstruction instr = (ReferenceInstruction) instruction; String methodSignature = ReferenceUtil.getReferenceString(instr.getReference()); if (!methodSignature.equals(METHOD_INVOKE_SIGNATURE)) { return false; } // Examine parent since maybe the method is not safe and invoke op will assume everything mutates to unknown. int[] parameterRegisters = ((InvokeOp) op).getParameterRegisters(); int methodRegister = parameterRegisters[0]; int[] parentAddresses = manipulator.getParentAddresses(address); Object methodValue = manipulator.getRegisterConsensusValue(parentAddresses, methodRegister); if (methodValue instanceof UnknownValue) { return false; } String className = manipulator.getMethod().getClassName(); java.lang.reflect.Method method = (java.lang.reflect.Method) methodValue; int methodAccessFlags = method.getModifiers(); String declaringClass = ClassNameUtils.toInternal(method.getDeclaringClass()); boolean isPrivate = Modifier.isPrivate(methodAccessFlags); if (isPrivate && !declaringClass.equals(className) && !method.isAccessible()) { return false; } return true; }
String referenceType = ReferenceUtil.getReferenceString(original.getReference()); if (!preCastType.equals(referenceType)) {
boolean canPeepClassForName(int address) { Op op = manipulator.getOp(address); if (!(op instanceof InvokeOp)) { return false; } BuilderInstruction instruction = manipulator.getInstruction(address); ReferenceInstruction instr = (ReferenceInstruction) instruction; String methodDescriptor = ReferenceUtil.getReferenceString(instr.getReference()); if (!methodDescriptor.equals(CLASS_FOR_NAME_SIGNATURE)) { return false; } int[] parameterRegisters = ((InvokeOp) op).getParameterRegisters(); int registerA = parameterRegisters[0]; HeapItem className = manipulator.getRegisterConsensus(address, registerA); if (className.isUnknown()) { return false; } return true; }
String methodSignature = ReferenceUtil.getReferenceString(instr.getReference()); if (!methodSignature.equals(FIELD_GET_SIGNATURE)) { return false;
@Override public NewArrayOp create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); Instruction22c instr = (Instruction22c) location.getInstruction(); int destRegister = instr.getRegisterA(); int sizeRegister = instr.getRegisterB(); String arrayType = ReferenceUtil.getReferenceString(instr.getReference()); return new NewArrayOp(location, child, destRegister, sizeRegister, arrayType, vm.getClassLoader()); }
BuilderInstruction buildUninitializedInstanceReferenceResultReplacement(int address) { InvokeOp invokeOp = (InvokeOp) manipulator.getOp(address); int instanceRegister = invokeOp.getParameterRegisters()[0]; HeapItem item = manipulator.getRegisterConsensus(address, instanceRegister); BuilderInstruction original = manipulator.getInstruction(address); int nextAddress = address + original.getCodeUnits(); MoveOp moveOp = (MoveOp) manipulator.getOp(nextAddress); int destRegsiter = moveOp.getToRegister(); ReferenceInstruction instr = (ReferenceInstruction) original; String methodDescriptor = ReferenceUtil.getReferenceString(instr.getReference()); BuilderInstruction replacementInstruction = null; if (methodDescriptor.equals(OBJECT_GET_CLASS_SIGNATURE)) { String smaliClassName = item.getType(); BuilderTypeReference classRef = manipulator.getDexBuilder().internTypeReference(smaliClassName); replacementInstruction = new BuilderInstruction21c(Opcode.CONST_CLASS, destRegsiter, classRef); } return replacementInstruction; }
@Override public ConstOp create(MethodLocation location, TIntObjectMap<MethodLocation> addressToLocation, VirtualMachine vm) { MethodLocation child = Utils.getNextLocation(location, addressToLocation); BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); int destRegister = ((OneRegisterInstruction) instruction).getRegisterA(); ConstantType constantType; Object literal; String opName = instruction.getOpcode().name; if (opName.matches("const-string(?:/jumbo)?")) { ReferenceInstruction instr = (ReferenceInstruction) location.getInstruction(); literal = ((StringReference) instr.getReference()).getString(); constantType = ConstantType.STRING; } else if (opName.endsWith("-class")) { // Don't lookup the class here. Defer to actual execution to handle any possible exceptions. ReferenceInstruction instr = (ReferenceInstruction) location.getInstruction(); Reference classRef = instr.getReference(); literal = ReferenceUtil.getReferenceString(classRef); constantType = ConstantType.CLASS; } else if (opName.contains("-wide")) { WideLiteralInstruction instr = (WideLiteralInstruction) location.getInstruction(); literal = instr.getWideLiteral(); constantType = ConstantType.WIDE; } else { NarrowLiteralInstruction instr = (NarrowLiteralInstruction) location.getInstruction(); literal = instr.getNarrowLiteral(); constantType = ConstantType.NARROW; } return new ConstOp(location, child, destRegister, constantType, literal, vm.getClassLoader(), vm.getExceptionFactory()); }
ex.addContext(String.format("opcode: %s", instructionToAnalyze.instruction.getOpcode().name)); ex.addContext(String.format("code address: %d", codeAddress)); ex.addContext(String.format("method: %s", ReferenceUtil.getReferenceString(method))); break;
private void testForExpectedInstruction(String register0, String expectedClassName) { ExecutionGraphManipulator manipulator = getOptimizedGraph(METHOD_NAME, 0, register0, "Ljava/lang/String;"); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(expectedClassName, actualClassName); } }
BuilderInstruction instruction = (BuilderInstruction) location.getInstruction(); Reference reference = ((ReferenceInstruction) instruction).getReference(); String typeReference = ReferenceUtil.getReferenceString(reference); int registerCount = ((VariableRegisterInstruction) instruction).getRegisterCount(); String opName = instruction.getOpcode().name;
@Test public void thisReferencedWithInvokeIsCorrectlyOptimizedAsConstClass() { String methodName = "invokeGetClassOnThis()V"; ExecutionGraphManipulator manipulator = getOptimizedGraph(vm, methodName, 1, new UninitializedInstance(thisReference), CLASS_NAME); assertEquals(BuilderInstruction21c.class, manipulator.getInstruction(ADDRESS).getClass()); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(CLASS_NAME, actualClassName); }
@Test public void thisReferencedWithInvokeRangeIsCorrectlyOptimizedAsConstClass() { String methodName = "invokeRangeGetClassOnThis()V"; ExecutionGraphManipulator manipulator = getOptimizedGraph(vm, methodName, 1, new UninitializedInstance(thisReference), CLASS_NAME); assertEquals(BuilderInstruction21c.class, manipulator.getInstruction(ADDRESS).getClass()); BuilderInstruction21c instruction = (BuilderInstruction21c) manipulator.getInstruction(ADDRESS); assertEquals(Opcode.CONST_CLASS, instruction.getOpcode()); assertEquals(0, instruction.getRegisterA()); String actualClassName = ReferenceUtil.getReferenceString(instruction.getReference()); assertEquals(CLASS_NAME, actualClassName); } }
@Nullable public static String getReferenceString(@Nonnull Reference reference) { return getReferenceString(reference, null); }
@Nullable public static String getReferenceString(@Nonnull Reference reference) { return getReferenceString(reference, null); }
} else { referenceWritable = indentingWriter -> { indentingWriter.write(ReferenceUtil.getReferenceString(reference, classContext)); }; Reference reference2 = dualReferenceInstruction.getReference2(); referenceWritable2 = indentingWriter -> { indentingWriter.write(ReferenceUtil.getReferenceString(reference2, classContext)); }; } catch (InvalidItemIndex ex) {
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { int startRegister = instruction.getStartRegister(); int endRegister = startRegister + instruction.getRegisterCount() - 1; String reference = ReferenceUtil.getReferenceString(instruction.getReference()); out.annotate(6, String.format("%s {%s .. %s}, %s", instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister), reference)); }
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { int startRegister = instruction.getStartRegister(); int endRegister = startRegister + instruction.getRegisterCount() - 1; String reference = ReferenceUtil.getReferenceString(instruction.getReference()); out.annotate(6, String.format("%s {%s .. %s}, %s", instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister), reference)); }
private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { int startRegister = instruction.getStartRegister(); int endRegister = startRegister + instruction.getRegisterCount() - 1; String reference = ReferenceUtil.getReferenceString(instruction.getReference()); out.annotate(6, String.format("%s {%s .. %s}, %s", instruction.getOpcode().name, formatRegister(startRegister), formatRegister(endRegister), reference)); }