blob: 7455704a7fd141568487aacb490920fca635a45f [file] [log] [blame]
Mathieu Chartierc2b4db62018-05-18 13:58:12 -07001/*
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 "base/utils.h"
Mathieu Chartier05dc23e2018-05-22 11:56:14 -070021#include "code_item_accessors.h"
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070022#include "dex_file.h"
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070023#include "invoke_type.h"
24#include "method_reference.h"
25#include "modifiers.h"
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070026
27namespace art {
28
Mathieu Chartier05dc23e2018-05-22 11:56:14 -070029class ClassIteratorData;
30
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070031// Classes to access Dex data.
32class ClassAccessor {
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070033 private:
34 class BaseItem {
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070035 public:
36 uint32_t GetIndex() const {
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070037 return index_;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070038 }
39
40 uint32_t GetAccessFlags() const {
41 return access_flags_;
42 }
43
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070044 bool IsFinal() const {
45 return (GetAccessFlags() & kAccFinal) != 0;
46 }
47
Mathieu Chartier0d896bd2018-05-25 00:20:27 -070048 protected:
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070049 uint32_t index_ = 0u;
50 uint32_t access_flags_ = 0u;
51 };
52
53 public:
54 // A decoded version of the method of a class_data_item.
55 class Method : public BaseItem {
56 public:
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070057 uint32_t GetCodeItemOffset() const {
58 return code_off_;
59 }
60
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070061 InvokeType GetInvokeType(uint32_t class_access_flags) const {
62 return is_static_or_direct_
63 ? GetDirectMethodInvokeType()
64 : GetVirtualMethodInvokeType(class_access_flags);
65 }
66
67 MethodReference GetReference() const {
68 return MethodReference(&dex_file_, GetIndex());
69 }
70
Mathieu Chartier05dc23e2018-05-22 11:56:14 -070071 CodeItemInstructionAccessor GetInstructions() const;
72
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070073 const DexFile::CodeItem* GetCodeItem() const;
74
Mathieu Chartier0d896bd2018-05-25 00:20:27 -070075 bool IsStaticOrDirect() const {
76 return is_static_or_direct_;
77 }
78
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070079 private:
Mathieu Chartier0d896bd2018-05-25 00:20:27 -070080 explicit Method(const DexFile& dex_file,
81 bool is_static_or_direct = true)
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070082 : dex_file_(dex_file),
83 is_static_or_direct_(is_static_or_direct) {}
Mathieu Chartier05dc23e2018-05-22 11:56:14 -070084
Mathieu Chartierc2b4db62018-05-18 13:58:12 -070085 const uint8_t* Read(const uint8_t* ptr);
86
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -070087 InvokeType GetDirectMethodInvokeType() const {
88 return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
89 }
90
91 InvokeType GetVirtualMethodInvokeType(uint32_t class_access_flags) const {
92 DCHECK_EQ(GetAccessFlags() & kAccStatic, 0U);
93 if ((class_access_flags & kAccInterface) != 0) {
94 return kInterface;
95 } else if ((GetAccessFlags() & kAccConstructor) != 0) {
96 return kSuper;
97 } else {
98 return kVirtual;
99 }
100 }
101
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700102 void NextSection() {
103 DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
104 is_static_or_direct_ = false;
105 index_ = 0u;
106 }
107
Mathieu Chartier05dc23e2018-05-22 11:56:14 -0700108 const DexFile& dex_file_;
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700109 bool is_static_or_direct_ = true;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700110 uint32_t code_off_ = 0u;
111
112 friend class ClassAccessor;
113 };
114
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -0700115 // A decoded version of the field of a class_data_item.
116 class Field : public BaseItem {
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700117 public:
118 explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
119
120 const DexFile& GetDexFile() const {
121 return dex_file_;
122 }
123
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700124 private:
125 const uint8_t* Read(const uint8_t* ptr);
126
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700127 void NextSection() {
128 index_ = 0u;
129 }
130
131 const DexFile& dex_file_;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700132 friend class ClassAccessor;
133 };
134
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700135 template <typename DataType>
136 class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
137 public:
138 using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
139 using difference_type =
140 typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;
141
142 DataIterator(const DexFile& dex_file,
143 uint32_t position,
144 uint32_t partition_pos,
145 uint32_t iterator_end,
146 const uint8_t* ptr_pos)
147 : data_(dex_file),
148 position_(position),
149 partition_pos_(partition_pos),
150 iterator_end_(iterator_end),
151 ptr_pos_(ptr_pos) {
152 ReadData();
153 }
154
155 bool IsValid() const {
156 return position_ < iterator_end_;
157 }
158
159 // Value after modification.
160 DataIterator& operator++() {
161 ++position_;
162 ReadData();
163 return *this;
164 }
165
166 const value_type& operator*() const {
167 return data_;
168 }
169
170 const value_type* operator->() const {
171 return &data_;
172 }
173
174 bool operator==(const DataIterator& rhs) const {
175 DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
176 return position_ == rhs.position_;
177 }
178
179 bool operator!=(const DataIterator& rhs) const {
180 return !(*this == rhs);
181 }
182
183 bool operator<(const DataIterator& rhs) const {
184 DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
185 return position_ < rhs.position_;
186 }
187
188 bool operator>(const DataIterator& rhs) const {
189 return rhs < *this;
190 }
191
192 bool operator<=(const DataIterator& rhs) const {
193 return !(rhs < *this);
194 }
195
196 bool operator>=(const DataIterator& rhs) const {
197 return !(*this < rhs);
198 }
199
200 private:
201 // Read data at current position.
202 void ReadData() {
203 if (IsValid()) {
204 // At the end of the first section, go to the next section.
205 if (position_ == partition_pos_) {
206 data_.NextSection();
207 }
208 DCHECK(ptr_pos_ != nullptr);
209 ptr_pos_ = data_.Read(ptr_pos_);
210 }
211 }
212
213 DataType data_;
214 // Iterator position.
215 uint32_t position_;
216 // At partition_pos_, we go to the next section.
217 const uint32_t partition_pos_;
218 // At iterator_end_, the iterator is no longer valid.
219 const uint32_t iterator_end_;
220 // Internal data pointer.
221 const uint8_t* ptr_pos_;
222 };
223
Mathieu Chartier05dc23e2018-05-22 11:56:14 -0700224 // Not explicit specifically for range-based loops.
225 ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);
226
227 ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def);
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700228
229 // Return the code item for a method.
230 const DexFile::CodeItem* GetCodeItem(const Method& method) const;
231
232 // Iterator data is not very iterator friendly, use visitors to get around this.
233 template <typename StaticFieldVisitor,
234 typename InstanceFieldVisitor,
235 typename DirectMethodVisitor,
236 typename VirtualMethodVisitor>
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -0700237 void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700238 const InstanceFieldVisitor& instance_field_visitor,
239 const DirectMethodVisitor& direct_method_visitor,
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700240 const VirtualMethodVisitor& virtual_method_visitor) const;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700241
242 template <typename DirectMethodVisitor,
243 typename VirtualMethodVisitor>
244 void VisitMethods(const DirectMethodVisitor& direct_method_visitor,
245 const VirtualMethodVisitor& virtual_method_visitor) const;
246
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -0700247 template <typename StaticFieldVisitor,
248 typename InstanceFieldVisitor>
249 void VisitFields(const StaticFieldVisitor& static_field_visitor,
250 const InstanceFieldVisitor& instance_field_visitor) const;
251
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700252 // Return the iteration range for all the fields.
253 IterationRange<DataIterator<Field>> GetFields() const;
254
255 // Return the iteration range for all the methods.
256 IterationRange<DataIterator<Method>> GetMethods() const;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700257
258 uint32_t NumStaticFields() const {
259 return num_static_fields_;
260 }
261
262 uint32_t NumInstanceFields() const {
263 return num_instance_fields_;
264 }
265
266 uint32_t NumDirectMethods() const {
267 return num_direct_methods_;
268 }
269
270 uint32_t NumVirtualMethods() const {
271 return num_virtual_methods_;
272 }
273
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -0700274 const char* GetDescriptor() const;
275
276 dex::TypeIndex GetClassIdx() const {
Mathieu Chartier05dc23e2018-05-22 11:56:14 -0700277 return descriptor_index_;
278 }
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700279
Mathieu Chartierc8c8d5f2018-05-22 11:56:14 -0700280 const DexFile& GetDexFile() const {
281 return dex_file_;
282 }
283
Mathieu Chartier05dc23e2018-05-22 11:56:14 -0700284 protected:
Mathieu Chartier0d896bd2018-05-25 00:20:27 -0700285 // Template visitor to reduce copy paste for visiting elements.
286 // No thread safety analysis since the visitor may require capabilities.
287 template <typename DataType, typename Visitor>
288 const uint8_t* VisitMembers(size_t count,
289 const Visitor& visitor,
290 const uint8_t* ptr,
291 DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
292
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700293 const DexFile& dex_file_;
Mathieu Chartier05dc23e2018-05-22 11:56:14 -0700294 const dex::TypeIndex descriptor_index_ = {};
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700295 const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item.
296 const uint32_t num_static_fields_ = 0u;
297 const uint32_t num_instance_fields_ = 0u;
298 const uint32_t num_direct_methods_ = 0u;
299 const uint32_t num_virtual_methods_ = 0u;
Mathieu Chartierc2b4db62018-05-18 13:58:12 -0700300};
301
302} // namespace art
303
304#endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_