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 <android-base/logging.h> 23 24 #include "dex_instruction.h" 25 26 namespace art { 27 28 namespace dex { 29 struct CodeItem; 30 struct TryItem; 31 } // namespace dex 32 33 class ArtMethod; 34 class DexFile; 35 class DexInstructionIterator; 36 template <typename Iter> 37 class IterationRange; 38 39 // Abstracts accesses to the instruction fields of code items for CompactDexFile and 40 // StandardDexFile. 41 class CodeItemInstructionAccessor { 42 public: 43 ALWAYS_INLINE CodeItemInstructionAccessor(const DexFile& dex_file, 44 const dex::CodeItem* code_item); 45 46 ALWAYS_INLINE explicit CodeItemInstructionAccessor(ArtMethod* method); 47 48 ALWAYS_INLINE DexInstructionIterator begin() const; 49 50 ALWAYS_INLINE DexInstructionIterator end() const; 51 52 IterationRange<DexInstructionIterator> InstructionsFrom(uint32_t start_dex_pc) const; 53 InsnsSizeInCodeUnits()54 uint32_t InsnsSizeInCodeUnits() const { 55 return insns_size_in_code_units_; 56 } 57 InsnsSizeInBytes()58 uint32_t InsnsSizeInBytes() const { 59 static constexpr uint32_t kCodeUnitSizeInBytes = 2u; 60 return insns_size_in_code_units_ * kCodeUnitSizeInBytes; 61 } 62 Insns()63 const uint16_t* Insns() const { 64 return insns_; 65 } 66 67 // Return the instruction for a dex pc. InstructionAt(uint32_t dex_pc)68 const Instruction& InstructionAt(uint32_t dex_pc) const { 69 DCHECK_LT(dex_pc, InsnsSizeInCodeUnits()); 70 return *Instruction::At(insns_ + dex_pc); 71 } 72 73 // Return true if the accessor has a code item. HasCodeItem()74 bool HasCodeItem() const { 75 return Insns() != nullptr; 76 } 77 78 protected: 79 CodeItemInstructionAccessor() = default; 80 81 ALWAYS_INLINE void Init(uint32_t insns_size_in_code_units, const uint16_t* insns); 82 ALWAYS_INLINE void Init(const DexFile& dex_file, const dex::CodeItem* code_item); 83 84 template <typename DexFileCodeItemType> 85 ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item); 86 87 private: 88 // size of the insns array, in 2 byte code units. 0 if there is no code item. 89 uint32_t insns_size_in_code_units_ = 0; 90 91 // Pointer to the instructions, null if there is no code item. 92 const uint16_t* insns_ = nullptr; 93 }; 94 95 // Abstracts accesses to code item fields other than debug info for CompactDexFile and 96 // StandardDexFile. 97 class CodeItemDataAccessor : public CodeItemInstructionAccessor { 98 public: 99 ALWAYS_INLINE CodeItemDataAccessor(const DexFile& dex_file, const dex::CodeItem* code_item); 100 RegistersSize()101 uint16_t RegistersSize() const { 102 return registers_size_; 103 } 104 InsSize()105 uint16_t InsSize() const { 106 return ins_size_; 107 } 108 OutsSize()109 uint16_t OutsSize() const { 110 return outs_size_; 111 } 112 TriesSize()113 uint16_t TriesSize() const { 114 return tries_size_; 115 } 116 117 IterationRange<const dex::TryItem*> TryItems() const; 118 119 const uint8_t* GetCatchHandlerData(size_t offset = 0) const; 120 121 const dex::TryItem* FindTryItem(uint32_t try_dex_pc) const; 122 123 inline const void* CodeItemDataEnd() const; 124 125 protected: 126 CodeItemDataAccessor() = default; 127 128 ALWAYS_INLINE void Init(const DexFile& dex_file, const dex::CodeItem* code_item); 129 130 template <typename DexFileCodeItemType> 131 ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item); 132 133 private: 134 // Fields mirrored from the dex/cdex code item. 135 uint16_t registers_size_; 136 uint16_t ins_size_; 137 uint16_t outs_size_; 138 uint16_t tries_size_; 139 }; 140 141 // Abstract accesses to code item data including debug info offset. More heavy weight than the other 142 // helpers. 143 class CodeItemDebugInfoAccessor : public CodeItemDataAccessor { 144 public: 145 CodeItemDebugInfoAccessor() = default; 146 147 // Initialize with an existing offset. CodeItemDebugInfoAccessor(const DexFile & dex_file,const dex::CodeItem * code_item,uint32_t dex_method_index)148 ALWAYS_INLINE CodeItemDebugInfoAccessor(const DexFile& dex_file, 149 const dex::CodeItem* code_item, 150 uint32_t dex_method_index) { 151 Init(dex_file, code_item, dex_method_index); 152 } 153 154 ALWAYS_INLINE void Init(const DexFile& dex_file, 155 const dex::CodeItem* code_item, 156 uint32_t dex_method_index); 157 158 ALWAYS_INLINE explicit CodeItemDebugInfoAccessor(ArtMethod* method); 159 DebugInfoOffset()160 uint32_t DebugInfoOffset() const { 161 return debug_info_offset_; 162 } 163 164 template<typename NewLocalVisitor> 165 bool DecodeDebugLocalInfo(bool is_static, 166 uint32_t method_idx, 167 const NewLocalVisitor& new_local) const; 168 169 // Visit each parameter in the debug information. Returns the line number. 170 // The argument of the Visitor is dex::StringIndex. 171 template <typename Visitor> 172 uint32_t VisitParameterNames(const Visitor& visitor) const; 173 174 template <typename Visitor> 175 bool DecodeDebugPositionInfo(const Visitor& visitor) const; 176 177 bool GetLineNumForPc(const uint32_t pc, uint32_t* line_num) const; 178 179 protected: 180 template <typename DexFileCodeItemType> 181 ALWAYS_INLINE void Init(const DexFileCodeItemType& code_item, uint32_t dex_method_index); 182 183 private: 184 const DexFile* dex_file_ = nullptr; 185 uint32_t debug_info_offset_ = 0u; 186 }; 187 188 } // namespace art 189 190 #endif // ART_LIBDEXFILE_DEX_CODE_ITEM_ACCESSORS_H_ 191