Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2018 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 #ifndef ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
     18 #define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
     19 
     20 #include "code_item_accessors.h"
     21 #include "dex_file_types.h"
     22 #include "invoke_type.h"
     23 #include "modifiers.h"
     24 
     25 namespace art {
     26 
     27 namespace dex {
     28 struct ClassDef;
     29 struct CodeItem;
     30 }  // namespace dex
     31 
     32 class ClassIteratorData;
     33 class DexFile;
     34 template <typename Iter> class IterationRange;
     35 class MethodReference;
     36 
     37 // Classes to access Dex data.
     38 class ClassAccessor {
     39  public:
     40   class BaseItem {
     41    public:
     42     explicit BaseItem(const DexFile& dex_file,
     43                       const uint8_t* ptr_pos,
     44                       const uint8_t* hiddenapi_ptr_pos)
     45         : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {}
     46 
     47     uint32_t GetIndex() const {
     48       return index_;
     49     }
     50 
     51     uint32_t GetAccessFlags() const {
     52       return access_flags_;
     53     }
     54 
     55     uint32_t GetHiddenapiFlags() const {
     56       return hiddenapi_flags_;
     57     }
     58 
     59     bool IsFinal() const {
     60       return (GetAccessFlags() & kAccFinal) != 0;
     61     }
     62 
     63     const DexFile& GetDexFile() const {
     64       return dex_file_;
     65     }
     66 
     67     const uint8_t* GetDataPointer() const {
     68       return ptr_pos_;
     69     }
     70 
     71     bool MemberIsNative() const {
     72       return GetAccessFlags() & kAccNative;
     73     }
     74 
     75     bool MemberIsFinal() const {
     76       return GetAccessFlags() & kAccFinal;
     77     }
     78 
     79    protected:
     80     // Internal data pointer for reading.
     81     const DexFile& dex_file_;
     82     const uint8_t* ptr_pos_ = nullptr;
     83     const uint8_t* hiddenapi_ptr_pos_ = nullptr;
     84     uint32_t index_ = 0u;
     85     uint32_t access_flags_ = 0u;
     86     uint32_t hiddenapi_flags_ = 0u;
     87   };
     88 
     89   // A decoded version of the method of a class_data_item.
     90   class Method : public BaseItem {
     91    public:
     92     uint32_t GetCodeItemOffset() const {
     93       return code_off_;
     94     }
     95 
     96     InvokeType GetInvokeType(uint32_t class_access_flags) const {
     97       return is_static_or_direct_
     98           ? GetDirectMethodInvokeType()
     99           : GetVirtualMethodInvokeType(class_access_flags);
    100     }
    101 
    102     MethodReference GetReference() const;
    103 
    104     CodeItemInstructionAccessor GetInstructions() const;
    105     CodeItemDataAccessor GetInstructionsAndData() const;
    106 
    107     const dex::CodeItem* GetCodeItem() const;
    108 
    109     bool IsStaticOrDirect() const {
    110       return is_static_or_direct_;
    111     }
    112 
    113    private:
    114     Method(const DexFile& dex_file,
    115            const uint8_t* ptr_pos,
    116            const uint8_t* hiddenapi_ptr_pos = nullptr,
    117            bool is_static_or_direct = true)
    118         : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos),
    119           is_static_or_direct_(is_static_or_direct) {}
    120 
    121     void Read();
    122 
    123     InvokeType GetDirectMethodInvokeType() const {
    124       return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
    125     }
    126 
    127     InvokeType GetVirtualMethodInvokeType(uint32_t class_access_flags) const {
    128       DCHECK_EQ(GetAccessFlags() & kAccStatic, 0U);
    129       if ((class_access_flags & kAccInterface) != 0) {
    130         return kInterface;
    131       } else if ((GetAccessFlags() & kAccConstructor) != 0) {
    132         return kSuper;
    133       } else {
    134         return kVirtual;
    135       }
    136     }
    137 
    138     // Move to virtual method section.
    139     void NextSection() {
    140       DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
    141       is_static_or_direct_ = false;
    142       index_ = 0u;
    143     }
    144 
    145     bool is_static_or_direct_ = true;
    146     uint32_t code_off_ = 0u;
    147 
    148     friend class ClassAccessor;
    149     friend class DexFileVerifier;
    150   };
    151 
    152   // A decoded version of the field of a class_data_item.
    153   class Field : public BaseItem {
    154    public:
    155     Field(const DexFile& dex_file,
    156           const uint8_t* ptr_pos,
    157           const uint8_t* hiddenapi_ptr_pos = nullptr)
    158         : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {}
    159 
    160     bool IsStatic() const {
    161      return is_static_;
    162     }
    163 
    164    private:
    165     void Read();
    166 
    167     // Move to instance fields section.
    168     void NextSection() {
    169       index_ = 0u;
    170       is_static_ = false;
    171     }
    172 
    173     bool is_static_ = true;
    174     friend class ClassAccessor;
    175     friend class DexFileVerifier;
    176   };
    177 
    178   template <typename DataType>
    179   class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
    180    public:
    181     using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
    182     using difference_type =
    183         typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;
    184 
    185     DataIterator(const DexFile& dex_file,
    186                  uint32_t position,
    187                  uint32_t partition_pos,
    188                  uint32_t iterator_end,
    189                  const uint8_t* ptr_pos,
    190                  const uint8_t* hiddenapi_ptr_pos)
    191         : data_(dex_file, ptr_pos, hiddenapi_ptr_pos),
    192           position_(position),
    193           partition_pos_(partition_pos),
    194           iterator_end_(iterator_end) {
    195       ReadData();
    196     }
    197 
    198     bool IsValid() const {
    199       return position_ < iterator_end_;
    200     }
    201 
    202     // Value after modification.
    203     DataIterator& operator++() {
    204       ++position_;
    205       ReadData();
    206       return *this;
    207     }
    208 
    209     const value_type& operator*() const {
    210       return data_;
    211     }
    212 
    213     const value_type* operator->() const {
    214       return &data_;
    215     }
    216 
    217     bool operator==(const DataIterator& rhs) const {
    218       DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
    219       return position_ == rhs.position_;
    220     }
    221 
    222     bool operator!=(const DataIterator& rhs) const {
    223       return !(*this == rhs);
    224     }
    225 
    226     bool operator<(const DataIterator& rhs) const {
    227       DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
    228       return position_ < rhs.position_;
    229     }
    230 
    231     bool operator>(const DataIterator& rhs) const {
    232       return rhs < *this;
    233     }
    234 
    235     bool operator<=(const DataIterator& rhs) const {
    236       return !(rhs < *this);
    237     }
    238 
    239     bool operator>=(const DataIterator& rhs) const {
    240       return !(*this < rhs);
    241     }
    242 
    243     const uint8_t* GetDataPointer() const {
    244       return data_.ptr_pos_;
    245     }
    246 
    247    private:
    248     // Read data at current position.
    249     void ReadData() {
    250       if (IsValid()) {
    251         // At the end of the first section, go to the next section.
    252         if (position_ == partition_pos_) {
    253           data_.NextSection();
    254         }
    255         data_.Read();
    256       }
    257     }
    258 
    259     DataType data_;
    260     // Iterator position.
    261     uint32_t position_;
    262     // At partition_pos_, we go to the next section.
    263     const uint32_t partition_pos_;
    264     // At iterator_end_, the iterator is no longer valid.
    265     const uint32_t iterator_end_;
    266 
    267     friend class DexFileVerifier;
    268   };
    269 
    270   // Not explicit specifically for range-based loops.
    271   ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);  // NOLINT [runtime/explicit] [5]
    272 
    273   ALWAYS_INLINE ClassAccessor(const DexFile& dex_file,
    274                               const dex::ClassDef& class_def,
    275                               bool parse_hiddenapi_class_data = false);
    276 
    277   ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index);
    278 
    279   ClassAccessor(const DexFile& dex_file,
    280                 const uint8_t* class_data,
    281                 uint32_t class_def_index = dex::kDexNoIndex,
    282                 bool parse_hiddenapi_class_data = false);
    283 
    284   // Return the code item for a method.
    285   const dex::CodeItem* GetCodeItem(const Method& method) const;
    286 
    287   // Iterator data is not very iterator friendly, use visitors to get around this.
    288   template <typename StaticFieldVisitor,
    289             typename InstanceFieldVisitor,
    290             typename DirectMethodVisitor,
    291             typename VirtualMethodVisitor>
    292   void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
    293                              const InstanceFieldVisitor& instance_field_visitor,
    294                              const DirectMethodVisitor& direct_method_visitor,
    295                              const VirtualMethodVisitor& virtual_method_visitor) const;
    296 
    297   template <typename DirectMethodVisitor,
    298             typename VirtualMethodVisitor>
    299   void VisitMethods(const DirectMethodVisitor& direct_method_visitor,
    300                     const VirtualMethodVisitor& virtual_method_visitor) const;
    301 
    302   template <typename StaticFieldVisitor,
    303             typename InstanceFieldVisitor>
    304   void VisitFields(const StaticFieldVisitor& static_field_visitor,
    305                    const InstanceFieldVisitor& instance_field_visitor) const;
    306 
    307   // Return the iteration range for all the fields.
    308   IterationRange<DataIterator<Field>> GetFields() const;
    309 
    310   // Return the iteration range for all the static fields.
    311   IterationRange<DataIterator<Field>> GetStaticFields() const;
    312 
    313   // Return the iteration range for all the instance fields.
    314   IterationRange<DataIterator<Field>> GetInstanceFields() const;
    315 
    316   // Return the iteration range for all the methods.
    317   IterationRange<DataIterator<Method>> GetMethods() const;
    318 
    319   // Return the iteration range for the direct methods.
    320   IterationRange<DataIterator<Method>> GetDirectMethods() const;
    321 
    322   // Return the iteration range for the virtual methods.
    323   IterationRange<DataIterator<Method>> GetVirtualMethods() const;
    324 
    325   uint32_t NumStaticFields() const {
    326     return num_static_fields_;
    327   }
    328 
    329   uint32_t NumInstanceFields() const {
    330     return num_instance_fields_;
    331   }
    332 
    333   uint32_t NumFields() const {
    334     return NumStaticFields() + NumInstanceFields();
    335   }
    336 
    337   uint32_t NumDirectMethods() const {
    338     return num_direct_methods_;
    339   }
    340 
    341   uint32_t NumVirtualMethods() const {
    342     return num_virtual_methods_;
    343   }
    344 
    345   uint32_t NumMethods() const {
    346     return NumDirectMethods() + NumVirtualMethods();
    347   }
    348 
    349   const char* GetDescriptor() const;
    350 
    351   dex::TypeIndex GetClassIdx() const;
    352 
    353   const DexFile& GetDexFile() const {
    354     return dex_file_;
    355   }
    356 
    357   bool HasClassData() const {
    358     return ptr_pos_ != nullptr;
    359   }
    360 
    361   bool HasHiddenapiClassData() const {
    362     return hiddenapi_ptr_pos_ != nullptr;
    363   }
    364 
    365   uint32_t GetClassDefIndex() const {
    366     return class_def_index_;
    367   }
    368 
    369   const dex::ClassDef& GetClassDef() const;
    370 
    371  protected:
    372   // Template visitor to reduce copy paste for visiting elements.
    373   // No thread safety analysis since the visitor may require capabilities.
    374   template <typename DataType, typename Visitor>
    375   void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
    376       NO_THREAD_SAFETY_ANALYSIS;
    377 
    378   // Return an iteration range for the first <count> fields.
    379   IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
    380 
    381   // Return an iteration range for the first <count> methods.
    382   IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
    383 
    384   const DexFile& dex_file_;
    385   const uint32_t class_def_index_;
    386   const uint8_t* ptr_pos_ = nullptr;  // Pointer into stream of class_data_item.
    387   const uint8_t* hiddenapi_ptr_pos_ = nullptr;  // Pointer into stream of hiddenapi_metadata.
    388   const uint32_t num_static_fields_ = 0u;
    389   const uint32_t num_instance_fields_ = 0u;
    390   const uint32_t num_direct_methods_ = 0u;
    391   const uint32_t num_virtual_methods_ = 0u;
    392 
    393   friend class DexFileVerifier;
    394 };
    395 
    396 }  // namespace art
    397 
    398 #endif  // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
    399