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