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),
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<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) {
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 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 HashMap<String, Opcode> opcodesByName;
@ -79,8 +79,6 @@ public class Opcodes {
}
private Opcodes(int api, int artVersion) {
if (api >= 21) {
this.api = api;
this.artVersion = mapApiToArtVersion(api);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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;

View File

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