Home | History | Annotate | Download | only in dex
      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 
     53   uint32_t InsnsSizeInCodeUnits() const {
     54     return insns_size_in_code_units_;
     55   }
     56 
     57   uint32_t InsnsSizeInBytes() const {
     58     static constexpr uint32_t kCodeUnitSizeInBytes = 2u;
     59     return insns_size_in_code_units_ * kCodeUnitSizeInBytes;
     60   }
     61 
     62   const uint16_t* Insns() const {
     63     return insns_;
     64   }
     65 
     66   // Return the instruction for a 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.
     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 
    100   uint16_t RegistersSize() const {
    101     return registers_size_;
    102   }
    103 
    104   uint16_t InsSize() const {
    105     return ins_size_;
    106   }
    107 
    108   uint16_t OutsSize() const {
    109     return outs_size_;
    110   }
    111 
    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.
    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 
    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