cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0])); } catch (IOException e) { throw new RuntimeException(e);
@Nonnull public static ClassPath fromClassPath(Iterable<String> classPathDirs, Iterable<String> classPath, DexFile dexFile, int api) { ArrayList<DexFile> dexFiles = Lists.newArrayList(); for (String classPathEntry: classPath) { dexFiles.add(loadClassPathEntry(classPathDirs, classPathEntry, api)); } dexFiles.add(dexFile); return new ClassPath(dexFiles, api); }
oatVersion = ((OatDexFile)dexFile).getContainer().getOatVersion(); return new ClassPath(resolver.getResolvedClassProviders(), checkPackagePrivateAccess, oatVersion);
Iterable<? extends org.jf.dexlib2.iface.instruction.Instruction> deodex() { try { DexFileModule m = myClass.getContainer(); ClassPathResolver path = new ClassPathResolver(Collections.singletonList(m.getFile().getParent() + '/'), Collections.<String>emptyList(), m.getDexFile()); ClassPath cp = new ClassPath(path.getResolvedClassProviders(), false, m.getDexFile().getOpcodes().artVersion); MethodAnalyzer analyzer = new MethodAnalyzer(cp, eMethod, null, false); return analyzer.getInstructions(); } catch (Exception e) { assert false : e; return eMethod.getImplementation().getInstructions(); } }
Iterable<? extends org.jf.dexlib2.iface.instruction.Instruction> deodex() { try { DexFileModule m = myClass.getContainer(); ClassPathResolver path = new ClassPathResolver(Collections.singletonList(m.getFile().getParent() + '/'), Collections.<String>emptyList(), m.getDexFile()); ClassPath cp = new ClassPath(path.getResolvedClassProviders(), false, m.getDexFile().getOpcodes().artVersion); MethodAnalyzer analyzer = new MethodAnalyzer(cp, eMethod, null, false); return analyzer.getInstructions(); } catch (Exception e) { assert false : e; return eMethod.getImplementation().getInstructions(); } }
public void runTest(String test, boolean registerInfo, boolean isArt) throws IOException, URISyntaxException { String dexFilePath = String.format("%s%sclasses.dex", test, File.separatorChar); DexFile dexFile = DexFileFactory.loadDexFile(findResource(dexFilePath), Opcodes.getDefault()); BaksmaliOptions options = new BaksmaliOptions(); if (registerInfo) { options.registerInfo = BaksmaliOptions.ALL | BaksmaliOptions.FULLMERGE; if (isArt) { options.classPath = new ClassPath(new ArrayList<ClassProvider>(), true, 56); } else { options.classPath = new ClassPath(); } } options.implicitReferences = false; for (ClassDef classDef: dexFile.getClasses()) { StringWriter stringWriter = new StringWriter(); IndentingWriter writer = new IndentingWriter(stringWriter); ClassDefinition classDefinition = new ClassDefinition(options, classDef); classDefinition.writeTo(writer); writer.close(); String className = classDef.getType(); String smaliPath = String.format("%s%s%s.smali", test, File.separatorChar, className.substring(1, className.length() - 1)); String smaliContents = readResource(smaliPath); Assert.assertEquals(BaksmaliTestUtils.normalizeWhitespace(smaliContents), BaksmaliTestUtils.normalizeWhitespace((stringWriter.toString()))); } }
@Test public void testGetSuperclassChain_Unresolved() throws IOException { // Ltest/one; isn't defined ClassDef twoClassDef = TestUtils.makeClassDef("Ltest/two;", "Ltest/one;"); ClassDef threeClassDef = TestUtils.makeClassDef("Ltest/three;", "Ltest/two;"); ImmutableSet<ClassDef> classes = ImmutableSet.<ClassDef>of(twoClassDef, threeClassDef); ClassPath classPath = new ClassPath(new DexClassProvider(new ImmutableDexFile(Opcodes.getDefault(), classes))); TypeProto unknownClassProto = classPath.getUnknownClass(); TypeProto oneClassProto = classPath.getClass("Ltest/one;"); TypeProto twoClassProto = classPath.getClass("Ltest/two;"); TypeProto threeClassProto = classPath.getClass("Ltest/three;"); Assert.assertEquals( ImmutableList.<TypeProto>of(oneClassProto, unknownClassProto), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(twoClassProto))); Assert.assertEquals( ImmutableList.<TypeProto>of(twoClassProto, oneClassProto, unknownClassProto), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(threeClassProto))); } }
@Test public void testGetSuperclassChain() throws IOException { ClassDef objectClassDef = TestUtils.makeClassDef("Ljava/lang/Object;", null); ClassDef oneClassDef = TestUtils.makeClassDef("Ltest/one;", "Ljava/lang/Object;"); ClassDef twoClassDef = TestUtils.makeClassDef("Ltest/two;", "Ltest/one;"); ClassDef threeClassDef = TestUtils.makeClassDef("Ltest/three;", "Ltest/two;"); ImmutableSet<ClassDef> classes = ImmutableSet.<ClassDef>of( objectClassDef, oneClassDef, twoClassDef, threeClassDef); ClassPath classPath = new ClassPath(new DexClassProvider(new ImmutableDexFile(Opcodes.getDefault(), classes))); TypeProto objectClassProto = classPath.getClass("Ljava/lang/Object;"); TypeProto oneClassProto = classPath.getClass("Ltest/one;"); TypeProto twoClassProto = classPath.getClass("Ltest/two;"); TypeProto threeClassProto = classPath.getClass("Ltest/three;"); Assert.assertEquals( ImmutableList.<TypeProto>of(), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(objectClassProto))); Assert.assertEquals( ImmutableList.<TypeProto>of(objectClassProto), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(oneClassProto))); Assert.assertEquals( ImmutableList.<TypeProto>of(oneClassProto, objectClassProto), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(twoClassProto))); Assert.assertEquals( ImmutableList.<TypeProto>of(twoClassProto, oneClassProto, objectClassProto), ImmutableList.copyOf(TypeProtoUtils.getSuperclassChain(threeClassProto))); }
@Test public void testCustomMethodInlineTable_Virtual() throws IOException { List<ImmutableInstruction> instructions = Lists.newArrayList( new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), new ImmutableInstruction10x(Opcode.RETURN_VOID)); ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PUBLIC.getValue(), null, methodImpl); ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, null, null, ImmutableList.of(method)); DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef)); ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile); ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART); InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false); Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); Assert.assertEquals(Opcode.INVOKE_VIRTUAL, deodexedInstruction.getOpcode()); MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); Assert.assertEquals(method, methodReference); }
@Test public void testCustomMethodInlineTable_Static() throws IOException { List<ImmutableInstruction> instructions = Lists.newArrayList( new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), new ImmutableInstruction10x(Opcode.RETURN_VOID)); ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.STATIC.getValue(), null, methodImpl); ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, null, ImmutableList.of(method), null); DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef)); ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile); ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART); InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false); Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); Assert.assertEquals(Opcode.INVOKE_STATIC, deodexedInstruction.getOpcode()); MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); Assert.assertEquals(method, methodReference); }
@Test public void testCustomMethodInlineTable_Direct() throws IOException { List<ImmutableInstruction> instructions = Lists.newArrayList( new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), new ImmutableInstruction10x(Opcode.RETURN_VOID)); ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null); ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PRIVATE.getValue(), null, methodImpl); ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, null, ImmutableList.of(method), null); DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef)); ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.<String>of(), dexFile); ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART); InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V"); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false); Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0); Assert.assertEquals(Opcode.INVOKE_DIRECT, deodexedInstruction.getOpcode()); MethodReference methodReference = (MethodReference)((Instruction35c)deodexedInstruction).getReference(); Assert.assertEquals(method, methodReference); } }
@Test public void testInstanceOfNarrowingEqz_art() throws IOException { MethodImplementationBuilder builder = new MethodImplementationBuilder(2); builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;"))); builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of"))); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); builder.addLabel("not_instance_of"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation methodImplementation = builder.getMethodImplementation(); Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation); ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method)); DexFile dexFile = new ImmutableDexFile(forArtVersion(56), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), true, 56); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false); List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions(); Assert.assertEquals("Lmain;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType()); }
@Test public void testOldOrder() { DexFile dexFile = getInputDexFile("FieldGapOrder", new BaksmaliOptions()); Assert.assertEquals(3, dexFile.getClasses().size()); ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), false, 66); ClassProto classProto = (ClassProto)classPath.getClass("LGapOrder;"); Assert.assertEquals("r1", classProto.getFieldByOffset(12).getName()); Assert.assertEquals("r2", classProto.getFieldByOffset(16).getName()); Assert.assertEquals("d", classProto.getFieldByOffset(24).getName()); Assert.assertEquals("s", classProto.getFieldByOffset(36).getName()); Assert.assertEquals("i", classProto.getFieldByOffset(32).getName()); }
@Test public void testInstanceOfNarrowingNez_art() throws IOException { MethodImplementationBuilder builder = new MethodImplementationBuilder(2); builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;"))); builder.addInstruction(new BuilderInstruction21t(Opcode.IF_NEZ, 0, builder.getLabel("instance_of"))); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); builder.addLabel("instance_of"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation methodImplementation = builder.getMethodImplementation(); Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation); ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method)); DexFile dexFile = new ImmutableDexFile(forArtVersion(56), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), true, 56); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false); List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions(); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Lmain;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType()); }
@Test public void testNewOrder() { DexFile dexFile = getInputDexFile("FieldGapOrder", new BaksmaliOptions()); Assert.assertEquals(3, dexFile.getClasses().size()); ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), false, 67); ClassProto classProto = (ClassProto)classPath.getClass("LGapOrder;"); Assert.assertEquals("s", classProto.getFieldByOffset(10).getName()); Assert.assertEquals("r1", classProto.getFieldByOffset(12).getName()); Assert.assertEquals("r2", classProto.getFieldByOffset(16).getName()); Assert.assertEquals("i", classProto.getFieldByOffset(20).getName()); Assert.assertEquals("d", classProto.getFieldByOffset(24).getName()); } }
@Test public void testInstanceOfNarrowingAfterMove_art() throws IOException { MethodImplementationBuilder builder = new MethodImplementationBuilder(3); builder.addInstruction(new BuilderInstruction12x(Opcode.MOVE_OBJECT, 1, 2)); builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;"))); builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of"))); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); builder.addLabel("not_instance_of"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation methodImplementation = builder.getMethodImplementation(); Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation); ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method)); DexFile dexFile = new ImmutableDexFile(forArtVersion(56), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), true, 56); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false); List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions(); Assert.assertEquals("Lmain;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Lmain;", analyzedInstructions.get(3).getPreInstructionRegisterType(2).type.getType()); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(4).getPreInstructionRegisterType(2).type.getType()); }
@Test public void testInstanceOfNarrowingEqz_dalvik() throws IOException { MethodImplementationBuilder builder = new MethodImplementationBuilder(2); builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;"))); builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of"))); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); builder.addLabel("not_instance_of"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation methodImplementation = builder.getMethodImplementation(); Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation); ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method)); DexFile dexFile = new ImmutableDexFile(Opcodes.forApi(19), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(new DexClassProvider(dexFile)); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false); List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions(); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType()); }
@Test public void testInstanceOfNarrowingNez_dalvik() throws IOException { MethodImplementationBuilder builder = new MethodImplementationBuilder(2); builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;"))); builder.addInstruction(new BuilderInstruction21t(Opcode.IF_NEZ, 0, builder.getLabel("instance_of"))); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); builder.addLabel("instance_of"); builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID)); MethodImplementation methodImplementation = builder.getMethodImplementation(); Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, methodImplementation); ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method)); DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(new DexClassProvider(dexFile)); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false); List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions(); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType()); Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType()); }
DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), Collections.singletonList(classDef)); ClassPath classPath = new ClassPath(new DexClassProvider(dexFile)); MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false);