diff options
-rw-r--r-- | disassembler_dex.cc | 54 | ||||
-rw-r--r-- | disassembler_dex.h | 8 | ||||
-rw-r--r-- | testdata/const-method-type-min.smali | 16 | ||||
-rw-r--r-- | type_dex.h | 4 |
4 files changed, 71 insertions, 11 deletions
diff --git a/disassembler_dex.cc b/disassembler_dex.cc index 74c5e69..8ea0314 100644 --- a/disassembler_dex.cc +++ b/disassembler_dex.cc @@ -844,10 +844,11 @@ bool ReadDexHeader(ConstBufferView image, ReadDexHeaderResults* opt_results) { dex_version = dex_version * 10 + (header->magic[i] - '0'); } - // Only support DEX versions 35, 37, and 38. - // TODO(ckitagawa): Handle version 39. - if (dex_version != 35 && dex_version != 37 && dex_version != 38) + // Only support DEX versions 35, 37, 38, and 39 + if (dex_version != 35 && dex_version != 37 && dex_version != 38 && + dex_version != 39) { return false; + } if (header->file_size > image.size() || header->file_size < sizeof(dex::HeaderItem) || @@ -960,6 +961,9 @@ std::vector<ReferenceGroup> DisassemblerDex::MakeReferenceGroups() const { {{2, TypeTag(kCodeToCallSiteId), PoolTag(kCallSiteId)}, &DisassemblerDex::MakeReadCodeToCallSiteId16, &DisassemblerDex::MakeWriteCallSiteId16}, + {{2, TypeTag(kCodeToMethodHandle), PoolTag(kMethodHandle)}, + &DisassemblerDex::MakeReadCodeToMethodHandle16, + &DisassemblerDex::MakeWriteMethodHandle16}, {{4, TypeTag(kProtoIdToParametersTypeList), PoolTag(kTypeList)}, &DisassemblerDex::MakeReadProtoIdToParametersTypeList, &DisassemblerDex::MakeWriteAbs32}, @@ -1424,12 +1428,17 @@ std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToProtoId16( offset_t hi) { auto filter = base::BindRepeating( [](const InstructionParser::Value& value) -> offset_t { - if (value.instr->format == dex::FormatId::c && - (value.instr->opcode == 0xFA || // invoke-polymorphic - value.instr->opcode == 0xFB)) { // invoke-polymorphic/range - // HHHH from e.g, invoke-polymorphic {vC, vD, vE, vF, vG}, - // meth@BBBB, proto@HHHH - return value.instr_offset + 6; + if (value.instr->format == dex::FormatId::c) { + if (value.instr->opcode == 0xFA || // invoke-polymorphic + value.instr->opcode == 0xFB) { // invoke-polymorphic/range + // HHHH from e.g, invoke-polymorphic {vC, vD, vE, vF, vG}, + // meth@BBBB, proto@HHHH + return value.instr_offset + 6; + } + if (value.instr->opcode == 0xFF) { // const-method-type + // BBBB from e.g., const-method-type vAA, proto@BBBB + return value.instr_offset + 2; + } } return kInvalidOffset; }); @@ -1460,6 +1469,25 @@ std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToCallSiteId16( image_, lo, hi, code_item_offsets_, std::move(filter), std::move(mapper)); } +std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToMethodHandle16( + offset_t lo, + offset_t hi) { + auto filter = base::BindRepeating( + [](const InstructionParser::Value& value) -> offset_t { + if (value.instr->format == dex::FormatId::c && + value.instr->opcode == 0xFE) { // const-method-handle + // BBBB from e.g, const-method-handle vAA, method_handle@BBBB + return value.instr_offset + 2; + } + return kInvalidOffset; + }); + auto mapper = base::BindRepeating(ReadTargetIndex<uint16_t>, image_, + method_handle_map_item_, + sizeof(dex::MethodHandleItem)); + return std::make_unique<InstructionReferenceReader>( + image_, lo, hi, code_item_offsets_, std::move(filter), std::move(mapper)); +} + std::unique_ptr<ReferenceReader> DisassemblerDex::MakeReadCodeToFieldId16( offset_t lo, offset_t hi) { @@ -1666,6 +1694,14 @@ std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteCallSiteId16( return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer)); } +std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteMethodHandle16( + MutableBufferView image) { + auto writer = + base::BindRepeating(WriteTargetIndex<uint16_t>, method_handle_map_item_, + sizeof(dex::MethodHandleItem)); + return std::make_unique<ReferenceWriterAdaptor>(image, std::move(writer)); +} + std::unique_ptr<ReferenceWriter> DisassemblerDex::MakeWriteRelCode8( MutableBufferView image) { auto writer = base::BindRepeating([](Reference ref, MutableBufferView image) { diff --git a/disassembler_dex.h b/disassembler_dex.h index e75d13e..8e739d0 100644 --- a/disassembler_dex.h +++ b/disassembler_dex.h @@ -33,7 +33,7 @@ class DisassemblerDex : public Disassembler { kMethodId, // kClassDef, // Unused kCallSiteId, - // kMethodHandle, // Unused + kMethodHandle, kTypeList, kAnnotationSetRefList, kAnnotionSet, @@ -83,6 +83,8 @@ class DisassemblerDex : public Disassembler { kCodeToCallSiteId, // kCallSiteId + kCodeToMethodHandle, // kMethodHandle + kProtoIdToParametersTypeList, // kTypeList kClassDefToInterfacesTypeList, @@ -220,6 +222,8 @@ class DisassemblerDex : public Disassembler { offset_t hi); std::unique_ptr<ReferenceReader> MakeReadCodeToCallSiteId16(offset_t lo, offset_t hi); + std::unique_ptr<ReferenceReader> MakeReadCodeToMethodHandle16(offset_t lo, + offset_t hi); std::unique_ptr<ReferenceReader> MakeReadCodeToRelCode8(offset_t lo, offset_t hi); std::unique_ptr<ReferenceReader> MakeReadCodeToRelCode16(offset_t lo, @@ -240,6 +244,8 @@ class DisassemblerDex : public Disassembler { std::unique_ptr<ReferenceWriter> MakeWriteMethodId32(MutableBufferView image); std::unique_ptr<ReferenceWriter> MakeWriteCallSiteId16( MutableBufferView image); + std::unique_ptr<ReferenceWriter> MakeWriteMethodHandle16( + MutableBufferView image); std::unique_ptr<ReferenceWriter> MakeWriteRelCode8(MutableBufferView image); std::unique_ptr<ReferenceWriter> MakeWriteRelCode16(MutableBufferView image); std::unique_ptr<ReferenceWriter> MakeWriteRelCode32(MutableBufferView image); diff --git a/testdata/const-method-type-min.smali b/testdata/const-method-type-min.smali new file mode 100644 index 0000000..8a0f632 --- /dev/null +++ b/testdata/const-method-type-min.smali @@ -0,0 +1,16 @@ +# Tests const-method-type added in DEX version 39. + +# Compile using smali: https://github.com/JesusFreke/smali +# java -jar smali.jar assemble const-method-type.smali --api 28 + +.class public LConstMethodTypeTest; +.super Ljava/lang/Object; + +.method public test(I)V + .registers 4 + const-method-type v0, ()I + const-method-type v1, (C)V + const-method-type v2, (I)V + const-method-type v3, (I)I + return-void +.end method @@ -12,7 +12,7 @@ namespace dex { // Contains types that models DEX executable format data structures. // See https://source.android.com/devices/tech/dalvik/dex-format -// The supported versions are 035, 037, and 038. +// The supported versions are 035, 037, 038, and 039. enum class FormatId : uint8_t { b, // 22b. @@ -114,6 +114,8 @@ constexpr Instruction kByteCode[] = { {0xFB, 4, FormatId::c}, {0xFC, 3, FormatId::c}, {0xFD, 3, FormatId::c}, + {0xFE, 2, FormatId::c}, + {0xFF, 2, FormatId::c}, }; // Supported by MSVC, g++, and clang++. Ensures no gaps in packing. |