Add support for dex version 39 in dexlib2

This commit is contained in:
Ben Gruver 2018-05-22 15:36:18 -07:00
parent 69d004cbfd
commit 2db1dec703
7 changed files with 48 additions and 13 deletions

View File

@ -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), 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), 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), PACKED_SWITCH_PAYLOAD(0x100, "packed-switch-payload", ReferenceType.NONE, Format.PackedSwitchPayload, 0),
SPARSE_SWITCH_PAYLOAD(0x200, "sparse-switch-payload", ReferenceType.NONE, Format.SparseSwitchPayload, 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_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(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 //if the instruction can throw an exception
public static final int CAN_THROW = 0x1; 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)); return Lists.newArrayList(new VersionConstraint(Range.atMost(api), Range.openClosed(0, 0), opcodeValue));
} }
private static List<VersionConstraint> betweenApi(int opcodeValue, int minApi, int maxApi) {
return Lists.newArrayList(new VersionConstraint(Range.closed(minApi, maxApi), Range.openClosed(0, 0),
opcodeValue));
}
private static List<VersionConstraint> firstArtVersion(int opcodeValue, int artVersion) { private static List<VersionConstraint> firstArtVersion(int opcodeValue, int artVersion) {
return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.atLeast(artVersion), opcodeValue)); return Lists.newArrayList(new VersionConstraint(Range.openClosed(0, 0), Range.atLeast(artVersion), opcodeValue));
} }

View File

