/*
* 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"
#include "dex_file.h"
#include "method_reference.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::ApiList(hiddenapi_flags_).IsValid());
}
}
inline MethodReference ClassAccessor::Method::GetReference() const {
return MethodReference(&dex_file_, GetIndex());
}
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::ApiList(hiddenapi_flags_).IsValid());
}
}
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_;
}
inline const dex::ClassDef& ClassAccessor::GetClassDef() const {
return dex_file_.GetClassDef(GetClassDefIndex());
}
} // namespace art
#endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_INL_H_