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