diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java index a502e5eb..5d0eeaed 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcode.java @@ -299,7 +299,7 @@ public enum Opcode 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), - SPUT_OBJECT_VOLATILE(firstApi(0xfe, 9), "sput-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.STATIC_FIELD_ACCESSOR), + SPUT_OBJECT_VOLATILE(betweenApi(0xfe, 9, 19), "sput-object-volatile", ReferenceType.FIELD, Format.Format21c, Opcode.ODEX_ONLY | Opcode.VOLATILE_FIELD_ACCESSOR | Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.STATIC_FIELD_ACCESSOR), PACKED_SWITCH_PAYLOAD(0x100, "packed-switch-payload", ReferenceType.NONE, Format.PackedSwitchPayload, 0), SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 0), @@ -309,7 +309,10 @@ public enum Opcode INVOKE_POLYMORPHIC_RANGE(firstArtVersion(0xfb, 87), "invoke-polymorphic/range", ReferenceType.METHOD, ReferenceType.METHOD_PROTO, Format.Format4rcc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), INVOKE_CUSTOM(firstArtVersion(0xfc, 111), "invoke-custom", ReferenceType.CALL_SITE, Format.Format35c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), - INVOKE_CUSTOM_RANGE(firstArtVersion(0xfd, 111), "invoke-custom/range", ReferenceType.CALL_SITE, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT); + INVOKE_CUSTOM_RANGE(firstArtVersion(0xfd, 111), "invoke-custom/range", ReferenceType.CALL_SITE, Format.Format3rc, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_RESULT), + + CONST_METHOD_HANDLE(firstArtVersion(0xfe, 134), "const-method-handle", ReferenceType.METHOD_HANDLE, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER), + CONST_METHOD_TYPE(firstArtVersion(0xff, 134), "const-method-type", ReferenceType.METHOD_PROTO, Format.Format21c, Opcode.CAN_THROW | Opcode.CAN_CONTINUE | Opcode.SETS_REGISTER); //if the instruction can throw an exception public static final int CAN_THROW = 0x1; @@ -398,6 +401,11 @@ public enum Opcode return Lists.newArrayList(new VersionConstraint(Range.atMost(api), Range.openClosed(0, 0), opcodeValue)); } + private static List betweenApi(int opcodeValue, int minApi, int maxApi) { + return Lists.newArrayList(new VersionConstraint(Range.closed(minApi, maxApi), Range.openClosed(0, 0), + opcodeValue)); + } + private static List firstArtVersion(int opcodeValue, int artVersion) { return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.atLeast(artVersion), opcodeValue)); } diff --git a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java index 53bd899c..298f0473 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/Opcodes.java @@ -50,7 +50,7 @@ public class Opcodes { */ public final int api; public final int artVersion; - @Nonnull private final Opcode[] opcodesByValue = new Opcode[255]; + @Nonnull private final Opcode[] opcodesByValue = new Opcode[256]; @Nonnull private final EnumMap opcodeValues; @Nonnull private final HashMap opcodesByName; @@ -79,8 +79,6 @@ public class Opcodes { } private Opcodes(int api, int artVersion) { - - if (api >= 21) { this.api = api; this.artVersion = mapApiToArtVersion(api); diff --git a/dexlib2/src/main/java/org/jf/dexlib2/VersionMap.java b/dexlib2/src/main/java/org/jf/dexlib2/VersionMap.java index a101ccd9..c30390b0 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/VersionMap.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/VersionMap.java @@ -44,10 +44,20 @@ public class VersionMap { if (dexVersion == 38) { return 27; } + if (dexVersion == 39) { + return 28; + } throw new RuntimeException("Unsupported dex version " + dexVersion); } public static int mapArtVersionToApi(int artVersion) { + // 144 is the current version in the master branch of AOSP as of 2018-05-22 + if (artVersion >= 144) { + return 28; + } + if (artVersion >= 131) { + return 27; + } if (artVersion >= 124) { return 26; } @@ -82,6 +92,11 @@ public class VersionMap { return 79; case 26: return 124; + case 27: + return 131; + case 28: + // 144 is the current version in the master branch of AOSP as of 2018-05-22 + return 144; } // NOTE: Art version 143 and api level 27 do not correspond to any diff --git a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/HeaderItem.java b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/HeaderItem.java index 618c7521..b3292b5f 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/HeaderItem.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/dexbacked/raw/HeaderItem.java @@ -43,7 +43,7 @@ public class HeaderItem { public static final int ITEM_SIZE = 0x70; private static final byte[] MAGIC_VALUE = new byte[] { 0x64, 0x65, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00 }; - private static final int[] SUPPORTED_DEX_VERSIONS = new int[] { 35, 37, 38 }; + private static final int[] SUPPORTED_DEX_VERSIONS = new int[] { 35, 37, 38, 39 }; public static final int LITTLE_ENDIAN_TAG = 0x12345678; public static final int BIG_ENDIAN_TAG = 0x78563412; @@ -235,8 +235,10 @@ public class HeaderItem { } if (api < 26) { // On android N and later we support dex version 037. return getMagicForDexVersion(37); - } else { + } else if (api < 28) { return getMagicForDexVersion(38); + } else { + return getMagicForDexVersion(39); } } 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 89d00900..9da2830a 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 @@ -51,6 +51,8 @@ public abstract class DexBackedReference { return new DexBackedFieldReference(dexFile, referenceIndex); case ReferenceType.METHOD_PROTO: return new DexBackedMethodProtoReference(dexFile, referenceIndex); + case ReferenceType.METHOD_HANDLE: + return new DexBackedMethodHandleReference(dexFile, referenceIndex); case ReferenceType.CALL_SITE: return new DexBackedCallSiteReference(dexFile, referenceIndex); default: 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 ceebd66e..e5d14026 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/DexWriter.java @@ -1036,7 +1036,7 @@ public abstract class DexWriter< InstructionWriter instructionWriter = InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, - methodSection, protoSection, callSiteSection); + methodSection, protoSection, methodHandleSection, callSiteSection); writer.writeInt(codeUnitCount); int codeOffset = 0; 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 f91cdb9e..f86f683f 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/writer/InstructionWriter.java @@ -50,7 +50,8 @@ import java.util.List; public class InstructionWriter { + ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference, + CallSiteKey extends CallSiteReference> { @Nonnull private final Opcodes opcodes; @Nonnull private final DexDataWriter writer; @Nonnull private final StringSection stringSection; @@ -58,12 +59,14 @@ public class InstructionWriter fieldSection; @Nonnull private final MethodSection methodSection; @Nonnull private final ProtoSection protoSection; + @Nonnull private final MethodHandleSection methodHandleSection; @Nonnull private final CallSiteSection callSiteSection; @Nonnull static - InstructionWriter + ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference, + CallSiteKey extends CallSiteReference> + InstructionWriter makeInstructionWriter( @Nonnull Opcodes opcodes, @Nonnull DexDataWriter writer, @@ -72,9 +75,12 @@ public class InstructionWriter fieldSection, @Nonnull MethodSection methodSection, @Nonnull ProtoSection protoSection, + @Nonnull MethodHandleSection methodHandleSection, @Nonnull CallSiteSection callSiteSection) { - return new InstructionWriter( - opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection, callSiteSection); + return new InstructionWriter< + StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey,CallSiteKey>( + opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection, + methodHandleSection, callSiteSection); } InstructionWriter(@Nonnull Opcodes opcodes, @@ -84,6 +90,7 @@ public class InstructionWriter fieldSection, @Nonnull MethodSection methodSection, @Nonnull ProtoSection protoSection, + @Nonnull MethodHandleSection methodHandleSection, @Nonnull CallSiteSection callSiteSection) { this.opcodes = opcodes; this.writer = writer; @@ -92,6 +99,7 @@ public class InstructionWriter