public void hookSuperclass(HookMap hooks, ClassDefItem classDef) { HookItem oldTarget = HookItem.getInstance(classDef.getSuperclass()); if (oldTarget == null) { return; } if (!hooks.containsKey(oldTarget)) { return; } TypeIdItem newTarget = (TypeIdItem) hooks.get(oldTarget); assert (newTarget != null); if (newTarget == classDef.getClassType()) { return; } classDef.setSuperclass(newTarget); HookClass classType = new HookClass(classDef.getClassType()); if (hooks.mIgnoreMethods.contains(classType)) { return; } if (hooks.mDead.isEmpty()) { return; } // get rid of virtual methods so the hooked class method is called instead String className = newTarget.getTypeDescriptor(); List<EncodedMethod> newDirects = new LinkedList<EncodedMethod>(); List<EncodedMethod> newVirtuals = new LinkedList<EncodedMethod>(); ClassDataItem classData = classDef.getClassData(); for (EncodedMethod encodedMethod : classData.getDirectMethods()) { newDirects.add(encodedMethod); } for (EncodedMethod encodedMethod : classData.getVirtualMethods()) { HookMethod method = new HookMethod(encodedMethod.method); method.mClasspath = className; if (!hooks.mDead.contains(method)) { newVirtuals.add(encodedMethod); } } classData.update(newDirects, newVirtuals); }
/** * Insert hooks into all code in the wrapped DexFile. * * @param hooks Description of what references to hook, and with what. */ public void hookReferences(HookMap hooks) { for (ClassDataItem classData : mDexFile.ClassDataSection.getItems()) { for (EncodedMethod method : classData.getDirectMethods()) { CodeItem code = method.codeItem; hookReferences(hooks, classData, code); } for (EncodedMethod method : classData.getVirtualMethods()) { CodeItem code = method.codeItem; hookReferences(hooks, classData, code); } } }
private void initClassMaps() { mClasses = new HashMap<HookClass, TypeIdItem>(); mClassMethods = new HashMap<HookClass, HashSet<EncodedMethod>>(); mSubclasses = new HashMap<String, Set<String>>(); for (ClassDefItem item : mDexFile.ClassDefsSection.getItems()) { TypeIdItem classType = item.getClassType(); HookClass classHook = new HookClass(classType); mClasses.put(classHook, classType); String superclassType = item.getSuperclass().getTypeDescriptor(); Set<String> subclassSet = mSubclasses.get(superclassType); if (subclassSet == null) { subclassSet = new TreeSet<String>(); mSubclasses.put(superclassType, subclassSet); } subclassSet.add(classType.getTypeDescriptor()); ClassDataItem classData = item.getClassData(); if (classData == null) { continue; } HashSet<EncodedMethod> classMethods = new HashSet<EncodedMethod>(); for (EncodedMethod method : classData.getDirectMethods()) { classMethods.add(method); } for (EncodedMethod method : classData.getVirtualMethods()) { classMethods.add(method); } mClassMethods.put(classHook, classMethods); } }
/** * Insert hooks into the specified CodeItems. * * @param hooks Description of what references to hook, and with what. * @param codeItems Collection containing all CodeItem objects where hooks should be placed. */ public void hookReferences(HookMap hooks, Collection<Item> codeItems) { for (ClassDataItem classData : mDexFile.ClassDataSection.getItems()) { for (EncodedMethod method : classData.getDirectMethods()) { CodeItem code = method.codeItem; if (!codeItems.contains(code)) { continue; } hookReferences(hooks, classData, code); } for (EncodedMethod method : classData.getVirtualMethods()) { CodeItem code = method.codeItem; if (!codeItems.contains(code)) { continue; } hookReferences(hooks, classData, code); } } }