diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedNullReferenceMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedNullReferenceMethodItem.java index 33545a1b..a8328977 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedNullReferenceMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/UnresolvedNullReferenceMethodItem.java @@ -53,6 +53,7 @@ public class UnresolvedNullReferenceMethodItem extends InstructionFormatMethodIt template.setAttribute("Register", formatRegister(instruction.ObjectRegisterNum)); switch (instruction.OriginalInstruction.opcode) { + case EXECUTE_INLINE_RANGE: case INVOKE_VIRTUAL_QUICK_RANGE: case INVOKE_SUPER_QUICK_RANGE: template.setAttribute("UseInvokeRange", 1); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java index 3eb2bc78..0bd92f62 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -255,6 +255,7 @@ public enum Opcode INVOKE_EXECUTE_INLINE((byte)0xee, "execute-inline", ReferenceType.none, Format.Format35ms, true), + EXECUTE_INLINE_RANGE((byte)0xef, "execute-inline/range", ReferenceType.none, Format.Format3rms, true), INVOKE_DIRECT_EMPTY((byte)0xf0, "invoke-direct-empty", ReferenceType.method, Format.Format35s, true), IGET_QUICK((byte)0xf2, "iget-quick", ReferenceType.none, Format.Format22cs, true), IGET_WIDE_QUICK((byte)0xf3, "iget-wide-quick", ReferenceType.none, Format.Format22cs, true), diff --git a/dexlib/src/main/java/org/jf/dexlib/Util/DeodexUtil.java b/dexlib/src/main/java/org/jf/dexlib/Util/DeodexUtil.java index 4fae6681..2f436f3e 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Util/DeodexUtil.java +++ b/dexlib/src/main/java/org/jf/dexlib/Util/DeodexUtil.java @@ -119,7 +119,8 @@ public class DeodexUtil { instructionThrowTable.set(Opcode.DIV_INT_LIT8.value & 0xFF); instructionThrowTable.set(Opcode.REM_INT_LIT8.value & 0xFF); instructionThrowTable.set(Opcode.THROW.value & 0xFF); - instructionThrowTable.set(Opcode.INVOKE_EXECUTE_INLINE.value & 0xFF); + instructionThrowTable.set(Opcode.INVOKE_EXECUTE_INLINE.value & 0xFF); + instructionThrowTable.set(Opcode.EXECUTE_INLINE_RANGE.value & 0xFF); instructionThrowTable.set(Opcode.IGET_QUICK.value & 0xFF); instructionThrowTable.set(Opcode.IGET_WIDE_QUICK.value & 0xFF); instructionThrowTable.set(Opcode.IGET_OBJECT_QUICK.value & 0xFF); @@ -275,6 +276,42 @@ public class DeodexUtil { return true; } + case EXECUTE_INLINE_RANGE: + { + int inlineMethodIndex = ((Instruction3rms)i.instruction).getMethodIndex(); + Deodexerant.InlineMethod inlineMethod = + deodexerant.lookupInlineMethod(inlineMethodIndex); + if (inlineMethod == null) { + throw new RuntimeException("Could not find the inline method with index " + inlineMethodIndex); + } + assert inlineMethod != null; + assert inlineMethod.getMethodIdItem() != null; + + Opcode opcode = null; + switch (inlineMethod.getMethodType()) { + case Direct: + opcode = Opcode.INVOKE_DIRECT_RANGE; + break; + case Static: + opcode = Opcode.INVOKE_STATIC_RANGE; + break; + case Virtual: + opcode = Opcode.INVOKE_VIRTUAL_RANGE; + break; + } + + i.fixedInstruction = new Instruction3rmsf(opcode, (Instruction3rms)i.instruction, + inlineMethod.getMethodIdItem()); + + insn nextInstruction = i.getInstructionAtOffset(i.offset + i.instruction.getSize(i.offset*2)/2); + assert nextInstruction != null; + if (nextInstruction.instruction.opcode == Opcode.MOVE_RESULT_OBJECT) { + nextInstruction.registerReferenceType = + inlineMethod.getMethodIdItem().getPrototype().getReturnType().getTypeDescriptor(); + } + + return true; + } case INVOKE_DIRECT_EMPTY: { i.fixedInstruction = new Instruction35sf((Instruction35s)i.instruction); @@ -897,6 +934,8 @@ public class DeodexUtil { this.insnsMap = insnsMap; if (instruction.opcode.odexOnly) { + //we don't need INVOKE_EXECUTE_INLINE or EXECUTE_INLINE_RANGE here, because we don't need to know + //the type of the object register in order to resolve which method is being called switch (instruction.opcode) { case IGET_QUICK: case IGET_WIDE_QUICK: