private void analyzeConstString(@Nonnull AnalyzedInstruction analyzedInstruction) { TypeProto stringClass = classPath.getClass("Ljava/lang/String;"); RegisterType stringType = RegisterType.getRegisterType(RegisterType.REFERENCE, stringClass); setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, stringType); }
ClassProto superclassProto = (ClassProto) classPath.getClass(superclass); for (String superclassInterface: superclassProto.getInterfaces().keySet()) { interfaces.put(superclassInterface, null); for (String interfaceType: getClassDef().getInterfaces()) { if (!interfaces.containsKey(interfaceType)) { ClassProto interfaceProto = (ClassProto)classPath.getClass(interfaceType); try { for (Entry<String, ClassDef> entry: interfaceProto.getInterfaces().entrySet()) { ClassDef interfaceDef = classPath.getClassDef(interfaceType); interfaces.put(interfaceType, interfaceDef); } catch (UnresolvedClassException ex) {
return classPath.getUnknownClass(); return classPath.getUnknownClass();
/** * Creates a new ClassPath instance that can load classes from the given providers * * @param classProviders An iterable of ClassProviders. When loading a class, these providers will be searched in * order * @param checkPackagePrivateAccess Whether checkPackagePrivateAccess is needed, enabled for ONLY early API 17 by * default * @param oatVersion The applicable oat version, or NOT_ART */ public ClassPath(@Nonnull Iterable<? extends ClassProvider> classProviders, boolean checkPackagePrivateAccess, int oatVersion) { // add fallbacks for certain special classes that must be present unknownClass = new UnknownClassProto(this); loadedClasses.put(unknownClass.getType(), unknownClass); this.checkPackagePrivateAccess = checkPackagePrivateAccess; this.oatVersion = oatVersion; loadPrimitiveType("Z"); loadPrimitiveType("B"); loadPrimitiveType("S"); loadPrimitiveType("C"); loadPrimitiveType("I"); loadPrimitiveType("J"); loadPrimitiveType("F"); loadPrimitiveType("D"); loadPrimitiveType("L"); this.classProviders = Lists.newArrayList(classProviders); this.classProviders.add(getBasicClasses()); }
superclassType = getSuperclass(); } catch (UnresolvedClassException ex) { vtable.addAll(((ClassProto)classPath.getClass("Ljava/lang/Object;")).getVtable()); vtableFullyResolved = false; return vtable; ClassProto superclass = (ClassProto) classPath.getClass(superclassType); vtable.addAll(superclass.getVtable()); ClassDef interfaceDef = classPath.getClassDef(interfaceType); Method candidate = vtable.get(j); if (MethodUtil.methodSignaturesMatch(candidate, interfaceMethod)) { if (!classPath.shouldCheckPackagePrivateAccess() || AnalyzedMethodUtil.canAccess(ClassProto.this, candidate, true, false, false)) { if (interfaceMethodOverrides(interfaceMethod, candidate)) { ClassProto existingInterface = (ClassProto)classPath.getClass( defaultMethods.get(defaultMethodIndex).getDefiningClass()); if (!existingInterface.implementsInterface(interfaceMethod.getDefiningClass())) { if (!AccessFlags.ABSTRACT.isSet(interfaceMethod.getAccessFlags())) { ClassProto existingInterface = (ClassProto)classPath.getClass( mirandaMethods.get(mirandaMethodIndex).getDefiningClass()); if (!existingInterface.implementsInterface(interfaceMethod.getDefiningClass())) {
cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0])); } catch (IOException e) { throw new RuntimeException(e);
@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 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))); } }
@Nullable public static TypeProto getSuperclassAsTypeProto(@Nonnull TypeProto type) { try { String next = type.getSuperclass(); if (next != null) { return type.getClassPath().getClass(next); } else { return null; } } catch (UnresolvedClassException ex) { return type.getClassPath().getUnknownClass(); } }
assert objectRegisterTypeProto != null; TypeProto classTypeProto = classPath.getClass(objectRegisterTypeProto.getType()); FieldReference resolvedField = classTypeProto.getFieldByOffset(fieldOffset); ClassDef thisClass = classPath.getClassDef(method.getDefiningClass()); if (!TypeUtils.canAccessClass(thisClass.getType(), classPath.getClassDef(resolvedField.getDefiningClass()))) { ClassDef fieldClass = classPath.getClassDef(objectRegisterTypeProto.getType()); while (!TypeUtils.canAccessClass(thisClass.getType(), fieldClass)) { String superclass = fieldClass.getSuperclass(); fieldClass = classPath.getClassDef(superclass); FieldReference newResolvedField = classPath.getClass(fieldClass.getType()).getFieldByOffset(fieldOffset); if (newResolvedField == null) { throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, instruction.getOpcode());
DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel); Iterable<String> bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"); ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel); FileOutputStream outStream = new FileOutputStream(outFile); ClassProto classProto = (ClassProto) classPath.getClass(classDef); List<Method> methods = classProto.getVtable(); String className = "Class " + classDef.getType() + " extends " + classDef.getSuperclass() + " : " + methods.size() + " methods\n";
@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); }
@Override public ClassDef get() { return classPath.getClassDef(type); } });
options.classPath = ClassPath.fromClassPath(options.bootClassPathDirs, Iterables.concat(options.bootClassPathEntries, extraClassPathEntries), dexFile, options.apiLevel);
oatVersion = ((OatDexFile)dexFile).getContainer().getOatVersion(); return new ClassPath(resolver.getResolvedClassProviders(), checkPackagePrivateAccess, oatVersion);
@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()); }
@Nullable public static TypeProto getSuperclassAsTypeProto(@Nonnull TypeProto type) { try { String next = type.getSuperclass(); if (next != null) { return type.getClassPath().getClass(next); } else { return null; } } catch (UnresolvedClassException ex) { return type.getClassPath().getUnknownClass(); } }
assert objectRegisterTypeProto != null; TypeProto classTypeProto = classPath.getClass(objectRegisterTypeProto.getType()); FieldReference resolvedField = classTypeProto.getFieldByOffset(fieldOffset); ClassDef thisClass = classPath.getClassDef(method.getDefiningClass()); if (!TypeUtils.canAccessClass(thisClass.getType(), classPath.getClassDef(resolvedField.getDefiningClass()))) { ClassDef fieldClass = classPath.getClassDef(objectRegisterTypeProto.getType()); while (!TypeUtils.canAccessClass(thisClass.getType(), fieldClass)) { String superclass = fieldClass.getSuperclass(); fieldClass = classPath.getClassDef(superclass); FieldReference newResolvedField = classPath.getClass(fieldClass.getType()).getFieldByOffset(fieldOffset); if (newResolvedField == null) { throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode( fieldType, instruction.getOpcode());
superclassType = getSuperclass(); } catch (UnresolvedClassException ex) { vtable.addAll(((ClassProto)classPath.getClass("Ljava/lang/Object;")).getVtable()); vtableFullyResolved = false; return vtable; ClassProto superclass = (ClassProto) classPath.getClass(superclassType); vtable.addAll(superclass.getVtable()); ClassDef interfaceDef = classPath.getClassDef(interfaceType); Method candidate = vtable.get(j); if (MethodUtil.methodSignaturesMatch(candidate, interfaceMethod)) { if (!classPath.shouldCheckPackagePrivateAccess() || AnalyzedMethodUtil.canAccess(ClassProto.this, candidate, true, false, false)) { if (interfaceMethodOverrides(interfaceMethod, candidate)) { ClassProto existingInterface = (ClassProto)classPath.getClass( defaultMethods.get(defaultMethodIndex).getDefiningClass()); if (!existingInterface.implementsInterface(interfaceMethod.getDefiningClass())) { if (!AccessFlags.ABSTRACT.isSet(interfaceMethod.getAccessFlags())) { ClassProto existingInterface = (ClassProto)classPath.getClass( mirandaMethods.get(mirandaMethodIndex).getDefiningClass()); if (!existingInterface.implementsInterface(interfaceMethod.getDefiningClass())) {
DexBackedDexFile dexFile = DexFileFactory.loadDexFile(dexFileFile, apiLevel); Iterable<String> bootClassPaths = Splitter.on(":").split("core.jar:ext.jar:framework.jar:android.policy.jar:services.jar"); ClassPath classPath = ClassPath.fromClassPath(bootClassPathDirs, bootClassPaths, dexFile, apiLevel); FileOutputStream outStream = new FileOutputStream(outFile); ClassProto classProto = (ClassProto) classPath.getClass(classDef); SparseArray<FieldReference> fields = classProto.getInstanceFields(); String className = "Class " + classDef.getType() + " : " + fields.size() + " instance fields\n";