diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 3858fa0a..d90226af 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -1095,6 +1095,9 @@ public class MethodAnalyzer { case SPUT_OBJECT_VOLATILE: analyzePutGetVolatile(analyzedInstruction); return true; + case INVOKE_OBJECT_INIT_JUMBO: + analyzeInvokeObjectInitJumbo(analyzedInstruction); + return true; default: assert false; return true; @@ -1589,6 +1592,7 @@ public class MethodAnalyzer { case IPUT_OBJECT_VOLATILE: case SGET_OBJECT_VOLATILE: case SPUT_OBJECT_VOLATILE: + case INVOKE_OBJECT_INIT_JUMBO: //TODO: throw validation exception? default: assert false; @@ -3639,6 +3643,17 @@ public class MethodAnalyzer { return true; } + private void analyzeInvokeObjectInitJumbo(AnalyzedInstruction analyzedInstruction) { + Instruction5rc instruction = (Instruction5rc)analyzedInstruction.instruction; + + Instruction5rc deodexedInstruction = new Instruction5rc(Opcode.INVOKE_DIRECT_JUMBO, + instruction.getRegCount(), instruction.getStartRegister(), instruction.getReferencedItem()); + + analyzedInstruction.setDeodexedInstruction(deodexedInstruction); + + analyzeInstruction(analyzedInstruction); + } + private static boolean checkArrayFieldAssignment(RegisterType.Category arrayFieldCategory, RegisterType.Category instructionCategory) { if (arrayFieldCategory == instructionCategory) { diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java index d12cf492..7c79e252 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction5rc.java @@ -111,7 +111,8 @@ public class Instruction5rc extends InstructionWithJumboReference implements Reg if (type.charAt(1) == 'J' || type.charAt(1) == 'D') { throw new RuntimeException("The type cannot be an array of longs or doubles"); } - } else if (opcode.value >= INVOKE_VIRTUAL_JUMBO.value && opcode.value <= INVOKE_INTERFACE_JUMBO.value) { + } else if (opcode.value >= INVOKE_VIRTUAL_JUMBO.value && opcode.value <= INVOKE_INTERFACE_JUMBO.value || + opcode == INVOKE_OBJECT_INIT_JUMBO) { //check data for invoke-*/range opcodes MethodIdItem methodIdItem = (MethodIdItem) item; int parameterRegisterCount = methodIdItem.getPrototype().getParameterRegisterCount(); 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 3fc0ecd5..bf70e1f5 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -322,7 +322,9 @@ public enum Opcode INVOKE_SUPER_JUMBO((short)0xff23, "invoke-super/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_DIRECT_JUMBO((short)0xff24, "invoke-direct/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_STATIC_JUMBO((short)0xff25, "invoke-static/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_INTERFACE_JUMBO((short)0xff26, "invoke-interface/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT); + INVOKE_INTERFACE_JUMBO((short)0xff26, "invoke-interface/jumbo", ReferenceType.method, Format.Format5rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + + INVOKE_OBJECT_INIT_JUMBO((short)0xfff2, "invoke-object-init/jumbo", ReferenceType.method, Format.Format5rc, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT); private static Opcode[] opcodesByValue; private static Opcode[] expandedOpcodesByValue; @@ -432,7 +434,7 @@ public enum Opcode SGET_CHAR_JUMBO, SGET_SHORT_JUMBO, SPUT_JUMBO, SPUT_WIDE_JUMBO, SPUT_OBJECT_JUMBO, SPUT_BOOLEAN_JUMBO, SPUT_BYTE_JUMBO, SPUT_CHAR_JUMBO, SPUT_SHORT_JUMBO, INVOKE_VIRTUAL_JUMBO, INVOKE_SUPER_JUMBO, INVOKE_DIRECT_JUMBO, INVOKE_STATIC_JUMBO, INVOKE_INTERFACE_JUMBO, - INVOKE_OBJECT_INIT_RANGE); + INVOKE_OBJECT_INIT_RANGE, INVOKE_OBJECT_INIT_JUMBO); addOpcodes(INVOKE_DIRECT_EMPTY); } } diff --git a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g index 84cfb65e..882744b5 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g @@ -747,6 +747,9 @@ INSTRUCTION_FORMAT5rc_METHOD | 'invoke-static/jumbo' | 'invoke-interface/jumbo'; +INSTRUCTION_FORMAT5rc_METHOD_ODEX + : 'invoke-object-init/jumbo'; + INSTRUCTION_FORMAT5rc_TYPE : 'filled-new-array/jumbo'; diff --git a/smali/src/main/antlr3/org/jf/smali/smaliParser.g b/smali/src/main/antlr3/org/jf/smali/smaliParser.g index 3fb50d0f..acf6064c 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliParser.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliParser.g @@ -866,9 +866,14 @@ instruction returns [int size] | //e.g. iput-object/jumbo v1, v0 Lorg/jf/HelloWorld2/HelloWorld2;->helloWorld:Ljava/lang/String; INSTRUCTION_FORMAT52c_FIELD REGISTER COMMA REGISTER COMMA fully_qualified_field {$size = Format.Format52c.size;} -> ^(I_STATEMENT_FORMAT52c_FIELD[$start, "I_STATEMENT_FORMAT52c_FIELD"] INSTRUCTION_FORMAT52c_FIELD REGISTER REGISTER fully_qualified_field) - | //e.g. invoke-virtual/jumbo {v25..v26}, java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder; + | //e.g. invoke-virtual/jumbo {v25..v26}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; INSTRUCTION_FORMAT5rc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;} -> ^(I_STATEMENT_FORMAT5rc_METHOD[$start, "I_STATEMENT_FORMAT5rc_METHOD"] INSTRUCTION_FORMAT5rc_METHOD register_range fully_qualified_method) + | //e.g. invoke-object-init/jumbo {v25}, Ljava/lang/Object->()V + INSTRUCTION_FORMAT5rc_METHOD_ODEX OPEN_BRACE register_range CLOSE_BRACE COMMA fully_qualified_method {$size = Format.Format5rc.size;} + { + throwOdexedInstructionException(input, $INSTRUCTION_FORMAT5rc_METHOD_ODEX.text); + } | //e.g. filled-new-array/jumbo {v0..v6}, I INSTRUCTION_FORMAT5rc_TYPE OPEN_BRACE register_range CLOSE_BRACE COMMA nonvoid_type_descriptor {$size = Format.Format5rc.size;} -> ^(I_STATEMENT_FORMAT5rc_TYPE[$start, "I_STATEMENT_FORMAT5rc_TYPE"] INSTRUCTION_FORMAT5rc_TYPE register_range nonvoid_type_descriptor) diff --git a/smali/src/main/jflex/smaliLexer.flex b/smali/src/main/jflex/smaliLexer.flex index 8ceec774..9713916b 100644 --- a/smali/src/main/jflex/smaliLexer.flex +++ b/smali/src/main/jflex/smaliLexer.flex @@ -599,6 +599,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} return newToken(INSTRUCTION_FORMAT5rc_METHOD); } + "invoke-object-init/jumbo" { + return newToken(INSTRUCTION_FORMAT5rc_METHOD_ODEX); + } + "filled-new-array/jumbo" { return newToken(INSTRUCTION_FORMAT5rc_TYPE); } diff --git a/smali/src/test/resources/LexerTest/InstructionTest.smali b/smali/src/test/resources/LexerTest/InstructionTest.smali index 7a85dce4..47cc6d65 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.smali +++ b/smali/src/test/resources/LexerTest/InstructionTest.smali @@ -264,4 +264,5 @@ invoke-super/jumbo invoke-direct/jumbo invoke-static/jumbo invoke-interface/jumbo -filled-new-array/jumbo \ No newline at end of file +filled-new-array/jumbo +invoke-object-init/jumbo \ No newline at end of file diff --git a/smali/src/test/resources/LexerTest/InstructionTest.tokens b/smali/src/test/resources/LexerTest/InstructionTest.tokens index fb0014c3..1de5aadc 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -264,4 +264,5 @@ INSTRUCTION_FORMAT5rc_METHOD("invoke-super/jumbo") INSTRUCTION_FORMAT5rc_METHOD("invoke-direct/jumbo") INSTRUCTION_FORMAT5rc_METHOD("invoke-static/jumbo") INSTRUCTION_FORMAT5rc_METHOD("invoke-interface/jumbo") -INSTRUCTION_FORMAT5rc_TYPE("filled-new-array/jumbo") \ No newline at end of file +INSTRUCTION_FORMAT5rc_TYPE("filled-new-array/jumbo") +INSTRUCTION_FORMAT5rc_METHOD_ODEX("invoke-object-init/jumbo") \ No newline at end of file