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