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