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