400 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			11 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_H_
 | 
						|
#define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
 | 
						|
 | 
						|
#include "code_item_accessors.h"
 | 
						|
#include "dex_file_types.h"
 | 
						|
#include "invoke_type.h"
 | 
						|
#include "modifiers.h"
 | 
						|
 | 
						|
namespace art {
 | 
						|
 | 
						|
namespace dex {
 | 
						|
struct ClassDef;
 | 
						|
struct CodeItem;
 | 
						|
class DexFileVerifier;
 | 
						|
}  // namespace dex
 | 
						|
 | 
						|
class ClassIteratorData;
 | 
						|
class DexFile;
 | 
						|
template <typename Iter> class IterationRange;
 | 
						|
class MethodReference;
 | 
						|
 | 
						|
// Classes to access Dex data.
 | 
						|
class ClassAccessor {
 | 
						|
 public:
 | 
						|
  class BaseItem {
 | 
						|
   public:
 | 
						|
    explicit BaseItem(const DexFile& dex_file,
 | 
						|
                      const uint8_t* ptr_pos,
 | 
						|
                      const uint8_t* hiddenapi_ptr_pos)
 | 
						|
        : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {}
 | 
						|
 | 
						|
    uint32_t GetIndex() const {
 | 
						|
      return index_;
 | 
						|
    }
 | 
						|
 | 
						|
    uint32_t GetAccessFlags() const {
 | 
						|
      return access_flags_;
 | 
						|
    }
 | 
						|
 | 
						|
    uint32_t GetHiddenapiFlags() const {
 | 
						|
      return hiddenapi_flags_;
 | 
						|
    }
 | 
						|
 | 
						|
    bool IsFinal() const {
 | 
						|
      return (GetAccessFlags() & kAccFinal) != 0;
 | 
						|
    }
 | 
						|
 | 
						|
    const DexFile& GetDexFile() const {
 | 
						|
      return dex_file_;
 | 
						|
    }
 | 
						|
 | 
						|
    const uint8_t* GetDataPointer() const {
 | 
						|
      return ptr_pos_;
 | 
						|
    }
 | 
						|
 | 
						|
    bool MemberIsNative() const {
 | 
						|
      return GetAccessFlags() & kAccNative;
 | 
						|
    }
 | 
						|
 | 
						|
    bool MemberIsFinal() const {
 | 
						|
      return GetAccessFlags() & kAccFinal;
 | 
						|
    }
 | 
						|
 | 
						|
   protected:
 | 
						|
    // Internal data pointer for reading.
 | 
						|
    const DexFile& dex_file_;
 | 
						|
    const uint8_t* ptr_pos_ = nullptr;
 | 
						|
    const uint8_t* hiddenapi_ptr_pos_ = nullptr;
 | 
						|
    uint32_t index_ = 0u;
 | 
						|
    uint32_t access_flags_ = 0u;
 | 
						|
    uint32_t hiddenapi_flags_ = 0u;
 | 
						|
  };
 | 
						|
 | 
						|
  // A decoded version of the method of a class_data_item.
 | 
						|
  class Method : public BaseItem {
 | 
						|
   public:
 | 
						|
    uint32_t GetCodeItemOffset() const {
 | 
						|
      return code_off_;
 | 
						|
    }
 | 
						|
 | 
						|
    InvokeType GetInvokeType(uint32_t class_access_flags) const {
 | 
						|
      return is_static_or_direct_
 | 
						|
          ? GetDirectMethodInvokeType()
 | 
						|
          : GetVirtualMethodInvokeType(class_access_flags);
 | 
						|
    }
 | 
						|
 | 
						|
    MethodReference GetReference() const;
 | 
						|
 | 
						|
    CodeItemInstructionAccessor GetInstructions() const;
 | 
						|
    CodeItemDataAccessor GetInstructionsAndData() const;
 | 
						|
 | 
						|
    const dex::CodeItem* GetCodeItem() const;
 | 
						|
 | 
						|
    bool IsStaticOrDirect() const {
 | 
						|
      return is_static_or_direct_;
 | 
						|
    }
 | 
						|
 | 
						|
   private:
 | 
						|
    Method(const DexFile& dex_file,
 | 
						|
           const uint8_t* ptr_pos,
 | 
						|
           const uint8_t* hiddenapi_ptr_pos = nullptr,
 | 
						|
           bool is_static_or_direct = true)
 | 
						|
        : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos),
 | 
						|
          is_static_or_direct_(is_static_or_direct) {}
 | 
						|
 | 
						|
    void Read();
 | 
						|
 | 
						|
    InvokeType GetDirectMethodInvokeType() const {
 | 
						|
      return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
 | 
						|
    }
 | 
						|
 | 
						|
    InvokeType GetVirtualMethodInvokeType(uint32_t class_access_flags) const {
 | 
						|
      DCHECK_EQ(GetAccessFlags() & kAccStatic, 0U);
 | 
						|
      if ((class_access_flags & kAccInterface) != 0) {
 | 
						|
        return kInterface;
 | 
						|
      } else if ((GetAccessFlags() & kAccConstructor) != 0) {
 | 
						|
        return kSuper;
 | 
						|
      } else {
 | 
						|
        return kVirtual;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // Move to virtual method section.
 | 
						|
    void NextSection() {
 | 
						|
      DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
 | 
						|
      is_static_or_direct_ = false;
 | 
						|
      index_ = 0u;
 | 
						|
    }
 | 
						|
 | 
						|
    bool is_static_or_direct_ = true;
 | 
						|
    uint32_t code_off_ = 0u;
 | 
						|
 | 
						|
    friend class ClassAccessor;
 | 
						|
    friend class dex::DexFileVerifier;
 | 
						|
  };
 | 
						|
 | 
						|
  // A decoded version of the field of a class_data_item.
 | 
						|
  class Field : public BaseItem {
 | 
						|
   public:
 | 
						|
    Field(const DexFile& dex_file,
 | 
						|
          const uint8_t* ptr_pos,
 | 
						|
          const uint8_t* hiddenapi_ptr_pos = nullptr)
 | 
						|
        : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {}
 | 
						|
 | 
						|
    bool IsStatic() const {
 | 
						|
     return is_static_;
 | 
						|
    }
 | 
						|
 | 
						|
   private:
 | 
						|
    void Read();
 | 
						|
 | 
						|
    // Move to instance fields section.
 | 
						|
    void NextSection() {
 | 
						|
      index_ = 0u;
 | 
						|
      is_static_ = false;
 | 
						|
    }
 | 
						|
 | 
						|
    bool is_static_ = true;
 | 
						|
    friend class ClassAccessor;
 | 
						|
    friend class dex::DexFileVerifier;
 | 
						|
  };
 | 
						|
 | 
						|
  template <typename DataType>
 | 
						|
  class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> {
 | 
						|
   public:
 | 
						|
    using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type;
 | 
						|
    using difference_type =
 | 
						|
        typename std::iterator<std::forward_iterator_tag, value_type>::difference_type;
 | 
						|
 | 
						|
    DataIterator(const DexFile& dex_file,
 | 
						|
                 uint32_t position,
 | 
						|
                 uint32_t partition_pos,
 | 
						|
                 uint32_t iterator_end,
 | 
						|
                 const uint8_t* ptr_pos,
 | 
						|
                 const uint8_t* hiddenapi_ptr_pos)
 | 
						|
        : data_(dex_file, ptr_pos, hiddenapi_ptr_pos),
 | 
						|
          position_(position),
 | 
						|
          partition_pos_(partition_pos),
 | 
						|
          iterator_end_(iterator_end) {
 | 
						|
      ReadData();
 | 
						|
    }
 | 
						|
 | 
						|
    bool IsValid() const {
 | 
						|
      return position_ < iterator_end_;
 | 
						|
    }
 | 
						|
 | 
						|
    // Value after modification.
 | 
						|
    DataIterator& operator++() {
 | 
						|
      ++position_;
 | 
						|
      ReadData();
 | 
						|
      return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    const value_type& operator*() const {
 | 
						|
      return data_;
 | 
						|
    }
 | 
						|
 | 
						|
    const value_type* operator->() const {
 | 
						|
      return &data_;
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator==(const DataIterator& rhs) const {
 | 
						|
      DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
 | 
						|
      return position_ == rhs.position_;
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator!=(const DataIterator& rhs) const {
 | 
						|
      return !(*this == rhs);
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator<(const DataIterator& rhs) const {
 | 
						|
      DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files.";
 | 
						|
      return position_ < rhs.position_;
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator>(const DataIterator& rhs) const {
 | 
						|
      return rhs < *this;
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator<=(const DataIterator& rhs) const {
 | 
						|
      return !(rhs < *this);
 | 
						|
    }
 | 
						|
 | 
						|
    bool operator>=(const DataIterator& rhs) const {
 | 
						|
      return !(*this < rhs);
 | 
						|
    }
 | 
						|
 | 
						|
    const uint8_t* GetDataPointer() const {
 | 
						|
      return data_.ptr_pos_;
 | 
						|
    }
 | 
						|
 | 
						|
   private:
 | 
						|
    // Read data at current position.
 | 
						|
    void ReadData() {
 | 
						|
      if (IsValid()) {
 | 
						|
        // At the end of the first section, go to the next section.
 | 
						|
        if (position_ == partition_pos_) {
 | 
						|
          data_.NextSection();
 | 
						|
        }
 | 
						|
        data_.Read();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    DataType data_;
 | 
						|
    // Iterator position.
 | 
						|
    uint32_t position_;
 | 
						|
    // At partition_pos_, we go to the next section.
 | 
						|
    const uint32_t partition_pos_;
 | 
						|
    // At iterator_end_, the iterator is no longer valid.
 | 
						|
    const uint32_t iterator_end_;
 | 
						|
 | 
						|
    friend class dex::DexFileVerifier;
 | 
						|
  };
 | 
						|
 | 
						|
  // Not explicit specifically for range-based loops.
 | 
						|
  ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data);  // NOLINT [runtime/explicit] [5]
 | 
						|
 | 
						|
  ALWAYS_INLINE ClassAccessor(const DexFile& dex_file,
 | 
						|
                              const dex::ClassDef& class_def,
 | 
						|
                              bool parse_hiddenapi_class_data = false);
 | 
						|
 | 
						|
  ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index);
 | 
						|
 | 
						|
  ClassAccessor(const DexFile& dex_file,
 | 
						|
                const uint8_t* class_data,
 | 
						|
                uint32_t class_def_index = dex::kDexNoIndex,
 | 
						|
                bool parse_hiddenapi_class_data = false);
 | 
						|
 | 
						|
  // Return the code item for a method.
 | 
						|
  const dex::CodeItem* GetCodeItem(const Method& method) const;
 | 
						|
 | 
						|
  // Iterator data is not very iterator friendly, use visitors to get around this.
 | 
						|
  template <typename StaticFieldVisitor,
 | 
						|
            typename InstanceFieldVisitor,
 | 
						|
            typename DirectMethodVisitor,
 | 
						|
            typename VirtualMethodVisitor>
 | 
						|
  void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor,
 | 
						|
                             const InstanceFieldVisitor& instance_field_visitor,
 | 
						|
                             const DirectMethodVisitor& direct_method_visitor,
 | 
						|
                             const VirtualMethodVisitor& virtual_method_visitor) const;
 | 
						|
 | 
						|
  template <typename DirectMethodVisitor,
 | 
						|
            typename VirtualMethodVisitor>
 | 
						|
  void VisitMethods(const DirectMethodVisitor& direct_method_visitor,
 | 
						|
                    const VirtualMethodVisitor& virtual_method_visitor) const;
 | 
						|
 | 
						|
  template <typename StaticFieldVisitor,
 | 
						|
            typename InstanceFieldVisitor>
 | 
						|
  void VisitFields(const StaticFieldVisitor& static_field_visitor,
 | 
						|
                   const InstanceFieldVisitor& instance_field_visitor) const;
 | 
						|
 | 
						|
  // Return the iteration range for all the fields.
 | 
						|
  IterationRange<DataIterator<Field>> GetFields() const;
 | 
						|
 | 
						|
  // Return the iteration range for all the static fields.
 | 
						|
  IterationRange<DataIterator<Field>> GetStaticFields() const;
 | 
						|
 | 
						|
  // Return the iteration range for all the instance fields.
 | 
						|
  IterationRange<DataIterator<Field>> GetInstanceFields() const;
 | 
						|
 | 
						|
  // Return the iteration range for all the methods.
 | 
						|
  IterationRange<DataIterator<Method>> GetMethods() const;
 | 
						|
 | 
						|
  // Return the iteration range for the direct methods.
 | 
						|
  IterationRange<DataIterator<Method>> GetDirectMethods() const;
 | 
						|
 | 
						|
  // Return the iteration range for the virtual methods.
 | 
						|
  IterationRange<DataIterator<Method>> GetVirtualMethods() const;
 | 
						|
 | 
						|
  uint32_t NumStaticFields() const {
 | 
						|
    return num_static_fields_;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t NumInstanceFields() const {
 | 
						|
    return num_instance_fields_;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t NumFields() const {
 | 
						|
    return NumStaticFields() + NumInstanceFields();
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t NumDirectMethods() const {
 | 
						|
    return num_direct_methods_;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t NumVirtualMethods() const {
 | 
						|
    return num_virtual_methods_;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t NumMethods() const {
 | 
						|
    return NumDirectMethods() + NumVirtualMethods();
 | 
						|
  }
 | 
						|
 | 
						|
  const char* GetDescriptor() const;
 | 
						|
 | 
						|
  dex::TypeIndex GetClassIdx() const;
 | 
						|
 | 
						|
  const DexFile& GetDexFile() const {
 | 
						|
    return dex_file_;
 | 
						|
  }
 | 
						|
 | 
						|
  bool HasClassData() const {
 | 
						|
    return ptr_pos_ != nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  bool HasHiddenapiClassData() const {
 | 
						|
    return hiddenapi_ptr_pos_ != nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  uint32_t GetClassDefIndex() const {
 | 
						|
    return class_def_index_;
 | 
						|
  }
 | 
						|
 | 
						|
  const dex::ClassDef& GetClassDef() const;
 | 
						|
 | 
						|
 protected:
 | 
						|
  // Template visitor to reduce copy paste for visiting elements.
 | 
						|
  // No thread safety analysis since the visitor may require capabilities.
 | 
						|
  template <typename DataType, typename Visitor>
 | 
						|
  void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
 | 
						|
      NO_THREAD_SAFETY_ANALYSIS;
 | 
						|
 | 
						|
  // Return an iteration range for the first <count> fields.
 | 
						|
  IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
 | 
						|
 | 
						|
  // Return an iteration range for the first <count> methods.
 | 
						|
  IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
 | 
						|
 | 
						|
  const DexFile& dex_file_;
 | 
						|
  const uint32_t class_def_index_;
 | 
						|
  const uint8_t* ptr_pos_ = nullptr;  // Pointer into stream of class_data_item.
 | 
						|
  const uint8_t* hiddenapi_ptr_pos_ = nullptr;  // Pointer into stream of hiddenapi_metadata.
 | 
						|
  const uint32_t num_static_fields_ = 0u;
 | 
						|
  const uint32_t num_instance_fields_ = 0u;
 | 
						|
  const uint32_t num_direct_methods_ = 0u;
 | 
						|
  const uint32_t num_virtual_methods_ = 0u;
 | 
						|
 | 
						|
  friend class dex::DexFileVerifier;
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace art
 | 
						|
 | 
						|
#endif  // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_
 |