| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_ |
| #define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_ |
| |
| #include "class_accessor.h" |
| |
| #include "base/hiddenapi_flags.h" |
| #include "base/leb128.h" |
| #include "base/utils.h" |
| #include "class_iterator.h" |
| #include "code_item_accessors-inl.h" |
| |
| namespace art { |
| |
| inline ClassAccessor::ClassAccessor(const ClassIteratorData& data) |
| : ClassAccessor(data.dex_file_, data.class_def_idx_) {} |
| |
| inline ClassAccessor::ClassAccessor(const DexFile& dex_file, |
| const dex::ClassDef& class_def, |
| bool parse_hiddenapi_class_data) |
| : ClassAccessor(dex_file, |
| dex_file.GetClassData(class_def), |
| dex_file.GetIndexForClassDef(class_def), |
| parse_hiddenapi_class_data) {} |
| |
| inline ClassAccessor::ClassAccessor(const DexFile& dex_file, uint32_t class_def_index) |
| : ClassAccessor(dex_file, dex_file.GetClassDef(class_def_index)) {} |
| |
| inline ClassAccessor::ClassAccessor(const DexFile& dex_file, |
| const uint8_t* class_data, |
| uint32_t class_def_index, |
| bool parse_hiddenapi_class_data) |
| : dex_file_(dex_file), |
| class_def_index_(class_def_index), |
| ptr_pos_(class_data), |
| hiddenapi_ptr_pos_(nullptr), |
| num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), |
| num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), |
| num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), |
| num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) { |
| if (parse_hiddenapi_class_data && class_def_index != DexFile::kDexNoIndex32) { |
| const dex::HiddenapiClassData* hiddenapi_class_data = dex_file.GetHiddenapiClassData(); |
| if (hiddenapi_class_data != nullptr) { |
| hiddenapi_ptr_pos_ = hiddenapi_class_data->GetFlagsPointer(class_def_index); |
| } |
| } |
| } |
| |
| inline void ClassAccessor::Method::Read() { |
| index_ += DecodeUnsignedLeb128(&ptr_pos_); |
| access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); |
| code_off_ = DecodeUnsignedLeb128(&ptr_pos_); |
| if (hiddenapi_ptr_pos_ != nullptr) { |
| hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_); |
| DCHECK(hiddenapi::AreValidDexFlags(hiddenapi_flags_)); |
| } |
| } |
| |
| inline void ClassAccessor::Field::Read() { |
| index_ += DecodeUnsignedLeb128(&ptr_pos_); |
| access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); |
| if (hiddenapi_ptr_pos_ != nullptr) { |
| hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_); |
| DCHECK(hiddenapi::AreValidDexFlags(hiddenapi_flags_)); |
| } |
| } |
| |
| template <typename DataType, typename Visitor> |
| inline void ClassAccessor::VisitMembers(size_t count, |
| const Visitor& visitor, |
| DataType* data) const { |
| DCHECK(data != nullptr); |
| for ( ; count != 0; --count) { |
| data->Read(); |
| visitor(*data); |
| } |
| } |
| |
| template <typename StaticFieldVisitor, |
| typename InstanceFieldVisitor, |
| typename DirectMethodVisitor, |
| typename VirtualMethodVisitor> |
| inline void ClassAccessor::VisitFieldsAndMethods( |
| const StaticFieldVisitor& static_field_visitor, |
| const InstanceFieldVisitor& instance_field_visitor, |
| const DirectMethodVisitor& direct_method_visitor, |
| const VirtualMethodVisitor& virtual_method_visitor) const { |
| Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_); |
| VisitMembers(num_static_fields_, static_field_visitor, &field); |
| field.NextSection(); |
| VisitMembers(num_instance_fields_, instance_field_visitor, &field); |
| |
| Method method(dex_file_, field.ptr_pos_, field.hiddenapi_ptr_pos_, /*is_static_or_direct*/ true); |
| VisitMembers(num_direct_methods_, direct_method_visitor, &method); |
| method.NextSection(); |
| VisitMembers(num_virtual_methods_, virtual_method_visitor, &method); |
| } |
| |
| template <typename DirectMethodVisitor, |
| typename VirtualMethodVisitor> |
| inline void ClassAccessor::VisitMethods(const DirectMethodVisitor& direct_method_visitor, |
| const VirtualMethodVisitor& virtual_method_visitor) const { |
| VisitFieldsAndMethods(VoidFunctor(), |
| VoidFunctor(), |
| direct_method_visitor, |
| virtual_method_visitor); |
| } |
| |
| template <typename StaticFieldVisitor, |
| typename InstanceFieldVisitor> |
| inline void ClassAccessor::VisitFields(const StaticFieldVisitor& static_field_visitor, |
| const InstanceFieldVisitor& instance_field_visitor) const { |
| VisitFieldsAndMethods(static_field_visitor, |
| instance_field_visitor, |
| VoidFunctor(), |
| VoidFunctor()); |
| } |
| |
| inline const dex::CodeItem* ClassAccessor::GetCodeItem(const Method& method) const { |
| return dex_file_.GetCodeItem(method.GetCodeItemOffset()); |
| } |
| |
| inline CodeItemInstructionAccessor ClassAccessor::Method::GetInstructions() const { |
| return CodeItemInstructionAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset())); |
| } |
| |
| inline CodeItemDataAccessor ClassAccessor::Method::GetInstructionsAndData() const { |
| return CodeItemDataAccessor(dex_file_, dex_file_.GetCodeItem(GetCodeItemOffset())); |
| } |
| |
| inline const char* ClassAccessor::GetDescriptor() const { |
| return dex_file_.StringByTypeIdx(GetClassIdx()); |
| } |
| |
| inline const dex::CodeItem* ClassAccessor::Method::GetCodeItem() const { |
| return dex_file_.GetCodeItem(code_off_); |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> |
| ClassAccessor::GetFieldsInternal(size_t count) const { |
| return { |
| DataIterator<Field>(dex_file_, |
| 0u, |
| num_static_fields_, |
| count, |
| ptr_pos_, |
| hiddenapi_ptr_pos_), |
| DataIterator<Field>(dex_file_, |
| count, |
| num_static_fields_, |
| count, |
| // The following pointers are bogus but unused in the `end` iterator. |
| ptr_pos_, |
| hiddenapi_ptr_pos_) }; |
| } |
| |
| // Return an iteration range for the first <count> methods. |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> |
| ClassAccessor::GetMethodsInternal(size_t count) const { |
| // Skip over the fields. |
| Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_); |
| VisitMembers(NumFields(), VoidFunctor(), &field); |
| // Return the iterator pair. |
| return { |
| DataIterator<Method>(dex_file_, |
| 0u, |
| num_direct_methods_, |
| count, |
| field.ptr_pos_, |
| field.hiddenapi_ptr_pos_), |
| DataIterator<Method>(dex_file_, |
| count, |
| num_direct_methods_, |
| count, |
| // The following pointers are bogus but unused in the `end` iterator. |
| field.ptr_pos_, |
| field.hiddenapi_ptr_pos_) }; |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields() |
| const { |
| return GetFieldsInternal(num_static_fields_ + num_instance_fields_); |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> |
| ClassAccessor::GetStaticFields() const { |
| return GetFieldsInternal(num_static_fields_); |
| } |
| |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> |
| ClassAccessor::GetInstanceFields() const { |
| IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields(); |
| // Skip the static fields. |
| return { std::next(fields.begin(), NumStaticFields()), fields.end() }; |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> |
| ClassAccessor::GetMethods() const { |
| return GetMethodsInternal(NumMethods()); |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> |
| ClassAccessor::GetDirectMethods() const { |
| return GetMethodsInternal(NumDirectMethods()); |
| } |
| |
| inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> |
| ClassAccessor::GetVirtualMethods() const { |
| IterationRange<DataIterator<Method>> methods = GetMethods(); |
| // Skip the direct fields. |
| return { std::next(methods.begin(), NumDirectMethods()), methods.end() }; |
| } |
| |
| inline dex::TypeIndex ClassAccessor::GetClassIdx() const { |
| return dex_file_.GetClassDef(class_def_index_).class_idx_; |
| } |
| |
| } // namespace art |
| |
| #endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_ |