xref: /aosp_15_r20/art/libdexfile/dex/class_accessor-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "class_accessor.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/hiddenapi_flags.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/leb128.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
25*795d594fSAndroid Build Coastguard Worker #include "class_iterator.h"
26*795d594fSAndroid Build Coastguard Worker #include "code_item_accessors-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex_file.h"
28*795d594fSAndroid Build Coastguard Worker #include "method_reference.h"
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker namespace art {
31*795d594fSAndroid Build Coastguard Worker 
ClassAccessor(const ClassIteratorData & data)32*795d594fSAndroid Build Coastguard Worker inline ClassAccessor::ClassAccessor(const ClassIteratorData& data)
33*795d594fSAndroid Build Coastguard Worker     : ClassAccessor(data.dex_file_, data.class_def_idx_) {}
34*795d594fSAndroid Build Coastguard Worker 
ClassAccessor(const DexFile & dex_file,const dex::ClassDef & class_def,bool parse_hiddenapi_class_data)35*795d594fSAndroid Build Coastguard Worker inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
36*795d594fSAndroid Build Coastguard Worker                                     const dex::ClassDef& class_def,
37*795d594fSAndroid Build Coastguard Worker                                     bool parse_hiddenapi_class_data)
38*795d594fSAndroid Build Coastguard Worker     : ClassAccessor(dex_file,
39*795d594fSAndroid Build Coastguard Worker                     dex_file.GetClassData(class_def),
40*795d594fSAndroid Build Coastguard Worker                     dex_file.GetIndexForClassDef(class_def),
41*795d594fSAndroid Build Coastguard Worker                     parse_hiddenapi_class_data) {}
42*795d594fSAndroid Build Coastguard Worker 
ClassAccessor(const DexFile & dex_file,uint32_t class_def_index)43*795d594fSAndroid Build Coastguard Worker inline ClassAccessor::ClassAccessor(const DexFile& dex_file, uint32_t class_def_index)
44*795d594fSAndroid Build Coastguard Worker     : ClassAccessor(dex_file, dex_file.GetClassDef(class_def_index)) {}
45*795d594fSAndroid Build Coastguard Worker 
ClassAccessor(const DexFile & dex_file,const uint8_t * class_data,uint32_t class_def_index,bool parse_hiddenapi_class_data)46*795d594fSAndroid Build Coastguard Worker inline ClassAccessor::ClassAccessor(const DexFile& dex_file,
47*795d594fSAndroid Build Coastguard Worker                                     const uint8_t* class_data,
48*795d594fSAndroid Build Coastguard Worker                                     uint32_t class_def_index,
49*795d594fSAndroid Build Coastguard Worker                                     bool parse_hiddenapi_class_data)
50*795d594fSAndroid Build Coastguard Worker     : dex_file_(dex_file),
51*795d594fSAndroid Build Coastguard Worker       class_def_index_(class_def_index),
52*795d594fSAndroid Build Coastguard Worker       ptr_pos_(class_data),
53*795d594fSAndroid Build Coastguard Worker       hiddenapi_ptr_pos_(nullptr),
54*795d594fSAndroid Build Coastguard Worker       num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
55*795d594fSAndroid Build Coastguard Worker       num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
56*795d594fSAndroid Build Coastguard Worker       num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
57*795d594fSAndroid Build Coastguard Worker       num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {
58*795d594fSAndroid Build Coastguard Worker   if (parse_hiddenapi_class_data && class_def_index != DexFile::kDexNoIndex32) {
59*795d594fSAndroid Build Coastguard Worker     const dex::HiddenapiClassData* hiddenapi_class_data = dex_file.GetHiddenapiClassData();
60*795d594fSAndroid Build Coastguard Worker     if (hiddenapi_class_data != nullptr) {
61*795d594fSAndroid Build Coastguard Worker       hiddenapi_ptr_pos_ = hiddenapi_class_data->GetFlagsPointer(class_def_index);
62*795d594fSAndroid Build Coastguard Worker     }
63*795d594fSAndroid Build Coastguard Worker   }
64*795d594fSAndroid Build Coastguard Worker }
65*795d594fSAndroid Build Coastguard Worker 
Read()66*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::Method::Read() {
67*795d594fSAndroid Build Coastguard Worker   index_ += DecodeUnsignedLeb128(&ptr_pos_);
68*795d594fSAndroid Build Coastguard Worker   access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
69*795d594fSAndroid Build Coastguard Worker   code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
70*795d594fSAndroid Build Coastguard Worker   if (hiddenapi_ptr_pos_ != nullptr) {
71*795d594fSAndroid Build Coastguard Worker     hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
72*795d594fSAndroid Build Coastguard Worker     DCHECK(hiddenapi::ApiList(hiddenapi_flags_).IsValid());
73*795d594fSAndroid Build Coastguard Worker   }
74*795d594fSAndroid Build Coastguard Worker }
75*795d594fSAndroid Build Coastguard Worker 
GetReference()76*795d594fSAndroid Build Coastguard Worker inline MethodReference ClassAccessor::Method::GetReference() const {
77*795d594fSAndroid Build Coastguard Worker   return MethodReference(&dex_file_, GetIndex());
78*795d594fSAndroid Build Coastguard Worker }
79*795d594fSAndroid Build Coastguard Worker 
80*795d594fSAndroid Build Coastguard Worker 
Read()81*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::Field::Read() {
82*795d594fSAndroid Build Coastguard Worker   index_ += DecodeUnsignedLeb128(&ptr_pos_);
83*795d594fSAndroid Build Coastguard Worker   access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
84*795d594fSAndroid Build Coastguard Worker   if (hiddenapi_ptr_pos_ != nullptr) {
85*795d594fSAndroid Build Coastguard Worker     hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_);
86*795d594fSAndroid Build Coastguard Worker     DCHECK(hiddenapi::ApiList(hiddenapi_flags_).IsValid());
87*795d594fSAndroid Build Coastguard Worker   }
88*795d594fSAndroid Build Coastguard Worker }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker template <typename DataType, typename Visitor>
VisitMembers(size_t count,const Visitor & visitor,DataType * data)91*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::VisitMembers(size_t count,
92*795d594fSAndroid Build Coastguard Worker                                         const Visitor& visitor,
93*795d594fSAndroid Build Coastguard Worker                                         DataType* data) const {
94*795d594fSAndroid Build Coastguard Worker   DCHECK(data != nullptr);
95*795d594fSAndroid Build Coastguard Worker   for ( ; count != 0; --count) {
96*795d594fSAndroid Build Coastguard Worker     data->Read();
97*795d594fSAndroid Build Coastguard Worker     visitor(*data);
98*795d594fSAndroid Build Coastguard Worker   }
99*795d594fSAndroid Build Coastguard Worker }
100*795d594fSAndroid Build Coastguard Worker 
101*795d594fSAndroid Build Coastguard Worker template <typename StaticFieldVisitor,
102*795d594fSAndroid Build Coastguard Worker           typename InstanceFieldVisitor,
103*795d594fSAndroid Build Coastguard Worker           typename DirectMethodVisitor,
104*795d594fSAndroid Build Coastguard Worker           typename VirtualMethodVisitor>
VisitFieldsAndMethods(const StaticFieldVisitor & static_field_visitor,const InstanceFieldVisitor & instance_field_visitor,const DirectMethodVisitor & direct_method_visitor,const VirtualMethodVisitor & virtual_method_visitor)105*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::VisitFieldsAndMethods(
106*795d594fSAndroid Build Coastguard Worker     const StaticFieldVisitor& static_field_visitor,
107*795d594fSAndroid Build Coastguard Worker     const InstanceFieldVisitor& instance_field_visitor,
108*795d594fSAndroid Build Coastguard Worker     const DirectMethodVisitor& direct_method_visitor,
109*795d594fSAndroid Build Coastguard Worker     const VirtualMethodVisitor& virtual_method_visitor) const {
110*795d594fSAndroid Build Coastguard Worker   Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
111*795d594fSAndroid Build Coastguard Worker   VisitMembers(num_static_fields_, static_field_visitor, &field);
112*795d594fSAndroid Build Coastguard Worker   field.NextSection();
113*795d594fSAndroid Build Coastguard Worker   VisitMembers(num_instance_fields_, instance_field_visitor, &field);
114*795d594fSAndroid Build Coastguard Worker 
115*795d594fSAndroid Build Coastguard Worker   Method method(dex_file_, field.ptr_pos_, field.hiddenapi_ptr_pos_, /*is_static_or_direct*/ true);
116*795d594fSAndroid Build Coastguard Worker   VisitMembers(num_direct_methods_, direct_method_visitor, &method);
117*795d594fSAndroid Build Coastguard Worker   method.NextSection();
118*795d594fSAndroid Build Coastguard Worker   VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
119*795d594fSAndroid Build Coastguard Worker }
120*795d594fSAndroid Build Coastguard Worker 
121*795d594fSAndroid Build Coastguard Worker template <typename DirectMethodVisitor,
122*795d594fSAndroid Build Coastguard Worker           typename VirtualMethodVisitor>
VisitMethods(const DirectMethodVisitor & direct_method_visitor,const VirtualMethodVisitor & virtual_method_visitor)123*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::VisitMethods(const DirectMethodVisitor& direct_method_visitor,
124*795d594fSAndroid Build Coastguard Worker                                         const VirtualMethodVisitor& virtual_method_visitor) const {
125*795d594fSAndroid Build Coastguard Worker   VisitFieldsAndMethods(VoidFunctor(),
126*795d594fSAndroid Build Coastguard Worker                         VoidFunctor(),
127*795d594fSAndroid Build Coastguard Worker                         direct_method_visitor,
128*795d594fSAndroid Build Coastguard Worker                         virtual_method_visitor);
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker 
131*795d594fSAndroid Build Coastguard Worker template <typename StaticFieldVisitor,
132*795d594fSAndroid Build Coastguard Worker           typename InstanceFieldVisitor>
VisitFields(const StaticFieldVisitor & static_field_visitor,const InstanceFieldVisitor & instance_field_visitor)133*795d594fSAndroid Build Coastguard Worker inline void ClassAccessor::VisitFields(const StaticFieldVisitor& static_field_visitor,
134*795d594fSAndroid Build Coastguard Worker                                        const InstanceFieldVisitor& instance_field_visitor) const {
135*795d594fSAndroid Build Coastguard Worker   VisitFieldsAndMethods(static_field_visitor,
136*795d594fSAndroid Build Coastguard Worker                         instance_field_visitor,
137*795d594fSAndroid Build Coastguard Worker                         VoidFunctor(),
138*795d594fSAndroid Build Coastguard Worker                         VoidFunctor());
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker 
GetCodeItem(const Method & method)141*795d594fSAndroid Build Coastguard Worker inline const dex::CodeItem* ClassAccessor::GetCodeItem(const Method& method) const {
142*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetCodeItem(method.GetCodeItemOffset());
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker 
GetInstructions()145*795d594fSAndroid Build Coastguard Worker inline CodeItemInstructionAccessor ClassAccessor::Method::GetInstructions() const {
146*795d594fSAndroid Build Coastguard Worker   return CodeItemInstructionAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset()));
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker 
GetInstructionsAndData()149*795d594fSAndroid Build Coastguard Worker inline CodeItemDataAccessor ClassAccessor::Method::GetInstructionsAndData() const {
150*795d594fSAndroid Build Coastguard Worker   return CodeItemDataAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset()));
151*795d594fSAndroid Build Coastguard Worker }
152*795d594fSAndroid Build Coastguard Worker 
GetDescriptor()153*795d594fSAndroid Build Coastguard Worker inline const char* ClassAccessor::GetDescriptor() const {
154*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetTypeDescriptor(GetClassIdx());
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker 
GetDescriptorView()157*795d594fSAndroid Build Coastguard Worker inline std::string_view ClassAccessor::GetDescriptorView() const {
158*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetTypeDescriptorView(GetClassIdx());
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker 
GetCodeItem()161*795d594fSAndroid Build Coastguard Worker inline const dex::CodeItem* ClassAccessor::Method::GetCodeItem() const {
162*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetCodeItem(code_off_);
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetFieldsInternal(size_t count)166*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetFieldsInternal(size_t count) const {
167*795d594fSAndroid Build Coastguard Worker   return {
168*795d594fSAndroid Build Coastguard Worker       DataIterator<Field>(dex_file_,
169*795d594fSAndroid Build Coastguard Worker                           0u,
170*795d594fSAndroid Build Coastguard Worker                           num_static_fields_,
171*795d594fSAndroid Build Coastguard Worker                           count,
172*795d594fSAndroid Build Coastguard Worker                           ptr_pos_,
173*795d594fSAndroid Build Coastguard Worker                           hiddenapi_ptr_pos_),
174*795d594fSAndroid Build Coastguard Worker       DataIterator<Field>(dex_file_,
175*795d594fSAndroid Build Coastguard Worker                           count,
176*795d594fSAndroid Build Coastguard Worker                           num_static_fields_,
177*795d594fSAndroid Build Coastguard Worker                           count,
178*795d594fSAndroid Build Coastguard Worker                           // The following pointers are bogus but unused in the `end` iterator.
179*795d594fSAndroid Build Coastguard Worker                           ptr_pos_,
180*795d594fSAndroid Build Coastguard Worker                           hiddenapi_ptr_pos_) };
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker 
183*795d594fSAndroid Build Coastguard Worker // Return an iteration range for the first <count> methods.
184*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetMethodsInternal(size_t count)185*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetMethodsInternal(size_t count) const {
186*795d594fSAndroid Build Coastguard Worker   // Skip over the fields.
187*795d594fSAndroid Build Coastguard Worker   Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_);
188*795d594fSAndroid Build Coastguard Worker   VisitMembers(NumFields(), VoidFunctor(), &field);
189*795d594fSAndroid Build Coastguard Worker   // Return the iterator pair.
190*795d594fSAndroid Build Coastguard Worker   return {
191*795d594fSAndroid Build Coastguard Worker       DataIterator<Method>(dex_file_,
192*795d594fSAndroid Build Coastguard Worker                            0u,
193*795d594fSAndroid Build Coastguard Worker                            num_direct_methods_,
194*795d594fSAndroid Build Coastguard Worker                            count,
195*795d594fSAndroid Build Coastguard Worker                            field.ptr_pos_,
196*795d594fSAndroid Build Coastguard Worker                            field.hiddenapi_ptr_pos_),
197*795d594fSAndroid Build Coastguard Worker       DataIterator<Method>(dex_file_,
198*795d594fSAndroid Build Coastguard Worker                            count,
199*795d594fSAndroid Build Coastguard Worker                            num_direct_methods_,
200*795d594fSAndroid Build Coastguard Worker                            count,
201*795d594fSAndroid Build Coastguard Worker                            // The following pointers are bogus but unused in the `end` iterator.
202*795d594fSAndroid Build Coastguard Worker                            field.ptr_pos_,
203*795d594fSAndroid Build Coastguard Worker                            field.hiddenapi_ptr_pos_) };
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker 
GetFields()206*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
207*795d594fSAndroid Build Coastguard Worker     const {
208*795d594fSAndroid Build Coastguard Worker   return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
209*795d594fSAndroid Build Coastguard Worker }
210*795d594fSAndroid Build Coastguard Worker 
211*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetStaticFields()212*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetStaticFields() const {
213*795d594fSAndroid Build Coastguard Worker   return GetFieldsInternal(num_static_fields_);
214*795d594fSAndroid Build Coastguard Worker }
215*795d594fSAndroid Build Coastguard Worker 
216*795d594fSAndroid Build Coastguard Worker 
217*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
GetInstanceFields()218*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetInstanceFields() const {
219*795d594fSAndroid Build Coastguard Worker   IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
220*795d594fSAndroid Build Coastguard Worker   // Skip the static fields.
221*795d594fSAndroid Build Coastguard Worker   return { std::next(fields.begin(), NumStaticFields()), fields.end() };
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetMethods()225*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetMethods() const {
226*795d594fSAndroid Build Coastguard Worker   return GetMethodsInternal(NumMethods());
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetDirectMethods()230*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetDirectMethods() const {
231*795d594fSAndroid Build Coastguard Worker   return GetMethodsInternal(NumDirectMethods());
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
GetVirtualMethods()235*795d594fSAndroid Build Coastguard Worker     ClassAccessor::GetVirtualMethods() const {
236*795d594fSAndroid Build Coastguard Worker   IterationRange<DataIterator<Method>> methods = GetMethods();
237*795d594fSAndroid Build Coastguard Worker   // Skip the direct fields.
238*795d594fSAndroid Build Coastguard Worker   return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
239*795d594fSAndroid Build Coastguard Worker }
240*795d594fSAndroid Build Coastguard Worker 
GetClassIdx()241*795d594fSAndroid Build Coastguard Worker inline dex::TypeIndex ClassAccessor::GetClassIdx() const {
242*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetClassDef(class_def_index_).class_idx_;
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker 
GetClassDef()245*795d594fSAndroid Build Coastguard Worker inline const dex::ClassDef& ClassAccessor::GetClassDef() const {
246*795d594fSAndroid Build Coastguard Worker   return dex_file_.GetClassDef(GetClassDefIndex());
247*795d594fSAndroid Build Coastguard Worker }
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker }  // namespace art
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker #endif  // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_
252