From afc1f1593936326e1c99f8328bbce8b495865000 Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Thu, 4 Aug 2016 17:31:18 +0100 Subject: [PATCH 1/2] smali/dexlib: deal with invoke-polymorphic / invoke-polymorphic/range. - Introduces two new instruction formats, 45cc and 4rcc. As the name suggests, these instructions are similar to 35c and 3rc, expect that they encode an additional constant pool reference in their 4th byte. - Introduce two new instructions, invoke-polymorphic and invoke-polymorphic/range - used to implement signature polymorphism. - Allow instructions to directly reference the proto_id section of the dex file. This involves the introduction of a new kind of reference (MethodProtoReference) and has the side effect of cleaning up a fair amount of special casing in ProtoPool. - Disable support for ART version based switches (and remove LambdaTest which depends on it). Experimental lambda support and support for ART version based switches will be removed in a follow up change. Bug: 30550796 Test: test-art Test: ./gradlew build --- .../Format/InstructionMethodItem.java | 66 +++++++++--- .../src/main/java/org/jf/dexlib2/Format.java | 2 + .../src/main/java/org/jf/dexlib2/Opcode.java | 15 ++- .../java/org/jf/dexlib2/ReferenceType.java | 9 +- .../reference/BaseMethodProtoReference.java | 66 ++++++++++++ .../instruction/BuilderInstruction35c.java | 2 +- .../instruction/BuilderInstruction45cc.java | 87 +++++++++++++++ .../instruction/BuilderInstruction4rcc.java | 72 +++++++++++++ .../instruction/DexBackedInstruction.java | 4 + .../instruction/DexBackedInstruction45cc.java | 101 ++++++++++++++++++ .../instruction/DexBackedInstruction4rcc.java | 80 ++++++++++++++ .../DexBackedMethodProtoReference.java | 77 +++++++++++++ .../reference/DexBackedReference.java | 2 + .../instruction/DualReferenceInstruction.java | 22 ++-- .../instruction/formats/Instruction45cc.java | 38 +++++++ .../instruction/formats/Instruction4rcc.java | 38 +++++++ .../iface/reference/MethodProtoReference.java | 96 +++++++++++++++++ .../instruction/ImmutableInstruction35c.java | 2 +- .../instruction/ImmutableInstruction35mi.java | 2 +- .../instruction/ImmutableInstruction35ms.java | 2 +- .../ImmutableMethodProtoReference.java | 72 +++++++++++++ .../reference/ImmutableReferenceFactory.java | 5 + .../org/jf/dexlib2/util/Preconditions.java | 2 +- .../org/jf/dexlib2/util/ReferenceUtil.java | 19 +++- .../java/org/jf/dexlib2/writer/DexWriter.java | 27 +++-- .../jf/dexlib2/writer/InstructionWriter.java | 74 ++++++++++--- .../org/jf/dexlib2/writer/MethodSection.java | 8 +- .../writer/builder/BuilderMethodPool.java | 8 +- ....java => BuilderMethodProtoReference.java} | 30 ++---- .../builder/BuilderMethodReference.java | 4 +- .../writer/builder/BuilderProtoPool.java | 91 +++++----------- .../jf/dexlib2/writer/builder/DexBuilder.java | 9 +- .../org/jf/dexlib2/writer/pool/DexPool.java | 5 +- .../jf/dexlib2/writer/pool/MethodPool.java | 13 +-- .../dexlib2/writer/pool/PoolMethodProto.java | 56 ++++++++++ .../org/jf/dexlib2/writer/pool/ProtoPool.java | 88 +++------------ smali/src/main/antlr/smaliParser.g | 20 +++- smali/src/main/antlr/smaliTreeWalker.g | 44 ++++++++ smali/src/main/jflex/smaliLexer.jflex | 8 ++ 39 files changed, 1125 insertions(+), 241 deletions(-) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodProtoReference.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction45cc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction4rcc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction45cc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction4rcc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java rename baksmali/src/test/java/org/jf/baksmali/LambdaTest.java => dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/DualReferenceInstruction.java (73%) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction45cc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction4rcc.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodProtoReference.java create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java rename dexlib2/src/main/java/org/jf/dexlib2/writer/builder/{BuilderProtoReference.java => BuilderMethodProtoReference.java} (69%) create mode 100644 dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethodProto.java 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 fc43d6f1..39485c90 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 @@ -79,11 +79,20 @@ public class InstructionMethodItem extends MethodItem { return opcode.isVolatileFieldAccessor() || opcode == Opcode.THROW_VERIFICATION_ERROR; } + private String writeInvalidItemIndex(InvalidItemIndex ex, int type, IndentingWriter writer) + throws IOException { + writer.write("#"); + writer.write(ex.getMessage()); + writer.write("\n"); + return String.format("%s@%d", ReferenceType.toString(type), ex.getInvalidIndex()); + } + @Override public boolean writeTo(IndentingWriter writer) throws IOException { Opcode opcode = instruction.getOpcode(); String verificationErrorName = null; String referenceString = null; + String referenceString2 = null; boolean commentOutInstruction = false; @@ -100,25 +109,19 @@ public class InstructionMethodItem extends MethodItem { if (instruction instanceof ReferenceInstruction) { ReferenceInstruction referenceInstruction = (ReferenceInstruction)instruction; + String classContext = null; + if (methodDef.classDef.options.useImplicitReferences) { + classContext = methodDef.method.getDefiningClass(); + } + try { Reference reference = referenceInstruction.getReference(); - - String classContext = null; - if (methodDef.classDef.options.useImplicitReferences) { - classContext = methodDef.method.getDefiningClass(); - } - referenceString = ReferenceUtil.getReferenceString(reference, classContext); assert referenceString != null; } catch (InvalidItemIndex ex) { - writer.write("#"); - writer.write(ex.getMessage()); - writer.write("\n"); commentOutInstruction = true; - - referenceString = String.format("%s@%d", - ReferenceType.toString(referenceInstruction.getReferenceType()), - ex.getInvalidIndex()); + referenceString = writeInvalidItemIndex(ex, referenceInstruction.getReferenceType(), + writer); } catch (ReferenceType.InvalidReferenceTypeException ex) { writer.write("#invalid reference type: "); writer.printSignedIntAsDec(ex.getReferenceType()); @@ -126,6 +129,25 @@ public class InstructionMethodItem extends MethodItem { referenceString = "invalid_reference"; } + + if (instruction instanceof DualReferenceInstruction) { + DualReferenceInstruction dualReferenceInstruction = + (DualReferenceInstruction) instruction; + try { + Reference reference2 = dualReferenceInstruction.getReference2(); + referenceString2 = ReferenceUtil.getReferenceString(reference2, classContext); + } catch (InvalidItemIndex ex) { + commentOutInstruction = true; + referenceString2 = writeInvalidItemIndex(ex, + dualReferenceInstruction.getReferenceType2(), writer); + } catch (ReferenceType.InvalidReferenceTypeException ex) { + writer.write("#invalid reference type: "); + writer.printSignedIntAsDec(ex.getReferenceType()); + commentOutInstruction = true; + + referenceString2 = "invalid_reference"; + } + } } if (instruction instanceof Instruction31t) { @@ -355,6 +377,24 @@ public class InstructionMethodItem extends MethodItem { writer.write(", "); writeVtableIndex(writer); break; + case Format45cc: + writeOpcode(writer); + writer.write(' '); + writeInvokeRegisters(writer); + writer.write(", "); + writer.write(referenceString); + writer.write(", "); + writer.write(referenceString2); + break; + case Format4rcc: + writeOpcode(writer); + writer.write(' '); + writeInvokeRangeRegisters(writer); + writer.write(", "); + writer.write(referenceString); + writer.write(", "); + writer.write(referenceString2); + break; default: assert false; return false; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Format.java b/dexlib2/src/main/java/org/jf/dexlib2/Format.java index ee34aa50..42e8e144 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Format.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Format.java @@ -63,6 +63,8 @@ public enum Format { Format3rc(6), Format3rmi(6), Format3rms(6), + Format45cc(8), + Format4rcc(8), Format51l(10), ArrayPayload(-1, true), PackedSwitchPayload(-1, true), diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java index 3a642358..9559760a 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java @@ -294,8 +294,8 @@ public enum Opcode INVOKE_VIRTUAL_QUICK(combine(allApis(0xf8), allArtVersions(0xe9)), "invoke-virtual-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_VIRTUAL_QUICK_RANGE(combine(allApis(0xf9), allArtVersions(0xea)), "invoke-virtual-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_SUPER_QUICK(allApis(0xfa), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_SUPER_QUICK_RANGE(allApis(0xfb), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_SUPER_QUICK(lastApi(0xfa, 25), "invoke-super-quick", ReferenceType.NONE, Format.Format35ms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_SUPER_QUICK_RANGE(lastApi(0xfb, 25), "invoke-super-quick/range", ReferenceType.NONE, Format.Format3rms, Opcode.ODEX_ONLY | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), IPUT_OBJECT_VOLATILE(firstApi(0xfc, 9), "iput-object-volatile", ReferenceType.FIELD, Format.Format22c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE), SGET_OBJECT_VOLATILE(firstApi(0xfd, 9), "sget-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER | Opcode.STATIC_FIELD_ACCESSOR), @@ -313,7 +313,9 @@ public enum Opcode // TODO: do we need a capture/liberate wide? LIBERATE_VARIABLE(allArtVersions(0xf7), "liberate-variable", ReferenceType.STRING, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), BOX_LAMBDA(allArtVersions(0xf8), "box-lambda", ReferenceType.NONE, Format.Format22x, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), - UNBOX_LAMBDA(allArtVersions(0xf9), "unbox-lambda", ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL); + UNBOX_LAMBDA(allArtVersions(0xf9), "unbox-lambda", ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), + INVOKE_POLYMORPHIC(firstApi(0xfa, 26), "invoke-polymorphic", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format45cc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + INVOKE_POLYMORPHIC_RANGE(firstApi(0xfb, 26), "invoke-polymorphic/range", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format4rcc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT); //if the instruction can throw an exception public static final int CAN_THROW = 0x1; @@ -359,6 +361,7 @@ public enum Opcode public final int referenceType; public final Format format; public final int flags; + public final int referenceType2; Opcode(int opcodeValue, String opcodeName, int referenceType, Format format) { this(opcodeValue, opcodeName, referenceType, format, 0); @@ -369,6 +372,11 @@ public enum Opcode } Opcode(List versionConstraints, String opcodeName, int referenceType, Format format, int flags) { + this(versionConstraints, opcodeName, referenceType, -1, format, flags); + } + + Opcode(List versionConstraints, String opcodeName, int referenceType, int referenceType2, + Format format, int flags) { ImmutableRangeMap.Builder apiToValueBuilder = ImmutableRangeMap.builder(); ImmutableRangeMap.Builder artVersionToValueBuilder = ImmutableRangeMap.builder(); @@ -385,6 +393,7 @@ public enum Opcode this.artVersionToValueMap = artVersionToValueBuilder.build(); this.name = opcodeName; this.referenceType = referenceType; + this.referenceType2 = referenceType2; this.format = format; this.flags = flags; } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java b/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java index 3371f818..fa8b9687 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/ReferenceType.java @@ -39,7 +39,8 @@ public final class ReferenceType { public static final int TYPE = 1; public static final int FIELD = 2; public static final int METHOD = 3; - public static final int NONE = 4; + public static final int METHOD_PROTO = 4; + public static final int NONE = 5; public static String toString(int referenceType) { switch (referenceType) { @@ -51,6 +52,8 @@ public final class ReferenceType { return "field"; case METHOD: return "method"; + case METHOD_PROTO: + return "method_proto"; default: throw new InvalidReferenceTypeException(referenceType); } @@ -65,6 +68,8 @@ public final class ReferenceType { return FIELD; } else if (reference instanceof MethodReference) { return METHOD; + } else if (reference instanceof MethodProtoReference) { + return METHOD_PROTO; } else { throw new IllegalStateException("Invalid reference"); } @@ -76,7 +81,7 @@ public final class ReferenceType { * @throws InvalidReferenceTypeException */ public static void validateReferenceType(int referenceType) { - if (referenceType < 0 || referenceType > 3) { + if (referenceType < 0 || referenceType > 4) { throw new InvalidReferenceTypeException(referenceType); } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodProtoReference.java new file mode 100644 index 00000000..c0d38b0b --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/base/reference/BaseMethodProtoReference.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016, 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.dexlib2.base.reference; + +import com.google.common.collect.Ordering; +import org.jf.dexlib2.iface.reference.MethodProtoReference; +import org.jf.util.CharSequenceUtils; +import org.jf.util.CollectionUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + + +public abstract class BaseMethodProtoReference implements MethodProtoReference { + @Override + public int hashCode() { + int hashCode = getReturnType().hashCode(); + return hashCode*31 + getParameterTypes().hashCode(); + } + + @Override + public boolean equals(@Nullable Object o) { + if (o instanceof MethodProtoReference) { + MethodProtoReference other = (MethodProtoReference)o; + return getReturnType().equals(other.getReturnType()) && + CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes()); + } + return false; + } + + @Override + public int compareTo(@Nonnull MethodProtoReference o) { + int res = getReturnType().compareTo(o.getReturnType()); + if (res != 0) return res; + return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameterTypes(), o.getParameterTypes()); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35c.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35c.java index 283464fe..5ec58a92 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35c.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction35c.java @@ -60,7 +60,7 @@ public class BuilderInstruction35c extends BuilderInstruction implements Instruc int registerG, @Nonnull Reference reference) { super(opcode); - this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount); this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction45cc.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction45cc.java new file mode 100644 index 00000000..b0e3f427 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction45cc.java @@ -0,0 +1,87 @@ +/* + * Copyright 2016, 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.dexlib2.builder.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.builder.BuilderInstruction; +import org.jf.dexlib2.iface.instruction.formats.Instruction45cc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class BuilderInstruction45cc extends BuilderInstruction implements Instruction45cc { + public static final Format FORMAT = Format.Format45cc; + + protected final int registerCount; + protected final int registerC; + protected final int registerD; + protected final int registerE; + protected final int registerF; + protected final int registerG; + @Nonnull protected final Reference reference; + @Nonnull protected final Reference reference2; + + public BuilderInstruction45cc(@Nonnull Opcode opcode, + int registerCount, + int registerC, + int registerD, + int registerE, + int registerF, + int registerG, + @Nonnull Reference reference, + @Nonnull Reference reference2) { + super(opcode); + this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount); + this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; + this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; + this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; + this.registerF = (registerCount>3) ? Preconditions.checkNibbleRegister(registerF) : 0; + this.registerG = (registerCount>4) ? Preconditions.checkNibbleRegister(registerG) : 0; + this.reference = reference; + this.reference2 = reference2; + } + + @Override public int getRegisterCount() { return registerCount; } + @Override public int getRegisterC() { return registerC; } + @Override public int getRegisterD() { return registerD; } + @Override public int getRegisterE() { return registerE; } + @Override public int getRegisterF() { return registerF; } + @Override public int getRegisterG() { return registerG; } + @Nonnull @Override public Reference getReference() { return reference; } + @Override public int getReferenceType() { return opcode.referenceType; } + @Nonnull @Override public Reference getReference2() { return reference2; } + @Override public int getReferenceType2() { return opcode.referenceType2; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction4rcc.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction4rcc.java new file mode 100644 index 00000000..3ee7ef9d --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction4rcc.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012, 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.dexlib2.builder.instruction; + +import org.jf.dexlib2.Format; +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.builder.BuilderInstruction; +import org.jf.dexlib2.iface.instruction.formats.Instruction4rcc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.dexlib2.util.Preconditions; + +import javax.annotation.Nonnull; + +public class BuilderInstruction4rcc extends BuilderInstruction implements Instruction4rcc { + public static final Format FORMAT = Format.Format4rcc; + + protected final int startRegister; + protected final int registerCount; + + @Nonnull protected final Reference reference; + @Nonnull protected final Reference reference2; + + public BuilderInstruction4rcc(@Nonnull Opcode opcode, + int startRegister, + int registerCount, + @Nonnull Reference reference, + @Nonnull Reference reference2) { + super(opcode); + this.startRegister = Preconditions.checkShortRegister(startRegister); + this.registerCount = Preconditions.checkRegisterRangeCount(registerCount); + this.reference = reference; + this.reference2 = reference2; + } + + @Override public int getStartRegister() { return startRegister; } + @Override public int getRegisterCount() { return registerCount; } + @Nonnull @Override public Reference getReference() { return reference; } + @Override public int getReferenceType() { return opcode.referenceType; } + @Nonnull @Override public Reference getReference2() { return reference2; } + @Override public int getReferenceType2() { return opcode.referenceType2; } + + @Override public Format getFormat() { return FORMAT; } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java index ac82f4b4..2973398a 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java @@ -139,6 +139,10 @@ public abstract class DexBackedInstruction implements Instruction { return new DexBackedInstruction3rmi(dexFile, opcode, instructionStartOffset); case Format3rms: return new DexBackedInstruction3rms(dexFile, opcode, instructionStartOffset); + case Format45cc: + return new DexBackedInstruction45cc(dexFile, opcode, instructionStartOffset); + case Format4rcc: + return new DexBackedInstruction4rcc(dexFile, opcode, instructionStartOffset); case Format51l: return new DexBackedInstruction51l(dexFile, opcode, instructionStartOffset); case PackedSwitchPayload: diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction45cc.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction45cc.java new file mode 100644 index 00000000..bbdc229f --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction45cc.java @@ -0,0 +1,101 @@ +/* + * Copyright 2016, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction45cc; +import org.jf.dexlib2.iface.reference.Reference; +import org.jf.util.NibbleUtils; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction45cc extends DexBackedInstruction implements Instruction45cc { + public DexBackedInstruction45cc(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Override + public int getRegisterC() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterD() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 4)); + } + + @Override + public int getRegisterE() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterF() { + return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 5)); + } + + @Override + public int getRegisterG() { + return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); + } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, + dexFile.readUshort(instructionStart + 2)); + } + + @Override + public int getReferenceType() { + return opcode.referenceType; + } + + @Override + public Reference getReference2() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType2, + dexFile.readUshort(instructionStart + 3)); + } + + @Override + public int getReferenceType2() { + return opcode.referenceType2; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction4rcc.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction4rcc.java new file mode 100644 index 00000000..629e753b --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction4rcc.java @@ -0,0 +1,80 @@ +/* + * Copyright 2016, 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.dexlib2.dexbacked.instruction; + +import org.jf.dexlib2.Opcode; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.reference.DexBackedReference; +import org.jf.dexlib2.iface.instruction.formats.Instruction4rcc; +import org.jf.dexlib2.iface.reference.Reference; + +import javax.annotation.Nonnull; + +public class DexBackedInstruction4rcc extends DexBackedInstruction implements Instruction4rcc { + public DexBackedInstruction4rcc(@Nonnull DexBackedDexFile dexFile, + @Nonnull Opcode opcode, + int instructionStart) { + super(dexFile, opcode, instructionStart); + } + + @Override public int getRegisterCount() { + return dexFile.readUbyte(instructionStart + 1); + } + + @Override + public int getStartRegister() { + return dexFile.readUshort(instructionStart + 4); + } + + @Nonnull + @Override + public Reference getReference() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType, + dexFile.readUshort(instructionStart + 2)); + } + + @Override + public int getReferenceType() { + return opcode.referenceType; + } + + @Override + public Reference getReference2() { + return DexBackedReference.makeReference(dexFile, opcode.referenceType2, + dexFile.readUshort(instructionStart + 3)); + } + + @Override + public int getReferenceType2() { + return opcode.referenceType2; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java new file mode 100644 index 00000000..12875b7b --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedMethodProtoReference.java @@ -0,0 +1,77 @@ +/* + * Copyright 2016, 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.dexlib2.dexbacked.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseMethodProtoReference; +import org.jf.dexlib2.dexbacked.DexBackedDexFile; +import org.jf.dexlib2.dexbacked.raw.ProtoIdItem; +import org.jf.dexlib2.dexbacked.raw.TypeListItem; +import org.jf.dexlib2.dexbacked.util.FixedSizeList; + +import java.util.List; +import javax.annotation.Nonnull; + +public class DexBackedMethodProtoReference extends BaseMethodProtoReference { + @Nonnull public final DexBackedDexFile dexFile; + private final int protoIdItemOffset; + + public DexBackedMethodProtoReference(@Nonnull DexBackedDexFile dexFile, int protoIndex) { + this.dexFile = dexFile; + this.protoIdItemOffset = dexFile.getProtoIdItemOffset(protoIndex); + } + + @Nonnull + @Override + public List getParameterTypes() { + final int parametersOffset = dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.PARAMETERS_OFFSET); + if (parametersOffset > 0) { + final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET); + final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET; + return new FixedSizeList() { + @Nonnull + @Override + public String readItem(final int index) { + return dexFile.getType(dexFile.readUshort(paramListStart + 2*index)); + } + @Override public int size() { return parameterCount; } + }; + } + return ImmutableList.of(); + } + + @Nonnull + @Override + public String getReturnType() { + return dexFile.getType(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET)); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java index b63c37c2..99d66ecd 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/reference/DexBackedReference.java @@ -49,6 +49,8 @@ public abstract class DexBackedReference { return new DexBackedMethodReference(dexFile, referenceIndex); case ReferenceType.FIELD: return new DexBackedFieldReference(dexFile, referenceIndex); + case ReferenceType.METHOD_PROTO: + return new DexBackedMethodProtoReference(dexFile, referenceIndex); default: throw new ExceptionWithContext("Invalid reference type: %d", referenceType); } diff --git a/baksmali/src/test/java/org/jf/baksmali/LambdaTest.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/DualReferenceInstruction.java similarity index 73% rename from baksmali/src/test/java/org/jf/baksmali/LambdaTest.java rename to dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/DualReferenceInstruction.java index 5431df54..0f1f81b2 100644 --- a/baksmali/src/test/java/org/jf/baksmali/LambdaTest.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/DualReferenceInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright 2015, Google Inc. + * Copyright 2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,21 +29,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.jf.baksmali; +package org.jf.dexlib2.iface.instruction; -import org.junit.Test; +import org.jf.dexlib2.iface.reference.Reference; -public class LambdaTest extends IdenticalRoundtripTest { +import javax.annotation.Nonnull; - private baksmaliOptions createOptions() { - baksmaliOptions options = new baksmaliOptions(); - options.apiLevel = 23; // since we need at least level 23 for lambda opcodes - options.experimental = true; // since these opcodes aren't implemented in runtime yet); - return options; - } - - @Test - public void testHelloWorldLambda() { - runTest("HelloWorldLambda", createOptions()); - } +public interface DualReferenceInstruction extends ReferenceInstruction { + @Nonnull Reference getReference2(); + int getReferenceType2(); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction45cc.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction45cc.java new file mode 100644 index 00000000..221fd623 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction45cc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.DualReferenceInstruction; +import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction; + +public interface Instruction45cc extends FiveRegisterInstruction, DualReferenceInstruction { +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction4rcc.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction4rcc.java new file mode 100644 index 00000000..d0b930b1 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction4rcc.java @@ -0,0 +1,38 @@ +/* + * Copyright 2016, 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.dexlib2.iface.instruction.formats; + +import org.jf.dexlib2.iface.instruction.DualReferenceInstruction; +import org.jf.dexlib2.iface.instruction.RegisterRangeInstruction; + +public interface Instruction4rcc extends RegisterRangeInstruction, DualReferenceInstruction { +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodProtoReference.java new file mode 100644 index 00000000..e150c214 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/iface/reference/MethodProtoReference.java @@ -0,0 +1,96 @@ +/* + * Copyright 20116, 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.dexlib2.iface.reference; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * This class represents a reference to a method prototype. + */ +public interface MethodProtoReference extends Reference, Comparable { + /** + * Gets a list of the types of the parameters of this method prototype. + * + * @return A list of the parameter types of this method prototype, as strings. + */ + @Nonnull List getParameterTypes(); + + /** + * Gets the return type of the referenced method prototype. + * + * @return The return type of the referenced method prototype. + */ + @Nonnull String getReturnType(); + + /** + * Returns a hashcode for this MethodProtoReference. + * + * This hashCode is defined to be the following: + * + *
+     * {@code
+     * int hashCode =  getReturnType().hashCode();
+     * hashCode = hashCode*31 + CharSequenceUtils.listHashCode(getParameters());
+     * }
+ * + * @return The hash code value for this ProtoReference + */ + @Override int hashCode(); + + /** + * Compares this MethodTypeReference to another MethodProtoReference for equality. + * + * This MethodTypeReference is equal to another MethodProtoReference if all of it's "fields" are equal. That is, if + * the return values of getReturnType() and getParameterTypes() are all equal. + * + * Equality for getParameters() should be tested by comparing the string representation of each element. I.e. + * CharSequenceUtils.listEquals(this.getParameterTypes(), other.getParameterTypes()) + * + * @param o The object to be compared for equality with this MethodProtoReference + * @return true if the specified object is equal to this MethodProtoReference + */ + @Override boolean equals(@Nullable Object o); + + /** + * Compare this MethodTypeReference to another MethodProtoReference. + * + * The comparison is based on the comparison of the return values of getReturnType() and getParameters(), + * in that order. getParameters() should be compared using the semantics of + * org.jf.util.CollectionUtils.compareAsList() + * + * @param o The MethodReference to compare with this MethodProtoReference + * @return An integer representing the result of the comparison + */ + @Override int compareTo(@Nonnull MethodProtoReference o); +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java index 20976f80..7ac1a8f6 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35c.java @@ -61,7 +61,7 @@ public class ImmutableInstruction35c extends ImmutableInstruction implements Ins int registerG, @Nonnull Reference reference) { super(opcode); - this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount); this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java index def7eb60..5e58cae9 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35mi.java @@ -58,7 +58,7 @@ public class ImmutableInstruction35mi extends ImmutableInstruction implements In int registerG, int inlineIndex) { super(opcode); - this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount); this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java index 16d7e913..0130f474 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction35ms.java @@ -58,7 +58,7 @@ public class ImmutableInstruction35ms extends ImmutableInstruction implements In int registerG, int vtableIndex) { super(opcode); - this.registerCount = Preconditions.check35cRegisterCount(registerCount); + this.registerCount = Preconditions.check35cAnd45ccRegisterCount(registerCount); this.registerC = (registerCount>0) ? Preconditions.checkNibbleRegister(registerC) : 0; this.registerD = (registerCount>1) ? Preconditions.checkNibbleRegister(registerD) : 0; this.registerE = (registerCount>2) ? Preconditions.checkNibbleRegister(registerE) : 0; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java new file mode 100644 index 00000000..8c2afe59 --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableMethodProtoReference.java @@ -0,0 +1,72 @@ +/* + * Copyright 2016, 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.dexlib2.immutable.reference; + +import com.google.common.collect.ImmutableList; +import org.jf.dexlib2.base.reference.BaseMethodProtoReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; +import org.jf.dexlib2.immutable.util.CharSequenceConverter; + +import java.util.List; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ImmutableMethodProtoReference extends BaseMethodProtoReference implements ImmutableReference { + @Nonnull protected final ImmutableList parameters; + @Nonnull protected final String returnType; + + public ImmutableMethodProtoReference(@Nullable Iterable parameters, + @Nonnull String returnType) { + this.parameters = CharSequenceConverter.immutableStringList(parameters); + this.returnType = returnType; + } + + @Nonnull public static ImmutableMethodProtoReference of(@Nonnull MethodProtoReference methodProtoReference) { + if (methodProtoReference instanceof ImmutableMethodProtoReference) { + return (ImmutableMethodProtoReference) methodProtoReference; + } + return new ImmutableMethodProtoReference( + methodProtoReference.getParameterTypes(), + methodProtoReference.getReturnType()); + } + + @Override + public List getParameterTypes() { + return parameters; + } + + @Override + public String getReturnType() { + return returnType; + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java index 0d27e47f..d0007479 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/reference/ImmutableReferenceFactory.java @@ -52,6 +52,9 @@ public class ImmutableReferenceFactory { if (reference instanceof MethodReference) { return ImmutableMethodReference.of((MethodReference)reference); } + if (reference instanceof MethodProtoReference) { + return ImmutableMethodProtoReference.of((MethodProtoReference) reference); + } throw new ExceptionWithContext("Invalid reference type"); } @@ -66,6 +69,8 @@ public class ImmutableReferenceFactory { return ImmutableFieldReference.of((FieldReference)reference); case ReferenceType.METHOD: return ImmutableMethodReference.of((MethodReference)reference); + case ReferenceType.METHOD_PROTO: + return ImmutableMethodProtoReference.of((MethodProtoReference)reference); } throw new ExceptionWithContext("Invalid reference type: %d", referenceType); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java index 51c083ca..3b30d075 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java @@ -125,7 +125,7 @@ public class Preconditions { return offset; } - public static int check35cRegisterCount(int registerCount) { + public static int check35cAnd45ccRegisterCount(int registerCount) { if (registerCount < 0 || registerCount > 5) { throw new IllegalArgumentException( String.format("Invalid register count: %d. Must be between 0 and 5, inclusive.", registerCount)); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java b/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java index 81b042ec..4e46a0e9 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/util/ReferenceUtil.java @@ -60,6 +60,17 @@ public final class ReferenceUtil { return sb.toString(); } + public static String getMethodProtoDescriptor(MethodProtoReference methodProtoReference) { + StringBuilder sb = new StringBuilder(); + sb.append('('); + for (CharSequence paramType : methodProtoReference.getParameterTypes()) { + sb.append(paramType); + } + sb.append(')'); + sb.append(methodProtoReference.getReturnType()); + return sb.toString(); + } + public static void writeMethodDescriptor(Writer writer, MethodReference methodReference) throws IOException { writeMethodDescriptor(writer, methodReference, false); } @@ -134,12 +145,16 @@ public final class ReferenceUtil { if (reference instanceof FieldReference) { FieldReference fieldReference = (FieldReference)reference; boolean useImplicitReference = fieldReference.getDefiningClass().equals(containingClass); - return getFieldDescriptor((FieldReference)reference, useImplicitReference); + return getFieldDescriptor(fieldReference, useImplicitReference); } if (reference instanceof MethodReference) { MethodReference methodReference = (MethodReference)reference; boolean useImplicitReference = methodReference.getDefiningClass().equals(containingClass); - return getMethodDescriptor((MethodReference)reference, useImplicitReference); + return getMethodDescriptor(methodReference, useImplicitReference); + } + if (reference instanceof MethodProtoReference) { + MethodProtoReference methodProtoReference = (MethodProtoReference)reference; + return getMethodProtoDescriptor(methodProtoReference); } return null; } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java index 4e81f7fa..5329351e 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java @@ -54,6 +54,7 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction; import org.jf.dexlib2.iface.instruction.ReferenceInstruction; import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.TypeReference; @@ -84,7 +85,7 @@ import java.util.zip.Adler32; public abstract class DexWriter< StringKey extends CharSequence, StringRef extends StringReference, TypeKey extends CharSequence, - TypeRef extends TypeReference, ProtoKey extends Comparable, + TypeRef extends TypeReference, ProtoRefKey extends MethodProtoReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, ClassKey extends Comparable, AnnotationKey extends Annotation, AnnotationSetKey, @@ -125,9 +126,9 @@ public abstract class DexWriter< protected final StringSection stringSection; protected final TypeSection typeSection; - protected final ProtoSection protoSection; + protected final ProtoSection protoSection; protected final FieldSection fieldSection; - protected final MethodSection methodSection; + protected final MethodSection methodSection; protected final ClassSection classSection; @@ -138,9 +139,9 @@ public abstract class DexWriter< protected DexWriter(Opcodes opcodes, StringSection stringSection, TypeSection typeSection, - ProtoSection protoSection, + ProtoSection protoSection, FieldSection fieldSection, - MethodSection methodSection, + MethodSection methodSection, ClassSection classSection, TypeListSection typeListSection, @@ -347,12 +348,12 @@ public abstract class DexWriter< protoSectionOffset = writer.getPosition(); int index = 0; - List> protoEntries = Lists.newArrayList(protoSection.getItems()); - Collections.sort(protoEntries, DexWriter.comparableKeyComparator()); + List> protoEntries = Lists.newArrayList(protoSection.getItems()); + Collections.sort(protoEntries, DexWriter.comparableKeyComparator()); - for (Map.Entry entry: protoEntries) { + for (Map.Entry entry: protoEntries) { entry.setValue(index++); - ProtoKey key = entry.getKey(); + ProtoRefKey key = entry.getKey(); writer.writeInt(stringSection.getItemIndex(protoSection.getShorty(key))); writer.writeInt(typeSection.getItemIndex(protoSection.getReturnType(key))); writer.writeInt(typeListSection.getNullableItemOffset(protoSection.getParameters(key))); @@ -946,7 +947,7 @@ public abstract class DexWriter< InstructionWriter instructionWriter = InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, - methodSection); + methodSection, protoSection); writer.writeInt(codeUnitCount); for (Instruction instruction: instructions) { @@ -1029,6 +1030,12 @@ public abstract class DexWriter< case Format3rc: instructionWriter.write((Instruction3rc)instruction); break; + case Format45cc: + instructionWriter.write((Instruction45cc) instruction); + break; + case Format4rcc: + instructionWriter.write((Instruction4rcc) instruction); + break; case Format51l: instructionWriter.write((Instruction51l)instruction); break; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java index f16256c5..c240c515 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java @@ -36,11 +36,14 @@ import com.google.common.primitives.Ints; import org.jf.dexlib2.Opcode; import org.jf.dexlib2.Opcodes; import org.jf.dexlib2.ReferenceType; +import org.jf.dexlib2.iface.instruction.DualReferenceInstruction; import org.jf.dexlib2.iface.instruction.ReferenceInstruction; import org.jf.dexlib2.iface.instruction.SwitchElement; import org.jf.dexlib2.iface.instruction.formats.*; import org.jf.dexlib2.iface.reference.FieldReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.Reference; import org.jf.dexlib2.iface.reference.StringReference; import org.jf.dexlib2.iface.reference.TypeReference; import org.jf.util.ExceptionWithContext; @@ -51,25 +54,29 @@ import java.util.Comparator; import java.util.List; public class InstructionWriter { + FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, + ProtoRefKey extends MethodProtoReference> { @Nonnull private final Opcodes opcodes; @Nonnull private final DexDataWriter writer; @Nonnull private final StringSection stringSection; @Nonnull private final TypeSection typeSection; @Nonnull private final FieldSection fieldSection; @Nonnull private final MethodSection methodSection; + @Nonnull private final ProtoSection protoSection; - @Nonnull static - InstructionWriter + @Nonnull static + InstructionWriter makeInstructionWriter( @Nonnull Opcodes opcodes, @Nonnull DexDataWriter writer, @Nonnull StringSection stringSection, @Nonnull TypeSection typeSection, @Nonnull FieldSection fieldSection, - @Nonnull MethodSection methodSection) { - return new InstructionWriter( - opcodes, writer, stringSection, typeSection, fieldSection, methodSection); + @Nonnull MethodSection methodSection, + @Nonnull ProtoSection protoSection) { + return new InstructionWriter( + opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection); } InstructionWriter(@Nonnull Opcodes opcodes, @@ -77,13 +84,15 @@ public class InstructionWriter stringSection, @Nonnull TypeSection typeSection, @Nonnull FieldSection fieldSection, - @Nonnull MethodSection methodSection) { + @Nonnull MethodSection methodSection, + @Nonnull ProtoSection protoSection) { this.opcodes = opcodes; this.writer = writer; this.stringSection = stringSection; this.typeSection = typeSection; this.fieldSection = fieldSection; this.methodSection = methodSection; + this.protoSection = protoSection; } private short getOpcodeValue(Opcode opcode) { @@ -347,6 +356,7 @@ public class InstructionWriter +public interface MethodSection extends IndexSection { @Nonnull TypeKey getDefiningClass(@Nonnull MethodRefKey key); - @Nonnull ProtoKey getPrototype(@Nonnull MethodRefKey key); - @Nonnull ProtoKey getPrototype(@Nonnull MethodKey key); + @Nonnull ProtoRefKey getPrototype(@Nonnull MethodRefKey key); + @Nonnull ProtoRefKey getPrototype(@Nonnull MethodKey key); @Nonnull StringKey getName(@Nonnull MethodRefKey key); int getMethodIndex(@Nonnull MethodKey key); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java index 7dc924e7..2c5dd816 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodPool.java @@ -43,7 +43,7 @@ import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; class BuilderMethodPool implements MethodSection{ + BuilderMethodProtoReference, BuilderMethodReference, BuilderMethod>{ @Nonnull private final BuilderContext context; @Nonnull private final ConcurrentMap internedItems = Maps.newConcurrentMap(); @@ -61,7 +61,7 @@ class BuilderMethodPool implements MethodSection { +public class BuilderMethodProtoReference extends BaseMethodProtoReference implements + MethodProtoReference, BuilderReference { @Nonnull final BuilderStringReference shorty; @Nonnull final BuilderTypeList parameterTypes; @Nonnull final BuilderTypeReference returnType; int index = DexWriter.NO_INDEX; - public BuilderProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes, - @Nonnull BuilderTypeReference returnType) { + public BuilderMethodProtoReference(@Nonnull BuilderStringReference shorty, @Nonnull BuilderTypeList parameterTypes, + @Nonnull BuilderTypeReference returnType) { this.shorty = shorty; this.parameterTypes = parameterTypes; this.returnType = returnType; @@ -62,25 +65,12 @@ public class BuilderProtoReference implements BuilderProtoPool.ProtoKey, Compara } @Override - public int hashCode() { - int hashCode = getReturnType().hashCode(); - return hashCode*31 + getParameterTypes().hashCode(); + public int getIndex() { + return index; } @Override - public boolean equals(@Nullable Object o) { - if (o != null && o instanceof BuilderProtoReference) { - BuilderProtoReference other = (BuilderProtoReference)o; - return returnType.equals(other.returnType) && - CharSequenceUtils.listEquals(parameterTypes, other.parameterTypes); - } - return false; - } - - @Override - public int compareTo(@Nonnull BuilderProtoReference o) { - int res = returnType.compareTo(o.returnType); - if (res != 0) return res; - return CollectionUtils.compareAsIterable(Ordering.usingToString(), parameterTypes, o.parameterTypes); + public void setIndex(int index) { + this.index = index; } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java index c913efa5..96708444 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderMethodReference.java @@ -39,12 +39,12 @@ import javax.annotation.Nonnull; public class BuilderMethodReference extends BaseMethodReference implements BuilderReference { @Nonnull final BuilderTypeReference definingClass; @Nonnull final BuilderStringReference name; - @Nonnull final BuilderProtoReference proto; + @Nonnull final BuilderMethodProtoReference proto; int index = DexWriter.NO_INDEX; BuilderMethodReference(@Nonnull BuilderTypeReference definingClass, @Nonnull BuilderStringReference name, - @Nonnull BuilderProtoReference proto) { + @Nonnull BuilderMethodProtoReference proto) { this.definingClass = definingClass; this.name = name; this.proto = proto; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java index 6ed18fe8..de19fa30 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/BuilderProtoPool.java @@ -32,114 +32,75 @@ package org.jf.dexlib2.writer.builder; import com.google.common.collect.Maps; +import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference; import org.jf.dexlib2.util.MethodUtil; import org.jf.dexlib2.writer.ProtoSection; -import org.jf.util.CharSequenceUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; -import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; class BuilderProtoPool - implements ProtoSection { + implements ProtoSection { @Nonnull private final BuilderContext context; - @Nonnull private final ConcurrentMap internedItems = + @Nonnull private final ConcurrentMap internedItems = Maps.newConcurrentMap(); BuilderProtoPool(@Nonnull BuilderContext context) { this.context = context; } - @Nonnull public BuilderProtoReference internProto(@Nonnull List parameters, - @Nonnull String returnType) { - ProtoKey key = new Key(parameters, returnType); - BuilderProtoReference ret = internedItems.get(key); + @Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodProtoReference methodProto) { + BuilderMethodProtoReference ret = internedItems.get(methodProto); if (ret != null) { return ret; } - BuilderProtoReference protoReference = new BuilderProtoReference( - context.stringPool.internString(MethodUtil.getShorty(parameters, returnType)), - context.typeListPool.internTypeList(parameters), - context.typePool.internType(returnType)); + BuilderMethodProtoReference protoReference = new BuilderMethodProtoReference( + context.stringPool.internString(MethodUtil.getShorty( + methodProto.getParameterTypes(), methodProto.getReturnType())), + context.typeListPool.internTypeList(methodProto.getParameterTypes()), + context.typePool.internType(methodProto.getReturnType())); ret = internedItems.putIfAbsent(protoReference, protoReference); return ret==null?protoReference:ret; } - @Nonnull public BuilderProtoReference internProto(@Nonnull MethodReference methodReference) { - return internProto(methodReference.getParameterTypes(), methodReference.getReturnType()); + @Nonnull public BuilderMethodProtoReference internMethodProto(@Nonnull MethodReference methodReference) { + return internMethodProto(new ImmutableMethodProtoReference( + methodReference.getParameterTypes(), methodReference.getReturnType())); } - @Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderProtoReference key) { - return key.shorty; + @Nonnull @Override public BuilderStringReference getShorty(@Nonnull BuilderMethodProtoReference proto) { + return proto.shorty; } - @Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderProtoReference key) { - return key.returnType; + @Nonnull @Override public BuilderTypeReference getReturnType(@Nonnull BuilderMethodProtoReference proto) { + return proto.returnType; } - @Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderProtoReference key) { - return key.parameterTypes; + @Nullable @Override public BuilderTypeList getParameters(@Nonnull BuilderMethodProtoReference proto) { + return proto.parameterTypes; } - @Override public int getItemIndex(@Nonnull BuilderProtoReference key) { - return key.index; + @Override public int getItemIndex(@Nonnull BuilderMethodProtoReference proto) { + return proto.getIndex(); } - @Nonnull @Override public Collection> getItems() { - return new BuilderMapEntryCollection(internedItems.values()) { - @Override protected int getValue(@Nonnull BuilderProtoReference key) { + @Nonnull @Override public Collection> getItems() { + return new BuilderMapEntryCollection(internedItems.values()) { + @Override protected int getValue(@Nonnull BuilderMethodProtoReference key) { return key.index; } - @Override protected int setValue(@Nonnull BuilderProtoReference key, int value) { + @Override protected int setValue(@Nonnull BuilderMethodProtoReference key, int value) { int prev = key.index; key.index = value; return prev; } }; } - - // a placeholder interface to unify the temporary probing key and the BuilderProtoReference class - interface ProtoKey { - @Nonnull List getParameterTypes(); - @Nonnull String getReturnType(); - } - - // a temporary lightweight class to allow a quick probe if the given prototype has already been interned - private static class Key implements ProtoKey { - @Nonnull private final List parameters; - @Nonnull private final String returnType; - - public Key(@Nonnull List parameters, @Nonnull String returnType) { - this.parameters = parameters; - this.returnType = returnType; - } - - @Nonnull public List getParameterTypes() { - return parameters; - } - - @Nonnull public String getReturnType() { - return returnType; - } - - @Override public int hashCode() { - int hashCode = returnType.hashCode(); - return hashCode*31 + parameters.hashCode(); - } - - @Override public boolean equals(Object o) { - if (o != null && o instanceof ProtoKey) { - ProtoKey other = (ProtoKey)o; - return getReturnType().equals(other.getReturnType()) && - CharSequenceUtils.listEquals(getParameterTypes(), other.getParameterTypes()); - } - return false; - } - } } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java index d1190249..b7507fa6 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/builder/DexBuilder.java @@ -54,7 +54,7 @@ import java.util.List; import java.util.Set; public class DexBuilder extends DexWriter { @@ -176,6 +176,10 @@ public class DexBuilder extends DexWriter, TypeListPool.Key>, Field, PoolMethod, EncodedValue, AnnotationElement> { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java index 7ae42fb6..8103d319 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/MethodPool.java @@ -31,13 +31,14 @@ package org.jf.dexlib2.writer.pool; +import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.iface.reference.MethodReference; import org.jf.dexlib2.writer.MethodSection; import javax.annotation.Nonnull; public class MethodPool extends BaseIndexPool - implements MethodSection { + implements MethodSection { @Nonnull private final StringPool stringPool; @Nonnull private final TypePool typePool; @Nonnull private final ProtoPool protoPool; @@ -53,7 +54,7 @@ public class MethodPool extends BaseIndexPool Integer prev = internedItems.put(method, 0); if (prev == null) { typePool.intern(method.getDefiningClass()); - protoPool.intern(method); + protoPool.intern(new PoolMethodProto(method)); stringPool.intern(method.getName()); } } @@ -62,12 +63,12 @@ public class MethodPool extends BaseIndexPool return methodReference.getDefiningClass(); } - @Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull MethodReference methodReference) { - return new ProtoPool.Key(methodReference); + @Nonnull @Override public MethodProtoReference getPrototype(@Nonnull MethodReference methodReference) { + return new PoolMethodProto(methodReference); } - @Nonnull @Override public ProtoPool.Key getPrototype(@Nonnull PoolMethod poolMethod) { - return new ProtoPool.Key(poolMethod); + @Nonnull @Override public MethodProtoReference getPrototype(@Nonnull PoolMethod poolMethod) { + return new PoolMethodProto(poolMethod); } @Nonnull @Override public CharSequence getName(@Nonnull MethodReference methodReference) { diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethodProto.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethodProto.java new file mode 100644 index 00000000..d180be1d --- /dev/null +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/PoolMethodProto.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016, 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.dexlib2.writer.pool; + +import org.jf.dexlib2.base.reference.BaseMethodProtoReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; +import org.jf.dexlib2.iface.reference.MethodReference; + +import java.util.List; + +public class PoolMethodProto extends BaseMethodProtoReference implements MethodProtoReference { + private final MethodReference methodReference; + + public PoolMethodProto(MethodReference methodReference) { + this.methodReference = methodReference; + } + + @Override + public List getParameterTypes() { + return methodReference.getParameterTypes(); + } + + @Override + public String getReturnType() { + return methodReference.getReturnType(); + } +} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java index eeabdf4a..523e5f4d 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/pool/ProtoPool.java @@ -31,21 +31,18 @@ package org.jf.dexlib2.writer.pool; -import com.google.common.collect.Ordering; -import org.jf.dexlib2.iface.reference.MethodReference; +import org.jf.dexlib2.iface.reference.MethodProtoReference; import org.jf.dexlib2.util.MethodUtil; -import org.jf.dexlib2.writer.pool.ProtoPool.Key; import org.jf.dexlib2.writer.ProtoSection; -import org.jf.util.CharSequenceUtils; -import org.jf.util.CollectionUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; -public class ProtoPool extends BaseIndexPool - implements ProtoSection>> { +public class ProtoPool extends BaseIndexPool + implements ProtoSection>> { @Nonnull private final StringPool stringPool; @Nonnull private final TypePool typePool; @Nonnull private final TypeListPool typeListPool; @@ -57,78 +54,25 @@ public class ProtoPool extends BaseIndexPool this.typeListPool = typeListPool; } - public void intern(@Nonnull MethodReference method) { - // We can't use method directly, because it is likely a full MethodReference. We use a wrapper that computes - // hashCode and equals based only on the prototype fields - Key key = new Key(method); - Integer prev = internedItems.put(key, 0); + public void intern(@Nonnull MethodProtoReference reference) { + Integer prev = internedItems.put(reference, 0); if (prev == null) { - stringPool.intern(key.getShorty()); - typePool.intern(method.getReturnType()); - typeListPool.intern(method.getParameterTypes()); + stringPool.intern(getShorty(reference)); + typePool.intern(reference.getReturnType()); + typeListPool.intern(reference.getParameterTypes()); } } - @Nonnull @Override public CharSequence getShorty(@Nonnull Key key) { - return key.getShorty(); + @Nonnull @Override public CharSequence getShorty(@Nonnull MethodProtoReference reference) { + return MethodUtil.getShorty(reference.getParameterTypes(), reference.getReturnType()); } - @Nonnull @Override public CharSequence getReturnType(@Nonnull Key key) { - return key.getReturnType(); + @Nonnull @Override public CharSequence getReturnType(@Nonnull MethodProtoReference protoReference) { + return protoReference.getReturnType(); } - @Nullable @Override public TypeListPool.Key> getParameters(@Nonnull Key key) { - return new TypeListPool.Key>(key.getParameters()); - } - - public static class Key implements Comparable { - @Nonnull private final MethodReference method; - - public Key(@Nonnull MethodReference method) { - this.method = method; - } - - @Nonnull public String getReturnType() { return method.getReturnType(); } - @Nonnull public List getParameters() { - return method.getParameterTypes(); - } - - public String getShorty() { - return MethodUtil.getShorty(method.getParameterTypes(), method.getReturnType()); - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('('); - for (CharSequence paramType: getParameters()) { - sb.append(paramType); - } - sb.append(')'); - sb.append(getReturnType()); - return sb.toString(); - } - - @Override - public int hashCode() { - int hashCode = getReturnType().hashCode(); - return hashCode*31 + CharSequenceUtils.listHashCode(getParameters()); - } - - @Override - public boolean equals(@Nullable Object o) { - if (o instanceof Key) { - Key other = (Key)o; - return getReturnType().equals(other.getReturnType()) && - CharSequenceUtils.listEquals(getParameters(), other.getParameters()); - } - return false; - } - - @Override - public int compareTo(@Nonnull Key o) { - int res = getReturnType().compareTo(o.getReturnType()); - if (res != 0) return res; - return CollectionUtils.compareAsIterable(Ordering.usingToString(), getParameters(), o.getParameters()); - } + @Nullable @Override public TypeListPool.Key> getParameters( + @Nonnull MethodProtoReference methodProto) { + return new TypeListPool.Key>(methodProto.getParameterTypes()); } } diff --git a/smali/src/main/antlr/smaliParser.g b/smali/src/main/antlr/smaliParser.g index fcccbe80..29148f7b 100644 --- a/smali/src/main/antlr/smaliParser.g +++ b/smali/src/main/antlr/smaliParser.g @@ -120,6 +120,8 @@ tokens { INSTRUCTION_FORMAT3rc_TYPE; INSTRUCTION_FORMAT3rmi_METHOD; INSTRUCTION_FORMAT3rms_METHOD; + INSTRUCTION_FORMAT45cc_METHOD; + INSTRUCTION_FORMAT4rcc_METHOD; INSTRUCTION_FORMAT51l; LINE_COMMENT; LINE_DIRECTIVE; @@ -234,6 +236,8 @@ tokens { I_STATEMENT_FORMAT35c_TYPE; I_STATEMENT_FORMAT3rc_METHOD; I_STATEMENT_FORMAT3rc_TYPE; + I_STATEMENT_FORMAT45cc_METHOD; + I_STATEMENT_FORMAT4rcc_METHOD; I_STATEMENT_FORMAT51l; I_STATEMENT_ARRAY_DATA; I_STATEMENT_PACKED_SWITCH; @@ -581,6 +585,8 @@ simple_name | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] + | INSTRUCTION_FORMAT45cc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT45cc_METHOD] + | INSTRUCTION_FORMAT4rcc_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT4rcc_METHOD] | INSTRUCTION_FORMAT51l -> SIMPLE_NAME[$INSTRUCTION_FORMAT51l]; member_name @@ -849,6 +855,8 @@ instruction | insn_format3rc_type | insn_format3rmi_method | insn_format3rms_method + | insn_format45cc_method + | insn_format4rcc_method | insn_format51l | insn_array_data_directive | insn_packed_switch_directive @@ -1106,6 +1114,16 @@ insn_format3rms_method throwOdexedInstructionException(input, $INSTRUCTION_FORMAT3rms_METHOD.text); }; +insn_format45cc_method + : //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J + INSTRUCTION_FORMAT45cc_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA method_reference COMMA method_prototype + -> ^(I_STATEMENT_FORMAT45cc_METHOD[$start, "I_STATEMENT_FORMAT45cc_METHOD"] INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype); + +insn_format4rcc_method + : //e.g. invoke-polymorphic/range {v0,v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J + INSTRUCTION_FORMAT4rcc_METHOD OPEN_BRACE register_range CLOSE_BRACE COMMA method_reference COMMA method_prototype + -> ^(I_STATEMENT_FORMAT4rcc_METHOD[$start, "I_STATEMENT_FORMAT4rcc_METHOD"] INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype); + insn_format51l : //e.g. const-wide v0, 5000000000L INSTRUCTION_FORMAT51l REGISTER COMMA fixed_literal @@ -1141,4 +1159,4 @@ insn_sparse_switch_directive (fixed_32bit_literal ARROW label_ref)* END_SPARSE_SWITCH_DIRECTIVE -> ^(I_STATEMENT_SPARSE_SWITCH[$start, "I_STATEMENT_SPARSE_SWITCH"] - ^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal label_ref)*)); \ No newline at end of file + ^(I_SPARSE_SWITCH_ELEMENTS[$start, "I_SPARSE_SWITCH_ELEMENTS"] (fixed_32bit_literal label_ref)*)); diff --git a/smali/src/main/antlr/smaliTreeWalker.g b/smali/src/main/antlr/smaliTreeWalker.g index c3a50994..7f5657a5 100644 --- a/smali/src/main/antlr/smaliTreeWalker.g +++ b/smali/src/main/antlr/smaliTreeWalker.g @@ -62,6 +62,7 @@ import org.jf.dexlib2.immutable.ImmutableAnnotation; import org.jf.dexlib2.immutable.ImmutableAnnotationElement; import org.jf.dexlib2.immutable.reference.ImmutableFieldReference; import org.jf.dexlib2.immutable.reference.ImmutableMethodReference; +import org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference; import org.jf.dexlib2.immutable.reference.ImmutableReference; import org.jf.dexlib2.immutable.reference.ImmutableTypeReference; import org.jf.dexlib2.immutable.value.*; @@ -766,6 +767,8 @@ instruction | insn_format35c_type | insn_format3rc_method | insn_format3rc_type + | insn_format45cc_method + | insn_format4rcc_method | insn_format51l_type | insn_array_data_directive | insn_packed_switch_directive @@ -1181,6 +1184,47 @@ insn_format3rc_type dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; +insn_format45cc_method + : //e.g. invoke-polymorphic {v0, v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J + ^(I_STATEMENT_FORMAT45cc_METHOD INSTRUCTION_FORMAT45cc_METHOD register_list method_reference method_prototype) + { + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT45cc_METHOD.text); + + //this depends on the fact that register_list returns a byte[5] + byte[] registers = $register_list.registers; + byte registerCount = $register_list.registerCount; + + ImmutableMethodReference methodReference = $method_reference.methodReference; + ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference( + $method_prototype.parameters, + $method_prototype.returnType); + + $method::methodBuilder.addInstruction(new BuilderInstruction45cc(opcode, registerCount, registers[0], registers[1], + registers[2], registers[3], registers[4], + dexBuilder.internMethodReference(methodReference), + dexBuilder.internMethodProtoReference(methodProtoReference))); + }; + +insn_format4rcc_method + : //e.g. invoke-polymorphic {v0..v1}, java/lang/invoke/MethodHandle;->invoke([Ljava/lang/Object;)Ljava/lang/Object;, (I)J + ^(I_STATEMENT_FORMAT4rcc_METHOD INSTRUCTION_FORMAT4rcc_METHOD register_range method_reference method_prototype) + { + Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT4rcc_METHOD.text); + int startRegister = $register_range.startRegister; + int endRegister = $register_range.endRegister; + + int registerCount = endRegister-startRegister+1; + + ImmutableMethodReference methodReference = $method_reference.methodReference; + ImmutableMethodProtoReference methodProtoReference = new ImmutableMethodProtoReference( + $method_prototype.parameters, + $method_prototype.returnType); + + $method::methodBuilder.addInstruction(new BuilderInstruction4rcc(opcode, startRegister, registerCount, + dexBuilder.internMethodReference(methodReference), + dexBuilder.internMethodProtoReference(methodProtoReference))); + }; + insn_format51l_type : //e.g. const-wide v0, 5000000000L ^(I_STATEMENT_FORMAT51l INSTRUCTION_FORMAT51l REGISTER fixed_64bit_literal) diff --git a/smali/src/main/jflex/smaliLexer.jflex b/smali/src/main/jflex/smaliLexer.jflex index 2f57a438..e0010a93 100644 --- a/smali/src/main/jflex/smaliLexer.jflex +++ b/smali/src/main/jflex/smaliLexer.jflex @@ -624,6 +624,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT3rms_METHOD); } + "invoke-polymorphic" { + return newToken(INSTRUCTION_FORMAT45cc_METHOD); + } + + "invoke-polymorphic/range" { + return newToken(INSTRUCTION_FORMAT4rcc_METHOD); + } + "const-wide" { return newToken(INSTRUCTION_FORMAT51l); } From 99b80bbc5a55f53e73a143a90f94faefbd5e4f7f Mon Sep 17 00:00:00 2001 From: Narayan Kamath Date: Wed, 17 Aug 2016 11:39:28 +0100 Subject: [PATCH 2/2] Revert "Add lambda experimental dalvik opcodes" This reverts commit 144951a9e9e6c87866245f2bdeebf0ebedaa0e38. --- .../Format/InstructionMethodItem.java | 42 -------- .../LambdaTest/HelloWorldLambda.smali | 55 ----------- .../src/main/java/org/jf/dexlib2/Format.java | 1 - .../src/main/java/org/jf/dexlib2/Opcode.java | 9 -- .../builder/MutableMethodImplementation.java | 15 --- .../instruction/BuilderInstruction25x.java | 82 ---------------- .../instruction/DexBackedInstruction.java | 2 - .../instruction/DexBackedInstruction25x.java | 83 ---------------- .../jf/dexlib2/dexbacked/raw/CodeItem.java | 27 ------ ...FixedFourParameterRegisterInstruction.java | 47 --------- .../instruction/formats/Instruction25x.java | 37 ------- .../instruction/ImmutableInstruction.java | 2 - .../instruction/ImmutableInstruction25x.java | 97 ------------------- .../org/jf/dexlib2/util/Preconditions.java | 9 -- .../java/org/jf/dexlib2/writer/DexWriter.java | 3 - .../jf/dexlib2/writer/InstructionWriter.java | 14 --- .../HelloWorldFunctionalInterface.smali | 8 -- .../HelloWorldLambda/HelloWorldLambda.smali | 57 ----------- smali/src/main/antlr/smaliParser.g | 36 ------- smali/src/main/antlr/smaliTreeWalker.g | 73 -------------- smali/src/main/jflex/smaliLexer.jflex | 20 +--- .../resources/LexerTest/InstructionTest.smali | 6 -- .../LexerTest/InstructionTest.tokens | 6 -- 23 files changed, 2 insertions(+), 729 deletions(-) delete mode 100644 baksmali/src/test/resources/LambdaTest/HelloWorldLambda.smali delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java delete mode 100644 dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java delete mode 100644 examples/HelloWorldLambda/HelloWorldFunctionalInterface.smali delete mode 100644 examples/HelloWorldLambda/HelloWorldLambda.smali 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 39485c90..fe85fe00 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 @@ -330,11 +330,6 @@ public class InstructionMethodItem extends MethodItem { writer.write(", "); writeThirdRegister(writer); break; - case Format25x: - writeOpcode(writer); - writer.write(' '); - writeInvoke25xRegisters(writer); // vC, {vD, ...} - break; case Format35c: writeOpcode(writer); writer.write(' '); @@ -478,43 +473,6 @@ public class InstructionMethodItem extends MethodItem { writer.write('}'); } - protected void writeInvoke25xRegisters(IndentingWriter writer) throws IOException { - OneFixedFourParameterRegisterInstruction instruction = - (OneFixedFourParameterRegisterInstruction)this.instruction; - final int parameterRegCount = instruction.getParameterRegisterCount(); - - writeRegister(writer, instruction.getRegisterFixedC()); // fixed register always present - - writer.write(", {"); - switch (parameterRegCount) { - case 1: - writeRegister(writer, instruction.getRegisterParameterD()); - break; - case 2: - writeRegister(writer, instruction.getRegisterParameterD()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterE()); - break; - case 3: - writeRegister(writer, instruction.getRegisterParameterD()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterE()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterF()); - break; - case 4: - writeRegister(writer, instruction.getRegisterParameterD()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterE()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterF()); - writer.write(", "); - writeRegister(writer, instruction.getRegisterParameterG()); - break; - } - writer.write('}'); - } - protected void writeInvokeRangeRegisters(IndentingWriter writer) throws IOException { RegisterRangeInstruction instruction = (RegisterRangeInstruction)this.instruction; diff --git a/baksmali/src/test/resources/LambdaTest/HelloWorldLambda.smali b/baksmali/src/test/resources/LambdaTest/HelloWorldLambda.smali deleted file mode 100644 index d70ced50..00000000 --- a/baksmali/src/test/resources/LambdaTest/HelloWorldLambda.smali +++ /dev/null @@ -1,55 +0,0 @@ -.class public LHelloWorldLambda; - -#Ye olde hello world application (with lambdas!) -#To assemble and run this on a phone or emulator: -# -#java -jar smali.jar -o classes.dex HelloWorldLambda.smali HelloWorldFunctionalInterface.smali -#zip HelloWorld.zip classes.dex -#adb push HelloWorld.zip /data/local -#adb shell dalvikvm -cp /data/local/HelloWorld.zip HelloWorld -# -#if you get out of memory type errors when running smali.jar, try -#java -Xmx512m -jar smali.jar HelloWorldLambda.smali -#instead - -.super Ljava/lang/Object; - -.method public static doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - .registers 6 # 4 parameters, 2 locals - liberate-variable v0, p0, "helloworld" - - sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; - invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V - - return-void -.end method - -.method public static main([Ljava/lang/String;)V - .registers 9 # 1 parameter, 8 locals - - sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream; - - const-string v1, "Hello World!" - const-string v2, "How" # vD - const-string v3, "are" # vE - const-string v4, "you" # vF - const-string v5, "doing?" # vG - - capture-variable v1, "helloworld" - - # TODO: do I need to pass the type of the lambda's functional interface here as a type id? - create-lambda v1, LHelloWorldLambda;->doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - # Method descriptor is not required here, because only the single-abstract method is ever invoked. - invoke-lambda v1, {v2, v3, v4, v5} - - box-lambda v6, v1 - invoke-virtual {v6, v2, v3, v4, v5}, LHelloWorldFunctionalInterface;->applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - - # FIXME: should be \HelloWorldFunctionalInterface; instead of L...; - - # TODO: do we really need the type descriptor here at all? - unbox-lambda v7, v6, LHelloWorldFunctionalInterface; - invoke-lambda v7, {v2, v3, v4, v5} - - return-void -.end method diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Format.java b/dexlib2/src/main/java/org/jf/dexlib2/Format.java index 42e8e144..fd90a6dd 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Format.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Format.java @@ -51,7 +51,6 @@ public enum Format { Format22t(4), Format22x(4), Format23x(4), - Format25x(4), Format30t(6), Format31c(6), Format31i(6), diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java index 9559760a..138c6c63 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java @@ -305,15 +305,6 @@ public enum Opcode SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0), ARRAY_PAYLOAD(0x300, "array-payload", ReferenceType.NONE, Format.ArrayPayload, 0), - // Reuse the deprecated f3-ff opcodes in Art: - INVOKE_LAMBDA(allArtVersions(0xf3),"invoke-lambda", ReferenceType.NONE, Format.Format25x, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT | Opcode.EXPERIMENTAL), - // TODO: What about JUMBO support if the string ID is too large? - CAPTURE_VARIABLE(allArtVersions(0xf5), "capture-variable", ReferenceType.STRING, Format.Format21c, Opcode.EXPERIMENTAL), - CREATE_LAMBDA(allArtVersions(0xf6), "create-lambda", ReferenceType.METHOD, Format.Format21c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), - // TODO: do we need a capture/liberate wide? - LIBERATE_VARIABLE(allArtVersions(0xf7), "liberate-variable", ReferenceType.STRING, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), - BOX_LAMBDA(allArtVersions(0xf8), "box-lambda", ReferenceType.NONE, Format.Format22x, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), - UNBOX_LAMBDA(allArtVersions(0xf9), "unbox-lambda", ReferenceType.TYPE, Format.Format22c, Opcode.SETS_REGISTER | Opcode.EXPERIMENTAL), INVOKE_POLYMORPHIC(firstApi(0xfa, 26), "invoke-polymorphic", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format45cc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_POLYMORPHIC_RANGE(firstApi(0xfb, 26), "invoke-polymorphic/range", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format4rcc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java index b1e5dbbf..148bafd1 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/builder/MutableMethodImplementation.java @@ -615,9 +615,6 @@ public class MutableMethodImplementation implements MethodImplementation { case Format23x: setInstruction(location, newBuilderInstruction23x((Instruction23x) instruction)); return; - case Format25x: - setInstruction(location, newBuilderInstruction25x((Instruction25x) instruction)); - return; case Format30t: setInstruction(location, newBuilderInstruction30t(location.codeAddress, codeAddressToIndex, @@ -871,18 +868,6 @@ public class MutableMethodImplementation implements MethodImplementation { instruction.getReference()); } - @Nonnull - private BuilderInstruction25x newBuilderInstruction25x(@Nonnull Instruction25x instruction) { - return new BuilderInstruction25x( - instruction.getOpcode(), - instruction.getParameterRegisterCount(), - instruction.getRegisterFixedC(), - instruction.getRegisterParameterD(), - instruction.getRegisterParameterE(), - instruction.getRegisterParameterF(), - instruction.getRegisterParameterG()); - } - @Nonnull private BuilderInstruction3rc newBuilderInstruction3rc(@Nonnull Instruction3rc instruction) { return new BuilderInstruction3rc( diff --git a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java deleted file mode 100644 index 3783d2b6..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/builder/instruction/BuilderInstruction25x.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2015, 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.dexlib2.builder.instruction; - -import org.jf.dexlib2.Format; -import org.jf.dexlib2.Opcode; -import org.jf.dexlib2.builder.BuilderInstruction; -import org.jf.dexlib2.iface.instruction.formats.Instruction25x; -import org.jf.dexlib2.util.Preconditions; - -import javax.annotation.Nonnull; - -public class BuilderInstruction25x extends BuilderInstruction implements Instruction25x { - public static final Format FORMAT = Format.Format25x; - - protected final int parameterRegisterCount; - protected final int registerClosure; - protected final int registerD; - protected final int registerE; - protected final int registerF; - protected final int registerG; - - public BuilderInstruction25x(@Nonnull Opcode opcode, - int parameterRegisterCount, - int registerClosure, - int registerD, - int registerE, - int registerF, - int registerG) { - super(opcode); - this.parameterRegisterCount = - Preconditions.check25xParameterRegisterCount(parameterRegisterCount); - this.registerClosure = Preconditions.checkNibbleRegister(registerClosure); //at least 1 reg - this.registerD = (parameterRegisterCount>0) ? - Preconditions.checkNibbleRegister(registerD) : 0; - this.registerE = (parameterRegisterCount>1) ? - Preconditions.checkNibbleRegister(registerE) : 0; - this.registerF = (parameterRegisterCount>2) ? - Preconditions.checkNibbleRegister(registerF) : 0; - this.registerG = (parameterRegisterCount>3) ? - Preconditions.checkNibbleRegister(registerG) : 0; - } - - @Override public int getRegisterCount() { return parameterRegisterCount + 1; } - @Override public int getParameterRegisterCount() { return parameterRegisterCount; } - @Override public int getRegisterFixedC() { return registerClosure; } - @Override public int getRegisterParameterD() { return registerD; } - @Override public int getRegisterParameterE() { return registerE; } - @Override public int getRegisterParameterF() { return registerF; } - @Override public int getRegisterParameterG() { return registerG; } - - @Override public Format getFormat() { return FORMAT; } -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java index 2973398a..975e6813 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction.java @@ -115,8 +115,6 @@ public abstract class DexBackedInstruction implements Instruction { return new DexBackedInstruction22x(dexFile, opcode, instructionStartOffset); case Format23x: return new DexBackedInstruction23x(dexFile, opcode, instructionStartOffset); - case Format25x: - return new DexBackedInstruction25x(dexFile, opcode, instructionStartOffset); case Format30t: return new DexBackedInstruction30t(dexFile, opcode, instructionStartOffset); case Format31c: diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java deleted file mode 100644 index 80fb8767..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/instruction/DexBackedInstruction25x.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015, 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.dexlib2.dexbacked.instruction; - -import org.jf.dexlib2.Opcode; -import org.jf.dexlib2.dexbacked.DexBackedDexFile; -import org.jf.dexlib2.iface.instruction.formats.Instruction25x; -import org.jf.util.NibbleUtils; - -import javax.annotation.Nonnull; - -public class DexBackedInstruction25x extends DexBackedInstruction implements Instruction25x { - public DexBackedInstruction25x(@Nonnull DexBackedDexFile dexFile, - @Nonnull Opcode opcode, - int instructionStart) { - super(dexFile, opcode, instructionStart); - } - - @Override - public int getRegisterCount() { - return getParameterRegisterCount() + 1; - } - - @Override - public int getParameterRegisterCount() { - return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); - } - - @Override - public int getRegisterFixedC() { - return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 2)); - } - - @Override - public int getRegisterParameterD() { - return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 2)); - } - - @Override - public int getRegisterParameterE() { - return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 3)); - } - - @Override - public int getRegisterParameterF() { - return NibbleUtils.extractHighUnsignedNibble(dexFile.readUbyte(instructionStart + 3)); - } - - @Override - public int getRegisterParameterG() { - return NibbleUtils.extractLowUnsignedNibble(dexFile.readUbyte(instructionStart + 1)); - } - -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java index 27d72ad1..eeaff457 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/CodeItem.java @@ -129,9 +129,6 @@ public class CodeItem { case Format10x: annotateInstruction10x(out, instruction); break; - case Format25x: - annotateInstruction25x(out, (Instruction25x) instruction); - break; case Format35c: annotateInstruction35c(out, (Instruction35c)instruction); break; @@ -285,30 +282,6 @@ public class CodeItem { instruction.getOpcode().name, Joiner.on(", ").join(args), reference)); } - private void annotateInstruction25x(@Nonnull AnnotatedBytes out, - @Nonnull Instruction25x instruction) { - List args = Lists.newArrayList(); - - int registerCount = instruction.getRegisterCount(); //at least 1. - if (registerCount == 2) { - args.add(formatRegister(instruction.getRegisterParameterD())); - } else if (registerCount == 3) { - args.add(formatRegister(instruction.getRegisterParameterD())); - args.add(formatRegister(instruction.getRegisterParameterE())); - } else if (registerCount == 4) { - args.add(formatRegister(instruction.getRegisterParameterD())); - args.add(formatRegister(instruction.getRegisterParameterE())); - args.add(formatRegister(instruction.getRegisterParameterF())); - } else if (registerCount == 5) { - args.add(formatRegister(instruction.getRegisterParameterD())); - args.add(formatRegister(instruction.getRegisterParameterE())); - args.add(formatRegister(instruction.getRegisterParameterF())); - args.add(formatRegister(instruction.getRegisterParameterG())); - } - out.annotate(6, String.format("%s %s, {%s}", - instruction.getOpcode().name, instruction.getRegisterFixedC(), Joiner.on(", ").join(args))); - } - private void annotateInstruction3rc(@Nonnull AnnotatedBytes out, @Nonnull Instruction3rc instruction) { int startRegister = instruction.getStartRegister(); int endRegister = startRegister + instruction.getRegisterCount() - 1; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java deleted file mode 100644 index c03bff77..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/OneFixedFourParameterRegisterInstruction.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015, 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.dexlib2.iface.instruction; - -public interface OneFixedFourParameterRegisterInstruction extends VariableRegisterInstruction { - int getRegisterFixedC(); - int getRegisterParameterD(); - int getRegisterParameterE(); - int getRegisterParameterF(); - int getRegisterParameterG(); - - /** Returns the count of just the parameter register counts; in range of [0, 4] */ - int getParameterRegisterCount(); - - /** Includes the total sum of both fixed and parameter register counts; at least 1 */ - @Override - int getRegisterCount(); -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java deleted file mode 100644 index 51df2dee..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/iface/instruction/formats/Instruction25x.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015, 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.dexlib2.iface.instruction.formats; - -import org.jf.dexlib2.iface.instruction.OneFixedFourParameterRegisterInstruction; - -public interface Instruction25x extends OneFixedFourParameterRegisterInstruction { -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java index ed50ef5b..432f1930 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction.java @@ -97,8 +97,6 @@ public abstract class ImmutableInstruction implements Instruction { return ImmutableInstruction22x.of((Instruction22x)instruction); case Format23x: return ImmutableInstruction23x.of((Instruction23x)instruction); - case Format25x: - return ImmutableInstruction25x.of((Instruction25x) instruction); case Format30t: return ImmutableInstruction30t.of((Instruction30t)instruction); case Format31c: diff --git a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java b/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java deleted file mode 100644 index 2f31eaea..00000000 --- a/dexlib2/src/main/java/org/jf/dexlib2/immutable/instruction/ImmutableInstruction25x.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2015, 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.dexlib2.immutable.instruction; - -import org.jf.dexlib2.Format; -import org.jf.dexlib2.Opcode; -import org.jf.dexlib2.iface.instruction.formats.Instruction25x; -import org.jf.dexlib2.util.Preconditions; - -import javax.annotation.Nonnull; - -public class ImmutableInstruction25x extends ImmutableInstruction implements Instruction25x { - public static final Format FORMAT = Format.Format25x; - - protected final int parameterRegisterCount; - protected final int registerClosure; - protected final int registerD; - protected final int registerE; - protected final int registerF; - protected final int registerG; - - public ImmutableInstruction25x(@Nonnull Opcode opcode, - int parameterRegisterCount, - int registerClosure, - int registerD, - int registerE, - int registerF, - int registerG) { - super(opcode); - this.parameterRegisterCount = - Preconditions.check25xParameterRegisterCount(parameterRegisterCount); - this.registerClosure = Preconditions.checkNibbleRegister(registerClosure); - this.registerD = (parameterRegisterCount>0) ? - Preconditions.checkNibbleRegister(registerD) : 0; - this.registerE = (parameterRegisterCount>1) ? - Preconditions.checkNibbleRegister(registerE) : 0; - this.registerF = (parameterRegisterCount>2) ? - Preconditions.checkNibbleRegister(registerF) : 0; - this.registerG = (parameterRegisterCount>3) ? - Preconditions.checkNibbleRegister(registerG) : 0; - } - - public static ImmutableInstruction25x of(Instruction25x instruction) { - if (instruction instanceof ImmutableInstruction25x) { - return (ImmutableInstruction25x)instruction; - } - return new ImmutableInstruction25x( - instruction.getOpcode(), - instruction.getRegisterCount(), - instruction.getRegisterFixedC(), - instruction.getRegisterParameterD(), - instruction.getRegisterParameterE(), - instruction.getRegisterParameterF(), - instruction.getRegisterParameterG()); - } - - - @Override public int getParameterRegisterCount() { return parameterRegisterCount; } - @Override public int getRegisterCount() { return parameterRegisterCount + 1; } - - @Override public int getRegisterFixedC() { return registerClosure; } - @Override public int getRegisterParameterD() { return registerD; } - @Override public int getRegisterParameterE() { return registerE; } - @Override public int getRegisterParameterF() { return registerF; } - @Override public int getRegisterParameterG() { return registerG; } - - @Override public Format getFormat() { return FORMAT; } -} diff --git a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java index 3b30d075..2f9fe2d7 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/util/Preconditions.java @@ -133,15 +133,6 @@ public class Preconditions { return registerCount; } - public static int check25xParameterRegisterCount(int registerCount) { - if (registerCount < 0 || registerCount > 4) { - throw new IllegalArgumentException( - String.format("Invalid parameter register count: %d. " + - "Must be between 0 and 4, inclusive.", registerCount)); - } - return registerCount; - } - public static int checkRegisterRangeCount(int registerCount) { if ((registerCount & 0xFFFFFF00) != 0) { throw new IllegalArgumentException( diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java index 5329351e..6ca1ce93 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java @@ -1006,9 +1006,6 @@ public abstract class DexWriter< case Format23x: instructionWriter.write((Instruction23x)instruction); break; - case Format25x: - instructionWriter.write((Instruction25x)instruction); - break; case Format30t: instructionWriter.write((Instruction30t)instruction); break; diff --git a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java index c240c515..1b883f1f 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java @@ -343,20 +343,6 @@ public class InstructionWriterout:Ljava/io/PrintStream; - - const-string v1, "Hello World!" - const-string v2, "How" # vD - const-string v3, "are" # vE - const-string v4, "you" # vF - const-string v5, "doing?" # vG - - capture-variable v1, "helloworld" - - # TODO: do I need to pass the type of the lambda's functional interface here as a type id? - create-lambda v1, LHelloWorldLambda;->doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - # Method descriptor is not required here, because only the single-abstract method is ever invoked. - invoke-lambda v1, {v2, v3, v4, v5} - - box-lambda v6, v1 # The type of v6 is now 'LHelloWorldFunctionalInterface;' - invoke-virtual {v6, v2, v3, v4, v5}, LHelloWorldFunctionalInterface;->applyFourStrings(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - - # FIXME: should be \HelloWorldFunctionalInterface; instead of L...; - - # TODO: do we really need the type descriptor here at all? - unbox-lambda v7, v6, LHelloWorldFunctionalInterface; # The type of v7 is now \HelloWorldFunctionalInterface; - invoke-lambda v7, {v2, v3, v4, v5} - - return-void -.end method - -.method public static doHelloWorld(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - .registers 6 # 4 parameters, 2 locals - - # This helloworld variable is brought to you by the variable liberation front - liberate-variable v0, p0, "helloworld" - - sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; - invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V - - return-void -.end method diff --git a/smali/src/main/antlr/smaliParser.g b/smali/src/main/antlr/smaliParser.g index 29148f7b..29cd141b 100644 --- a/smali/src/main/antlr/smaliParser.g +++ b/smali/src/main/antlr/smaliParser.g @@ -86,8 +86,6 @@ tokens { INSTRUCTION_FORMAT21c_FIELD_ODEX; INSTRUCTION_FORMAT21c_STRING; INSTRUCTION_FORMAT21c_TYPE; - INSTRUCTION_FORMAT21c_LAMBDA; - INSTRUCTION_FORMAT21c_METHOD; INSTRUCTION_FORMAT21ih; INSTRUCTION_FORMAT21lh; INSTRUCTION_FORMAT21s; @@ -96,14 +94,12 @@ tokens { INSTRUCTION_FORMAT22c_FIELD; INSTRUCTION_FORMAT22c_FIELD_ODEX; INSTRUCTION_FORMAT22c_TYPE; - INSTRUCTION_FORMAT22c_STRING; INSTRUCTION_FORMAT22cs_FIELD; INSTRUCTION_FORMAT22s; INSTRUCTION_FORMAT22s_OR_ID; INSTRUCTION_FORMAT22t; INSTRUCTION_FORMAT22x; INSTRUCTION_FORMAT23x; - INSTRUCTION_FORMAT25x; INSTRUCTION_FORMAT30t; INSTRUCTION_FORMAT31c; INSTRUCTION_FORMAT31i; @@ -212,8 +208,6 @@ tokens { I_STATEMENT_FORMAT21c_TYPE; I_STATEMENT_FORMAT21c_FIELD; I_STATEMENT_FORMAT21c_STRING; - I_STATEMENT_FORMAT21c_LAMBDA; - I_STATEMENT_FORMAT21c_METHOD; I_STATEMENT_FORMAT21ih; I_STATEMENT_FORMAT21lh; I_STATEMENT_FORMAT21s; @@ -221,12 +215,10 @@ tokens { I_STATEMENT_FORMAT22b; I_STATEMENT_FORMAT22c_FIELD; I_STATEMENT_FORMAT22c_TYPE; - I_STATEMENT_FORMAT22c_STRING; I_STATEMENT_FORMAT22s; I_STATEMENT_FORMAT22t; I_STATEMENT_FORMAT22x; I_STATEMENT_FORMAT23x; - I_STATEMENT_FORMAT25x; I_STATEMENT_FORMAT30t; I_STATEMENT_FORMAT31c; I_STATEMENT_FORMAT31i; @@ -566,18 +558,14 @@ simple_name | INSTRUCTION_FORMAT21c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_FIELD_ODEX] | INSTRUCTION_FORMAT21c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_STRING] | INSTRUCTION_FORMAT21c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_TYPE] - | INSTRUCTION_FORMAT21c_LAMBDA -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_LAMBDA] - | INSTRUCTION_FORMAT21c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT21c_METHOD] | INSTRUCTION_FORMAT21t -> SIMPLE_NAME[$INSTRUCTION_FORMAT21t] | INSTRUCTION_FORMAT22c_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD] | INSTRUCTION_FORMAT22c_FIELD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_FIELD_ODEX] | INSTRUCTION_FORMAT22c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_TYPE] - | INSTRUCTION_FORMAT22c_STRING -> SIMPLE_NAME[$INSTRUCTION_FORMAT22c_STRING] | INSTRUCTION_FORMAT22cs_FIELD -> SIMPLE_NAME[$INSTRUCTION_FORMAT22cs_FIELD] | INSTRUCTION_FORMAT22s_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT22s_OR_ID] | INSTRUCTION_FORMAT22t -> SIMPLE_NAME[$INSTRUCTION_FORMAT22t] | INSTRUCTION_FORMAT23x -> SIMPLE_NAME[$INSTRUCTION_FORMAT23x] - | INSTRUCTION_FORMAT25x -> SIMPLE_NAME[$INSTRUCTION_FORMAT25x] | INSTRUCTION_FORMAT31i_OR_ID -> SIMPLE_NAME[$INSTRUCTION_FORMAT31i_OR_ID] | INSTRUCTION_FORMAT31t -> SIMPLE_NAME[$INSTRUCTION_FORMAT31t] | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] @@ -823,8 +811,6 @@ instruction | insn_format21c_field_odex | insn_format21c_string | insn_format21c_type - | insn_format21c_lambda - | insn_format21c_method | insn_format21ih | insn_format21lh | insn_format21s @@ -833,13 +819,11 @@ instruction | insn_format22c_field | insn_format22c_field_odex | insn_format22c_type - | insn_format22c_string | insn_format22cs_field | insn_format22s | insn_format22t | insn_format22x | insn_format23x - | insn_format25x | insn_format30t | insn_format31c | insn_format31i @@ -935,16 +919,6 @@ insn_format21c_type INSTRUCTION_FORMAT21c_TYPE REGISTER COMMA nonvoid_type_descriptor -> ^(I_STATEMENT_FORMAT21c_TYPE[$start, "I_STATEMENT_FORMAT21c"] INSTRUCTION_FORMAT21c_TYPE REGISTER nonvoid_type_descriptor); -insn_format21c_lambda - : //e.g. capture-variable v1, "foobar" - INSTRUCTION_FORMAT21c_LAMBDA REGISTER COMMA STRING_LITERAL - -> ^(I_STATEMENT_FORMAT21c_LAMBDA[$start, "I_STATEMENT_FORMAT21c_LAMBDA"] INSTRUCTION_FORMAT21c_LAMBDA REGISTER STRING_LITERAL); - -insn_format21c_method - : //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V - INSTRUCTION_FORMAT21c_METHOD REGISTER COMMA method_reference - -> ^(I_STATEMENT_FORMAT21c_METHOD[$start, "I_STATEMENT_FORMAT21c_METHOD"] INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference); - insn_format21ih : //e.g. const/high16 v1, 1234 INSTRUCTION_FORMAT21ih REGISTER COMMA fixed_32bit_literal @@ -990,11 +964,6 @@ insn_format22c_type INSTRUCTION_FORMAT22c_TYPE REGISTER COMMA REGISTER COMMA nonvoid_type_descriptor -> ^(I_STATEMENT_FORMAT22c_TYPE[$start, "I_STATEMENT_FORMAT22c_TYPE"] INSTRUCTION_FORMAT22c_TYPE REGISTER REGISTER nonvoid_type_descriptor); -insn_format22c_string - : //e.g. liberate-variable v0, v1, "baz" - INSTRUCTION_FORMAT22c_STRING REGISTER COMMA REGISTER COMMA STRING_LITERAL - -> ^(I_STATEMENT_FORMAT22c_STRING[$start, "I_STATEMENT_FORMAT22c_STRING"] INSTRUCTION_FORMAT22c_STRING REGISTER REGISTER STRING_LITERAL); - insn_format22cs_field : //e.g. iget-quick v0, v1, field@0xc INSTRUCTION_FORMAT22cs_FIELD REGISTER COMMA REGISTER COMMA FIELD_OFFSET @@ -1022,11 +991,6 @@ insn_format23x INSTRUCTION_FORMAT23x REGISTER COMMA REGISTER COMMA REGISTER -> ^(I_STATEMENT_FORMAT23x[$start, "I_STATEMENT_FORMAT23x"] INSTRUCTION_FORMAT23x REGISTER REGISTER REGISTER); -insn_format25x - : //e.g. invoke-lambda vClosure, {vA, vB, vC, vD} -- up to 4 parameters + the closure. - INSTRUCTION_FORMAT25x REGISTER COMMA OPEN_BRACE register_list CLOSE_BRACE - -> ^(I_STATEMENT_FORMAT25x[$start, "I_STATEMENT_FORMAT25x"] INSTRUCTION_FORMAT25x REGISTER register_list); - insn_format30t : //e.g. goto/32 endloop: INSTRUCTION_FORMAT30t label_ref diff --git a/smali/src/main/antlr/smaliTreeWalker.g b/smali/src/main/antlr/smaliTreeWalker.g index 7f5657a5..d074579b 100644 --- a/smali/src/main/antlr/smaliTreeWalker.g +++ b/smali/src/main/antlr/smaliTreeWalker.g @@ -675,22 +675,6 @@ register_list returns[byte[\] registers, byte registerCount] $registers[$registerCount++] = parseRegister_nibble($REGISTER.text); })*); -register_list4 returns[byte[\] registers, byte registerCount] - @init - { - $registers = new byte[4]; - $registerCount = 0; - } - : ^(I_REGISTER_LIST - (REGISTER - { - if ($registerCount == 4) { - throw new SemanticException(input, $I_REGISTER_LIST, "A list4 of registers can only have a maximum of 4 " + - "registers. Use the /range alternate opcode instead."); - } - $registers[$registerCount++] = parseRegister_nibble($REGISTER.text); - })*); - register_range returns[int startRegister, int endRegister] : ^(I_REGISTER_RANGE (startReg=REGISTER endReg=REGISTER?)?) { @@ -743,8 +727,6 @@ instruction | insn_format21c_field | insn_format21c_string | insn_format21c_type - | insn_format21c_lambda - | insn_format21c_method | insn_format21ih | insn_format21lh | insn_format21s @@ -752,12 +734,10 @@ instruction | insn_format22b | insn_format22c_field | insn_format22c_type - | insn_format22c_string | insn_format22s | insn_format22t | insn_format22x | insn_format23x - | insn_format25x | insn_format30t | insn_format31c | insn_format31i @@ -884,30 +864,6 @@ insn_format21c_type dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; -insn_format21c_lambda - : //e.g. capture-variable v1, "foobar" - ^(I_STATEMENT_FORMAT21c_LAMBDA INSTRUCTION_FORMAT21c_LAMBDA REGISTER string_literal) - { - Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_LAMBDA.text); - short regA = parseRegister_byte($REGISTER.text); - - $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, - dexBuilder.internStringReference($string_literal.value))); - }; - -insn_format21c_method - : //e.g. create-lambda v1, java/io/PrintStream/print(Ljava/lang/Stream;)V - ^(I_STATEMENT_FORMAT21c_METHOD INSTRUCTION_FORMAT21c_METHOD REGISTER method_reference) - { - Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT21c_METHOD.text); - short regA = parseRegister_byte($REGISTER.text); - - ImmutableMethodReference methodReference = $method_reference.methodReference; - - $method::methodBuilder.addInstruction(new BuilderInstruction21c(opcode, regA, - dexBuilder.internMethodReference(methodReference))); - }; - insn_format21ih : //e.g. const/high16 v1, 1234 ^(I_STATEMENT_FORMAT21ih INSTRUCTION_FORMAT21ih REGISTER fixed_32bit_literal) @@ -994,18 +950,6 @@ insn_format22c_type dexBuilder.internTypeReference($nonvoid_type_descriptor.type))); }; -insn_format22c_string - : //e.g. liberate-variable v0, v1, "baz" - ^(I_STATEMENT_FORMAT22c_STRING INSTRUCTION_FORMAT22c_STRING registerA=REGISTER registerB=REGISTER string_literal) - { - Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT22c_STRING.text); - byte regA = parseRegister_nibble($registerA.text); - byte regB = parseRegister_nibble($registerB.text); - - $method::methodBuilder.addInstruction(new BuilderInstruction22c(opcode, regA, regB, - dexBuilder.internStringReference($string_literal.value))); - }; - insn_format22s : //e.g. add-int/lit16 v0, v1, 12345 ^(I_STATEMENT_FORMAT22s INSTRUCTION_FORMAT22s registerA=REGISTER registerB=REGISTER short_integral_literal) @@ -1053,23 +997,6 @@ insn_format23x $method::methodBuilder.addInstruction(new BuilderInstruction23x(opcode, regA, regB, regC)); }; -insn_format25x - : //e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- up to 4 parameters + the closure. - ^(I_STATEMENT_FORMAT25x INSTRUCTION_FORMAT25x REGISTER register_list4) - { - Opcode opcode = opcodes.getOpcodeByName($INSTRUCTION_FORMAT25x.text); - - byte closureRegister = parseRegister_nibble($REGISTER.text); - - //this depends on the fact that register_list4 returns a byte[4] - byte[] registers = $register_list4.registers; - int parameterRegisterCount = $register_list4.registerCount; // don't count closure register - - $method::methodBuilder.addInstruction(new BuilderInstruction25x(opcode, - parameterRegisterCount, closureRegister, registers[0], registers[1], - registers[2], registers[3])); - }; - insn_format30t : //e.g. goto/32 endloop: ^(I_STATEMENT_FORMAT30t INSTRUCTION_FORMAT30t label_ref) diff --git a/smali/src/main/jflex/smaliLexer.jflex b/smali/src/main/jflex/smaliLexer.jflex index e0010a93..2cf3c869 100644 --- a/smali/src/main/jflex/smaliLexer.jflex +++ b/smali/src/main/jflex/smaliLexer.jflex @@ -476,14 +476,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT21c_TYPE); } - "capture-variable" { // e.g. 'capture-variable vB, ' - return newToken(INSTRUCTION_FORMAT21c_LAMBDA); - } - - "create-lambda" { // e.g. 'create-lambda vClosure, ' - return newToken(INSTRUCTION_FORMAT21c_METHOD); - } - "const/high16" { return newToken(INSTRUCTION_FORMAT21ih); } @@ -515,14 +507,10 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT22c_FIELD_ODEX); } - "instance-of" | "new-array" | "unbox-lambda" { + "instance-of" | "new-array" { return newToken(INSTRUCTION_FORMAT22c_TYPE); } - "liberate-variable" { - return newToken(INSTRUCTION_FORMAT22c_STRING); - } - "iget-quick" | "iget-wide-quick" | "iget-object-quick" | "iput-quick" | "iput-wide-quick" | "iput-object-quick" | "iput-boolean-quick" | "iput-byte-quick" | "iput-char-quick" | "iput-short-quick" { return newToken(INSTRUCTION_FORMAT22cs_FIELD); @@ -541,7 +529,7 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT22t); } - "move/from16" | "move-wide/from16" | "move-object/from16" | "box-lambda" { + "move/from16" | "move-wide/from16" | "move-object/from16" { return newToken(INSTRUCTION_FORMAT22x); } @@ -555,10 +543,6 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} | return newToken(INSTRUCTION_FORMAT23x); } - "invoke-lambda" { // e.g. invoke-lambda vClosure, {vD, vE, vF, vG} -- at most 4 params - return newToken(INSTRUCTION_FORMAT25x); - } - "goto/32" { return newToken(INSTRUCTION_FORMAT30t); } diff --git a/smali/src/test/resources/LexerTest/InstructionTest.smali b/smali/src/test/resources/LexerTest/InstructionTest.smali index 174cff8c..62e51006 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.smali +++ b/smali/src/test/resources/LexerTest/InstructionTest.smali @@ -85,8 +85,6 @@ const-string check-cast new-instance const-class -capture-variable -create-lambda const/high16 const-wide/high16 const/16 @@ -125,8 +123,6 @@ iput-wide-volatile iput-object-volatile instance-of new-array -unbox-lambda -liberate-variable iget-quick iget-wide-quick iget-object-quick @@ -153,7 +149,6 @@ if-le move/from16 move-wide/from16 move-object/from16 -box-lambda cmpl-float cmpg-float cmpl-double @@ -204,7 +199,6 @@ add-double sub-double mul-double div-double -invoke-lambda goto/32 const-string/jumbo const diff --git a/smali/src/test/resources/LexerTest/InstructionTest.tokens b/smali/src/test/resources/LexerTest/InstructionTest.tokens index fa959bad..dfbd584b 100644 --- a/smali/src/test/resources/LexerTest/InstructionTest.tokens +++ b/smali/src/test/resources/LexerTest/InstructionTest.tokens @@ -85,8 +85,6 @@ INSTRUCTION_FORMAT21c_STRING("const-string") INSTRUCTION_FORMAT21c_TYPE("check-cast") INSTRUCTION_FORMAT21c_TYPE("new-instance") INSTRUCTION_FORMAT21c_TYPE("const-class") -INSTRUCTION_FORMAT21c_LAMBDA("capture-variable") -INSTRUCTION_FORMAT21c_METHOD("create-lambda") INSTRUCTION_FORMAT21ih("const/high16") INSTRUCTION_FORMAT21lh("const-wide/high16") INSTRUCTION_FORMAT21s("const/16") @@ -125,8 +123,6 @@ INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-wide-volatile") INSTRUCTION_FORMAT22c_FIELD_ODEX("iput-object-volatile") INSTRUCTION_FORMAT22c_TYPE("instance-of") INSTRUCTION_FORMAT22c_TYPE("new-array") -INSTRUCTION_FORMAT22c_TYPE("unbox-lambda") -INSTRUCTION_FORMAT22c_STRING("liberate-variable") INSTRUCTION_FORMAT22cs_FIELD("iget-quick") INSTRUCTION_FORMAT22cs_FIELD("iget-wide-quick") INSTRUCTION_FORMAT22cs_FIELD("iget-object-quick") @@ -153,7 +149,6 @@ INSTRUCTION_FORMAT22t("if-le") INSTRUCTION_FORMAT22x("move/from16") INSTRUCTION_FORMAT22x("move-wide/from16") INSTRUCTION_FORMAT22x("move-object/from16") -INSTRUCTION_FORMAT22x("box-lambda") INSTRUCTION_FORMAT23x("cmpl-float") INSTRUCTION_FORMAT23x("cmpg-float") INSTRUCTION_FORMAT23x("cmpl-double") @@ -204,7 +199,6 @@ INSTRUCTION_FORMAT23x("add-double") INSTRUCTION_FORMAT23x("sub-double") INSTRUCTION_FORMAT23x("mul-double") INSTRUCTION_FORMAT23x("div-double") -INSTRUCTION_FORMAT25x("invoke-lambda") INSTRUCTION_FORMAT30t("goto/32") INSTRUCTION_FORMAT31c("const-string/jumbo") INSTRUCTION_FORMAT31i_OR_ID("const")