@ -50,7 +50,7 @@ public class Opcodes {
*/ */
public final int api; public final int api;
public final int artVersion; public final int artVersion;
@Nonnull private final Opcode[] opcodesByValue = new Opcode[255]; @Nonnull private final Opcode[] opcodesByValue = new Opcode[256];
@Nonnull private final EnumMap<Opcode, Short> opcodeValues; @Nonnull private final EnumMap<Opcode, Short> opcodeValues;
@Nonnull private final HashMap<String, Opcode> opcodesByName; @Nonnull private final HashMap<String, Opcode> opcodesByName;
@ -79,8 +79,6 @@ public class Opcodes {
} }
private Opcodes(int api, int artVersion) { private Opcodes(int api, int artVersion) {
if (api >= 21) { if (api >= 21) {
this.api = api; this.api = api;
this.artVersion = mapApiToArtVersion(api); this.artVersion = mapApiToArtVersion(api);

View File

@ -44,10 +44,20 @@ public class VersionMap {
if (dexVersion == 38) { if (dexVersion == 38) {
return 27; return 27;
} }
if (dexVersion == 39) {
return 28;
}
throw new RuntimeException("Unsupported dex version " + dexVersion); throw new RuntimeException("Unsupported dex version " + dexVersion);
} }
public static int mapArtVersionToApi(int artVersion) { 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) { if (artVersion >= 124) {
return 26; return 26;
} }
@ -82,6 +92,11 @@ public class VersionMap {
return 79; return 79;
case 26: case 26:
return 124; 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 // NOTE: Art version 143 and api level 27 do not correspond to any

View File

@ -43,7 +43,7 @@ public class HeaderItem {
public static final int ITEM_SIZE = 0x70; 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 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 LITTLE_ENDIAN_TAG = 0x12345678;
public static final int BIG_ENDIAN_TAG = 0x78563412; public static final int BIG_ENDIAN_TAG = 0x78563412;
@ -235,8 +235,10 @@ public class HeaderItem {
} if (api < 26) { } if (api < 26) {
// On android N and later we support dex version 037. // On android N and later we support dex version 037.
return getMagicForDexVersion(37); return getMagicForDexVersion(37);
} else { } else if (api < 28) {
return getMagicForDexVersion(38); return getMagicForDexVersion(38);
} else {
return getMagicForDexVersion(39);
} }
} }

View File

@ -51,6 +51,8 @@ public abstract class DexBackedReference {
return new DexBackedFieldReference(dexFile, referenceIndex); return new DexBackedFieldReference(dexFile, referenceIndex);
case ReferenceType.METHOD_PROTO: case ReferenceType.METHOD_PROTO:
return new DexBackedMethodProtoReference(dexFile, referenceIndex); return new DexBackedMethodProtoReference(dexFile, referenceIndex);
case ReferenceType.METHOD_HANDLE:
return new DexBackedMethodHandleReference(dexFile, referenceIndex);
case ReferenceType.CALL_SITE: case ReferenceType.CALL_SITE:
return new DexBackedCallSiteReference(dexFile, referenceIndex); return new DexBackedCallSiteReference(dexFile, referenceIndex);
default: default:

View File

@ -1036,7 +1036,7 @@ public abstract class DexWriter<
InstructionWriter instructionWriter = InstructionWriter instructionWriter =
InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection, InstructionWriter.makeInstructionWriter(opcodes, writer, stringSection, typeSection, fieldSection,
methodSection, protoSection, callSiteSection); methodSection, protoSection, methodHandleSection, callSiteSection);
writer.writeInt(codeUnitCount); writer.writeInt(codeUnitCount);
int codeOffset = 0; int codeOffset = 0;

View File

@ -50,7 +50,8 @@ import java.util.List;
public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference, public class InstructionWriter<StringRef extends StringReference, TypeRef extends TypeReference,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
ProtoRefKey extends MethodProtoReference, CallSiteKey extends CallSiteReference> { ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference,
CallSiteKey extends CallSiteReference> {
@Nonnull private final Opcodes opcodes; @Nonnull private final Opcodes opcodes;
@Nonnull private final DexDataWriter writer; @Nonnull private final DexDataWriter writer;
@Nonnull private final StringSection<?, StringRef> stringSection; @Nonnull private final StringSection<?, StringRef> stringSection;
@ -58,12 +59,14 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection; @Nonnull private final FieldSection<?, ?, FieldRefKey, ?> fieldSection;
@Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection; @Nonnull private final MethodSection<?, ?, ?, MethodRefKey, ?> methodSection;
@Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection; @Nonnull private final ProtoSection<?, ?, ProtoRefKey, ?> protoSection;
@Nonnull private final MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection;
@Nonnull private final CallSiteSection<CallSiteKey, ?> callSiteSection; @Nonnull private final CallSiteSection<CallSiteKey, ?> callSiteSection;
@Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference, @Nonnull static <StringRef extends StringReference, TypeRef extends TypeReference,
FieldRefKey extends FieldReference, MethodRefKey extends MethodReference, FieldRefKey extends FieldReference, MethodRefKey extends MethodReference,
ProtoRefKey extends MethodProtoReference, CallSiteKey extends CallSiteReference> ProtoRefKey extends MethodProtoReference, MethodHandleKey extends MethodHandleReference,
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, CallSiteKey> CallSiteKey extends CallSiteReference>
InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey, CallSiteKey>
makeInstructionWriter( makeInstructionWriter(
@Nonnull Opcodes opcodes, @Nonnull Opcodes opcodes,
@Nonnull DexDataWriter writer, @Nonnull DexDataWriter writer,
@ -72,9 +75,12 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
@Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection,
@Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) { @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
return new InstructionWriter<StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, CallSiteKey>( return new InstructionWriter<
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection, callSiteSection); StringRef, TypeRef, FieldRefKey, MethodRefKey, ProtoRefKey, MethodHandleKey,CallSiteKey>(
opcodes, writer, stringSection, typeSection, fieldSection, methodSection, protoSection,
methodHandleSection, callSiteSection);
} }
InstructionWriter(@Nonnull Opcodes opcodes, InstructionWriter(@Nonnull Opcodes opcodes,
@ -84,6 +90,7 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
@Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection, @Nonnull FieldSection<?, ?, FieldRefKey, ?> fieldSection,
@Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection, @Nonnull MethodSection<?, ?, ?, MethodRefKey, ?> methodSection,
@Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection, @Nonnull ProtoSection<?, ?, ProtoRefKey, ?> protoSection,
@Nonnull MethodHandleSection<MethodHandleKey, ?, ?> methodHandleSection,
@Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) { @Nonnull CallSiteSection<CallSiteKey, ?> callSiteSection) {
this.opcodes = opcodes; this.opcodes = opcodes;
this.writer = writer; this.writer = writer;
@ -92,6 +99,7 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
this.fieldSection = fieldSection; this.fieldSection = fieldSection;
this.methodSection = methodSection; this.methodSection = methodSection;
this.protoSection = protoSection; this.protoSection = protoSection;
this.methodHandleSection = methodHandleSection;
this.callSiteSection = callSiteSection; this.callSiteSection = callSiteSection;
} }
@ -551,6 +559,8 @@ public class InstructionWriter<StringRef extends StringReference, TypeRef extend
return typeSection.getItemIndex((TypeRef) reference); return typeSection.getItemIndex((TypeRef) reference);
case ReferenceType.METHOD_PROTO: case ReferenceType.METHOD_PROTO:
return protoSection.getItemIndex((ProtoRefKey) reference); return protoSection.getItemIndex((ProtoRefKey) reference);
case ReferenceType.METHOD_HANDLE:
return methodHandleSection.getItemIndex((MethodHandleKey) reference);
case ReferenceType.CALL_SITE: case ReferenceType.CALL_SITE:
return callSiteSection.getItemIndex((CallSiteKey) reference); return callSiteSection.getItemIndex((CallSiteKey) reference);
default: default: