diff options
14 files changed, 273 insertions, 3 deletions
diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java index a39ded32..a3528824 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/Format/InstructionMethodItem.java @@ -136,6 +136,7 @@ public class InstructionMethodItem<T extends Instruction> extends MethodItem { writeLiteral(writer); return true; case Format22c: + case Format52c: writeOpcode(writer); writer.write(' '); writeFirstRegister(writer); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java index 198dc263..60a88eb7 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Format.java @@ -63,6 +63,7 @@ public enum Format { Format3rms(Instruction3rms.Factory, 6), Format41c(Instruction41c.Factory, 8), Format51l(Instruction51l.Factory, 10), + Format52c(Instruction52c.Factory, 10), ArrayData(null, -1, true), PackedSwitchData(null, -1, true), SparseSwitchData(null, -1, true), diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java index 46b2c5a3..3ffb71c8 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction22c.java @@ -62,6 +62,10 @@ public class Instruction22c extends InstructionWithReference implements TwoRegis } protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { + if(getReferencedItem().getIndex() > 0xFFFF) { + throw new RuntimeException(String.format("%s index is too large. Use the %s/jumbo instruction instead.", opcode.referenceType.name(), opcode.name)); + } + out.writeByte(opcode.value); out.writeByte((regB << 4) | regA); out.writeShort(getReferencedItem().getIndex()); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java new file mode 100644 index 00000000..0d7f3f55 --- /dev/null +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Format/Instruction52c.java @@ -0,0 +1,94 @@ +/* + * Copyright 2011, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Code.Format; + +import org.jf.dexlib.Code.Instruction; +import org.jf.dexlib.Code.Opcode; +import org.jf.dexlib.Code.TwoRegisterInstruction; +import org.jf.dexlib.DexFile; +import org.jf.dexlib.Item; +import org.jf.dexlib.Util.AnnotatedOutput; +import org.jf.dexlib.Util.NumberUtils; + +public class Instruction52c extends InstructionWithJumboReference implements TwoRegisterInstruction { + public static final InstructionFactory Factory = new Factory(); + private short regA; + private short regB; + + public Instruction52c(Opcode opcode, int regA, int regB, Item referencedItem) { + super(opcode, referencedItem); + + if (regA >= 1 << 16) { + throw new RuntimeException("The register number must be less than v65536"); + } + + if (regB >= 1 << 16) { + throw new RuntimeException("The register number must be less than v65536"); + } + + this.regA = (short)regA; + this.regB = (short)regB; + } + + private Instruction52c(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + super(dexFile, opcode, buffer, bufferIndex); + + this.regA = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 6); + this.regB = (short)NumberUtils.decodeUnsignedShort(buffer, bufferIndex + 8); + } + + protected void writeInstruction(AnnotatedOutput out, int currentCodeAddress) { + out.writeByte(0xFF); + out.writeByte(opcode.value); + out.writeInt(getReferencedItem().getIndex()); + out.writeShort(getRegisterA()); + out.writeShort(getRegisterB()); + } + + public Format getFormat() { + return Format.Format52c; + } + + public int getRegisterA() { + return regA & 0xFFFF; + } + + public int getRegisterB() { + return regB & 0xFFFF; + } + + private static class Factory implements InstructionFactory { + public Instruction makeInstruction(DexFile dexFile, Opcode opcode, byte[] buffer, int bufferIndex) { + return new Instruction52c(dexFile, opcode, buffer, bufferIndex); + } + } +} 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 1a884a1a..5679feb6 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Opcode.java @@ -284,7 +284,9 @@ public enum Opcode CONST_CLASS_JUMBO((short)0xff00, "const-class/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), CHECK_CAST_JUMBO((short)0xff01, "check-cast/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + INSTANCE_OF_JUMBO((short)0xff02, "instance-of/jumbo", ReferenceType.type, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), NEW_INSTANCE_JUMBO((short)0xff03, "new-instance/jumbo", ReferenceType.type, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + NEW_ARRAY_JUMBO((short)0xff04, "new-array/jumbo", ReferenceType.type, Format.Format52c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), SGET_JUMBO((short)0xff14, "sget/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), SGET_WIDE_JUMBO((short)0xff15, "sget-wide/jumbo", ReferenceType.field, Format.Format41c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.SETS_WIDE_REGISTER), diff --git a/smali-integration-tests/src/test/smali/jumbo-type-tests/Assert.smali b/smali-integration-tests/src/test/smali/jumbo-type-tests/Assert.smali new file mode 100644 index 00000000..9d2ae5e0 --- /dev/null +++ b/smali-integration-tests/src/test/smali/jumbo-type-tests/Assert.smali @@ -0,0 +1,41 @@ +.class public LAssert; +.super Ljava/lang/Object; +.source "Assert.smali" + +#junit's Assert doesn't have an AssertEquals method for ints, only longs +.method public static assertEquals(II)V + .registers 4 + + int-to-long v0, p1 + int-to-long p0, p0 + + invoke-static {v0, v1, p0, p1}, Lorg/junit/Assert;->assertEquals(JJ)V + return-void +.end method + +#junit's Assert doesn't have an AssertEquals method for floats, only doubles +.method public static assertEquals(FF)V + .registers 6 + + float-to-double v0, p0 + float-to-double v2, p1 + + const-wide v4, .00001 + + invoke-static/range {v0..v5}, Lorg/junit/Assert;->assertEquals(DDD)V + return-void +.end method + +#convenience method that supplies a default "Delta" argument +.method public static assertEquals(DD)V + .registers 6 + + move-wide v0, p0 + move-wide v2, p2 + + const-wide v4, .00001 + + invoke-static/range {v0..v5}, Lorg/junit/Assert;->assertEquals(DDD)V + + return-void +.end method
\ No newline at end of file diff --git a/smali-integration-tests/src/test/smali/jumbo-type-tests/Format52c.smali b/smali-integration-tests/src/test/smali/jumbo-type-tests/Format52c.smali new file mode 100644 index 00000000..b407cd3f --- /dev/null +++ b/smali-integration-tests/src/test/smali/jumbo-type-tests/Format52c.smali @@ -0,0 +1,98 @@ +#Copyright 2011, Google Inc. +#All rights reserved. +# +#Redistribution and use in source and binary forms, with or without +#modification, are permitted provided that the following conditions are +#met: +# +# * Redistributions of source code must retain the above copyright +#notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +#copyright notice, this list of conditions and the following disclaimer +#in the documentation and/or other materials provided with the +#distribution. +# * Neither the name of Google Inc. nor the names of its +#contributors may be used to endorse or promote products derived from +#this software without specific prior written permission. +# +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +#A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +#OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +#SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +#LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +#DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +#THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + +.class public LFormat52c; +.super Ljava/lang/Object; +.source "Format52c.smali" + +.method public constructor <init>()V + .registers 1 + invoke-direct {p0}, Ljava/lang/Object;-><init>()V + return-void +.end method + +.method public test-instance-of-jumbo-success()V + .registers 258 + .annotation runtime Lorg/junit/Test; + .end annotation + + const-string v0, "test" + + new-instance v1, LStringWrapper; + invoke-direct {v1, v0}, LStringWrapper;-><init>(Ljava/lang/String;)V + + move-object/16 v256, v1 + + instance-of/jumbo v257, v256, Ljava/lang/Object; + + const v0, 1 + move/16 v256, v0 + + invoke-static/range {v256 .. v257}, LAssert;->assertEquals(II)V + return-void +.end method + +.method public test-instance-of-jumbo-failure()V + .registers 258 + .annotation runtime Lorg/junit/Test; + .end annotation + + const-string v0, "test" + + new-instance v1, LStringWrapper; + invoke-direct {v1, v0}, LStringWrapper;-><init>(Ljava/lang/String;)V + + move-object/16 v256, v1 + + instance-of/jumbo v257, v256, Lzzz99999; + + const v0, 0 + move/16 v256, v0 + + invoke-static/range {v256 .. v257}, LAssert;->assertEquals(II)V + return-void +.end method + +.method public test-new-array-jumbo()V + .registers 258 + .annotation runtime Lorg/junit/Test; + .end annotation + + const v0, 1 + move/16 v256, v0 + + new-array/jumbo v257, v256, [Lzzz99999; + + move-object/16 v1, v257 + + array-length v2, v1 + + invoke-static {v0, v2}, LAssert;->assertEquals(II)V + return-void +.end method
\ No newline at end of file diff --git a/smali-integration-tests/src/test/smali/jumbo-type-tests/TestSuite.smali b/smali-integration-tests/src/test/smali/jumbo-type-tests/TestSuite.smali index c6e53500..001e18f6 100644 --- a/smali-integration-tests/src/test/smali/jumbo-type-tests/TestSuite.smali +++ b/smali-integration-tests/src/test/smali/jumbo-type-tests/TestSuite.smali @@ -35,5 +35,7 @@ .end annotation .annotation runtime Lorg/junit/runners/Suite$SuiteClasses; - value = { LFormat41c; } + value = { LFormat41c;, + LFormat52c; + } .end annotation
\ No newline at end of file diff --git a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g index d4484621..ce1a6237 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliLexer.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliLexer.g @@ -714,6 +714,10 @@ INSTRUCTION_FORMAT41c_FIELD INSTRUCTION_FORMAT51l : 'const-wide'; +INSTRUCTION_FORMAT52c_TYPE + : 'instance-of/jumbo' + | 'new-array/jumbo'; + /********************************************************** * Types diff --git a/smali/src/main/antlr3/org/jf/smali/smaliParser.g b/smali/src/main/antlr3/org/jf/smali/smaliParser.g index 318ac14f..8b22556f 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliParser.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliParser.g @@ -120,6 +120,7 @@ tokens { I_STATEMENT_FORMAT41c_TYPE; I_STATEMENT_FORMAT41c_FIELD; I_STATEMENT_FORMAT51l; + I_STATEMENT_FORMAT52c_TYPE; I_STATEMENT_ARRAY_DATA; I_STATEMENT_PACKED_SWITCH; I_STATEMENT_SPARSE_SWITCH; @@ -845,6 +846,9 @@ instruction returns [int size] | //e.g. const-wide v0, 5000000000L INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal {$size = Format.Format51l.size;} -> ^(I_STATEMENT_FORMAT51l[$start, "I_STATEMENT_FORMAT51l"] INSTRUCTION_FORMAT51l REGISTER fixed_literal) + | //e.g. instance-of/jumbo v0, v1, Ljava/lang/String; + INSTRUCTION_FORMAT52c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor {$size = Format.Format52c.size;} + -> ^(I_STATEMENT_FORMAT52c_TYPE[$start, "I_STATEMENT_FORMAT52c_TYPE"] INSTRUCTION_FORMAT52c_TYPE REGISTER REGISTER nonvoid_type_descriptor) | ARRAY_DATA_DIRECTIVE { diff --git a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g index 8055c499..f4ffefa0 100644 --- a/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g +++ b/smali/src/main/antlr3/org/jf/smali/smaliTreeWalker.g @@ -1279,6 +1279,17 @@ instruction[int totalMethodRegisters, int methodParameterRegisters, List<Instruc $instructions.add(new Instruction51l(opcode, regA, litB)); } + | //e.g. instance-of/jumbo v0, v1, Ljava/lang/String; + ^(I_STATEMENT_FORMAT52c_TYPE INSTRUCTION_FORMAT52c_TYPE registerA=REGISTER registerB=REGISTER nonvoid_type_descriptor) + { + Opcode opcode = Opcode.getOpcodeByName($INSTRUCTION_FORMAT52c_TYPE.text); + int regA = parseRegister_short($registerA.text, $totalMethodRegisters, $methodParameterRegisters); + int regB = parseRegister_short($registerB.text, $totalMethodRegisters, $methodParameterRegisters); + + TypeIdItem typeIdItem = $nonvoid_type_descriptor.type; + + $instructions.add(new Instruction52c(opcode, regA, regB, typeIdItem)); + } | //e.g. .array-data 4 1000000 .end array-data ^(I_STATEMENT_ARRAY_DATA ^(I_ARRAY_ELEMENT_SIZE short_integral_literal) array_elements) { diff --git a/smali/src/main/jflex/smaliLexer.flex b/smali/src/main/jflex/smaliLexer.flex index 97da209e..5bd13d35 100644 --- a/smali/src/main/jflex/smaliLexer.flex +++ b/smali/src/main/jflex/smaliLexer.flex @@ -575,6 +575,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayDescriptor} "const-wide" { return newToken(INSTRUCTION_FORMAT51l); } + + "instance-of/jumbo" | "new-array/jumbo" { + return newToken(INSTRUCTION_FORMAT52c_TYPE); + } } /*Types*/ diff --git a/smali/src/test/resources/LexerTest/InstructionTest.smali b/smali/src/test/resources/LexerTest/InstructionTest.smali index c80dc8eb..c747c601 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.smali +++ b/smali/src/test/resources/LexerTest/InstructionTest.smali @@ -239,4 +239,6 @@ sput-boolean/jumbo sput-byte/jumbo sput-char/jumbo sput-short/jumbo -const-wide
\ No newline at end of file +const-wide +instance-of/jumbo +new-array/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 871c5a01..86d2981e 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -239,4 +239,6 @@ INSTRUCTION_FORMAT41c_FIELD("sput-boolean/jumbo") INSTRUCTION_FORMAT41c_FIELD("sput-byte/jumbo") INSTRUCTION_FORMAT41c_FIELD("sput-char/jumbo") INSTRUCTION_FORMAT41c_FIELD("sput-short/jumbo") -INSTRUCTION_FORMAT51l("const-wide")
\ No newline at end of file +INSTRUCTION_FORMAT51l("const-wide") +INSTRUCTION_FORMAT52c_TYPE("instance-of/jumbo") +INSTRUCTION_FORMAT52c_TYPE("new-array/jumbo")
\ No newline at end of file |