/** * Inserts hooks into a single code item. * * @param hooks * @param classData * @param code */ private void hookReferences(HookMap hooks, ClassDataItem classData, CodeItem code) { if (code == null) { return; } Instruction[] instructions = code.getInstructions(); for (int index = 0; index < instructions.length; index++) { Instruction i = instructions[index]; if (i instanceof InstructionWithReference) { InstructionWithReference inst = (InstructionWithReference) i; HookItem oldTarget = HookItem.getInstance(inst.getReferencedItem()); if (!hooks.containsKey(oldTarget)) { continue; } Item newTarget = hooks.get(oldTarget); inst.referencedItem = newTarget; if (newTarget instanceof MethodIdItem) { // Need to update the invoke type if it changed updateInvokeType(inst, (MethodIdItem) newTarget); } } } }
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); }