• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
BaseItem(const DexFile & dex_file,const uint8_t * ptr_pos,const uint8_t * hiddenapi_ptr_pos)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 
GetIndex()47     uint32_t GetIndex() const {
48       return index_;
49     }
50 
GetAccessFlags()51     uint32_t GetAccessFlags() const {
52       return access_flags_;
53     }
54 
GetHiddenapiFlags()55     uint32_t GetHiddenapiFlags() const {
56       return hiddenapi_flags_;
57     }
58 
IsFinal()59     bool IsFinal() const {
60       return (GetAccessFlags() & kAccFinal) != 0;
61     }
62 
GetDexFile()63     const DexFile& GetDexFile() const {
64       return dex_file_;
65     }
66 
GetDataPointer()67     const uint8_t* GetDataPointer() const {
68       return ptr_pos_;
69     }
70 
MemberIsNative()71     bool MemberIsNative() const {
72       return GetAccessFlags() & kAccNative;
73     }
74 
MemberIsFinal()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:
GetCodeItemOffset()92     uint32_t GetCodeItemOffset() const {
93       return code_off_;
94     }
95 
GetInvokeType(uint32_t class_access_flags)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 
IsStaticOrDirect()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)
BaseItem(dex_file,ptr_pos,hiddenapi_ptr_pos)118         : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos),
119           is_static_or_direct_(is_static_or_direct) {}
120 
121     void Read();
122 
GetDirectMethodInvokeType()123     InvokeType GetDirectMethodInvokeType() const {
124       return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
125     }
126 
GetVirtualMethodInvokeType(uint32_t class_access_flags)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.
NextSection()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)
BaseItem(dex_file,ptr_pos,hiddenapi_ptr_pos)158         : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {}
159 
IsStatic()160     bool IsStatic() const {
161      return is_static_;
162     }
163 
164    private:
165     void Read();
166 
167     // Move to instance fields section.
NextSection()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 
DataIterator(const DexFile & dex_file,uint32_t position,uint32_t partition_pos,uint32_t iterator_end,const uint8_t * ptr_pos,const uint8_t * hiddenapi_ptr_pos)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 
IsValid()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 
GetDataPointer()243     const uint8_t* GetDataPointer() const {
244       return data_.ptr_pos_;
245     }
246 
247    private:
248     // Read data at current position.
ReadData()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 
NumStaticFields()325   uint32_t NumStaticFields() const {
326     return num_static_fields_;
327   }
328 
NumInstanceFields()329   uint32_t NumInstanceFields() const {
330     return num_instance_fields_;
331   }
332 
NumFields()333   uint32_t NumFields() const {
334     return NumStaticFields() + NumInstanceFields();
335   }
336 
NumDirectMethods()337   uint32_t NumDirectMethods() const {
338     return num_direct_methods_;
339   }
340 
NumVirtualMethods()341   uint32_t NumVirtualMethods() const {
342     return num_virtual_methods_;
343   }
344 
NumMethods()345   uint32_t NumMethods() const {
346     return NumDirectMethods() + NumVirtualMethods();
347   }
348 
349   const char* GetDescriptor() const;
350 
351   dex::TypeIndex GetClassIdx() const;
352 
GetDexFile()353   const DexFile& GetDexFile() const {
354     return dex_file_;
355   }
356 
HasClassData()357   bool HasClassData() const {
358     return ptr_pos_ != nullptr;
359   }
360 
HasHiddenapiClassData()361   bool HasHiddenapiClassData() const {
362     return hiddenapi_ptr_pos_ != nullptr;
363   }
364 
GetClassDefIndex()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