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