You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1363 lines
45 KiB
1363 lines
45 KiB
/*
|
|
* 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&&) = default;
|
|
Iterator& operator=(const Iterator&) = default;
|
|
Iterator& operator=(Iterator&&) = 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_
|