| /* |
| * Copyright (C) 2016 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. |
| * |
| * Header file of an in-memory representation of DEX files. |
| */ |
| |
| #ifndef ART_DEXLAYOUT_DEX_IR_H_ |
| #define ART_DEXLAYOUT_DEX_IR_H_ |
| |
| #include <stdint.h> |
| |
| #include <vector> |
| |
| #include "base/iteration_range.h" |
| #include "base/leb128.h" |
| #include "base/safe_map.h" |
| #include "base/stl_util.h" |
| #include "dex/dex_file-inl.h" |
| #include "dex/dex_file_types.h" |
| #include "dex/utf.h" |
| |
| namespace art { |
| namespace dex_ir { |
| |
| // Forward declarations for classes used in containers or pointed to. |
| class AnnotationItem; |
| class AnnotationsDirectoryItem; |
| class AnnotationSetItem; |
| class AnnotationSetRefList; |
| class CallSiteId; |
| class ClassData; |
| class ClassDef; |
| class CodeItem; |
| class DebugInfoItem; |
| class EncodedAnnotation; |
| class EncodedArrayItem; |
| class EncodedValue; |
| class FieldId; |
| class FieldItem; |
| class Header; |
| class HiddenapiClassData; |
| class MapList; |
| class MapItem; |
| class MethodHandleItem; |
| class MethodId; |
| class MethodItem; |
| class ParameterAnnotation; |
| class ProtoId; |
| class StringData; |
| class StringId; |
| class TryItem; |
| class TypeId; |
| class TypeList; |
| |
| // Item size constants. |
| static constexpr size_t kHeaderItemSize = 112; |
| static constexpr size_t kStringIdItemSize = 4; |
| static constexpr size_t kTypeIdItemSize = 4; |
| static constexpr size_t kProtoIdItemSize = 12; |
| static constexpr size_t kFieldIdItemSize = 8; |
| static constexpr size_t kMethodIdItemSize = 8; |
| static constexpr size_t kClassDefItemSize = 32; |
| static constexpr size_t kCallSiteIdItemSize = 4; |
| static constexpr size_t kMethodHandleItemSize = 8; |
| |
| // Visitor support |
| class AbstractDispatcher { |
| public: |
| AbstractDispatcher() = default; |
| virtual ~AbstractDispatcher() { } |
| |
| virtual void Dispatch(Header* header) = 0; |
| virtual void Dispatch(const StringData* string_data) = 0; |
| virtual void Dispatch(const StringId* string_id) = 0; |
| virtual void Dispatch(const TypeId* type_id) = 0; |
| virtual void Dispatch(const ProtoId* proto_id) = 0; |
| virtual void Dispatch(const FieldId* field_id) = 0; |
| virtual void Dispatch(const MethodId* method_id) = 0; |
| virtual void Dispatch(const CallSiteId* call_site_id) = 0; |
| virtual void Dispatch(const MethodHandleItem* method_handle_item) = 0; |
| virtual void Dispatch(ClassData* class_data) = 0; |
| virtual void Dispatch(ClassDef* class_def) = 0; |
| virtual void Dispatch(FieldItem* field_item) = 0; |
| virtual void Dispatch(MethodItem* method_item) = 0; |
| virtual void Dispatch(EncodedArrayItem* array_item) = 0; |
| virtual void Dispatch(CodeItem* code_item) = 0; |
| virtual void Dispatch(TryItem* try_item) = 0; |
| virtual void Dispatch(DebugInfoItem* debug_info_item) = 0; |
| virtual void Dispatch(AnnotationItem* annotation_item) = 0; |
| virtual void Dispatch(AnnotationSetItem* annotation_set_item) = 0; |
| virtual void Dispatch(AnnotationSetRefList* annotation_set_ref_list) = 0; |
| virtual void Dispatch(AnnotationsDirectoryItem* annotations_directory_item) = 0; |
| virtual void Dispatch(HiddenapiClassData* hiddenapi_class_data) = 0; |
| virtual void Dispatch(MapList* map_list) = 0; |
| virtual void Dispatch(MapItem* map_item) = 0; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(AbstractDispatcher); |
| }; |
| |
| template<class T> class Iterator : public std::iterator<std::random_access_iterator_tag, T> { |
| public: |
| using value_type = typename std::iterator<std::random_access_iterator_tag, T>::value_type; |
| using difference_type = |
| typename std::iterator<std::random_access_iterator_tag, value_type>::difference_type; |
| using pointer = typename std::iterator<std::random_access_iterator_tag, value_type>::pointer; |
| using reference = typename std::iterator<std::random_access_iterator_tag, value_type>::reference; |
| |
| Iterator(const Iterator&) = default; |
| Iterator(Iterator&&) noexcept = default; |
| Iterator& operator=(const Iterator&) = default; |
| Iterator& operator=(Iterator&&) noexcept = default; |
| |
| Iterator(const std::vector<T>& vector, |
| uint32_t position, |
| uint32_t iterator_end) |
| : vector_(&vector), |
| position_(position), |
| iterator_end_(iterator_end) { } |
| Iterator() : vector_(nullptr), position_(0U), iterator_end_(0U) { } |
| |
| bool IsValid() const { return position_ < iterator_end_; } |
| |
| bool operator==(const Iterator& rhs) const { return position_ == rhs.position_; } |
| bool operator!=(const Iterator& rhs) const { return !(*this == rhs); } |
| bool operator<(const Iterator& rhs) const { return position_ < rhs.position_; } |
| bool operator>(const Iterator& rhs) const { return rhs < *this; } |
| bool operator<=(const Iterator& rhs) const { return !(rhs < *this); } |
| bool operator>=(const Iterator& rhs) const { return !(*this < rhs); } |
| |
| Iterator& operator++() { // Value after modification. |
| ++position_; |
| return *this; |
| } |
| |
| Iterator operator++(int) { |
| Iterator temp = *this; |
| ++position_; |
| return temp; |
| } |
| |
| Iterator& operator+=(difference_type delta) { |
| position_ += delta; |
| return *this; |
| } |
| |
| Iterator operator+(difference_type delta) const { |
| Iterator temp = *this; |
| temp += delta; |
| return temp; |
| } |
| |
| Iterator& operator--() { // Value after modification. |
| --position_; |
| return *this; |
| } |
| |
| Iterator operator--(int) { |
| Iterator temp = *this; |
| --position_; |
| return temp; |
| } |
| |
| Iterator& operator-=(difference_type delta) { |
| position_ -= delta; |
| return *this; |
| } |
| |
| Iterator operator-(difference_type delta) const { |
| Iterator temp = *this; |
| temp -= delta; |
| return temp; |
| } |
| |
| difference_type operator-(const Iterator& rhs) { |
| return position_ - rhs.position_; |
| } |
| |
| reference operator*() const { |
| return const_cast<reference>((*vector_)[position_]); |
| } |
| |
| pointer operator->() const { |
| return const_cast<pointer>(&((*vector_)[position_])); |
| } |
| |
| reference operator[](difference_type n) const { |
| return (*vector_)[position_ + n]; |
| } |
| |
| private: |
| const std::vector<T>* vector_; |
| uint32_t position_; |
| uint32_t iterator_end_; |
| |
| template <typename U> |
| friend bool operator<(const Iterator<U>& lhs, const Iterator<U>& rhs); |
| }; |
| |
| // Collections become owners of the objects added by moving them into unique pointers. |
| class CollectionBase { |
| public: |
| CollectionBase() = default; |
| virtual ~CollectionBase() { } |
| |
| uint32_t GetOffset() const { return offset_; } |
| void SetOffset(uint32_t new_offset) { offset_ = new_offset; } |
| virtual uint32_t Size() const = 0; |
| bool Empty() const { return Size() == 0u; } |
| |
| private: |
| // Start out unassigned. |
| uint32_t offset_ = 0u; |
| |
| DISALLOW_COPY_AND_ASSIGN(CollectionBase); |
| }; |
| |
| template<class T> class CollectionVector : public CollectionBase { |
| public: |
| using ElementType = std::unique_ptr<T>; |
| |
| CollectionVector() { } |
| explicit CollectionVector(size_t size) { |
| // Preallocate so that assignment does not invalidate pointers into the vector. |
| collection_.reserve(size); |
| } |
| ~CollectionVector() override { } |
| |
| template<class... Args> |
| T* CreateAndAddItem(Args&&... args) { |
| T* object = new T(std::forward<Args>(args)...); |
| collection_.push_back(std::unique_ptr<T>(object)); |
| return object; |
| } |
| |
| uint32_t Size() const override { return collection_.size(); } |
| |
| Iterator<ElementType> begin() const { return Iterator<ElementType>(collection_, 0U, Size()); } |
| Iterator<ElementType> end() const { return Iterator<ElementType>(collection_, Size(), Size()); } |
| |
| const ElementType& operator[](size_t index) const { |
| DCHECK_LT(index, Size()); |
| return collection_[index]; |
| } |
| ElementType& operator[](size_t index) { |
| DCHECK_LT(index, Size()); |
| return collection_[index]; |
| } |
| |
| // Sort the vector by copying pointers over. |
| template <typename MapType> |
| void SortByMapOrder(const MapType& map) { |
| auto it = map.begin(); |
| CHECK_EQ(map.size(), Size()); |
| for (size_t i = 0; i < Size(); ++i) { |
| // There are times when the array will temporarily contain the same pointer twice, doing the |
| // release here sure there is no double free errors. |
| collection_[i].release(); |
| collection_[i].reset(it->second); |
| ++it; |
| } |
| } |
| |
| protected: |
| std::vector<ElementType> collection_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(CollectionVector); |
| }; |
| |
| template<class T> class IndexedCollectionVector : public CollectionVector<T> { |
| public: |
| using Vector = std::vector<std::unique_ptr<T>>; |
| IndexedCollectionVector() = default; |
| explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { } |
| |
| template <class... Args> |
| T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) { |
| T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...); |
| object->SetIndex(index); |
| return object; |
| } |
| |
| T* operator[](size_t index) const { |
| DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr)); |
| return CollectionVector<T>::collection_[index].get(); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(IndexedCollectionVector); |
| }; |
| |
| class Item { |
| public: |
| Item() { } |
| virtual ~Item() { } |
| |
| Item(Item&&) = default; |
| |
| // Return the assigned offset. |
| uint32_t GetOffset() const WARN_UNUSED { |
| CHECK(OffsetAssigned()); |
| return offset_; |
| } |
| uint32_t GetSize() const WARN_UNUSED { return size_; } |
| void SetOffset(uint32_t offset) { offset_ = offset; } |
| void SetSize(uint32_t size) { size_ = size; } |
| bool OffsetAssigned() const { |
| return offset_ != kOffsetUnassigned; |
| } |
| |
| protected: |
| Item(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { } |
| |
| // 0 is the dex file header and shouldn't be a valid offset for any part of the dex file. |
| static constexpr uint32_t kOffsetUnassigned = 0u; |
| |
| // Start out unassigned. |
| uint32_t offset_ = kOffsetUnassigned; |
| uint32_t size_ = 0; |
| }; |
| |
| class IndexedItem : public Item { |
| public: |
| IndexedItem() { } |
| virtual ~IndexedItem() { } |
| |
| uint32_t GetIndex() const { return index_; } |
| void SetIndex(uint32_t index) { index_ = index; } |
| |
| protected: |
| IndexedItem(uint32_t offset, uint32_t size, uint32_t index) |
| : Item(offset, size), index_(index) { } |
| |
| uint32_t index_ = 0; |
| }; |
| |
| class Header : public Item { |
| public: |
| Header(const uint8_t* magic, |
| uint32_t checksum, |
| const uint8_t* signature, |
| uint32_t endian_tag, |
| uint32_t file_size, |
| uint32_t header_size, |
| uint32_t link_size, |
| uint32_t link_offset, |
| uint32_t data_size, |
| uint32_t data_offset, |
| bool support_default_methods) |
| : Item(0, kHeaderItemSize), support_default_methods_(support_default_methods) { |
| ConstructorHelper(magic, |
| checksum, |
| signature, |
| endian_tag, |
| file_size, |
| header_size, |
| link_size, |
| link_offset, |
| data_size, |
| data_offset); |
| } |
| |
| Header(const uint8_t* magic, |
| uint32_t checksum, |
| const uint8_t* signature, |
| uint32_t endian_tag, |
| uint32_t file_size, |
| uint32_t header_size, |
| uint32_t link_size, |
| uint32_t link_offset, |
| uint32_t data_size, |
| uint32_t data_offset, |
| bool support_default_methods, |
| uint32_t num_string_ids, |
| uint32_t num_type_ids, |
| uint32_t num_proto_ids, |
| uint32_t num_field_ids, |
| uint32_t num_method_ids, |
| uint32_t num_class_defs) |
| : Item(0, kHeaderItemSize), |
| support_default_methods_(support_default_methods), |
| string_ids_(num_string_ids), |
| type_ids_(num_type_ids), |
| proto_ids_(num_proto_ids), |
| field_ids_(num_field_ids), |
| method_ids_(num_method_ids), |
| class_defs_(num_class_defs) { |
| ConstructorHelper(magic, |
| checksum, |
| signature, |
| endian_tag, |
| file_size, |
| header_size, |
| link_size, |
| link_offset, |
| data_size, |
| data_offset); |
| } |
| ~Header() override { } |
| |
| static size_t ItemSize() { return kHeaderItemSize; } |
| |
| const uint8_t* Magic() const { return magic_; } |
| uint32_t Checksum() const { return checksum_; } |
| const uint8_t* Signature() const { return signature_; } |
| uint32_t EndianTag() const { return endian_tag_; } |
| uint32_t FileSize() const { return file_size_; } |
| uint32_t HeaderSize() const { return header_size_; } |
| uint32_t LinkSize() const { return link_size_; } |
| uint32_t LinkOffset() const { return link_offset_; } |
| uint32_t DataSize() const { return data_size_; } |
| uint32_t DataOffset() const { return data_offset_; } |
| |
| void SetChecksum(uint32_t new_checksum) { checksum_ = new_checksum; } |
| void SetSignature(const uint8_t* new_signature) { |
| memcpy(signature_, new_signature, sizeof(signature_)); |
| } |
| void SetFileSize(uint32_t new_file_size) { file_size_ = new_file_size; } |
| void SetHeaderSize(uint32_t new_header_size) { header_size_ = new_header_size; } |
| void SetLinkSize(uint32_t new_link_size) { link_size_ = new_link_size; } |
| void SetLinkOffset(uint32_t new_link_offset) { link_offset_ = new_link_offset; } |
| void SetDataSize(uint32_t new_data_size) { data_size_ = new_data_size; } |
| void SetDataOffset(uint32_t new_data_offset) { data_offset_ = new_data_offset; } |
| |
| IndexedCollectionVector<StringId>& StringIds() { return string_ids_; } |
| const IndexedCollectionVector<StringId>& StringIds() const { return string_ids_; } |
| IndexedCollectionVector<TypeId>& TypeIds() { return type_ids_; } |
| const IndexedCollectionVector<TypeId>& TypeIds() const { return type_ids_; } |
| IndexedCollectionVector<ProtoId>& ProtoIds() { return proto_ids_; } |
| const IndexedCollectionVector<ProtoId>& ProtoIds() const { return proto_ids_; } |
| IndexedCollectionVector<FieldId>& FieldIds() { return field_ids_; } |
| const IndexedCollectionVector<FieldId>& FieldIds() const { return field_ids_; } |
| IndexedCollectionVector<MethodId>& MethodIds() { return method_ids_; } |
| const IndexedCollectionVector<MethodId>& MethodIds() const { return method_ids_; } |
| IndexedCollectionVector<ClassDef>& ClassDefs() { return class_defs_; } |
| const IndexedCollectionVector<ClassDef>& ClassDefs() const { return class_defs_; } |
| IndexedCollectionVector<CallSiteId>& CallSiteIds() { return call_site_ids_; } |
| const IndexedCollectionVector<CallSiteId>& CallSiteIds() const { return call_site_ids_; } |
| IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() { return method_handle_items_; } |
| const IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() const { |
| return method_handle_items_; |
| } |
| CollectionVector<StringData>& StringDatas() { return string_datas_; } |
| const CollectionVector<StringData>& StringDatas() const { return string_datas_; } |
| CollectionVector<TypeList>& TypeLists() { return type_lists_; } |
| const CollectionVector<TypeList>& TypeLists() const { return type_lists_; } |
| CollectionVector<EncodedArrayItem>& EncodedArrayItems() { return encoded_array_items_; } |
| const CollectionVector<EncodedArrayItem>& EncodedArrayItems() const { |
| return encoded_array_items_; |
| } |
| CollectionVector<AnnotationItem>& AnnotationItems() { return annotation_items_; } |
| const CollectionVector<AnnotationItem>& AnnotationItems() const { return annotation_items_; } |
| CollectionVector<AnnotationSetItem>& AnnotationSetItems() { return annotation_set_items_; } |
| const CollectionVector<AnnotationSetItem>& AnnotationSetItems() const { |
| return annotation_set_items_; |
| } |
| CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() { |
| return annotation_set_ref_lists_; |
| } |
| const CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() const { |
| return annotation_set_ref_lists_; |
| } |
| CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() { |
| return annotations_directory_items_; |
| } |
| const CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() const { |
| return annotations_directory_items_; |
| } |
| IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() { |
| return hiddenapi_class_datas_; |
| } |
| const IndexedCollectionVector<HiddenapiClassData>& HiddenapiClassDatas() const { |
| return hiddenapi_class_datas_; |
| } |
| CollectionVector<DebugInfoItem>& DebugInfoItems() { return debug_info_items_; } |
| const CollectionVector<DebugInfoItem>& DebugInfoItems() const { return debug_info_items_; } |
| CollectionVector<CodeItem>& CodeItems() { return code_items_; } |
| const CollectionVector<CodeItem>& CodeItems() const { return code_items_; } |
| CollectionVector<ClassData>& ClassDatas() { return class_datas_; } |
| const CollectionVector<ClassData>& ClassDatas() const { return class_datas_; } |
| |
| StringId* GetStringIdOrNullPtr(uint32_t index) { |
| return index == dex::kDexNoIndex ? nullptr : StringIds()[index]; |
| } |
| TypeId* GetTypeIdOrNullPtr(uint16_t index) { |
| return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index]; |
| } |
| |
| uint32_t MapListOffset() const { return map_list_offset_; } |
| void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = new_offset; } |
| |
| const std::vector<uint8_t>& LinkData() const { return link_data_; } |
| void SetLinkData(std::vector<uint8_t>&& link_data) { link_data_ = std::move(link_data); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| bool SupportDefaultMethods() const { |
| return support_default_methods_; |
| } |
| |
| private: |
| uint8_t magic_[8]; |
| uint32_t checksum_; |
| uint8_t signature_[DexFile::kSha1DigestSize]; |
| uint32_t endian_tag_; |
| uint32_t file_size_; |
| uint32_t header_size_; |
| uint32_t link_size_; |
| uint32_t link_offset_; |
| uint32_t data_size_; |
| uint32_t data_offset_; |
| const bool support_default_methods_; |
| |
| void ConstructorHelper(const uint8_t* magic, |
| uint32_t checksum, |
| const uint8_t* signature, |
| uint32_t endian_tag, |
| uint32_t file_size, |
| uint32_t header_size, |
| uint32_t link_size, |
| uint32_t link_offset, |
| uint32_t data_size, |
| uint32_t data_offset) { |
| checksum_ = checksum; |
| endian_tag_ = endian_tag; |
| file_size_ = file_size; |
| header_size_ = header_size; |
| link_size_ = link_size; |
| link_offset_ = link_offset; |
| data_size_ = data_size; |
| data_offset_ = data_offset; |
| memcpy(magic_, magic, sizeof(magic_)); |
| memcpy(signature_, signature, sizeof(signature_)); |
| } |
| |
| // Collection vectors own the IR data. |
| IndexedCollectionVector<StringId> string_ids_; |
| IndexedCollectionVector<TypeId> type_ids_; |
| IndexedCollectionVector<ProtoId> proto_ids_; |
| IndexedCollectionVector<FieldId> field_ids_; |
| IndexedCollectionVector<MethodId> method_ids_; |
| IndexedCollectionVector<ClassDef> class_defs_; |
| IndexedCollectionVector<CallSiteId> call_site_ids_; |
| IndexedCollectionVector<MethodHandleItem> method_handle_items_; |
| IndexedCollectionVector<StringData> string_datas_; |
| IndexedCollectionVector<TypeList> type_lists_; |
| IndexedCollectionVector<EncodedArrayItem> encoded_array_items_; |
| IndexedCollectionVector<AnnotationItem> annotation_items_; |
| IndexedCollectionVector<AnnotationSetItem> annotation_set_items_; |
| IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_; |
| IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_; |
| IndexedCollectionVector<HiddenapiClassData> hiddenapi_class_datas_; |
| // The order of the vectors controls the layout of the output file by index order, to change the |
| // layout just sort the vector. Note that you may only change the order of the non indexed vectors |
| // below. Indexed vectors are accessed by indices in other places, changing the sorting order will |
| // invalidate the existing indices and is not currently supported. |
| CollectionVector<DebugInfoItem> debug_info_items_; |
| CollectionVector<CodeItem> code_items_; |
| CollectionVector<ClassData> class_datas_; |
| |
| uint32_t map_list_offset_ = 0; |
| |
| // Link data. |
| std::vector<uint8_t> link_data_; |
| |
| DISALLOW_COPY_AND_ASSIGN(Header); |
| }; |
| |
| class StringData : public Item { |
| public: |
| explicit StringData(const char* data) : data_(strdup(data)) { |
| size_ = UnsignedLeb128Size(CountModifiedUtf8Chars(data)) + strlen(data); |
| } |
| |
| const char* Data() const { return data_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| UniqueCPtr<const char> data_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StringData); |
| }; |
| |
| class StringId : public IndexedItem { |
| public: |
| explicit StringId(StringData* string_data) : string_data_(string_data) { |
| size_ = kStringIdItemSize; |
| } |
| ~StringId() override { } |
| |
| static size_t ItemSize() { return kStringIdItemSize; } |
| |
| const char* Data() const { return string_data_->Data(); } |
| StringData* DataItem() const { return string_data_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| StringData* string_data_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StringId); |
| }; |
| |
| class TypeId : public IndexedItem { |
| public: |
| explicit TypeId(StringId* string_id) : string_id_(string_id) { size_ = kTypeIdItemSize; } |
| ~TypeId() override { } |
| |
| static size_t ItemSize() { return kTypeIdItemSize; } |
| |
| StringId* GetStringId() const { return string_id_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| StringId* string_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TypeId); |
| }; |
| |
| using TypeIdVector = std::vector<const TypeId*>; |
| |
| class TypeList : public Item { |
| public: |
| explicit TypeList(TypeIdVector* type_list) : type_list_(type_list) { |
| size_ = sizeof(uint32_t) + (type_list->size() * sizeof(uint16_t)); |
| } |
| ~TypeList() override { } |
| |
| const TypeIdVector* GetTypeList() const { return type_list_.get(); } |
| |
| private: |
| std::unique_ptr<TypeIdVector> type_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TypeList); |
| }; |
| |
| class ProtoId : public IndexedItem { |
| public: |
| ProtoId(const StringId* shorty, const TypeId* return_type, TypeList* parameters) |
| : shorty_(shorty), return_type_(return_type), parameters_(parameters) |
| { size_ = kProtoIdItemSize; } |
| ~ProtoId() override { } |
| |
| static size_t ItemSize() { return kProtoIdItemSize; } |
| |
| const StringId* Shorty() const { return shorty_; } |
| const TypeId* ReturnType() const { return return_type_; } |
| const TypeList* Parameters() const { return parameters_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| const StringId* shorty_; |
| const TypeId* return_type_; |
| TypeList* parameters_; // This can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(ProtoId); |
| }; |
| |
| class FieldId : public IndexedItem { |
| public: |
| FieldId(const TypeId* klass, const TypeId* type, const StringId* name) |
| : class_(klass), type_(type), name_(name) { size_ = kFieldIdItemSize; } |
| ~FieldId() override { } |
| |
| static size_t ItemSize() { return kFieldIdItemSize; } |
| |
| const TypeId* Class() const { return class_; } |
| const TypeId* Type() const { return type_; } |
| const StringId* Name() const { return name_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| const TypeId* class_; |
| const TypeId* type_; |
| const StringId* name_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FieldId); |
| }; |
| |
| class MethodId : public IndexedItem { |
| public: |
| MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name) |
| : class_(klass), proto_(proto), name_(name) { size_ = kMethodIdItemSize; } |
| ~MethodId() override { } |
| |
| static size_t ItemSize() { return kMethodIdItemSize; } |
| |
| const TypeId* Class() const { return class_; } |
| const ProtoId* Proto() const { return proto_; } |
| const StringId* Name() const { return name_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| const TypeId* class_; |
| const ProtoId* proto_; |
| const StringId* name_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MethodId); |
| }; |
| |
| class FieldItem : public Item { |
| public: |
| FieldItem(uint32_t access_flags, const FieldId* field_id) |
| : access_flags_(access_flags), field_id_(field_id) { } |
| ~FieldItem() override { } |
| |
| FieldItem(FieldItem&&) = default; |
| |
| uint32_t GetAccessFlags() const { return access_flags_; } |
| const FieldId* GetFieldId() const { return field_id_; } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| uint32_t access_flags_; |
| const FieldId* field_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FieldItem); |
| }; |
| |
| using FieldItemVector = std::vector<FieldItem>; |
| |
| class MethodItem : public Item { |
| public: |
| MethodItem(uint32_t access_flags, const MethodId* method_id, CodeItem* code) |
| : access_flags_(access_flags), method_id_(method_id), code_(code) { } |
| ~MethodItem() override { } |
| |
| MethodItem(MethodItem&&) = default; |
| |
| uint32_t GetAccessFlags() const { return access_flags_; } |
| const MethodId* GetMethodId() const { return method_id_; } |
| CodeItem* GetCodeItem() { return code_; } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| uint32_t access_flags_; |
| const MethodId* method_id_; |
| CodeItem* code_; // This can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(MethodItem); |
| }; |
| |
| using MethodItemVector = std::vector<MethodItem>; |
| |
| class EncodedValue { |
| public: |
| explicit EncodedValue(uint8_t type) : type_(type) { } |
| |
| int8_t Type() const { return type_; } |
| |
| void SetBoolean(bool z) { u_.bool_val_ = z; } |
| void SetByte(int8_t b) { u_.byte_val_ = b; } |
| void SetShort(int16_t s) { u_.short_val_ = s; } |
| void SetChar(uint16_t c) { u_.char_val_ = c; } |
| void SetInt(int32_t i) { u_.int_val_ = i; } |
| void SetLong(int64_t l) { u_.long_val_ = l; } |
| void SetFloat(float f) { u_.float_val_ = f; } |
| void SetDouble(double d) { u_.double_val_ = d; } |
| void SetStringId(StringId* string_id) { u_.string_val_ = string_id; } |
| void SetTypeId(TypeId* type_id) { u_.type_val_ = type_id; } |
| void SetProtoId(ProtoId* proto_id) { u_.proto_val_ = proto_id; } |
| void SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; } |
| void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; } |
| void SetMethodHandle(MethodHandleItem* method_handle) { u_.method_handle_val_ = method_handle; } |
| void SetEncodedArray(EncodedArrayItem* encoded_array) { encoded_array_.reset(encoded_array); } |
| void SetEncodedAnnotation(EncodedAnnotation* encoded_annotation) |
| { encoded_annotation_.reset(encoded_annotation); } |
| |
| bool GetBoolean() const { return u_.bool_val_; } |
| int8_t GetByte() const { return u_.byte_val_; } |
| int16_t GetShort() const { return u_.short_val_; } |
| uint16_t GetChar() const { return u_.char_val_; } |
| int32_t GetInt() const { return u_.int_val_; } |
| int64_t GetLong() const { return u_.long_val_; } |
| float GetFloat() const { return u_.float_val_; } |
| double GetDouble() const { return u_.double_val_; } |
| StringId* GetStringId() const { return u_.string_val_; } |
| TypeId* GetTypeId() const { return u_.type_val_; } |
| ProtoId* GetProtoId() const { return u_.proto_val_; } |
| FieldId* GetFieldId() const { return u_.field_val_; } |
| MethodId* GetMethodId() const { return u_.method_val_; } |
| MethodHandleItem* GetMethodHandle() const { return u_.method_handle_val_; } |
| EncodedArrayItem* GetEncodedArray() const { return encoded_array_.get(); } |
| EncodedAnnotation* GetEncodedAnnotation() const { return encoded_annotation_.get(); } |
| |
| EncodedAnnotation* ReleaseEncodedAnnotation() { return encoded_annotation_.release(); } |
| |
| private: |
| uint8_t type_; |
| union { |
| bool bool_val_; |
| int8_t byte_val_; |
| int16_t short_val_; |
| uint16_t char_val_; |
| int32_t int_val_; |
| int64_t long_val_; |
| float float_val_; |
| double double_val_; |
| StringId* string_val_; |
| TypeId* type_val_; |
| ProtoId* proto_val_; |
| FieldId* field_val_; |
| MethodId* method_val_; |
| MethodHandleItem* method_handle_val_; |
| } u_; |
| std::unique_ptr<EncodedArrayItem> encoded_array_; |
| std::unique_ptr<EncodedAnnotation> encoded_annotation_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EncodedValue); |
| }; |
| |
| using EncodedValueVector = std::vector<std::unique_ptr<EncodedValue>>; |
| |
| class AnnotationElement { |
| public: |
| AnnotationElement(StringId* name, EncodedValue* value) : name_(name), value_(value) { } |
| |
| StringId* GetName() const { return name_; } |
| EncodedValue* GetValue() const { return value_.get(); } |
| |
| private: |
| StringId* name_; |
| std::unique_ptr<EncodedValue> value_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AnnotationElement); |
| }; |
| |
| using AnnotationElementVector = std::vector<std::unique_ptr<AnnotationElement>>; |
| |
| class EncodedAnnotation { |
| public: |
| EncodedAnnotation(TypeId* type, AnnotationElementVector* elements) |
| : type_(type), elements_(elements) { } |
| |
| TypeId* GetType() const { return type_; } |
| AnnotationElementVector* GetAnnotationElements() const { return elements_.get(); } |
| |
| private: |
| TypeId* type_; |
| std::unique_ptr<AnnotationElementVector> elements_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EncodedAnnotation); |
| }; |
| |
| class EncodedArrayItem : public Item { |
| public: |
| explicit EncodedArrayItem(EncodedValueVector* encoded_values) |
| : encoded_values_(encoded_values) { } |
| |
| EncodedValueVector* GetEncodedValues() const { return encoded_values_.get(); } |
| |
| private: |
| std::unique_ptr<EncodedValueVector> encoded_values_; |
| |
| DISALLOW_COPY_AND_ASSIGN(EncodedArrayItem); |
| }; |
| |
| class ClassData : public Item { |
| public: |
| ClassData(FieldItemVector* static_fields, |
| FieldItemVector* instance_fields, |
| MethodItemVector* direct_methods, |
| MethodItemVector* virtual_methods) |
| : static_fields_(static_fields), |
| instance_fields_(instance_fields), |
| direct_methods_(direct_methods), |
| virtual_methods_(virtual_methods) { } |
| |
| ~ClassData() override = default; |
| FieldItemVector* StaticFields() { return static_fields_.get(); } |
| FieldItemVector* InstanceFields() { return instance_fields_.get(); } |
| MethodItemVector* DirectMethods() { return direct_methods_.get(); } |
| MethodItemVector* VirtualMethods() { return virtual_methods_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| std::unique_ptr<FieldItemVector> static_fields_; |
| std::unique_ptr<FieldItemVector> instance_fields_; |
| std::unique_ptr<MethodItemVector> direct_methods_; |
| std::unique_ptr<MethodItemVector> virtual_methods_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ClassData); |
| }; |
| |
| class ClassDef : public IndexedItem { |
| public: |
| ClassDef(const TypeId* class_type, |
| uint32_t access_flags, |
| const TypeId* superclass, |
| TypeList* interfaces, |
| const StringId* source_file, |
| AnnotationsDirectoryItem* annotations, |
| EncodedArrayItem* static_values, |
| ClassData* class_data) |
| : class_type_(class_type), |
| access_flags_(access_flags), |
| superclass_(superclass), |
| interfaces_(interfaces), |
| source_file_(source_file), |
| annotations_(annotations), |
| class_data_(class_data), |
| static_values_(static_values) { size_ = kClassDefItemSize; } |
| |
| ~ClassDef() override { } |
| |
| static size_t ItemSize() { return kClassDefItemSize; } |
| |
| const TypeId* ClassType() const { return class_type_; } |
| uint32_t GetAccessFlags() const { return access_flags_; } |
| const TypeId* Superclass() const { return superclass_; } |
| const TypeList* Interfaces() { return interfaces_; } |
| uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); } |
| const StringId* SourceFile() const { return source_file_; } |
| AnnotationsDirectoryItem* Annotations() const { return annotations_; } |
| ClassData* GetClassData() { return class_data_; } |
| EncodedArrayItem* StaticValues() { return static_values_; } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| const TypeId* class_type_; |
| uint32_t access_flags_; |
| const TypeId* superclass_; // This can be nullptr. |
| TypeList* interfaces_; // This can be nullptr. |
| const StringId* source_file_; // This can be nullptr. |
| AnnotationsDirectoryItem* annotations_; // This can be nullptr. |
| ClassData* class_data_; // This can be nullptr. |
| EncodedArrayItem* static_values_; // This can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(ClassDef); |
| }; |
| |
| class TypeAddrPair { |
| public: |
| TypeAddrPair(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { } |
| |
| const TypeId* GetTypeId() const { return type_id_; } |
| uint32_t GetAddress() const { return address_; } |
| |
| private: |
| const TypeId* type_id_; // This can be nullptr. |
| uint32_t address_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TypeAddrPair); |
| }; |
| |
| using TypeAddrPairVector = std::vector<std::unique_ptr<const TypeAddrPair>>; |
| |
| class CatchHandler { |
| public: |
| explicit CatchHandler(bool catch_all, uint16_t list_offset, TypeAddrPairVector* handlers) |
| : catch_all_(catch_all), list_offset_(list_offset), handlers_(handlers) { } |
| |
| bool HasCatchAll() const { return catch_all_; } |
| uint16_t GetListOffset() const { return list_offset_; } |
| TypeAddrPairVector* GetHandlers() const { return handlers_.get(); } |
| |
| private: |
| bool catch_all_; |
| uint16_t list_offset_; |
| std::unique_ptr<TypeAddrPairVector> handlers_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CatchHandler); |
| }; |
| |
| using CatchHandlerVector = std::vector<std::unique_ptr<const CatchHandler>>; |
| |
| class TryItem : public Item { |
| public: |
| TryItem(uint32_t start_addr, uint16_t insn_count, const CatchHandler* handlers) |
| : start_addr_(start_addr), insn_count_(insn_count), handlers_(handlers) { } |
| ~TryItem() override { } |
| |
| uint32_t StartAddr() const { return start_addr_; } |
| uint16_t InsnCount() const { return insn_count_; } |
| const CatchHandler* GetHandlers() const { return handlers_; } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| uint32_t start_addr_; |
| uint16_t insn_count_; |
| const CatchHandler* handlers_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TryItem); |
| }; |
| |
| using TryItemVector = std::vector<std::unique_ptr<const TryItem>>; |
| |
| class CodeFixups { |
| public: |
| CodeFixups(std::vector<TypeId*> type_ids, |
| std::vector<StringId*> string_ids, |
| std::vector<MethodId*> method_ids, |
| std::vector<FieldId*> field_ids) |
| : type_ids_(std::move(type_ids)), |
| string_ids_(std::move(string_ids)), |
| method_ids_(std::move(method_ids)), |
| field_ids_(std::move(field_ids)) { } |
| |
| const std::vector<TypeId*>& TypeIds() const { return type_ids_; } |
| const std::vector<StringId*>& StringIds() const { return string_ids_; } |
| const std::vector<MethodId*>& MethodIds() const { return method_ids_; } |
| const std::vector<FieldId*>& FieldIds() const { return field_ids_; } |
| |
| private: |
| std::vector<TypeId*> type_ids_; |
| std::vector<StringId*> string_ids_; |
| std::vector<MethodId*> method_ids_; |
| std::vector<FieldId*> field_ids_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CodeFixups); |
| }; |
| |
| class CodeItem : public Item { |
| public: |
| CodeItem(uint16_t registers_size, |
| uint16_t ins_size, |
| uint16_t outs_size, |
| DebugInfoItem* debug_info, |
| uint32_t insns_size, |
| uint16_t* insns, |
| TryItemVector* tries, |
| CatchHandlerVector* handlers) |
| : registers_size_(registers_size), |
| ins_size_(ins_size), |
| outs_size_(outs_size), |
| debug_info_(debug_info), |
| insns_size_(insns_size), |
| insns_(insns), |
| tries_(tries), |
| handlers_(handlers) { } |
| |
| ~CodeItem() override { } |
| |
| uint16_t RegistersSize() const { return registers_size_; } |
| uint16_t InsSize() const { return ins_size_; } |
| uint16_t OutsSize() const { return outs_size_; } |
| uint16_t TriesSize() const { return tries_ == nullptr ? 0 : tries_->size(); } |
| DebugInfoItem* DebugInfo() const { return debug_info_; } |
| uint32_t InsnsSize() const { return insns_size_; } |
| uint16_t* Insns() const { return insns_.get(); } |
| TryItemVector* Tries() const { return tries_.get(); } |
| CatchHandlerVector* Handlers() const { return handlers_.get(); } |
| |
| void SetCodeFixups(CodeFixups* fixups) { fixups_.reset(fixups); } |
| CodeFixups* GetCodeFixups() const { return fixups_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| IterationRange<DexInstructionIterator> Instructions() const { |
| return MakeIterationRange(DexInstructionIterator(Insns(), 0u), |
| DexInstructionIterator(Insns(), InsnsSize())); |
| } |
| |
| private: |
| uint16_t registers_size_; |
| uint16_t ins_size_; |
| uint16_t outs_size_; |
| DebugInfoItem* debug_info_; // This can be nullptr. |
| uint32_t insns_size_; |
| std::unique_ptr<uint16_t[]> insns_; |
| std::unique_ptr<TryItemVector> tries_; // This can be nullptr. |
| std::unique_ptr<CatchHandlerVector> handlers_; // This can be nullptr. |
| std::unique_ptr<CodeFixups> fixups_; // This can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(CodeItem); |
| }; |
| |
| class DebugInfoItem : public Item { |
| public: |
| DebugInfoItem(uint32_t debug_info_size, uint8_t* debug_info) |
| : debug_info_size_(debug_info_size), debug_info_(debug_info) { } |
| |
| uint32_t GetDebugInfoSize() const { return debug_info_size_; } |
| uint8_t* GetDebugInfo() const { return debug_info_.get(); } |
| |
| private: |
| uint32_t debug_info_size_; |
| std::unique_ptr<uint8_t[]> debug_info_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DebugInfoItem); |
| }; |
| |
| class AnnotationItem : public Item { |
| public: |
| AnnotationItem(uint8_t visibility, EncodedAnnotation* annotation) |
| : visibility_(visibility), annotation_(annotation) { } |
| |
| uint8_t GetVisibility() const { return visibility_; } |
| EncodedAnnotation* GetAnnotation() const { return annotation_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| uint8_t visibility_; |
| std::unique_ptr<EncodedAnnotation> annotation_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AnnotationItem); |
| }; |
| |
| class AnnotationSetItem : public Item { |
| public: |
| explicit AnnotationSetItem(std::vector<AnnotationItem*>* items) : items_(items) { |
| size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t); |
| } |
| ~AnnotationSetItem() override { } |
| |
| std::vector<AnnotationItem*>* GetItems() { return items_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| std::unique_ptr<std::vector<AnnotationItem*>> items_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AnnotationSetItem); |
| }; |
| |
| class AnnotationSetRefList : public Item { |
| public: |
| explicit AnnotationSetRefList(std::vector<AnnotationSetItem*>* items) : items_(items) { |
| size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t); |
| } |
| ~AnnotationSetRefList() override { } |
| |
| std::vector<AnnotationSetItem*>* GetItems() { return items_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| std::unique_ptr<std::vector<AnnotationSetItem*>> items_; // Elements of vector can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList); |
| }; |
| |
| class FieldAnnotation { |
| public: |
| FieldAnnotation(FieldId* field_id, AnnotationSetItem* annotation_set_item) |
| : field_id_(field_id), annotation_set_item_(annotation_set_item) { } |
| |
| FieldId* GetFieldId() const { return field_id_; } |
| AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; } |
| |
| private: |
| FieldId* field_id_; |
| AnnotationSetItem* annotation_set_item_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FieldAnnotation); |
| }; |
| |
| using FieldAnnotationVector = std::vector<std::unique_ptr<FieldAnnotation>>; |
| |
| class MethodAnnotation { |
| public: |
| MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item) |
| : method_id_(method_id), annotation_set_item_(annotation_set_item) { } |
| |
| MethodId* GetMethodId() const { return method_id_; } |
| AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; } |
| |
| private: |
| MethodId* method_id_; |
| AnnotationSetItem* annotation_set_item_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MethodAnnotation); |
| }; |
| |
| using MethodAnnotationVector = std::vector<std::unique_ptr<MethodAnnotation>>; |
| |
| class ParameterAnnotation { |
| public: |
| ParameterAnnotation(MethodId* method_id, AnnotationSetRefList* annotations) |
| : method_id_(method_id), annotations_(annotations) { } |
| |
| MethodId* GetMethodId() const { return method_id_; } |
| AnnotationSetRefList* GetAnnotations() { return annotations_; } |
| |
| private: |
| MethodId* method_id_; |
| AnnotationSetRefList* annotations_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation); |
| }; |
| |
| using ParameterAnnotationVector = std::vector<std::unique_ptr<ParameterAnnotation>>; |
| |
| class AnnotationsDirectoryItem : public Item { |
| public: |
| AnnotationsDirectoryItem(AnnotationSetItem* class_annotation, |
| FieldAnnotationVector* field_annotations, |
| MethodAnnotationVector* method_annotations, |
| ParameterAnnotationVector* parameter_annotations) |
| : class_annotation_(class_annotation), |
| field_annotations_(field_annotations), |
| method_annotations_(method_annotations), |
| parameter_annotations_(parameter_annotations) { } |
| |
| AnnotationSetItem* GetClassAnnotation() const { return class_annotation_; } |
| FieldAnnotationVector* GetFieldAnnotations() { return field_annotations_.get(); } |
| MethodAnnotationVector* GetMethodAnnotations() { return method_annotations_.get(); } |
| ParameterAnnotationVector* GetParameterAnnotations() { return parameter_annotations_.get(); } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| AnnotationSetItem* class_annotation_; // This can be nullptr. |
| std::unique_ptr<FieldAnnotationVector> field_annotations_; // This can be nullptr. |
| std::unique_ptr<MethodAnnotationVector> method_annotations_; // This can be nullptr. |
| std::unique_ptr<ParameterAnnotationVector> parameter_annotations_; // This can be nullptr. |
| |
| DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem); |
| }; |
| |
| class CallSiteId : public IndexedItem { |
| public: |
| explicit CallSiteId(EncodedArrayItem* call_site_item) : call_site_item_(call_site_item) { |
| size_ = kCallSiteIdItemSize; |
| } |
| ~CallSiteId() override { } |
| |
| static size_t ItemSize() { return kCallSiteIdItemSize; } |
| |
| EncodedArrayItem* CallSiteItem() const { return call_site_item_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| EncodedArrayItem* call_site_item_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CallSiteId); |
| }; |
| |
| class MethodHandleItem : public IndexedItem { |
| public: |
| MethodHandleItem(DexFile::MethodHandleType method_handle_type, IndexedItem* field_or_method_id) |
| : method_handle_type_(method_handle_type), |
| field_or_method_id_(field_or_method_id) { |
| size_ = kMethodHandleItemSize; |
| } |
| ~MethodHandleItem() override { } |
| |
| static size_t ItemSize() { return kMethodHandleItemSize; } |
| |
| DexFile::MethodHandleType GetMethodHandleType() const { return method_handle_type_; } |
| IndexedItem* GetFieldOrMethodId() const { return field_or_method_id_; } |
| |
| void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } |
| |
| private: |
| DexFile::MethodHandleType method_handle_type_; |
| IndexedItem* field_or_method_id_; |
| |
| DISALLOW_COPY_AND_ASSIGN(MethodHandleItem); |
| }; |
| |
| using HiddenapiFlagsMap = SafeMap<const Item*, uint32_t>; |
| |
| class HiddenapiClassData : public IndexedItem { |
| public: |
| HiddenapiClassData(const ClassDef* class_def, std::unique_ptr<HiddenapiFlagsMap> flags) |
| : class_def_(class_def), flags_(std::move(flags)) { } |
| ~HiddenapiClassData() override { } |
| |
| const ClassDef* GetClassDef() const { return class_def_; } |
| |
| uint32_t GetFlags(const Item* field_or_method_item) const { |
| return (flags_ == nullptr) ? 0u : flags_->Get(field_or_method_item); |
| } |
| |
| static uint32_t GetFlags(Header* header, ClassDef* class_def, const Item* field_or_method_item) { |
| DCHECK(header != nullptr); |
| DCHECK(class_def != nullptr); |
| return (header->HiddenapiClassDatas().Empty()) |
| ? 0u |
| : header->HiddenapiClassDatas()[class_def->GetIndex()]->GetFlags(field_or_method_item); |
| } |
| |
| uint32_t ItemSize() const { |
| uint32_t size = 0u; |
| bool has_non_zero_entries = false; |
| if (flags_ != nullptr) { |
| for (const auto& entry : *flags_) { |
| size += UnsignedLeb128Size(entry.second); |
| has_non_zero_entries |= (entry.second != 0u); |
| } |
| } |
| return has_non_zero_entries ? size : 0u; |
| } |
| |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| const ClassDef* class_def_; |
| std::unique_ptr<HiddenapiFlagsMap> flags_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HiddenapiClassData); |
| }; |
| |
| // TODO(sehr): implement MapList. |
| class MapList : public Item { |
| public: |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MapList); |
| }; |
| |
| class MapItem : public Item { |
| public: |
| void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MapItem); |
| }; |
| |
| // Interface for building a vector of file sections for use by other clients. |
| struct DexFileSection { |
| public: |
| DexFileSection(const std::string& name, uint16_t type, uint32_t size, uint32_t offset) |
| : name(name), type(type), size(size), offset(offset) { } |
| std::string name; |
| // The type (DexFile::MapItemType). |
| uint16_t type; |
| // The size (in elements, not bytes). |
| uint32_t size; |
| // The byte offset from the start of the file. |
| uint32_t offset; |
| }; |
| |
| enum class SortDirection { |
| kSortAscending, |
| kSortDescending |
| }; |
| |
| std::vector<DexFileSection> GetSortedDexFileSections(dex_ir::Header* header, |
| SortDirection direction); |
| |
| } // namespace dex_ir |
| } // namespace art |
| |
| #endif // ART_DEXLAYOUT_DEX_IR_H_ |