248 lines
9.4 KiB
C++
248 lines
9.4 KiB
C++
/*
|
|
* 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_
|