1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump. 18 19 #ifndef ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ 20 #define ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ 21 22 #include "compact_dex_file.h" 23 #include "dex_file.h" 24 #include "dex_instruction_iterator.h" 25 #include "standard_dex_file.h" 26 27 namespace art { 28 29 class ArtMethod; 30 31 // Abstracts accesses to the instruction fields of code items for CompactDexFile and 32 // StandardDexFile. 33 class CodeItemInstructionAccessor { 34 public: 35 ALWAYS_INLINE CodeItemInstructionAccessor(const DexFile& dex_file, 36 const DexFile::CodeItem* code_item); 37 38 ALWAYS_INLINE explicit CodeItemInstructionAccessor(ArtMethod* method); 39 40 ALWAYS_INLINE DexInstructionIterator begin() const; 41 42 ALWAYS_INLINE DexInstructionIterator end() const; 43 44 IterationRange<DexInstructionIterator> InstructionsFrom(uint32_t start_dex_pc) const; 45 InsnsSizeInCodeUnits()46 uint32_t InsnsSizeInCodeUnits() const { 47 return insns_size_in_code_units_; 48 } 49 Insns()50 const uint16_t* Insns() const { 51 return insns_; 52 } 53 54 // Return the instruction for a dex pc. InstructionAt(uint32_t dex_pc)55 const Instruction& InstructionAt(uint32_t dex_pc) const { 56 DCHECK_LT(dex_pc, InsnsSizeInCodeUnits()); 57 return *Instruction::At(insns_ + dex_pc); 58 } 59 60 // Return true if the accessor has a code item. HasCodeItem()61 bool HasCodeItem() const { 62 return Insns() != nullptr; 63 } 64 65 protected: 66 CodeItemInstructionAccessor() = default; 67 68 ALWAYS_INLINE void Init(uint32_t insns_size_in_code_units, const uint16_t* insns); 69 ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item); 70 ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item); 71 ALWAYS_INLINE void Init(const DexFile& dex_file, const DexFile::CodeItem* code_item); 72 73 private: 74 // size of the insns array, in 2 byte code units. 0 if there is no code item. 75 uint32_t insns_size_in_code_units_ = 0; 76 77 // Pointer to the instructions, null if there is no code item. 78 const uint16_t* insns_ = 0; 79 }; 80 81 // Abstracts accesses to code item fields other than debug info for CompactDexFile and 82 // StandardDexFile. 83 class CodeItemDataAccessor : public CodeItemInstructionAccessor { 84 public: 85 ALWAYS_INLINE CodeItemDataAccessor(const DexFile& dex_file, const DexFile::CodeItem* code_item); 86 RegistersSize()87 uint16_t RegistersSize() const { 88 return registers_size_; 89 } 90 InsSize()91 uint16_t InsSize() const { 92 return ins_size_; 93 } 94 OutsSize()95 uint16_t OutsSize() const { 96 return outs_size_; 97 } 98 TriesSize()99 uint16_t TriesSize() const { 100 return tries_size_; 101 } 102 103 IterationRange<const DexFile::TryItem*> TryItems() const; 104 105 const uint8_t* GetCatchHandlerData(size_t offset = 0) const; 106 107 const DexFile::TryItem* FindTryItem(uint32_t try_dex_pc) const; 108 109 inline const void* CodeItemDataEnd() const; 110 111 protected: 112 CodeItemDataAccessor() = default; 113 114 ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item); 115 ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item); 116 ALWAYS_INLINE void Init(const DexFile& dex_file, const DexFile::CodeItem* code_item); 117 118 private: 119 // Fields mirrored from the dex/cdex code item. 120 uint16_t registers_size_; 121 uint16_t ins_size_; 122 uint16_t outs_size_; 123 uint16_t tries_size_; 124 }; 125 126 // Abstract accesses to code item data including debug info offset. More heavy weight than the other 127 // helpers. 128 class CodeItemDebugInfoAccessor : public CodeItemDataAccessor { 129 public: 130 CodeItemDebugInfoAccessor() = default; 131 132 // Initialize with an existing offset. CodeItemDebugInfoAccessor(const DexFile & dex_file,const DexFile::CodeItem * code_item,uint32_t dex_method_index)133 ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile& dex_file, 134 const DexFile::CodeItem* code_item, 135 uint32_t dex_method_index) { 136 Init(dex_file, code_item, dex_method_index); 137 } 138 139 ALWAYS_INLINE void Init(const DexFile& dex_file, 140 const DexFile::CodeItem* code_item, 141 uint32_t dex_method_index); 142 143 ALWAYS_INLINE explicit CodeItemDebugInfoAccessor(ArtMethod* method); 144 DebugInfoOffset()145 uint32_t DebugInfoOffset() const { 146 return debug_info_offset_; 147 } 148 149 template<typename NewLocalCallback> 150 bool DecodeDebugLocalInfo(bool is_static, 151 uint32_t method_idx, 152 NewLocalCallback new_local, 153 void* context) const; 154 155 protected: 156 ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item, uint32_t dex_method_index); 157 ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item); 158 159 private: 160 const DexFile* dex_file_ = nullptr; 161 uint32_t debug_info_offset_ = 0u; 162 }; 163 164 } // namespace art 165 166 #endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ 167