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_
 |