diff options
author | 2016-09-01 13:03:50 -0700 | |
---|---|---|
committer | 2016-09-06 14:06:23 -0700 | |
commit | 853a8e10844b9b9e791c6d40e5d332cd38af97d6 (patch) | |
tree | 7339753d96f5e346c28a5c57a561a9464d83e719 | |
parent | 3e65825978056adf7cbad646d4ab92c161a60e09 (diff) |
Separate DexIr building from constructors.
Move all the construction from DexFile out of the constructors of the
basic IR.
Bug: 29921113
Change-Id: I3f79c104ce7183ddde73f143c047061416009a54
Test: test-art-host-gtest
-rwxr-xr-x | dexlayout/Android.mk | 2 | ||||
-rw-r--r-- | dexlayout/dex_ir.cc | 390 | ||||
-rw-r--r-- | dexlayout/dex_ir.h | 464 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 507 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.h | 32 | ||||
-rw-r--r-- | dexlayout/dexlayout.cc | 202 |
6 files changed, 917 insertions, 680 deletions
diff --git a/dexlayout/Android.mk b/dexlayout/Android.mk index 3095866cf0..de02580bf6 100755 --- a/dexlayout/Android.mk +++ b/dexlayout/Android.mk @@ -16,7 +16,7 @@ LOCAL_PATH:= $(call my-dir) -dexlayout_src_files := dexlayout_main.cc dexlayout.cc dex_ir.cc +dexlayout_src_files := dexlayout_main.cc dexlayout.cc dex_ir_builder.cc dexlayout_c_includes := art/runtime dexlayout_libraries := libart diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc deleted file mode 100644 index 0ed040eba5..0000000000 --- a/dexlayout/dex_ir.cc +++ /dev/null @@ -1,390 +0,0 @@ -/* - * 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. - * - * Implementation file of the dex file intermediate representation. - * - * Utilities for reading dex files into an internal representation, - * manipulating them, and writing them out. - */ - -#include "dex_ir.h" - -#include <map> -#include <vector> - -#include "dex_file.h" -#include "dex_file-inl.h" -#include "utils.h" - -namespace art { -namespace dex_ir { - -namespace { -static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) { - uint64_t value = 0; - for (uint32_t i = 0; i <= length; i++) { - value |= static_cast<uint64_t>(*(*data)++) << (i * 8); - } - if (sign_extend) { - int shift = (7 - length) * 8; - return (static_cast<int64_t>(value) << shift) >> shift; - } - return value; -} - -static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) { - DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context); - std::vector<std::unique_ptr<PositionInfo>>& positions = debug_info->GetPositionInfo(); - positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_))); - return false; -} - -static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) { - DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context); - std::vector<std::unique_ptr<LocalInfo>>& locals = debug_info->GetLocalInfo(); - const char* name = entry.name_ != nullptr ? entry.name_ : "(null)"; - const char* signature = entry.signature_ != nullptr ? entry.signature_ : ""; - locals.push_back(std::unique_ptr<LocalInfo>( - new LocalInfo(name, entry.descriptor_, signature, entry.start_address_, - entry.end_address_, entry.reg_))); -} -} // namespace - -Header::Header(const DexFile& dex_file) : dex_file_(dex_file) { - const DexFile::Header& disk_header = dex_file.GetHeader(); - memcpy(magic_, disk_header.magic_, sizeof(magic_)); - checksum_ = disk_header.checksum_; - // TODO(sehr): clearly the signature will need to be recomputed before dumping. - memcpy(signature_, disk_header.signature_, sizeof(signature_)); - endian_tag_ = disk_header.endian_tag_; - file_size_ = disk_header.file_size_; - header_size_ = disk_header.header_size_; - link_size_ = disk_header.link_size_; - link_offset_ = disk_header.link_off_; - data_size_ = disk_header.data_size_; - data_offset_ = disk_header.data_off_; - // Walk the rest of the header fields. - string_ids_.SetOffset(disk_header.string_ids_off_); - for (uint32_t i = 0; i < dex_file_.NumStringIds(); ++i) { - string_ids_.AddWithPosition(i, new StringId(dex_file_.GetStringId(i), *this)); - } - type_ids_.SetOffset(disk_header.type_ids_off_); - for (uint32_t i = 0; i < dex_file_.NumTypeIds(); ++i) { - type_ids_.AddWithPosition(i, new TypeId(dex_file_.GetTypeId(i), *this)); - } - proto_ids_.SetOffset(disk_header.proto_ids_off_); - for (uint32_t i = 0; i < dex_file_.NumProtoIds(); ++i) { - proto_ids_.AddWithPosition(i, new ProtoId(dex_file_.GetProtoId(i), *this)); - } - field_ids_.SetOffset(disk_header.field_ids_off_); - for (uint32_t i = 0; i < dex_file_.NumFieldIds(); ++i) { - field_ids_.AddWithPosition(i, new FieldId(dex_file_.GetFieldId(i), *this)); - } - method_ids_.SetOffset(disk_header.method_ids_off_); - for (uint32_t i = 0; i < dex_file_.NumMethodIds(); ++i) { - method_ids_.AddWithPosition(i, new MethodId(dex_file_.GetMethodId(i), *this)); - } - class_defs_.SetOffset(disk_header.class_defs_off_); - for (uint32_t i = 0; i < dex_file_.NumClassDefs(); ++i) { - class_defs_.AddWithPosition(i, new ClassDef(dex_file_.GetClassDef(i), *this)); - } -} - -ArrayItem::ArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) { - Read(header, data, type, length); -} - -ArrayItem::ArrayItem(Header& header, const uint8_t** data) { - const uint8_t encoded_value = *(*data)++; - Read(header, data, encoded_value & 0x1f, encoded_value >> 5); -} - -void ArrayItem::Read(Header& header, const uint8_t** data, uint8_t type, uint8_t length) { - type_ = type; - switch (type_) { - case DexFile::kDexAnnotationByte: - item_.byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false)); - break; - case DexFile::kDexAnnotationShort: - item_.short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true)); - break; - case DexFile::kDexAnnotationChar: - item_.char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false)); - break; - case DexFile::kDexAnnotationInt: - item_.int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true)); - break; - case DexFile::kDexAnnotationLong: - item_.long_val_ = static_cast<int64_t>(ReadVarWidth(data, length, true)); - break; - case DexFile::kDexAnnotationFloat: { - // Fill on right. - union { - float f; - uint32_t data; - } conv; - conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8; - item_.float_val_ = conv.f; - break; - } - case DexFile::kDexAnnotationDouble: { - // Fill on right. - union { - double d; - uint64_t data; - } conv; - conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8; - item_.double_val_ = conv.d; - break; - } - case DexFile::kDexAnnotationString: { - const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item_.string_val_ = header.StringIds()[string_index].get(); - break; - } - case DexFile::kDexAnnotationType: { - const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item_.string_val_ = header.TypeIds()[string_index]->GetStringId(); - break; - } - case DexFile::kDexAnnotationField: - case DexFile::kDexAnnotationEnum: { - const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item_.field_val_ = header.FieldIds()[field_index].get(); - break; - } - case DexFile::kDexAnnotationMethod: { - const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item_.method_val_ = header.MethodIds()[method_index].get(); - break; - } - case DexFile::kDexAnnotationArray: { - item_.annotation_array_val_ = new std::vector<std::unique_ptr<ArrayItem>>(); - // Decode all elements. - const uint32_t size = DecodeUnsignedLeb128(data); - for (uint32_t i = 0; i < size; i++) { - item_.annotation_array_val_->push_back( - std::unique_ptr<ArrayItem>(new ArrayItem(header, data))); - } - break; - } - case DexFile::kDexAnnotationAnnotation: { - const uint32_t type_idx = DecodeUnsignedLeb128(data); - item_.annotation_annotation_val_.string_ = header.TypeIds()[type_idx]->GetStringId(); - item_.annotation_annotation_val_.array_ = new std::vector<std::unique_ptr<NameValuePair>>(); - // Decode all name=value pairs. - const uint32_t size = DecodeUnsignedLeb128(data); - for (uint32_t i = 0; i < size; i++) { - const uint32_t name_index = DecodeUnsignedLeb128(data); - item_.annotation_annotation_val_.array_->push_back(std::unique_ptr<NameValuePair>( - new NameValuePair(header.StringIds()[name_index].get(), new ArrayItem(header, data)))); - } - break; - } - case DexFile::kDexAnnotationNull: - break; - case DexFile::kDexAnnotationBoolean: - item_.bool_val_ = (length != 0); - break; - default: - break; - } -} - -ClassDef::ClassDef(const DexFile::ClassDef& disk_class_def, Header& header) { - class_type_ = header.TypeIds()[disk_class_def.class_idx_].get(); - access_flags_ = disk_class_def.access_flags_; - superclass_ = header.GetTypeIdOrNullPtr(disk_class_def.superclass_idx_); - - const DexFile::TypeList* type_list = header.GetDexFile().GetInterfacesList(disk_class_def); - interfaces_offset_ = disk_class_def.interfaces_off_; - if (type_list != nullptr) { - for (uint32_t index = 0; index < type_list->Size(); ++index) { - interfaces_.push_back(header.TypeIds()[type_list->GetTypeItem(index).type_idx_].get()); - } - } - source_file_ = header.GetStringIdOrNullPtr(disk_class_def.source_file_idx_); - // Annotations. - const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item = - header.GetDexFile().GetAnnotationsDirectory(disk_class_def); - if (disk_annotations_directory_item == nullptr) { - annotations_.reset(nullptr); - } else { - annotations_.reset(new AnnotationsDirectoryItem(disk_annotations_directory_item, header)); - annotations_->SetOffset(disk_class_def.annotations_off_); - } - // Static field initializers. - static_values_ = nullptr; - const uint8_t* static_data = header.GetDexFile().GetEncodedStaticFieldValuesArray(disk_class_def); - if (static_data != nullptr) { - uint32_t static_value_count = static_data == nullptr ? 0 : DecodeUnsignedLeb128(&static_data); - if (static_value_count > 0) { - static_values_ = new std::vector<std::unique_ptr<ArrayItem>>(); - for (uint32_t i = 0; i < static_value_count; ++i) { - static_values_->push_back(std::unique_ptr<ArrayItem>(new ArrayItem(header, &static_data))); - } - } - } - // Read the fields and methods defined by the class, resolving the circular reference from those - // to classes by setting class at the same time. - const uint8_t* encoded_data = header.GetDexFile().GetClassData(disk_class_def); - class_data_.SetOffset(disk_class_def.class_data_off_); - if (encoded_data != nullptr) { - ClassDataItemIterator cdii(header.GetDexFile(), encoded_data); - // Static fields. - for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) { - FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get(); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - class_data_.StaticFields().push_back( - std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); - } - // Instance fields. - for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) { - FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get(); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - class_data_.InstanceFields().push_back( - std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); - } - // Direct methods. - for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) { - class_data_.DirectMethods().push_back( - std::unique_ptr<MethodItem>(GenerateMethodItem(header, cdii))); - } - // Virtual methods. - for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) { - class_data_.VirtualMethods().push_back( - std::unique_ptr<MethodItem>(GenerateMethodItem(header, cdii))); - } - } -} - -MethodItem* ClassDef::GenerateMethodItem(Header& header, ClassDataItemIterator& cdii) { - MethodId* method_item = header.MethodIds()[cdii.GetMemberIndex()].get(); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); - CodeItem* code_item = nullptr; - DebugInfoItem* debug_info = nullptr; - if (disk_code_item != nullptr) { - code_item = new CodeItem(*disk_code_item, header); - code_item->SetOffset(cdii.GetMethodCodeItemOffset()); - debug_info = code_item->DebugInfo(); - } - if (debug_info != nullptr) { - bool is_static = (access_flags & kAccStatic) != 0; - header.GetDexFile().DecodeDebugLocalInfo( - disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info); - header.GetDexFile().DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info); - } - return new MethodItem(access_flags, method_item, code_item); -} - -CodeItem::CodeItem(const DexFile::CodeItem& disk_code_item, Header& header) { - registers_size_ = disk_code_item.registers_size_; - ins_size_ = disk_code_item.ins_size_; - outs_size_ = disk_code_item.outs_size_; - tries_size_ = disk_code_item.tries_size_; - - const uint8_t* debug_info_stream = header.GetDexFile().GetDebugInfoStream(&disk_code_item); - if (debug_info_stream != nullptr) { - debug_info_.reset(new DebugInfoItem()); - } else { - debug_info_.reset(nullptr); - } - - insns_size_ = disk_code_item.insns_size_in_code_units_; - insns_.reset(new uint16_t[insns_size_]); - memcpy(insns_.get(), disk_code_item.insns_, insns_size_ * sizeof(uint16_t)); - - if (tries_size_ > 0) { - tries_ = new std::vector<std::unique_ptr<const TryItem>>(); - for (uint32_t i = 0; i < tries_size_; ++i) { - const DexFile::TryItem* disk_try_item = header.GetDexFile().GetTryItems(disk_code_item, i); - tries_->push_back(std::unique_ptr<const TryItem>( - new TryItem(*disk_try_item, disk_code_item, header))); - } - } else { - tries_ = nullptr; - } -} - -AnnotationSetItem::AnnotationSetItem(const DexFile::AnnotationSetItem& disk_annotations_item, - Header& header) { - if (disk_annotations_item.size_ == 0) { - return; - } - for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) { - const DexFile::AnnotationItem* annotation = - header.GetDexFile().GetAnnotationItem(&disk_annotations_item, i); - if (annotation == nullptr) { - continue; - } - uint8_t visibility = annotation->visibility_; - const uint8_t* annotation_data = annotation->annotation_; - ArrayItem* array_item = - new ArrayItem(header, &annotation_data, DexFile::kDexAnnotationAnnotation, 0); - items_.push_back(std::unique_ptr<AnnotationItem>(new AnnotationItem(visibility, array_item))); - } -} - -AnnotationsDirectoryItem::AnnotationsDirectoryItem( - const DexFile::AnnotationsDirectoryItem* disk_annotations_item, Header& header) { - const DexFile::AnnotationSetItem* class_set_item = - header.GetDexFile().GetClassAnnotationSet(disk_annotations_item); - if (class_set_item == nullptr) { - class_annotation_.reset(nullptr); - } else { - class_annotation_.reset(new AnnotationSetItem(*class_set_item, header)); - } - const DexFile::FieldAnnotationsItem* fields = - header.GetDexFile().GetFieldAnnotations(disk_annotations_item); - if (fields != nullptr) { - for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) { - FieldId* field_id = header.FieldIds()[fields[i].field_idx_].get(); - const DexFile::AnnotationSetItem* field_set_item = - header.GetDexFile().GetFieldAnnotationSetItem(fields[i]); - dex_ir::AnnotationSetItem* annotation_set_item = - new AnnotationSetItem(*field_set_item, header); - field_annotations_.push_back(std::unique_ptr<FieldAnnotation>( - new FieldAnnotation(field_id, annotation_set_item))); - } - } - const DexFile::MethodAnnotationsItem* methods = - header.GetDexFile().GetMethodAnnotations(disk_annotations_item); - if (methods != nullptr) { - for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) { - MethodId* method_id = header.MethodIds()[methods[i].method_idx_].get(); - const DexFile::AnnotationSetItem* method_set_item = - header.GetDexFile().GetMethodAnnotationSetItem(methods[i]); - dex_ir::AnnotationSetItem* annotation_set_item = - new AnnotationSetItem(*method_set_item, header); - method_annotations_.push_back(std::unique_ptr<MethodAnnotation>( - new MethodAnnotation(method_id, annotation_set_item))); - } - } - const DexFile::ParameterAnnotationsItem* parameters = - header.GetDexFile().GetParameterAnnotations(disk_annotations_item); - if (parameters != nullptr) { - for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) { - MethodId* method_id = header.MethodIds()[parameters[i].method_idx_].get(); - const DexFile::AnnotationSetRefList* list = - header.GetDexFile().GetParameterAnnotationSetRefList(¶meters[i]); - parameter_annotations_.push_back(std::unique_ptr<ParameterAnnotation>( - new ParameterAnnotation(method_id, list, header))); - } - } -} - -} // namespace dex_ir -} // namespace art diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index fcd3ab0c1e..514d6fdc58 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -19,12 +19,10 @@ #ifndef ART_DEXLAYOUT_DEX_IR_H_ #define ART_DEXLAYOUT_DEX_IR_H_ -#include <iostream> -#include <map> #include <vector> #include <stdint.h> -#include "dex_file.h" +#include "dex_file-inl.h" namespace art { namespace dex_ir { @@ -106,19 +104,39 @@ template<class T> class CollectionWithOffset { class Item { public: virtual ~Item() { } + uint32_t GetOffset() const { return offset_; } void SetOffset(uint32_t offset) { offset_ = offset; } + protected: uint32_t offset_ = 0; }; class Header : public Item { public: - explicit Header(const DexFile& dex_file); + 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) + : 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_)); + } ~Header() OVERRIDE { } - const DexFile& GetDexFile() const { return dex_file_; } - const uint8_t* Magic() const { return magic_; } uint32_t Checksum() const { return checksum_; } const uint8_t* Signature() const { return signature_; } @@ -178,7 +196,6 @@ class Header : public Item { void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: - const DexFile& dex_file_; uint8_t magic_[8]; uint32_t checksum_; uint8_t signature_[DexFile::kSha1DigestSize]; @@ -201,9 +218,7 @@ class Header : public Item { class StringId : public Item { public: - StringId(const DexFile::StringId& disk_string_id, Header& header) : - data_(strdup(header.GetDexFile().GetStringData(disk_string_id))) { - } + explicit StringId(const char* data) : data_(strdup(data)) { } ~StringId() OVERRIDE { } const char* Data() const { return data_.get(); } @@ -217,9 +232,7 @@ class StringId : public Item { class TypeId : public Item { public: - TypeId(const DexFile::TypeId& disk_type_id, Header& header) : - string_id_(header.StringIds()[disk_type_id.descriptor_idx_].get()) { - } + explicit TypeId(StringId* string_id) : string_id_(string_id) { } ~TypeId() OVERRIDE { } StringId* GetStringId() const { return string_id_; } @@ -231,39 +244,31 @@ class TypeId : public Item { DISALLOW_COPY_AND_ASSIGN(TypeId); }; +using TypeIdVector = std::vector<const TypeId*>; + class ProtoId : public Item { public: - ProtoId(const DexFile::ProtoId& disk_proto_id, Header& header) { - shorty_ = header.StringIds()[disk_proto_id.shorty_idx_].get(); - return_type_ = header.TypeIds()[disk_proto_id.return_type_idx_].get(); - DexFileParameterIterator dfpi(header.GetDexFile(), disk_proto_id); - while (dfpi.HasNext()) { - parameters_.push_back(header.TypeIds()[dfpi.GetTypeIdx()].get()); - dfpi.Next(); - } - } + ProtoId(const StringId* shorty, const TypeId* return_type, TypeIdVector* parameters) + : shorty_(shorty), return_type_(return_type), parameters_(parameters) { } ~ProtoId() OVERRIDE { } const StringId* Shorty() const { return shorty_; } const TypeId* ReturnType() const { return return_type_; } - const std::vector<const TypeId*>& Parameters() const { return parameters_; } + const std::vector<const TypeId*>& Parameters() const { return *parameters_; } void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } private: const StringId* shorty_; const TypeId* return_type_; - std::vector<const TypeId*> parameters_; + std::unique_ptr<TypeIdVector> parameters_; DISALLOW_COPY_AND_ASSIGN(ProtoId); }; class FieldId : public Item { public: - FieldId(const DexFile::FieldId& disk_field_id, Header& header) { - class_ = header.TypeIds()[disk_field_id.class_idx_].get(); - type_ = header.TypeIds()[disk_field_id.type_idx_].get(); - name_ = header.StringIds()[disk_field_id.name_idx_].get(); - } + FieldId(const TypeId* klass, const TypeId* type, const StringId* name) + : class_(klass), type_(type), name_(name) { } ~FieldId() OVERRIDE { } const TypeId* Class() const { return class_; } @@ -281,11 +286,8 @@ class FieldId : public Item { class MethodId : public Item { public: - MethodId(const DexFile::MethodId& disk_method_id, Header& header) { - class_ = header.TypeIds()[disk_method_id.class_idx_].get(); - proto_ = header.ProtoIds()[disk_method_id.proto_idx_].get(); - name_ = header.StringIds()[disk_method_id.name_idx_].get(); - } + MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name) + : class_(klass), proto_(proto), name_(name) { } ~MethodId() OVERRIDE { } const TypeId* Class() const { return class_; } @@ -303,8 +305,8 @@ class MethodId : public Item { class FieldItem : public Item { public: - FieldItem(uint32_t access_flags, const FieldId* field_id) : - access_flags_(access_flags), field_id_(field_id) { } + FieldItem(uint32_t access_flags, const FieldId* field_id) + : access_flags_(access_flags), field_id_(field_id) { } ~FieldItem() OVERRIDE { } uint32_t GetAccessFlags() const { return access_flags_; } @@ -318,10 +320,12 @@ class FieldItem : public Item { DISALLOW_COPY_AND_ASSIGN(FieldItem); }; +using FieldItemVector = std::vector<std::unique_ptr<FieldItem>>; + class MethodItem : public Item { public: - MethodItem(uint32_t access_flags, const MethodId* method_id, const CodeItem* code) : - access_flags_(access_flags), method_id_(method_id), code_(code) { } + MethodItem(uint32_t access_flags, const MethodId* method_id, const CodeItem* code) + : access_flags_(access_flags), method_id_(method_id), code_(code) { } ~MethodItem() OVERRIDE { } uint32_t GetAccessFlags() const { return access_flags_; } @@ -337,12 +341,14 @@ class MethodItem : public Item { DISALLOW_COPY_AND_ASSIGN(MethodItem); }; +using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>; + class ArrayItem : public Item { public: class NameValuePair { public: - NameValuePair(StringId* name, ArrayItem* value) : - name_(name), value_(value) { } + NameValuePair(StringId* name, ArrayItem* value) + : name_(name), value_(value) { } StringId* Name() const { return name_; } ArrayItem* Value() const { return value_.get(); } @@ -353,8 +359,26 @@ class ArrayItem : public Item { DISALLOW_COPY_AND_ASSIGN(NameValuePair); }; - ArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length); - ArrayItem(Header& header, const uint8_t** data); + union PayloadUnion { + 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_; + FieldId* field_val_; + MethodId* method_val_; + std::vector<std::unique_ptr<ArrayItem>>* annotation_array_val_; + struct { + StringId* string_; + std::vector<std::unique_ptr<NameValuePair>>* array_; + } annotation_annotation_val_; + }; + + explicit ArrayItem(uint8_t type) : type_(type) { } ~ArrayItem() OVERRIDE { } int8_t Type() const { return type_; } @@ -378,67 +402,79 @@ class ArrayItem : public Item { std::vector<std::unique_ptr<NameValuePair>>* GetAnnotationAnnotationNameValuePairArray() const { return item_.annotation_annotation_val_.array_; } + // Used to construct the item union. Ugly, but necessary. + PayloadUnion* GetPayloadUnion() { return &item_; } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: - void Read(Header& header, const uint8_t** data, uint8_t type, uint8_t length); 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_; - FieldId* field_val_; - MethodId* method_val_; - std::vector<std::unique_ptr<ArrayItem>>* annotation_array_val_; - struct { - StringId* string_; - std::vector<std::unique_ptr<NameValuePair>>* array_; - } annotation_annotation_val_; - } item_; + PayloadUnion item_; DISALLOW_COPY_AND_ASSIGN(ArrayItem); }; +using ArrayItemVector = std::vector<std::unique_ptr<ArrayItem>>; + class ClassData : public Item { public: - ClassData() = default; + 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; - std::vector<std::unique_ptr<FieldItem>>& StaticFields() { return static_fields_; } - std::vector<std::unique_ptr<FieldItem>>& InstanceFields() { return instance_fields_; } - std::vector<std::unique_ptr<MethodItem>>& DirectMethods() { return direct_methods_; } - std::vector<std::unique_ptr<MethodItem>>& VirtualMethods() { return virtual_methods_; } + 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::vector<std::unique_ptr<FieldItem>> static_fields_; - std::vector<std::unique_ptr<FieldItem>> instance_fields_; - std::vector<std::unique_ptr<MethodItem>> direct_methods_; - std::vector<std::unique_ptr<MethodItem>> virtual_methods_; + 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 Item { public: - ClassDef(const DexFile::ClassDef& disk_class_def, Header& header); + ClassDef(const TypeId* class_type, + uint32_t access_flags, + const TypeId* superclass, + TypeIdVector* interfaces, + uint32_t interfaces_offset, + const StringId* source_file, + AnnotationsDirectoryItem* annotations, + ArrayItemVector* static_values, + ClassData* class_data) + : class_type_(class_type), + access_flags_(access_flags), + superclass_(superclass), + interfaces_(interfaces), + interfaces_offset_(interfaces_offset), + source_file_(source_file), + annotations_(annotations), + static_values_(static_values), + class_data_(class_data) { } + ~ClassDef() OVERRIDE { } const TypeId* ClassType() const { return class_type_; } uint32_t GetAccessFlags() const { return access_flags_; } const TypeId* Superclass() const { return superclass_; } - std::vector<TypeId*>* Interfaces() { return &interfaces_; } + TypeIdVector* Interfaces() { return interfaces_.get(); } uint32_t InterfacesOffset() const { return interfaces_offset_; } void SetInterfacesOffset(uint32_t new_offset) { interfaces_offset_ = new_offset; } const StringId* SourceFile() const { return source_file_; } AnnotationsDirectoryItem* Annotations() const { return annotations_.get(); } - std::vector<std::unique_ptr<ArrayItem>>* StaticValues() { return static_values_; } - ClassData* GetClassData() { return &class_data_; } + ArrayItemVector* StaticValues() { return static_values_.get(); } + ClassData* GetClassData() { return class_data_.get(); } MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii); @@ -448,28 +484,78 @@ class ClassDef : public Item { const TypeId* class_type_; uint32_t access_flags_; const TypeId* superclass_; - std::vector<TypeId*> interfaces_; + std::unique_ptr<TypeIdVector> interfaces_; uint32_t interfaces_offset_; const StringId* source_file_; std::unique_ptr<AnnotationsDirectoryItem> annotations_; - std::vector<std::unique_ptr<ArrayItem>>* static_values_; - ClassData class_data_; + std::unique_ptr<ArrayItemVector> static_values_; + std::unique_ptr<ClassData> class_data_; DISALLOW_COPY_AND_ASSIGN(ClassDef); }; +class CatchHandler { + public: + CatchHandler(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_; + uint32_t address_; + 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, CatchHandlerVector* 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 CatchHandlerVector& GetHandlers() const { return *handlers_.get(); } + + void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } + + private: + uint32_t start_addr_; + uint16_t insn_count_; + std::unique_ptr<CatchHandlerVector> handlers_; + DISALLOW_COPY_AND_ASSIGN(TryItem); +}; + +using TryItemVector = std::vector<std::unique_ptr<const TryItem>>; + class CodeItem : public Item { public: - CodeItem(const DexFile::CodeItem& disk_code_item, Header& header); + 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) + : registers_size_(registers_size), + ins_size_(ins_size), + outs_size_(outs_size), + debug_info_(debug_info), + insns_size_(insns_size), + insns_(insns), + tries_(tries) { } + ~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_size_; } + uint16_t TriesSize() const { return tries_ == nullptr ? 0 : tries_->size(); } DebugInfoItem* DebugInfo() const { return debug_info_.get(); } uint32_t InsnsSize() const { return insns_size_; } uint16_t* Insns() const { return insns_.get(); } - std::vector<std::unique_ptr<const TryItem>>* Tries() const { return tries_; } + TryItemVector* Tries() const { return tries_.get(); } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } @@ -477,56 +563,13 @@ class CodeItem : public Item { uint16_t registers_size_; uint16_t ins_size_; uint16_t outs_size_; - uint16_t tries_size_; std::unique_ptr<DebugInfoItem> debug_info_; uint32_t insns_size_; std::unique_ptr<uint16_t[]> insns_; - std::vector<std::unique_ptr<const TryItem>>* tries_; + std::unique_ptr<TryItemVector> tries_; DISALLOW_COPY_AND_ASSIGN(CodeItem); }; -class TryItem : public Item { - public: - class CatchHandler { - public: - CatchHandler(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_; - uint32_t address_; - DISALLOW_COPY_AND_ASSIGN(CatchHandler); - }; - - TryItem(const DexFile::TryItem& disk_try_item, - const DexFile::CodeItem& disk_code_item, - Header& header) { - start_addr_ = disk_try_item.start_addr_; - insn_count_ = disk_try_item.insn_count_; - for (CatchHandlerIterator it(disk_code_item, disk_try_item); it.HasNext(); it.Next()) { - const uint16_t type_index = it.GetHandlerTypeIndex(); - const TypeId* type_id = header.GetTypeIdOrNullPtr(type_index); - handlers_.push_back(std::unique_ptr<const CatchHandler>( - new CatchHandler(type_id, it.GetHandlerAddress()))); - } - } - ~TryItem() OVERRIDE { } - - uint32_t StartAddr() const { return start_addr_; } - uint16_t InsnCount() const { return insn_count_; } - const std::vector<std::unique_ptr<const CatchHandler>>& GetHandlers() const { return handlers_; } - - void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } - - private: - uint32_t start_addr_; - uint16_t insn_count_; - std::vector<std::unique_ptr<const CatchHandler>> handlers_; - DISALLOW_COPY_AND_ASSIGN(TryItem); -}; - struct PositionInfo { PositionInfo(uint32_t address, uint32_t line) : address_(address), line_(line) { } @@ -535,11 +578,21 @@ struct PositionInfo { uint32_t line_; }; +using PositionInfoVector = std::vector<std::unique_ptr<PositionInfo>>; + struct LocalInfo { - LocalInfo(const char* name, const char* descriptor, const char* signature, uint32_t start_address, - uint32_t end_address, uint16_t reg) : - name_(name), descriptor_(descriptor), signature_(signature), start_address_(start_address), - end_address_(end_address), reg_(reg) { } + LocalInfo(const char* name, + const char* descriptor, + const char* signature, + uint32_t start_address, + uint32_t end_address, + uint16_t reg) + : name_(name), + descriptor_(descriptor), + signature_(signature), + start_address_(start_address), + end_address_(end_address), + reg_(reg) { } std::string name_; std::string descriptor_; @@ -549,124 +602,123 @@ struct LocalInfo { uint16_t reg_; }; +using LocalInfoVector = std::vector<std::unique_ptr<LocalInfo>>; + class DebugInfoItem : public Item { public: DebugInfoItem() = default; - std::vector<std::unique_ptr<PositionInfo>>& GetPositionInfo() { return positions_; } - std::vector<std::unique_ptr<LocalInfo>>& GetLocalInfo() { return locals_; } + PositionInfoVector& GetPositionInfo() { return positions_; } + LocalInfoVector& GetLocalInfo() { return locals_; } private: - std::vector<std::unique_ptr<PositionInfo>> positions_; - std::vector<std::unique_ptr<LocalInfo>> locals_; + PositionInfoVector positions_; + LocalInfoVector locals_; DISALLOW_COPY_AND_ASSIGN(DebugInfoItem); }; -class AnnotationSetItem : public Item { +class AnnotationItem { public: - class AnnotationItem { - public: - AnnotationItem(uint8_t visibility, ArrayItem* item) : - visibility_(visibility), item_(item) { } + AnnotationItem(uint8_t visibility, ArrayItem* item) : visibility_(visibility), item_(item) { } - uint8_t GetVisibility() const { return visibility_; } - ArrayItem* GetItem() const { return item_.get(); } + uint8_t GetVisibility() const { return visibility_; } + ArrayItem* GetItem() const { return item_.get(); } - private: - uint8_t visibility_; - std::unique_ptr<ArrayItem> item_; - DISALLOW_COPY_AND_ASSIGN(AnnotationItem); - }; + private: + uint8_t visibility_; + std::unique_ptr<ArrayItem> item_; + DISALLOW_COPY_AND_ASSIGN(AnnotationItem); +}; - AnnotationSetItem(const DexFile::AnnotationSetItem& disk_annotations_item, Header& header); +using AnnotationItemVector = std::vector<std::unique_ptr<AnnotationItem>>; + +class AnnotationSetItem : public Item { + public: + explicit AnnotationSetItem(AnnotationItemVector* items) : items_(items) { } ~AnnotationSetItem() OVERRIDE { } - std::vector<std::unique_ptr<AnnotationItem>>& GetItems() { return items_; } + AnnotationItemVector* GetItems() { return items_.get(); } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: - std::vector<std::unique_ptr<AnnotationItem>> items_; + std::unique_ptr<AnnotationItemVector> items_; DISALLOW_COPY_AND_ASSIGN(AnnotationSetItem); }; -class AnnotationsDirectoryItem : public Item { +using AnnotationSetItemVector = std::vector<std::unique_ptr<AnnotationSetItem>>; + +class FieldAnnotation { public: - class FieldAnnotation { - public: - FieldAnnotation(FieldId* field_id, AnnotationSetItem* annotation_set_item) : - field_id_(field_id), annotation_set_item_(annotation_set_item) { } + 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_.get(); } + FieldId* GetFieldId() const { return field_id_; } + AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); } - private: - FieldId* field_id_; - std::unique_ptr<AnnotationSetItem> annotation_set_item_; - DISALLOW_COPY_AND_ASSIGN(FieldAnnotation); - }; + private: + FieldId* field_id_; + std::unique_ptr<AnnotationSetItem> annotation_set_item_; + DISALLOW_COPY_AND_ASSIGN(FieldAnnotation); +}; - class MethodAnnotation { - public: - MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item) : - method_id_(method_id), annotation_set_item_(annotation_set_item) { } +using FieldAnnotationVector = std::vector<std::unique_ptr<FieldAnnotation>>; - MethodId* GetMethodId() const { return method_id_; } - AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); } +class MethodAnnotation { + public: + MethodAnnotation(MethodId* method_id, AnnotationSetItem* annotation_set_item) + : method_id_(method_id), annotation_set_item_(annotation_set_item) { } - private: - MethodId* method_id_; - std::unique_ptr<AnnotationSetItem> annotation_set_item_; - DISALLOW_COPY_AND_ASSIGN(MethodAnnotation); - }; + MethodId* GetMethodId() const { return method_id_; } + AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); } - class ParameterAnnotation { - public: - ParameterAnnotation(MethodId* method_id, - const DexFile::AnnotationSetRefList* annotation_set_ref_list, - Header& header) : - method_id_(method_id) { - for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) { - const DexFile::AnnotationSetItem* annotation_set_item = - header.GetDexFile().GetSetRefItemItem(&annotation_set_ref_list->list_[i]); - annotations_.push_back(std::unique_ptr<AnnotationSetItem>( - new AnnotationSetItem(*annotation_set_item, header))); - } - } - - MethodId* GetMethodId() const { return method_id_; } - std::vector<std::unique_ptr<AnnotationSetItem>>& GetAnnotations() { return annotations_; } + private: + MethodId* method_id_; + std::unique_ptr<AnnotationSetItem> annotation_set_item_; + DISALLOW_COPY_AND_ASSIGN(MethodAnnotation); +}; - private: - MethodId* method_id_; - std::vector<std::unique_ptr<AnnotationSetItem>> annotations_; - DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation); - }; +using MethodAnnotationVector = std::vector<std::unique_ptr<MethodAnnotation>>; - AnnotationsDirectoryItem(const DexFile::AnnotationsDirectoryItem* disk_annotations_item, - Header& header); +class ParameterAnnotation { + public: + ParameterAnnotation(MethodId* method_id, AnnotationSetItemVector* annotations) + : method_id_(method_id), annotations_(annotations) { } - AnnotationSetItem* GetClassAnnotation() const { return class_annotation_.get(); } + MethodId* GetMethodId() const { return method_id_; } + AnnotationSetItemVector* GetAnnotations() { return annotations_.get(); } - std::vector<std::unique_ptr<FieldAnnotation>>& GetFieldAnnotations() { - return field_annotations_; - } + private: + MethodId* method_id_; + std::unique_ptr<AnnotationSetItemVector> annotations_; + DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation); +}; - std::vector<std::unique_ptr<MethodAnnotation>>& GetMethodAnnotations() { - return method_annotations_; - } +using ParameterAnnotationVector = std::vector<std::unique_ptr<ParameterAnnotation>>; - std::vector<std::unique_ptr<ParameterAnnotation>>& GetParameterAnnotations() { - return parameter_annotations_; - } +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_.get(); } + 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: std::unique_ptr<AnnotationSetItem> class_annotation_; - std::vector<std::unique_ptr<FieldAnnotation>> field_annotations_; - std::vector<std::unique_ptr<MethodAnnotation>> method_annotations_; - std::vector<std::unique_ptr<ParameterAnnotation>> parameter_annotations_; + std::unique_ptr<FieldAnnotationVector> field_annotations_; + std::unique_ptr<MethodAnnotationVector> method_annotations_; + std::unique_ptr<ParameterAnnotationVector> parameter_annotations_; DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem); }; diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc new file mode 100644 index 0000000000..38f35e79bb --- /dev/null +++ b/dexlayout/dex_ir_builder.cc @@ -0,0 +1,507 @@ +/* + * 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. + */ + +#include <stdint.h> +#include <vector> + +#include "dex_ir_builder.h" + +namespace art { +namespace dex_ir { + +namespace { + +static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) { + uint64_t value = 0; + for (uint32_t i = 0; i <= length; i++) { + value |= static_cast<uint64_t>(*(*data)++) << (i * 8); + } + if (sign_extend) { + int shift = (7 - length) * 8; + return (static_cast<int64_t>(value) << shift) >> shift; + } + return value; +} + +// Prototype to break cyclic dependency. +void ReadPayloadUnion(Header& header, + const uint8_t** data, + uint8_t type, + uint8_t length, + ArrayItem::PayloadUnion* item); + +ArrayItem* ReadArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) { + ArrayItem* item = new ArrayItem(type); + ReadPayloadUnion(header, data, type, length, item->GetPayloadUnion()); + return item; +} + +ArrayItem* ReadArrayItem(Header& header, const uint8_t** data) { + const uint8_t encoded_value = *(*data)++; + const uint8_t type = encoded_value & 0x1f; + ArrayItem* item = new ArrayItem(type); + ReadPayloadUnion(header, data, type, encoded_value >> 5, item->GetPayloadUnion()); + return item; +} + +void ReadPayloadUnion(Header& header, + const uint8_t** data, + uint8_t type, + uint8_t length, + ArrayItem::PayloadUnion* item) { + switch (type) { + case DexFile::kDexAnnotationByte: + item->byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false)); + break; + case DexFile::kDexAnnotationShort: + item->short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true)); + break; + case DexFile::kDexAnnotationChar: + item->char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false)); + break; + case DexFile::kDexAnnotationInt: + item->int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true)); + break; + case DexFile::kDexAnnotationLong: + item->long_val_ = static_cast<int64_t>(ReadVarWidth(data, length, true)); + break; + case DexFile::kDexAnnotationFloat: { + // Fill on right. + union { + float f; + uint32_t data; + } conv; + conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8; + item->float_val_ = conv.f; + break; + } + case DexFile::kDexAnnotationDouble: { + // Fill on right. + union { + double d; + uint64_t data; + } conv; + conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8; + item->double_val_ = conv.d; + break; + } + case DexFile::kDexAnnotationString: { + const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->string_val_ = header.StringIds()[string_index].get(); + break; + } + case DexFile::kDexAnnotationType: { + const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->string_val_ = header.TypeIds()[string_index]->GetStringId(); + break; + } + case DexFile::kDexAnnotationField: + case DexFile::kDexAnnotationEnum: { + const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->field_val_ = header.FieldIds()[field_index].get(); + break; + } + case DexFile::kDexAnnotationMethod: { + const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->method_val_ = header.MethodIds()[method_index].get(); + break; + } + case DexFile::kDexAnnotationArray: { + item->annotation_array_val_ = new ArrayItemVector(); + // Decode all elements. + const uint32_t size = DecodeUnsignedLeb128(data); + for (uint32_t i = 0; i < size; i++) { + item->annotation_array_val_->push_back( + std::unique_ptr<ArrayItem>(ReadArrayItem(header, data))); + } + break; + } + case DexFile::kDexAnnotationAnnotation: { + const uint32_t type_idx = DecodeUnsignedLeb128(data); + item->annotation_annotation_val_.string_ = header.TypeIds()[type_idx]->GetStringId(); + item->annotation_annotation_val_.array_ = + new std::vector<std::unique_ptr<ArrayItem::NameValuePair>>(); + // Decode all name=value pairs. + const uint32_t size = DecodeUnsignedLeb128(data); + for (uint32_t i = 0; i < size; i++) { + const uint32_t name_index = DecodeUnsignedLeb128(data); + item->annotation_annotation_val_.array_->push_back( + std::unique_ptr<ArrayItem::NameValuePair>( + new ArrayItem::NameValuePair(header.StringIds()[name_index].get(), + ReadArrayItem(header, data)))); + } + break; + } + case DexFile::kDexAnnotationNull: + break; + case DexFile::kDexAnnotationBoolean: + item->bool_val_ = (length != 0); + break; + default: + break; + } +} + +static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) { + DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context); + PositionInfoVector& positions = debug_info->GetPositionInfo(); + positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_))); + return false; +} + +static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) { + DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context); + LocalInfoVector& locals = debug_info->GetLocalInfo(); + const char* name = entry.name_ != nullptr ? entry.name_ : "(null)"; + const char* signature = entry.signature_ != nullptr ? entry.signature_ : ""; + locals.push_back(std::unique_ptr<LocalInfo>( + new LocalInfo(name, entry.descriptor_, signature, entry.start_address_, + entry.end_address_, entry.reg_))); +} + +CodeItem* ReadCodeItem(const DexFile& dex_file, + const DexFile::CodeItem& disk_code_item, + Header& header) { + uint16_t registers_size = disk_code_item.registers_size_; + uint16_t ins_size = disk_code_item.ins_size_; + uint16_t outs_size = disk_code_item.outs_size_; + uint32_t tries_size = disk_code_item.tries_size_; + + const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item); + DebugInfoItem* debug_info = nullptr; + if (debug_info_stream != nullptr) { + debug_info = new DebugInfoItem(); + } + + uint32_t insns_size = disk_code_item.insns_size_in_code_units_; + uint16_t* insns = new uint16_t[insns_size]; + memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t)); + + TryItemVector* tries = nullptr; + if (tries_size > 0) { + tries = new TryItemVector(); + for (uint32_t i = 0; i < tries_size; ++i) { + const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i); + uint32_t start_addr = disk_try_item->start_addr_; + uint16_t insn_count = disk_try_item->insn_count_; + CatchHandlerVector* handlers = new CatchHandlerVector(); + for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) { + const uint16_t type_index = it.GetHandlerTypeIndex(); + const TypeId* type_id = header.GetTypeIdOrNullPtr(type_index); + handlers->push_back(std::unique_ptr<const CatchHandler>( + new CatchHandler(type_id, it.GetHandlerAddress()))); + } + TryItem* try_item = new TryItem(start_addr, insn_count, handlers); + tries->push_back(std::unique_ptr<const TryItem>(try_item)); + } + } + return new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries); +} + +MethodItem* GenerateMethodItem(const DexFile& dex_file, + dex_ir::Header& header, + ClassDataItemIterator& cdii) { + MethodId* method_item = header.MethodIds()[cdii.GetMemberIndex()].get(); + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); + CodeItem* code_item = nullptr; + DebugInfoItem* debug_info = nullptr; + if (disk_code_item != nullptr) { + code_item = ReadCodeItem(dex_file, *disk_code_item, header); + code_item->SetOffset(cdii.GetMethodCodeItemOffset()); + debug_info = code_item->DebugInfo(); + } + if (debug_info != nullptr) { + bool is_static = (access_flags & kAccStatic) != 0; + dex_file.DecodeDebugLocalInfo( + disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info); + dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info); + } + return new MethodItem(access_flags, method_item, code_item); +} + +AnnotationSetItem* ReadAnnotationSetItem(const DexFile& dex_file, + const DexFile::AnnotationSetItem& disk_annotations_item, + Header& header) { + if (disk_annotations_item.size_ == 0) { + return nullptr; + } + AnnotationItemVector* items = new AnnotationItemVector(); + for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) { + const DexFile::AnnotationItem* annotation = + dex_file.GetAnnotationItem(&disk_annotations_item, i); + if (annotation == nullptr) { + continue; + } + uint8_t visibility = annotation->visibility_; + const uint8_t* annotation_data = annotation->annotation_; + ArrayItem* array_item = + ReadArrayItem(header, &annotation_data, DexFile::kDexAnnotationAnnotation, 0); + items->push_back(std::unique_ptr<AnnotationItem>(new AnnotationItem(visibility, array_item))); + } + return new AnnotationSetItem(items); +} + +ParameterAnnotation* ReadParameterAnnotation( + const DexFile& dex_file, + MethodId* method_id, + const DexFile::AnnotationSetRefList* annotation_set_ref_list, + Header& header) { + AnnotationSetItemVector* annotations = new AnnotationSetItemVector(); + for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) { + const DexFile::AnnotationSetItem* annotation_set_item = + dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]); + annotations->push_back(std::unique_ptr<AnnotationSetItem>( + ReadAnnotationSetItem(dex_file, *annotation_set_item, header))); + } + return new ParameterAnnotation(method_id, annotations); +} + +AnnotationsDirectoryItem* ReadAnnotationsDirectoryItem( + const DexFile& dex_file, + const DexFile::AnnotationsDirectoryItem* disk_annotations_item, + Header& header) { + const DexFile::AnnotationSetItem* class_set_item = + dex_file.GetClassAnnotationSet(disk_annotations_item); + AnnotationSetItem* class_annotation = nullptr; + if (class_set_item != nullptr) { + class_annotation = ReadAnnotationSetItem(dex_file, *class_set_item, header); + } + const DexFile::FieldAnnotationsItem* fields = + dex_file.GetFieldAnnotations(disk_annotations_item); + FieldAnnotationVector* field_annotations = nullptr; + if (fields != nullptr) { + field_annotations = new FieldAnnotationVector(); + for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) { + FieldId* field_id = header.FieldIds()[fields[i].field_idx_].get(); + const DexFile::AnnotationSetItem* field_set_item = + dex_file.GetFieldAnnotationSetItem(fields[i]); + AnnotationSetItem* annotation_set_item = + ReadAnnotationSetItem(dex_file, *field_set_item, header); + field_annotations->push_back(std::unique_ptr<FieldAnnotation>( + new FieldAnnotation(field_id, annotation_set_item))); + } + } + const DexFile::MethodAnnotationsItem* methods = + dex_file.GetMethodAnnotations(disk_annotations_item); + MethodAnnotationVector* method_annotations = nullptr; + if (methods != nullptr) { + method_annotations = new MethodAnnotationVector(); + for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) { + MethodId* method_id = header.MethodIds()[methods[i].method_idx_].get(); + const DexFile::AnnotationSetItem* method_set_item = + dex_file.GetMethodAnnotationSetItem(methods[i]); + AnnotationSetItem* annotation_set_item = + ReadAnnotationSetItem(dex_file, *method_set_item, header); + method_annotations->push_back(std::unique_ptr<MethodAnnotation>( + new MethodAnnotation(method_id, annotation_set_item))); + } + } + const DexFile::ParameterAnnotationsItem* parameters = + dex_file.GetParameterAnnotations(disk_annotations_item); + ParameterAnnotationVector* parameter_annotations = nullptr; + if (parameters != nullptr) { + parameter_annotations = new ParameterAnnotationVector(); + for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) { + MethodId* method_id = header.MethodIds()[parameters[i].method_idx_].get(); + const DexFile::AnnotationSetRefList* list = + dex_file.GetParameterAnnotationSetRefList(¶meters[i]); + parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>( + ReadParameterAnnotation(dex_file, method_id, list, header))); + } + } + + return new AnnotationsDirectoryItem(class_annotation, + field_annotations, + method_annotations, + parameter_annotations); +} + +ClassDef* ReadClassDef(const DexFile& dex_file, + const DexFile::ClassDef& disk_class_def, + Header& header) { + const TypeId* class_type = header.TypeIds()[disk_class_def.class_idx_].get(); + uint32_t access_flags = disk_class_def.access_flags_; + const TypeId* superclass = header.GetTypeIdOrNullPtr(disk_class_def.superclass_idx_); + + TypeIdVector* interfaces = nullptr; + const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def); + uint32_t interfaces_offset = disk_class_def.interfaces_off_; + if (type_list != nullptr) { + interfaces = new TypeIdVector(); + for (uint32_t index = 0; index < type_list->Size(); ++index) { + interfaces->push_back(header.TypeIds()[type_list->GetTypeItem(index).type_idx_].get()); + } + } + const StringId* source_file = header.GetStringIdOrNullPtr(disk_class_def.source_file_idx_); + // Annotations. + AnnotationsDirectoryItem* annotations = nullptr; + const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item = + dex_file.GetAnnotationsDirectory(disk_class_def); + if (disk_annotations_directory_item != nullptr) { + annotations = ReadAnnotationsDirectoryItem(dex_file, disk_annotations_directory_item, header); + annotations->SetOffset(disk_class_def.annotations_off_); + } + // Static field initializers. + ArrayItemVector* static_values = nullptr; + const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def); + if (static_data != nullptr) { + uint32_t static_value_count = static_data == nullptr ? 0 : DecodeUnsignedLeb128(&static_data); + if (static_value_count > 0) { + static_values = new ArrayItemVector(); + for (uint32_t i = 0; i < static_value_count; ++i) { + static_values->push_back(std::unique_ptr<ArrayItem>(ReadArrayItem(header, &static_data))); + } + } + } + // Read the fields and methods defined by the class, resolving the circular reference from those + // to classes by setting class at the same time. + const uint8_t* encoded_data = dex_file.GetClassData(disk_class_def); + ClassData* class_data = nullptr; + if (encoded_data != nullptr) { + uint32_t offset = disk_class_def.class_data_off_; + ClassDataItemIterator cdii(dex_file, encoded_data); + // Static fields. + FieldItemVector* static_fields = new FieldItemVector(); + for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) { + FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get(); + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); + } + // Instance fields. + FieldItemVector* instance_fields = new FieldItemVector(); + for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) { + FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get(); + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + instance_fields->push_back( + std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item))); + } + // Direct methods. + MethodItemVector* direct_methods = new MethodItemVector(); + for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) { + direct_methods->push_back( + std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii))); + } + // Virtual methods. + MethodItemVector* virtual_methods = new MethodItemVector(); + for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) { + virtual_methods->push_back( + std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii))); + } + class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods); + class_data->SetOffset(offset); + } + return new ClassDef(class_type, + access_flags, + superclass, + interfaces, + interfaces_offset, + source_file, + annotations, + static_values, + class_data); +} + +} // namespace + +Header* DexIrBuilder(const DexFile& dex_file) { + const DexFile::Header& disk_header = dex_file.GetHeader(); + Header* header = new Header(disk_header.magic_, + disk_header.checksum_, + disk_header.signature_, + disk_header.endian_tag_, + disk_header.file_size_, + disk_header.header_size_, + disk_header.link_size_, + disk_header.link_off_, + disk_header.data_size_, + disk_header.data_off_); + // Walk the rest of the header fields. + // StringId table. + std::vector<std::unique_ptr<StringId>>& string_ids = header->StringIds(); + header->SetStringIdsOffset(disk_header.string_ids_off_); + for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) { + const DexFile::StringId& disk_string_id = dex_file.GetStringId(i); + StringId* string_id = new StringId(dex_file.GetStringData(disk_string_id)); + string_id->SetOffset(i); + string_ids.push_back(std::unique_ptr<StringId>(string_id)); + } + // TypeId table. + std::vector<std::unique_ptr<TypeId>>& type_ids = header->TypeIds(); + header->SetTypeIdsOffset(disk_header.type_ids_off_); + for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) { + const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i); + TypeId* type_id = new TypeId(header->StringIds()[disk_type_id.descriptor_idx_].get()); + type_id->SetOffset(i); + type_ids.push_back(std::unique_ptr<TypeId>(type_id)); + } + // ProtoId table. + std::vector<std::unique_ptr<ProtoId>>& proto_ids = header->ProtoIds(); + header->SetProtoIdsOffset(disk_header.proto_ids_off_); + for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) { + const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i); + // Build the parameter type vector. + TypeIdVector* parameters = new TypeIdVector(); + DexFileParameterIterator dfpi(dex_file, disk_proto_id); + while (dfpi.HasNext()) { + parameters->push_back(header->TypeIds()[dfpi.GetTypeIdx()].get()); + dfpi.Next(); + } + ProtoId* proto_id = new ProtoId(header->StringIds()[disk_proto_id.shorty_idx_].get(), + header->TypeIds()[disk_proto_id.return_type_idx_].get(), + parameters); + proto_id->SetOffset(i); + proto_ids.push_back(std::unique_ptr<ProtoId>(proto_id)); + } + // FieldId table. + std::vector<std::unique_ptr<FieldId>>& field_ids = header->FieldIds(); + header->SetFieldIdsOffset(disk_header.field_ids_off_); + for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) { + const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i); + FieldId* field_id = new FieldId(header->TypeIds()[disk_field_id.class_idx_].get(), + header->TypeIds()[disk_field_id.type_idx_].get(), + header->StringIds()[disk_field_id.name_idx_].get()); + field_id->SetOffset(i); + field_ids.push_back(std::unique_ptr<FieldId>(field_id)); + } + // MethodId table. + std::vector<std::unique_ptr<MethodId>>& method_ids = header->MethodIds(); + header->SetMethodIdsOffset(disk_header.method_ids_off_); + for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) { + const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i); + MethodId* method_id = new MethodId(header->TypeIds()[disk_method_id.class_idx_].get(), + header->ProtoIds()[disk_method_id.proto_idx_].get(), + header->StringIds()[disk_method_id.name_idx_].get()); + method_id->SetOffset(i); + method_ids.push_back(std::unique_ptr<MethodId>(method_id)); + } + // ClassDef table. + std::vector<std::unique_ptr<ClassDef>>& class_defs = header->ClassDefs(); + header->SetClassDefsOffset(disk_header.class_defs_off_); + for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) { + const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i); + ClassDef* class_def = ReadClassDef(dex_file, disk_class_def, *header); + class_def->SetOffset(i); + class_defs.push_back(std::unique_ptr<ClassDef>(class_def)); + } + + return header; +} + +} // namespace dex_ir +} // namespace art diff --git a/dexlayout/dex_ir_builder.h b/dexlayout/dex_ir_builder.h new file mode 100644 index 0000000000..c53157b5fc --- /dev/null +++ b/dexlayout/dex_ir_builder.h @@ -0,0 +1,32 @@ +/* + * 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_BUILDER_H_ +#define ART_DEXLAYOUT_DEX_IR_BUILDER_H_ + +#include "dex_ir.h" + +namespace art { +namespace dex_ir { + +dex_ir::Header* DexIrBuilder(const DexFile& dex_file); + +} // namespace dex_ir +} // namespace art + +#endif // ART_DEXLAYOUT_DEX_IR_BUILDER_H_ diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 0b3161426a..0d0b37a9c0 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -30,7 +30,7 @@ #include <sstream> #include <vector> -#include "dex_ir.h" +#include "dex_ir_builder.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "utils.h" @@ -501,20 +501,33 @@ static void DumpClassDef(dex_ir::Header* header, int idx) { } fprintf(out_file_, "annotations_off : %d (0x%06x)\n", annotations_offset, annotations_offset); - fprintf(out_file_, "class_data_off : %d (0x%06x)\n", - class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset()); + if (class_def->GetClassData() == nullptr) { + fprintf(out_file_, "class_data_off : %d (0x%06x)\n", 0, 0); + } else { + fprintf(out_file_, "class_data_off : %d (0x%06x)\n", + class_def->GetClassData()->GetOffset(), class_def->GetClassData()->GetOffset()); + } // Fields and methods. dex_ir::ClassData* class_data = class_def->GetClassData(); - if (class_data != nullptr) { - fprintf(out_file_, "static_fields_size : %zu\n", class_data->StaticFields().size()); - fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields().size()); - fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods().size()); - fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods().size()); + if (class_data != nullptr && class_data->StaticFields() != nullptr) { + fprintf(out_file_, "static_fields_size : %zu\n", class_data->StaticFields()->size()); } else { fprintf(out_file_, "static_fields_size : 0\n"); + } + if (class_data != nullptr && class_data->InstanceFields() != nullptr) { + fprintf(out_file_, "instance_fields_size: %zu\n", class_data->InstanceFields()->size()); + } else { fprintf(out_file_, "instance_fields_size: 0\n"); + } + if (class_data != nullptr && class_data->DirectMethods() != nullptr) { + fprintf(out_file_, "direct_methods_size : %zu\n", class_data->DirectMethods()->size()); + } else { fprintf(out_file_, "direct_methods_size : 0\n"); + } + if (class_data != nullptr && class_data->VirtualMethods() != nullptr) { + fprintf(out_file_, "virtual_methods_size: %zu\n", class_data->VirtualMethods()->size()); + } else { fprintf(out_file_, "virtual_methods_size: 0\n"); } fprintf(out_file_, "\n"); @@ -524,12 +537,11 @@ static void DumpClassDef(dex_ir::Header* header, int idx) { * Dumps an annotation set item. */ static void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item) { - if (set_item == nullptr || set_item->GetItems().size() == 0) { + if (set_item == nullptr || set_item->GetItems()->size() == 0) { fputs(" empty-annotation-set\n", out_file_); return; } - for (std::unique_ptr<dex_ir::AnnotationSetItem::AnnotationItem>& annotation : - set_item->GetItems()) { + for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : *set_item->GetItems()) { if (annotation == nullptr) { continue; } @@ -561,12 +573,9 @@ static void DumpClassAnnotations(dex_ir::Header* header, int idx) { fprintf(out_file_, "Class #%d annotations:\n", idx); dex_ir::AnnotationSetItem* class_set_item = annotations_directory->GetClassAnnotation(); - std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::FieldAnnotation>>& fields = - annotations_directory->GetFieldAnnotations(); - std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::MethodAnnotation>>& methods = - annotations_directory->GetMethodAnnotations(); - std::vector<std::unique_ptr<dex_ir::AnnotationsDirectoryItem::ParameterAnnotation>>& parameters = - annotations_directory->GetParameterAnnotations(); + dex_ir::FieldAnnotationVector* fields = annotations_directory->GetFieldAnnotations(); + dex_ir::MethodAnnotationVector* methods = annotations_directory->GetMethodAnnotations(); + dex_ir::ParameterAnnotationVector* parameters = annotations_directory->GetParameterAnnotations(); // Annotations on the class itself. if (class_set_item != nullptr) { @@ -575,34 +584,40 @@ static void DumpClassAnnotations(dex_ir::Header* header, int idx) { } // Annotations on fields. - for (auto& field : fields) { - const dex_ir::FieldId* field_id = field->GetFieldId(); - const uint32_t field_idx = field_id->GetOffset(); - const char* field_name = field_id->Name()->Data(); - fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name); - DumpAnnotationSetItem(field->GetAnnotationSetItem()); + if (fields != nullptr) { + for (auto& field : *fields) { + const dex_ir::FieldId* field_id = field->GetFieldId(); + const uint32_t field_idx = field_id->GetOffset(); + const char* field_name = field_id->Name()->Data(); + fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name); + DumpAnnotationSetItem(field->GetAnnotationSetItem()); + } } // Annotations on methods. - for (auto& method : methods) { - const dex_ir::MethodId* method_id = method->GetMethodId(); - const uint32_t method_idx = method_id->GetOffset(); - const char* method_name = method_id->Name()->Data(); - fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name); - DumpAnnotationSetItem(method->GetAnnotationSetItem()); + if (methods != nullptr) { + for (auto& method : *methods) { + const dex_ir::MethodId* method_id = method->GetMethodId(); + const uint32_t method_idx = method_id->GetOffset(); + const char* method_name = method_id->Name()->Data(); + fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name); + DumpAnnotationSetItem(method->GetAnnotationSetItem()); + } } // Annotations on method parameters. - for (auto& parameter : parameters) { - const dex_ir::MethodId* method_id = parameter->GetMethodId(); - const uint32_t method_idx = method_id->GetOffset(); - const char* method_name = method_id->Name()->Data(); - fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name); - uint32_t j = 0; - for (auto& annotation : parameter->GetAnnotations()) { - fprintf(out_file_, "#%u\n", j); - DumpAnnotationSetItem(annotation.get()); - ++j; + if (parameters != nullptr) { + for (auto& parameter : *parameters) { + const dex_ir::MethodId* method_id = parameter->GetMethodId(); + const uint32_t method_idx = method_id->GetOffset(); + const char* method_name = method_id->Name()->Data(); + fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name); + uint32_t j = 0; + for (auto& annotation : *parameter->GetAnnotations()) { + fprintf(out_file_, "#%u\n", j); + DumpAnnotationSetItem(annotation.get()); + ++j; + } } } @@ -612,7 +627,7 @@ static void DumpClassAnnotations(dex_ir::Header* header, int idx) { /* * Dumps an interface that a class declares to implement. */ -static void DumpInterface(dex_ir::TypeId* type_item, int i) { +static void DumpInterface(const dex_ir::TypeId* type_item, int i) { const char* interface_name = type_item->GetStringId()->Data(); if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " #%d : '%s'\n", i, interface_name); @@ -1260,8 +1275,8 @@ static void DumpCFG(const DexFile* dex_file, int idx) { } while (it.HasNextVirtualMethod()) { DumpCFG(dex_file, - it.GetMemberIndex(), - it.GetMethodCodeItem()); + it.GetMemberIndex(), + it.GetMethodCodeItem()); it.Next(); } } @@ -1274,7 +1289,10 @@ static void DumpCFG(const DexFile* dex_file, int idx) { * If "*last_package" is nullptr or does not match the current class' package, * the value will be replaced with a newly-allocated string. */ -static void DumpClass(dex_ir::Header* header, int idx, char** last_package) { +static void DumpClass(const DexFile* dex_file, + dex_ir::Header* header, + int idx, + char** last_package) { dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get(); // Omitting non-public class. if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) { @@ -1290,7 +1308,7 @@ static void DumpClass(dex_ir::Header* header, int idx, char** last_package) { } if (options_.show_cfg_) { - DumpCFG(&header->GetDexFile(), idx); + DumpCFG(dex_file, idx); return; } @@ -1368,10 +1386,12 @@ static void DumpClass(dex_ir::Header* header, int idx, char** last_package) { } // Interfaces. - std::vector<dex_ir::TypeId*>* interfaces = class_def->Interfaces(); - for (uint32_t i = 0; i < interfaces->size(); i++) { - DumpInterface((*interfaces)[i], i); - } // for + dex_ir::TypeIdVector* interfaces = class_def->Interfaces(); + if (interfaces != nullptr) { + for (uint32_t i = 0; i < interfaces->size(); i++) { + DumpInterface((*interfaces)[i], i); + } // for + } // Fields and methods. dex_ir::ClassData* class_data = class_def->GetClassData(); @@ -1383,52 +1403,68 @@ static void DumpClass(dex_ir::Header* header, int idx, char** last_package) { if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " Static fields -\n"); } - std::vector<std::unique_ptr<dex_ir::FieldItem>>& static_fields = class_data->StaticFields(); - for (uint32_t i = 0; i < static_fields.size(); i++) { - DumpSField(header, - static_fields[i]->GetFieldId()->GetOffset(), - static_fields[i]->GetAccessFlags(), - i, - i < static_values_size ? (*static_values)[i].get() : nullptr); - } // for + if (class_data != nullptr) { + dex_ir::FieldItemVector* static_fields = class_data->StaticFields(); + if (static_fields != nullptr) { + for (uint32_t i = 0; i < static_fields->size(); i++) { + DumpSField(header, + (*static_fields)[i]->GetFieldId()->GetOffset(), + (*static_fields)[i]->GetAccessFlags(), + i, + i < static_values_size ? (*static_values)[i].get() : nullptr); + } // for + } + } // Instance fields. if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " Instance fields -\n"); } - std::vector<std::unique_ptr<dex_ir::FieldItem>>& instance_fields = class_data->InstanceFields(); - for (uint32_t i = 0; i < instance_fields.size(); i++) { - DumpIField(header, - instance_fields[i]->GetFieldId()->GetOffset(), - instance_fields[i]->GetAccessFlags(), - i); - } // for + if (class_data != nullptr) { + dex_ir::FieldItemVector* instance_fields = class_data->InstanceFields(); + if (instance_fields != nullptr) { + for (uint32_t i = 0; i < instance_fields->size(); i++) { + DumpIField(header, + (*instance_fields)[i]->GetFieldId()->GetOffset(), + (*instance_fields)[i]->GetAccessFlags(), + i); + } // for + } + } // Direct methods. if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " Direct methods -\n"); } - std::vector<std::unique_ptr<dex_ir::MethodItem>>& direct_methods = class_data->DirectMethods(); - for (uint32_t i = 0; i < direct_methods.size(); i++) { - DumpMethod(header, - direct_methods[i]->GetMethodId()->GetOffset(), - direct_methods[i]->GetAccessFlags(), - direct_methods[i]->GetCodeItem(), - i); - } // for + if (class_data != nullptr) { + dex_ir::MethodItemVector* direct_methods = class_data->DirectMethods(); + if (direct_methods != nullptr) { + for (uint32_t i = 0; i < direct_methods->size(); i++) { + DumpMethod(header, + (*direct_methods)[i]->GetMethodId()->GetOffset(), + (*direct_methods)[i]->GetAccessFlags(), + (*direct_methods)[i]->GetCodeItem(), + i); + } // for + } + } // Virtual methods. if (options_.output_format_ == kOutputPlain) { fprintf(out_file_, " Virtual methods -\n"); } - std::vector<std::unique_ptr<dex_ir::MethodItem>>& virtual_methods = class_data->VirtualMethods(); - for (uint32_t i = 0; i < virtual_methods.size(); i++) { - DumpMethod(header, - virtual_methods[i]->GetMethodId()->GetOffset(), - virtual_methods[i]->GetAccessFlags(), - virtual_methods[i]->GetCodeItem(), - i); - } // for + if (class_data != nullptr) { + dex_ir::MethodItemVector* virtual_methods = class_data->VirtualMethods(); + if (virtual_methods != nullptr) { + for (uint32_t i = 0; i < virtual_methods->size(); i++) { + DumpMethod(header, + (*virtual_methods)[i]->GetMethodId()->GetOffset(), + (*virtual_methods)[i]->GetAccessFlags(), + (*virtual_methods)[i]->GetCodeItem(), + i); + } // for + } + } // End of class. if (options_.output_format_ == kOutputPlain) { @@ -1454,11 +1490,11 @@ static void ProcessDexFile(const char* file_name, const DexFile* dex_file) { fprintf(out_file_, "Opened '%s', DEX version '%.3s'\n", file_name, dex_file->GetHeader().magic_ + 4); } - dex_ir::Header header(*dex_file); + dex_ir::Header* header = dex_ir::DexIrBuilder(*dex_file); // Headers. if (options_.show_file_headers_) { - DumpFileHeader(&header); + DumpFileHeader(header); } // Open XML context. @@ -1468,9 +1504,9 @@ static void ProcessDexFile(const char* file_name, const DexFile* dex_file) { // Iterate over all classes. char* package = nullptr; - const uint32_t class_defs_size = header.ClassDefsSize(); + const uint32_t class_defs_size = header->ClassDefsSize(); for (uint32_t i = 0; i < class_defs_size; i++) { - DumpClass(&header, i, &package); + DumpClass(dex_file, header, i, &package); } // for // Free the last package allocated. |