diff options
Diffstat (limited to 'runtime/dex_to_dex_decompiler.cc')
-rw-r--r-- | runtime/dex_to_dex_decompiler.cc | 100 |
1 files changed, 43 insertions, 57 deletions
diff --git a/runtime/dex_to_dex_decompiler.cc b/runtime/dex_to_dex_decompiler.cc index c15c9ec448..b82f4f74a9 100644 --- a/runtime/dex_to_dex_decompiler.cc +++ b/runtime/dex_to_dex_decompiler.cc @@ -18,9 +18,10 @@ #include "base/logging.h" #include "base/mutex.h" +#include "bytecode_utils.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" -#include "bytecode_utils.h" +#include "quicken_info.h" namespace art { namespace optimizer { @@ -31,27 +32,21 @@ class DexDecompiler { const ArrayRef<const uint8_t>& quickened_info, bool decompile_return_instruction) : code_item_(code_item), - quickened_info_ptr_(quickened_info.data()), - quickened_info_start_(quickened_info.data()), - quickened_info_end_(quickened_info.data() + quickened_info.size()), + quicken_info_(quickened_info.data()), + quicken_info_number_of_indices_(QuickenInfoTable::NumberOfIndices(quickened_info.size())), decompile_return_instruction_(decompile_return_instruction) {} bool Decompile(); private: - void DecompileInstanceFieldAccess(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode) { - uint16_t index = GetIndexAt(dex_pc); + void DecompileInstanceFieldAccess(Instruction* inst, Instruction::Code new_opcode) { + uint16_t index = NextIndex(); inst->SetOpcode(new_opcode); inst->SetVRegC_22c(index); } - void DecompileInvokeVirtual(Instruction* inst, - uint32_t dex_pc, - Instruction::Code new_opcode, - bool is_range) { - uint16_t index = GetIndexAt(dex_pc); + void DecompileInvokeVirtual(Instruction* inst, Instruction::Code new_opcode, bool is_range) { + const uint16_t index = NextIndex(); inst->SetOpcode(new_opcode); if (is_range) { inst->SetVRegB_3rc(index); @@ -60,40 +55,32 @@ class DexDecompiler { } } - void DecompileNop(Instruction* inst, uint32_t dex_pc) { - if (quickened_info_ptr_ == quickened_info_end_) { + void DecompileNop(Instruction* inst) { + const uint16_t reference_index = NextIndex(); + if (reference_index == DexFile::kDexNoIndex16) { + // This means it was a normal nop and not a check-cast. return; } - const uint8_t* temporary_pointer = quickened_info_ptr_; - uint32_t quickened_pc = DecodeUnsignedLeb128(&temporary_pointer); - if (quickened_pc != dex_pc) { - return; - } - uint16_t reference_index = GetIndexAt(dex_pc); - uint16_t type_index = GetIndexAt(dex_pc); + const uint16_t type_index = NextIndex(); inst->SetOpcode(Instruction::CHECK_CAST); inst->SetVRegA_21c(reference_index); inst->SetVRegB_21c(type_index); } - uint16_t GetIndexAt(uint32_t dex_pc) { - // Note that as a side effect, DecodeUnsignedLeb128 update the given pointer - // to the new position in the buffer. - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint32_t quickened_pc = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LT(quickened_info_ptr_, quickened_info_end_); - uint16_t index = DecodeUnsignedLeb128(&quickened_info_ptr_); - DCHECK_LE(quickened_info_ptr_, quickened_info_end_); - DCHECK_EQ(quickened_pc, dex_pc); - return index; + uint16_t NextIndex() { + DCHECK_LT(quicken_index_, quicken_info_number_of_indices_); + const uint16_t ret = quicken_info_.GetData(quicken_index_); + quicken_index_++; + return ret; } const DexFile::CodeItem& code_item_; - const uint8_t* quickened_info_ptr_; - const uint8_t* const quickened_info_start_; - const uint8_t* const quickened_info_end_; + const QuickenInfoTable quicken_info_; + const size_t quicken_info_number_of_indices_; const bool decompile_return_instruction_; + size_t quicken_index_ = 0u; + DISALLOW_COPY_AND_ASSIGN(DexDecompiler); }; @@ -103,7 +90,6 @@ bool DexDecompiler::Decompile() { // unquickening is a rare need and not performance sensitive, it is not worth the // added storage to also add the RETURN_VOID quickening in the quickened data. for (CodeItemIterator it(code_item_); !it.Done(); it.Advance()) { - uint32_t dex_pc = it.CurrentDexPc(); Instruction* inst = const_cast<Instruction*>(&it.CurrentInstruction()); switch (inst->Opcode()) { @@ -114,71 +100,71 @@ bool DexDecompiler::Decompile() { break; case Instruction::NOP: - DecompileNop(inst, dex_pc); + DecompileNop(inst); break; case Instruction::IGET_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET); + DecompileInstanceFieldAccess(inst, Instruction::IGET); break; case Instruction::IGET_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_WIDE); + DecompileInstanceFieldAccess(inst, Instruction::IGET_WIDE); break; case Instruction::IGET_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_OBJECT); + DecompileInstanceFieldAccess(inst, Instruction::IGET_OBJECT); break; case Instruction::IGET_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BOOLEAN); + DecompileInstanceFieldAccess(inst, Instruction::IGET_BOOLEAN); break; case Instruction::IGET_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_BYTE); + DecompileInstanceFieldAccess(inst, Instruction::IGET_BYTE); break; case Instruction::IGET_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_CHAR); + DecompileInstanceFieldAccess(inst, Instruction::IGET_CHAR); break; case Instruction::IGET_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IGET_SHORT); + DecompileInstanceFieldAccess(inst, Instruction::IGET_SHORT); break; case Instruction::IPUT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT); break; case Instruction::IPUT_BOOLEAN_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BOOLEAN); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_BOOLEAN); break; case Instruction::IPUT_BYTE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_BYTE); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_BYTE); break; case Instruction::IPUT_CHAR_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_CHAR); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_CHAR); break; case Instruction::IPUT_SHORT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_SHORT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_SHORT); break; case Instruction::IPUT_WIDE_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_WIDE); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_WIDE); break; case Instruction::IPUT_OBJECT_QUICK: - DecompileInstanceFieldAccess(inst, dex_pc, Instruction::IPUT_OBJECT); + DecompileInstanceFieldAccess(inst, Instruction::IPUT_OBJECT); break; case Instruction::INVOKE_VIRTUAL_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL, false); + DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL, false); break; case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: - DecompileInvokeVirtual(inst, dex_pc, Instruction::INVOKE_VIRTUAL_RANGE, true); + DecompileInvokeVirtual(inst, Instruction::INVOKE_VIRTUAL_RANGE, true); break; default: @@ -186,14 +172,14 @@ bool DexDecompiler::Decompile() { } } - if (quickened_info_ptr_ != quickened_info_end_) { - if (quickened_info_start_ == quickened_info_ptr_) { + if (quicken_index_ != quicken_info_number_of_indices_) { + if (quicken_index_ == 0) { LOG(WARNING) << "Failed to use any value in quickening info," << " potentially due to duplicate methods."; } else { LOG(FATAL) << "Failed to use all values in quickening info." - << " Actual: " << std::hex << reinterpret_cast<uintptr_t>(quickened_info_ptr_) - << " Expected: " << reinterpret_cast<uintptr_t>(quickened_info_end_); + << " Actual: " << std::hex << quicken_index_ + << " Expected: " << quicken_info_number_of_indices_; return false; } } |