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