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_INL_H_
18 #define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
19
20 #include "class_accessor.h"
21
22 #include "base/hiddenapi_flags.h"
23 #include "base/leb128.h"
24 #include "base/utils.h"
25 #include "class_iterator.h"
26 #include "code_item_accessors-inl.h"
27 #include "dex_file.h"
28 #include "method_reference.h"
29
30 namespace art {
31
ClassAccessor(const ClassIteratorData & data)32 inline ClassAccessor::ClassAccessor(const ClassIteratorData& data)
33 : ClassAccessor(data.dex_file_, data.class_def_idx_) {}
34
ClassAccessor(const DexFile & dex_file,const dex::ClassDef & class_def,bool parse_hiddenapi_class_data)35 inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
36 const dex::ClassDef& class_def,
37 bool parse_hiddenapi_class_data)
38 : ClassAccessor(dex_file,
39 dex_file.GetClassData(class_def),
40 dex_file.GetIndexForClassDef(class_def),
41 parse_hiddenapi_class_data) {}
42
ClassAccessor(const DexFile & dex_file,uint32_t class_def_index)43 inline ClassAccessor::ClassAccessor(const DexFile& dex_file, uint32_t class_def_index)
44 : ClassAccessor(dex_file, dex_file.GetClassDef(class_def_index)) {}
45
ClassAccessor(const DexFile & dex_file,const uint8_t * class_data,uint32_t class_def_index,bool parse_hiddenapi_class_data)46 inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
47 const uint8_t* class_data,
48 uint32_t class_def_index,
49 bool parse_hiddenapi_class_data)
50 : dex_file_(dex_file),
51 class_def_index_(class_def_index),
52 ptr_pos_(class_data),
53 hiddenapi_ptr_pos_(nullptr),
54 num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
55 num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
56 num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
57 num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {
58 if (parse_hiddenapi_class_data && class_def_index != DexFile::kDexNoIndex32) {
59 const dex::HiddenapiClassData* hiddenapi_class_data = dex_file.GetHiddenapiClassData();
60 if (hiddenapi_class_data != nullptr) {
61 hiddenapi_ptr_pos_ = hiddenapi_class_data->GetFlagsPointer(class_def_index);
62 }
63 }
64 }
65
Read()66 inline void ClassAccessor::Method::Read() {
67 index_ += DecodeUnsignedLeb128(&ptr_pos_);
68 access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
69 code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
70 if (hiddenapi_ptr_pos_ != nullptr) {
71 hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
72 DCHECK(hiddenapi::ApiList(hiddenapi_flags_).IsValid());
73 }
74 }
75
GetReference()76 inline MethodReference ClassAccessor::Method::GetReference() const {
77 return MethodReference(&dex_file_, GetIndex());
78 }
79
80
Read()81 inline void ClassAccessor::Field::Read() {
82 index_ += DecodeUnsignedLeb128(&ptr_pos_);
83 access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
84 if (hiddenapi_ptr_pos_ != nullptr) {
85 hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
86 DCHECK(hiddenapi::ApiList(hiddenapi_flags_).IsValid());
87 }
88 }
89
90 template <typename DataType, typename Visitor>
VisitMembers(size_t count,const Visitor & visitor,DataType * data)91 inline void ClassAccessor::VisitMembers(size_t count,
92 const Visitor& visitor,
93 DataType* data) const {
94 DCHECK(data != nullptr);
95 for ( ; count != 0; --count) {
96 data->Read();
97 visitor(*data);
98 }
99 }
100
101 template <typename StaticFieldVisitor,
102 typename InstanceFieldVisitor,
103 typename DirectMethodVisitor,
104 typename VirtualMethodVisitor>
VisitFieldsAndMethods(const StaticFieldVisitor & static_field_visitor,const InstanceFieldVisitor & instance_field_visitor,const DirectMethodVisitor & direct_method_visitor,const VirtualMethodVisitor & virtual_method_visitor)105 inline void ClassAccessor::VisitFieldsAndMethods(
106 const StaticFieldVisitor& static_field_visitor,
107 const InstanceFieldVisitor& instance_field_visitor,
108 const DirectMethodVisitor& direct_method_visitor,
109 const VirtualMethodVisitor& virtual_method_visitor) const {
110 Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
111 VisitMembers(num_static_fields_, static_field_visitor, &field);
112 field.NextSection();
113 VisitMembers(num_instance_fields_, instance_field_visitor, &field);
114
115 Method method(dex_file_, field.ptr_pos_, field.hiddenapi_ptr_pos_, /*is_static_or_direct*/ true);
116 VisitMembers(num_direct_methods_, direct_method_visitor, &method);
117 method.NextSection();
118 VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
119 }
120
121 template <typename DirectMethodVisitor,
122 typename VirtualMethodVisitor>
VisitMethods(const DirectMethodVisitor & direct_method_visitor,const VirtualMethodVisitor & virtual_method_visitor)123 inline void ClassAccessor::VisitMethods(const DirectMethodVisitor& direct_method_visitor,
124 const VirtualMethodVisitor& virtual_method_visitor) const {
125 VisitFieldsAndMethods(VoidFunctor(),
126 VoidFunctor(),
127 direct_method_visitor,
128 virtual_method_visitor);
129 }
130
131 template <typename StaticFieldVisitor,
132 typename InstanceFieldVisitor>
VisitFields(const StaticFieldVisitor & static_field_visitor,const InstanceFieldVisitor & instance_field_visitor)133 inline void ClassAccessor::VisitFields(const StaticFieldVisitor& static_field_visitor,
134 const InstanceFieldVisitor& instance_field_visitor) const {
135 VisitFieldsAndMethods(static_field_visitor,
136 instance_field_visitor,
137 VoidFunctor(),
138 VoidFunctor());
139 }
140
GetCodeItem(const Method & method)141 inline const dex::CodeItem* ClassAccessor::GetCodeItem(const Method& method) const {
142 return dex_file_.GetCodeItem(method.GetCodeItemOffset());
143 }
144
GetInstructions()145 inline CodeItemInstructionAccessor ClassAccessor::Method::GetInstructions() const {
146 return CodeItemInstructionAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset()));
147 }
148
GetInstructionsAndData()149 inline CodeItemDataAccessor ClassAccessor::Method::GetInstructionsAndData() const {
150 return CodeItemDataAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset()));
151 }
152
GetDescriptor()153 inline const char* ClassAccessor::GetDescriptor() const {
154 return dex_file_.StringByTypeIdx(GetClassIdx());
155 }
156
GetCodeItem()157 inline const dex::CodeItem* ClassAccessor::Method::GetCodeItem() const {
158 return dex_file_.GetCodeItem(code_off_);
159 }
160
161 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetFieldsInternal(size_t count)162 ClassAccessor::GetFieldsInternal(size_t count) const {
163 return {
164 DataIterator<Field>(dex_file_,
165 0u,
166 num_static_fields_,
167 count,
168 ptr_pos_,
169 hiddenapi_ptr_pos_),
170 DataIterator<Field>(dex_file_,
171 count,
172 num_static_fields_,
173 count,
174 // The following pointers are bogus but unused in the `end` iterator.
175 ptr_pos_,
176 hiddenapi_ptr_pos_) };
177 }
178
179 // Return an iteration range for the first <count> methods.
180 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetMethodsInternal(size_t count)181 ClassAccessor::GetMethodsInternal(size_t count) const {
182 // Skip over the fields.
183 Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
184 VisitMembers(NumFields(), VoidFunctor(), &field);
185 // Return the iterator pair.
186 return {
187 DataIterator<Method>(dex_file_,
188 0u,
189 num_direct_methods_,
190 count,
191 field.ptr_pos_,
192 field.hiddenapi_ptr_pos_),
193 DataIterator<Method>(dex_file_,
194 count,
195 num_direct_methods_,
196 count,
197 // The following pointers are bogus but unused in the `end` iterator.
198 field.ptr_pos_,
199 field.hiddenapi_ptr_pos_) };
200 }
201
GetFields()202 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
203 const {
204 return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
205 }
206
207 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetStaticFields()208 ClassAccessor::GetStaticFields() const {
209 return GetFieldsInternal(num_static_fields_);
210 }
211
212
213 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetInstanceFields()214 ClassAccessor::GetInstanceFields() const {
215 IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
216 // Skip the static fields.
217 return { std::next(fields.begin(), NumStaticFields()), fields.end() };
218 }
219
220 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetMethods()221 ClassAccessor::GetMethods() const {
222 return GetMethodsInternal(NumMethods());
223 }
224
225 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetDirectMethods()226 ClassAccessor::GetDirectMethods() const {
227 return GetMethodsInternal(NumDirectMethods());
228 }
229
230 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetVirtualMethods()231 ClassAccessor::GetVirtualMethods() const {
232 IterationRange<DataIterator<Method>> methods = GetMethods();
233 // Skip the direct fields.
234 return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
235 }
236
GetClassIdx()237 inline dex::TypeIndex ClassAccessor::GetClassIdx() const {
238 return dex_file_.GetClassDef(class_def_index_).class_idx_;
239 }
240
GetClassDef()241 inline const dex::ClassDef& ClassAccessor::GetClassDef() const {
242 return dex_file_.GetClassDef(GetClassDefIndex());
243 }
244
245 } // namespace art
246
247 #endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
248