Dexlayout changes to support offset/size output of items.
- Created offset & size fields for items, initially populated with
values from original dex file.
- Created index field for indexed items in header.
- Created Item objects for StringData and TypeList.
- Created Collections container to hold unique_ptrs for all objects
- Reorganized EncodedArrayItems to make it easier to collect them
- Added relevant annotations-related items to Collections
- Some size calculations and section offsets left as TODO
Bug: 29921113
Test: mm test-art-host-gtest-dexlayout_test
Change-Id: Id812f104c1930a3ee381e885f353a9a49f29ac9b
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 163cb01..c411572 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -18,6 +18,7 @@
srcs: [
"dexlayout_main.cc",
"dexlayout.cc",
+ "dex_ir.cc",
"dex_ir_builder.cc",
],
cflags: ["-Wall"],
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
new file mode 100644
index 0000000..aff03cd
--- /dev/null
+++ b/dexlayout/dex_ir.cc
@@ -0,0 +1,487 @@
+/*
+ * 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 dexlayout utility.
+ *
+ * This is a tool to read dex files into an internal representation,
+ * reorganize the representation, and emit dex files with a better
+ * file layout.
+ */
+
+#include "dex_ir.h"
+#include "dex_ir_builder.h"
+
+namespace art {
+namespace dex_ir {
+
+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);
+ 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_)));
+}
+
+EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
+ const uint8_t encoded_value = *(*data)++;
+ const uint8_t type = encoded_value & 0x1f;
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(data, type, encoded_value >> 5, item);
+ return item;
+}
+
+EncodedValue* Collections::ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length) {
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(data, type, length, item);
+ return item;
+}
+
+void Collections::ReadEncodedValue(
+ const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item) {
+ switch (type) {
+ case DexFile::kDexAnnotationByte:
+ item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationShort:
+ item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationChar:
+ item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationInt:
+ item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationLong:
+ item->SetLong(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->SetFloat(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->SetDouble(conv.d);
+ break;
+ }
+ case DexFile::kDexAnnotationString: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetStringId(GetStringId(string_index));
+ break;
+ }
+ case DexFile::kDexAnnotationType: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetTypeId(GetTypeId(string_index));
+ break;
+ }
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum: {
+ const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetFieldId(GetFieldId(field_index));
+ break;
+ }
+ case DexFile::kDexAnnotationMethod: {
+ const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetMethodId(GetMethodId(method_index));
+ break;
+ }
+ case DexFile::kDexAnnotationArray: {
+ EncodedValueVector* values = new EncodedValueVector();
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all elements.
+ for (uint32_t i = 0; i < size; i++) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(data)));
+ }
+ item->SetEncodedArray(new EncodedArrayItem(values));
+ break;
+ }
+ case DexFile::kDexAnnotationAnnotation: {
+ AnnotationElementVector* elements = new AnnotationElementVector();
+ const uint32_t type_idx = DecodeUnsignedLeb128(data);
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all name=value pairs.
+ for (uint32_t i = 0; i < size; i++) {
+ const uint32_t name_index = DecodeUnsignedLeb128(data);
+ elements->push_back(std::unique_ptr<AnnotationElement>(
+ new AnnotationElement(GetStringId(name_index), ReadEncodedValue(data))));
+ }
+ item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
+ break;
+ }
+ case DexFile::kDexAnnotationNull:
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ item->SetBoolean(length != 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
+ StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
+ string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
+
+ StringId* string_id = new StringId(string_data);
+ string_ids_.AddIndexedItem(string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
+}
+
+void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i);
+ TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_));
+ type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
+}
+
+void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
+ const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
+ TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_, true);
+
+ ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_),
+ GetTypeId(disk_proto_id.return_type_idx_),
+ parameter_type_list);
+ proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
+}
+
+void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
+ FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_),
+ GetTypeId(disk_field_id.type_idx_),
+ GetStringId(disk_field_id.name_idx_));
+ field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
+}
+
+void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
+ MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_),
+ GetProtoId(disk_method_id.proto_idx_),
+ GetStringId(disk_method_id.name_idx_));
+ method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
+}
+
+void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
+ const TypeId* class_type = GetTypeId(disk_class_def.class_idx_);
+ uint32_t access_flags = disk_class_def.access_flags_;
+ const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
+
+ const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
+ TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_, false);
+
+ const StringId* source_file = 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 = CreateAnnotationsDirectoryItem(
+ dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
+ }
+ // Static field initializers.
+ const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
+ EncodedArrayItem* static_values =
+ CreateEncodedArrayItem(static_data, disk_class_def.static_values_off_);
+ ClassData* class_data = CreateClassData(
+ dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
+ ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
+ source_file, annotations, static_values, class_data);
+ class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
+}
+
+TypeList* Collections::CreateTypeList(
+ const DexFile::TypeList* dex_type_list, uint32_t offset, bool allow_empty) {
+ if (dex_type_list == nullptr && !allow_empty) {
+ return nullptr;
+ }
+ // TODO: Create more efficient lookup for existing type lists.
+ for (std::unique_ptr<TypeList>& type_list : TypeLists()) {
+ if (type_list->GetOffset() == offset) {
+ return type_list.get();
+ }
+ }
+ TypeIdVector* type_vector = new TypeIdVector();
+ uint32_t size = dex_type_list == nullptr ? 0 : dex_type_list->Size();
+ for (uint32_t index = 0; index < size; ++index) {
+ type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_));
+ }
+ TypeList* new_type_list = new TypeList(type_vector);
+ type_lists_.AddItem(new_type_list, offset);
+ return new_type_list;
+}
+
+EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset) {
+ if (static_data == nullptr) {
+ return nullptr;
+ }
+ uint32_t size = DecodeUnsignedLeb128(&static_data);
+ EncodedValueVector* values = new EncodedValueVector();
+ for (uint32_t i = 0; i < size; ++i) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(&static_data)));
+ }
+ // TODO: Calculate the size of the encoded array.
+ EncodedArrayItem* encoded_array_item = new EncodedArrayItem(values);
+ encoded_array_items_.AddItem(encoded_array_item, offset);
+ return encoded_array_item;
+}
+
+AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
+ uint32_t offset) {
+ uint8_t visibility = annotation->visibility_;
+ const uint8_t* annotation_data = annotation->annotation_;
+ EncodedValue* encoded_value =
+ ReadEncodedValue(&annotation_data, DexFile::kDexAnnotationAnnotation, 0);
+ // TODO: Calculate the size of the annotation.
+ AnnotationItem* annotation_item =
+ new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
+ annotation_items_.AddItem(annotation_item, offset);
+ return annotation_item;
+}
+
+
+AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset) {
+ if (disk_annotations_item.size_ == 0) {
+ return nullptr;
+ }
+ std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
+ 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;
+ }
+ AnnotationItem* annotation_item =
+ CreateAnnotationItem(annotation, disk_annotations_item.entries_[i]);
+ items->push_back(annotation_item);
+ }
+ AnnotationSetItem* annotation_set_item = new AnnotationSetItem(items);
+ annotation_set_items_.AddItem(annotation_set_item, offset);
+ return annotation_set_item;
+}
+
+AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
+ const DexFile::AnnotationSetItem* class_set_item =
+ dex_file.GetClassAnnotationSet(disk_annotations_item);
+ AnnotationSetItem* class_annotation = nullptr;
+ if (class_set_item != nullptr) {
+ uint32_t offset = disk_annotations_item->class_annotations_off_;
+ class_annotation = CreateAnnotationSetItem(dex_file, *class_set_item, offset);
+ }
+ 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 = GetFieldId(fields[i].field_idx_);
+ const DexFile::AnnotationSetItem* field_set_item =
+ dex_file.GetFieldAnnotationSetItem(fields[i]);
+ uint32_t annotation_set_offset = fields[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, *field_set_item, annotation_set_offset);
+ 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 = GetMethodId(methods[i].method_idx_);
+ const DexFile::AnnotationSetItem* method_set_item =
+ dex_file.GetMethodAnnotationSetItem(methods[i]);
+ uint32_t annotation_set_offset = methods[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, *method_set_item, annotation_set_offset);
+ 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 = GetMethodId(parameters[i].method_idx_);
+ const DexFile::AnnotationSetRefList* list =
+ dex_file.GetParameterAnnotationSetRefList(¶meters[i]);
+ parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
+ GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
+ }
+ }
+ // TODO: Calculate the size of the annotations directory.
+ AnnotationsDirectoryItem* annotations_directory_item = new AnnotationsDirectoryItem(
+ class_annotation, field_annotations, method_annotations, parameter_annotations);
+ annotations_directory_items_.AddItem(annotations_directory_item, offset);
+ return annotations_directory_item;
+}
+
+ParameterAnnotation* Collections::GenerateParameterAnnotation(
+ const DexFile& dex_file, MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
+ std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
+ 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]);
+ uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
+ annotations->push_back(CreateAnnotationSetItem(dex_file, *annotation_set_item, set_offset));
+ }
+ AnnotationSetRefList* new_ref_list = new AnnotationSetRefList(annotations);
+ annotation_set_ref_lists_.AddItem(new_ref_list, offset);
+ return new ParameterAnnotation(method_id, new_ref_list);
+}
+
+CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
+ const DexFile::CodeItem& disk_code_item, uint32_t offset) {
+ 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_;
+
+ // TODO: Calculate the size of the debug info.
+ 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();
+ debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
+ }
+
+ 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 = 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));
+ }
+ }
+ // TODO: Calculate the size of the code item.
+ CodeItem* code_item =
+ new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
+ code_items_.AddItem(code_item, offset);
+ return code_item;
+}
+
+MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
+ MethodId* method_item = GetMethodId(cdii.GetMemberIndex());
+ 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 = CreateCodeItem(dex_file, *disk_code_item, 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);
+}
+
+ClassData* Collections::CreateClassData(
+ const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
+ // Read the fields and methods defined by the class, resolving the circular reference from those
+ // to classes by setting class at the same time.
+ ClassData* class_data = nullptr;
+ if (encoded_data != nullptr) {
+ 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 = GetFieldId(cdii.GetMemberIndex());
+ 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 = GetFieldId(cdii.GetMemberIndex());
+ 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, 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, cdii)));
+ }
+ // TODO: Calculate the size of the class data.
+ class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
+ class_datas_.AddItem(class_data, offset);
+ }
+ return class_data;
+}
+
+} // namespace dex_ir
+} // namespace art
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index cbb4404..6ae9f1c 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -23,18 +23,23 @@
#include <stdint.h>
#include "dex_file-inl.h"
+#include "leb128.h"
namespace art {
namespace dex_ir {
// Forward declarations for classes used in containers or pointed to.
+class AnnotationItem;
class AnnotationsDirectoryItem;
class AnnotationSetItem;
-class ArrayItem;
+class AnnotationSetRefList;
class ClassData;
class ClassDef;
class CodeItem;
class DebugInfoItem;
+class EncodedAnnotation;
+class EncodedArrayItem;
+class EncodedValue;
class FieldId;
class FieldItem;
class Header;
@@ -42,10 +47,22 @@
class MapItem;
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;
// Visitor support
class AbstractDispatcher {
@@ -54,6 +71,7 @@
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;
@@ -63,11 +81,13 @@
virtual void Dispatch(ClassDef* class_def) = 0;
virtual void Dispatch(FieldItem* field_item) = 0;
virtual void Dispatch(MethodItem* method_item) = 0;
- virtual void Dispatch(ArrayItem* array_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(MapList* map_list) = 0;
virtual void Dispatch(MapItem* map_item) = 0;
@@ -82,9 +102,14 @@
CollectionWithOffset() = default;
std::vector<std::unique_ptr<T>>& Collection() { return collection_; }
// Read-time support methods
- void AddWithPosition(uint32_t position, T* object) {
+ void AddItem(T* object, uint32_t offset) {
+ object->SetOffset(offset);
collection_.push_back(std::unique_ptr<T>(object));
- collection_.back()->SetOffset(position);
+ }
+ void AddIndexedItem(T* object, uint32_t offset, uint32_t index) {
+ object->SetOffset(offset);
+ object->SetIndex(index);
+ collection_.push_back(std::unique_ptr<T>(object));
}
// Ordinary object insertion into collection.
void Insert(T object ATTRIBUTE_UNUSED) {
@@ -98,18 +123,160 @@
private:
std::vector<std::unique_ptr<T>> collection_;
uint32_t offset_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(CollectionWithOffset);
};
+class Collections {
+ public:
+ Collections() = default;
+
+ std::vector<std::unique_ptr<StringId>>& StringIds() { return string_ids_.Collection(); }
+ std::vector<std::unique_ptr<TypeId>>& TypeIds() { return type_ids_.Collection(); }
+ std::vector<std::unique_ptr<ProtoId>>& ProtoIds() { return proto_ids_.Collection(); }
+ std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); }
+ std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); }
+ std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); }
+
+ std::vector<std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); }
+ std::vector<std::unique_ptr<EncodedArrayItem>>& EncodedArrayItems()
+ { return encoded_array_items_.Collection(); }
+
+ void CreateStringId(const DexFile& dex_file, uint32_t i);
+ void CreateTypeId(const DexFile& dex_file, uint32_t i);
+ void CreateProtoId(const DexFile& dex_file, uint32_t i);
+ void CreateFieldId(const DexFile& dex_file, uint32_t i);
+ void CreateMethodId(const DexFile& dex_file, uint32_t i);
+ void CreateClassDef(const DexFile& dex_file, uint32_t i);
+
+ TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset, bool allow_empty);
+ EncodedArrayItem* CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset);
+ AnnotationItem* CreateAnnotationItem(const DexFile::AnnotationItem* annotation, uint32_t offset);
+ AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset);
+ AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
+ CodeItem* CreateCodeItem(
+ const DexFile& dex_file, const DexFile::CodeItem& disk_code_item, uint32_t offset);
+ ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset);
+
+ StringId* GetStringId(uint32_t index) { return StringIds()[index].get(); }
+ TypeId* GetTypeId(uint32_t index) { return TypeIds()[index].get(); }
+ ProtoId* GetProtoId(uint32_t index) { return ProtoIds()[index].get(); }
+ FieldId* GetFieldId(uint32_t index) { return FieldIds()[index].get(); }
+ MethodId* GetMethodId(uint32_t index) { return MethodIds()[index].get(); }
+ ClassDef* GetClassDef(uint32_t index) { return ClassDefs()[index].get(); }
+
+ StringId* GetStringIdOrNullPtr(uint32_t index) {
+ return index == DexFile::kDexNoIndex ? nullptr : GetStringId(index);
+ }
+ TypeId* GetTypeIdOrNullPtr(uint16_t index) {
+ return index == DexFile::kDexNoIndex16 ? nullptr : GetTypeId(index);
+ }
+
+ uint32_t StringIdsOffset() const { return string_ids_.GetOffset(); }
+ uint32_t TypeIdsOffset() const { return type_ids_.GetOffset(); }
+ uint32_t ProtoIdsOffset() const { return proto_ids_.GetOffset(); }
+ uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
+ uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
+ uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
+ uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); }
+ uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); }
+ uint32_t EncodedArrayOffset() const { return encoded_array_items_.GetOffset(); }
+ uint32_t AnnotationOffset() const { return annotation_items_.GetOffset(); }
+ uint32_t AnnotationSetOffset() const { return annotation_set_items_.GetOffset(); }
+ uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); }
+ uint32_t AnnotationsDirectoryOffset() const { return annotations_directory_items_.GetOffset(); }
+ uint32_t DebugInfoOffset() const { return debug_info_items_.GetOffset(); }
+ uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); }
+ uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); }
+
+ void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
+ void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
+ void SetProtoIdsOffset(uint32_t new_offset) { proto_ids_.SetOffset(new_offset); }
+ void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
+ void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
+ void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
+ void SetStringDatasOffset(uint32_t new_offset) { string_datas_.SetOffset(new_offset); }
+ void SetTypeListsOffset(uint32_t new_offset) { type_lists_.SetOffset(new_offset); }
+ void SetEncodedArrayOffset(uint32_t new_offset) { encoded_array_items_.SetOffset(new_offset); }
+ void SetAnnotationOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); }
+ void SetAnnotationSetOffset(uint32_t new_offset) { annotation_set_items_.SetOffset(new_offset); }
+ void SetAnnotationSetRefListsOffset(uint32_t new_offset)
+ { annotation_set_ref_lists_.SetOffset(new_offset); }
+ void SetAnnotationsDirectoryOffset(uint32_t new_offset)
+ { annotations_directory_items_.SetOffset(new_offset); }
+ void SetDebugInfoOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); }
+ void SetCodeItemsOffset(uint32_t new_offset) { code_items_.SetOffset(new_offset); }
+ void SetClassDatasOffset(uint32_t new_offset) { class_datas_.SetOffset(new_offset); }
+
+ uint32_t StringIdsSize() const { return string_ids_.Size(); }
+ uint32_t TypeIdsSize() const { return type_ids_.Size(); }
+ uint32_t ProtoIdsSize() const { return proto_ids_.Size(); }
+ uint32_t FieldIdsSize() const { return field_ids_.Size(); }
+ uint32_t MethodIdsSize() const { return method_ids_.Size(); }
+ uint32_t ClassDefsSize() const { return class_defs_.Size(); }
+
+ private:
+ EncodedValue* ReadEncodedValue(const uint8_t** data);
+ EncodedValue* ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length);
+ void ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item);
+
+ ParameterAnnotation* GenerateParameterAnnotation(const DexFile& dex_file, MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset);
+ MethodItem* GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+
+ CollectionWithOffset<StringId> string_ids_;
+ CollectionWithOffset<TypeId> type_ids_;
+ CollectionWithOffset<ProtoId> proto_ids_;
+ CollectionWithOffset<FieldId> field_ids_;
+ CollectionWithOffset<MethodId> method_ids_;
+ CollectionWithOffset<ClassDef> class_defs_;
+
+ CollectionWithOffset<StringData> string_datas_;
+ CollectionWithOffset<TypeList> type_lists_;
+ CollectionWithOffset<EncodedArrayItem> encoded_array_items_;
+ CollectionWithOffset<AnnotationItem> annotation_items_;
+ CollectionWithOffset<AnnotationSetItem> annotation_set_items_;
+ CollectionWithOffset<AnnotationSetRefList> annotation_set_ref_lists_;
+ CollectionWithOffset<AnnotationsDirectoryItem> annotations_directory_items_;
+ CollectionWithOffset<DebugInfoItem> debug_info_items_;
+ CollectionWithOffset<CodeItem> code_items_;
+ CollectionWithOffset<ClassData> class_datas_;
+
+ DISALLOW_COPY_AND_ASSIGN(Collections);
+};
+
class Item {
public:
+ Item() { }
virtual ~Item() { }
uint32_t GetOffset() const { return offset_; }
+ uint32_t GetSize() const { return size_; }
void SetOffset(uint32_t offset) { offset_ = offset; }
+ void SetSize(uint32_t size) { size_ = size; }
protected:
+ Item(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { }
+
uint32_t offset_ = 0;
+ 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 {
@@ -124,7 +291,8 @@
uint32_t link_offset,
uint32_t data_size,
uint32_t data_offset)
- : checksum_(checksum),
+ : Item(0, kHeaderItemSize),
+ checksum_(checksum),
endian_tag_(endian_tag),
file_size_(file_size),
header_size_(header_size),
@@ -137,6 +305,8 @@
}
~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_; }
@@ -159,39 +329,7 @@
void SetDataSize(uint32_t new_data_size) { data_size_ = new_data_size; }
void SetDataOffset(uint32_t new_data_offset) { data_offset_ = new_data_offset; }
- // Collections.
- std::vector<std::unique_ptr<StringId>>& StringIds() { return string_ids_.Collection(); }
- std::vector<std::unique_ptr<TypeId>>& TypeIds() { return type_ids_.Collection(); }
- std::vector<std::unique_ptr<ProtoId>>& ProtoIds() { return proto_ids_.Collection(); }
- std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); }
- std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); }
- std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); }
- uint32_t StringIdsOffset() const { return string_ids_.GetOffset(); }
- uint32_t TypeIdsOffset() const { return type_ids_.GetOffset(); }
- uint32_t ProtoIdsOffset() const { return proto_ids_.GetOffset(); }
- uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
- uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
- uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
- void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
- void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
- void SetProtoIdsOffset(uint32_t new_offset) { proto_ids_.SetOffset(new_offset); }
- void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
- void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
- void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
- uint32_t StringIdsSize() const { return string_ids_.Size(); }
- uint32_t TypeIdsSize() const { return type_ids_.Size(); }
- uint32_t ProtoIdsSize() const { return proto_ids_.Size(); }
- uint32_t FieldIdsSize() const { return field_ids_.Size(); }
- uint32_t MethodIdsSize() const { return method_ids_.Size(); }
- uint32_t ClassDefsSize() const { return class_defs_.Size(); }
-
- TypeId* GetTypeIdOrNullPtr(uint16_t index) {
- return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index].get();
- }
-
- StringId* GetStringIdOrNullPtr(uint32_t index) {
- return index == DexFile::kDexNoIndex ? nullptr : StringIds()[index].get();
- }
+ Collections& GetCollections() { return collections_; }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
@@ -207,19 +345,16 @@
uint32_t data_size_;
uint32_t data_offset_;
- CollectionWithOffset<StringId> string_ids_;
- CollectionWithOffset<TypeId> type_ids_;
- CollectionWithOffset<ProtoId> proto_ids_;
- CollectionWithOffset<FieldId> field_ids_;
- CollectionWithOffset<MethodId> method_ids_;
- CollectionWithOffset<ClassDef> class_defs_;
+ Collections collections_;
+
DISALLOW_COPY_AND_ASSIGN(Header);
};
-class StringId : public Item {
+class StringData : public Item {
public:
- explicit StringId(const char* data) : data_(strdup(data)) { }
- ~StringId() OVERRIDE { }
+ explicit StringData(const char* data) : data_(strdup(data)) {
+ size_ = UnsignedLeb128Size(strlen(data)) + strlen(data);
+ }
const char* Data() const { return data_.get(); }
@@ -227,50 +362,95 @@
private:
std::unique_ptr<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 Item {
+class TypeId : public IndexedItem {
public:
- explicit TypeId(StringId* string_id) : string_id_(string_id) { }
+ 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 ProtoId : public Item {
+class TypeList : public Item {
public:
- ProtoId(const StringId* shorty, const TypeId* return_type, TypeIdVector* parameters)
- : shorty_(shorty), return_type_(return_type), parameters_(parameters) { }
+ 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 std::vector<const TypeId*>& Parameters() const { return *parameters_; }
+ const TypeIdVector& Parameters() const { return *parameters_->GetTypeList(); }
void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
private:
const StringId* shorty_;
const TypeId* return_type_;
- std::unique_ptr<TypeIdVector> parameters_;
+ TypeList* parameters_;
+
DISALLOW_COPY_AND_ASSIGN(ProtoId);
};
-class FieldId : public Item {
+class FieldId : public IndexedItem {
public:
FieldId(const TypeId* klass, const TypeId* type, const StringId* name)
- : class_(klass), type_(type), name_(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_; }
@@ -281,15 +461,18 @@
const TypeId* class_;
const TypeId* type_;
const StringId* name_;
+
DISALLOW_COPY_AND_ASSIGN(FieldId);
};
-class MethodId : public Item {
+class MethodId : public IndexedItem {
public:
MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name)
- : class_(klass), proto_(proto), name_(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_; }
@@ -300,6 +483,7 @@
const TypeId* class_;
const ProtoId* proto_;
const StringId* name_;
+
DISALLOW_COPY_AND_ASSIGN(MethodId);
};
@@ -317,6 +501,7 @@
private:
uint32_t access_flags_;
const FieldId* field_id_;
+
DISALLOW_COPY_AND_ASSIGN(FieldItem);
};
@@ -330,93 +515,126 @@
uint32_t GetAccessFlags() const { return access_flags_; }
const MethodId* GetMethodId() const { return method_id_; }
- const CodeItem* GetCodeItem() const { return code_.get(); }
+ const CodeItem* GetCodeItem() const { return code_; }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
uint32_t access_flags_;
const MethodId* method_id_;
- std::unique_ptr<const CodeItem> code_;
+ const CodeItem* code_;
+
DISALLOW_COPY_AND_ASSIGN(MethodItem);
};
using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>;
-class ArrayItem : public Item {
+class EncodedValue {
public:
- class NameValuePair {
- public:
- NameValuePair(StringId* name, ArrayItem* value)
- : name_(name), value_(value) { }
-
- StringId* Name() const { return name_; }
- ArrayItem* Value() const { return value_.get(); }
-
- private:
- StringId* name_;
- std::unique_ptr<ArrayItem> value_;
- DISALLOW_COPY_AND_ASSIGN(NameValuePair);
- };
-
- struct ArrayItemVariant {
- public:
- 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_;
- } u_;
- std::unique_ptr<std::vector<std::unique_ptr<ArrayItem>>> annotation_array_val_;
- struct {
- StringId* string_;
- std::unique_ptr<std::vector<std::unique_ptr<NameValuePair>>> array_;
- } annotation_annotation_val_;
- };
-
- explicit ArrayItem(uint8_t type) : type_(type) { }
- ~ArrayItem() OVERRIDE { }
+ explicit EncodedValue(uint8_t type) : type_(type) { }
int8_t Type() const { return type_; }
- bool GetBoolean() const { return item_.u_.bool_val_; }
- int8_t GetByte() const { return item_.u_.byte_val_; }
- int16_t GetShort() const { return item_.u_.short_val_; }
- uint16_t GetChar() const { return item_.u_.char_val_; }
- int32_t GetInt() const { return item_.u_.int_val_; }
- int64_t GetLong() const { return item_.u_.long_val_; }
- float GetFloat() const { return item_.u_.float_val_; }
- double GetDouble() const { return item_.u_.double_val_; }
- StringId* GetStringId() const { return item_.u_.string_val_; }
- FieldId* GetFieldId() const { return item_.u_.field_val_; }
- MethodId* GetMethodId() const { return item_.u_.method_val_; }
- std::vector<std::unique_ptr<ArrayItem>>* GetAnnotationArray() const {
- return item_.annotation_array_val_.get();
- }
- StringId* GetAnnotationAnnotationString() const {
- return item_.annotation_annotation_val_.string_;
- }
- std::vector<std::unique_ptr<NameValuePair>>* GetAnnotationAnnotationNameValuePairArray() const {
- return item_.annotation_annotation_val_.array_.get();
- }
- // Used to construct the item union. Ugly, but necessary.
- ArrayItemVariant* GetArrayItemVariant() { return &item_; }
- void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
+ 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 SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; }
+ void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; }
+ 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_; }
+ FieldId* GetFieldId() const { return u_.field_val_; }
+ MethodId* GetMethodId() const { return u_.method_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_;
- ArrayItemVariant item_;
- DISALLOW_COPY_AND_ASSIGN(ArrayItem);
+ 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_;
+ FieldId* field_val_;
+ MethodId* method_val_;
+ } u_;
+ std::unique_ptr<EncodedArrayItem> encoded_array_;
+ std::unique_ptr<EncodedAnnotation> encoded_annotation_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncodedValue);
};
-using ArrayItemVector = std::vector<std::unique_ptr<ArrayItem>>;
+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:
@@ -442,42 +660,43 @@
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 {
+class ClassDef : public IndexedItem {
public:
ClassDef(const TypeId* class_type,
uint32_t access_flags,
const TypeId* superclass,
- TypeIdVector* interfaces,
- uint32_t interfaces_offset,
+ TypeList* interfaces,
const StringId* source_file,
AnnotationsDirectoryItem* annotations,
- ArrayItemVector* static_values,
+ EncodedArrayItem* 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) { }
+ class_data_(class_data) { 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_; }
- TypeIdVector* Interfaces() { return interfaces_.get(); }
- uint32_t InterfacesOffset() const { return interfaces_offset_; }
- void SetInterfacesOffset(uint32_t new_offset) { interfaces_offset_ = new_offset; }
+ const TypeIdVector* Interfaces()
+ { return interfaces_ == nullptr ? nullptr: interfaces_->GetTypeList(); }
+ uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); }
const StringId* SourceFile() const { return source_file_; }
- AnnotationsDirectoryItem* Annotations() const { return annotations_.get(); }
- ArrayItemVector* StaticValues() { return static_values_.get(); }
- ClassData* GetClassData() { return class_data_.get(); }
+ AnnotationsDirectoryItem* Annotations() const { return annotations_; }
+ EncodedArrayItem* StaticValues() { return static_values_; }
+ ClassData* GetClassData() { return class_data_; }
MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii);
@@ -487,12 +706,12 @@
const TypeId* class_type_;
uint32_t access_flags_;
const TypeId* superclass_;
- std::unique_ptr<TypeIdVector> interfaces_;
- uint32_t interfaces_offset_;
+ TypeList* interfaces_;
const StringId* source_file_;
- std::unique_ptr<AnnotationsDirectoryItem> annotations_;
- std::unique_ptr<ArrayItemVector> static_values_;
- std::unique_ptr<ClassData> class_data_;
+ AnnotationsDirectoryItem* annotations_;
+ EncodedArrayItem* static_values_;
+ ClassData* class_data_;
+
DISALLOW_COPY_AND_ASSIGN(ClassDef);
};
@@ -506,6 +725,7 @@
private:
const TypeId* type_id_;
uint32_t address_;
+
DISALLOW_COPY_AND_ASSIGN(CatchHandler);
};
@@ -527,6 +747,7 @@
uint32_t start_addr_;
uint16_t insn_count_;
std::unique_ptr<CatchHandlerVector> handlers_;
+
DISALLOW_COPY_AND_ASSIGN(TryItem);
};
@@ -555,7 +776,7 @@
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_.get(); }
+ 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(); }
@@ -566,14 +787,14 @@
uint16_t registers_size_;
uint16_t ins_size_;
uint16_t outs_size_;
- std::unique_ptr<DebugInfoItem> debug_info_;
+ DebugInfoItem* debug_info_;
uint32_t insns_size_;
std::unique_ptr<uint16_t[]> insns_;
std::unique_ptr<TryItemVector> tries_;
+
DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
-
struct PositionInfo {
PositionInfo(uint32_t address, uint32_t line) : address_(address), line_(line) { }
@@ -617,39 +838,60 @@
private:
PositionInfoVector positions_;
LocalInfoVector locals_;
+
DISALLOW_COPY_AND_ASSIGN(DebugInfoItem);
};
-class AnnotationItem {
+class AnnotationItem : public Item {
public:
- AnnotationItem(uint8_t visibility, ArrayItem* item) : visibility_(visibility), item_(item) { }
+ AnnotationItem(uint8_t visibility, EncodedAnnotation* annotation)
+ : visibility_(visibility), annotation_(annotation) { }
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);
-};
-
-using AnnotationItemVector = std::vector<std::unique_ptr<AnnotationItem>>;
-
-class AnnotationSetItem : public Item {
- public:
- explicit AnnotationSetItem(AnnotationItemVector* items) : items_(items) { }
- ~AnnotationSetItem() OVERRIDE { }
-
- AnnotationItemVector* GetItems() { return items_.get(); }
+ EncodedAnnotation* GetAnnotation() const { return annotation_.get(); }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- std::unique_ptr<AnnotationItemVector> items_;
+ 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);
};
-using AnnotationSetItemVector = std::vector<std::unique_ptr<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_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList);
+};
class FieldAnnotation {
public:
@@ -657,11 +899,12 @@
: field_id_(field_id), annotation_set_item_(annotation_set_item) { }
FieldId* GetFieldId() const { return field_id_; }
- AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+ AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }
private:
FieldId* field_id_;
- std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+ AnnotationSetItem* annotation_set_item_;
+
DISALLOW_COPY_AND_ASSIGN(FieldAnnotation);
};
@@ -673,11 +916,12 @@
: method_id_(method_id), annotation_set_item_(annotation_set_item) { }
MethodId* GetMethodId() const { return method_id_; }
- AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+ AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }
private:
MethodId* method_id_;
- std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+ AnnotationSetItem* annotation_set_item_;
+
DISALLOW_COPY_AND_ASSIGN(MethodAnnotation);
};
@@ -685,15 +929,16 @@
class ParameterAnnotation {
public:
- ParameterAnnotation(MethodId* method_id, AnnotationSetItemVector* annotations)
+ ParameterAnnotation(MethodId* method_id, AnnotationSetRefList* annotations)
: method_id_(method_id), annotations_(annotations) { }
MethodId* GetMethodId() const { return method_id_; }
- AnnotationSetItemVector* GetAnnotations() { return annotations_.get(); }
+ AnnotationSetRefList* GetAnnotations() { return annotations_; }
private:
MethodId* method_id_;
- std::unique_ptr<AnnotationSetItemVector> annotations_;
+ AnnotationSetRefList* annotations_;
+
DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation);
};
@@ -710,7 +955,7 @@
method_annotations_(method_annotations),
parameter_annotations_(parameter_annotations) { }
- AnnotationSetItem* GetClassAnnotation() const { return class_annotation_.get(); }
+ AnnotationSetItem* GetClassAnnotation() const { return class_annotation_; }
FieldAnnotationVector* GetFieldAnnotations() { return field_annotations_.get(); }
MethodAnnotationVector* GetMethodAnnotations() { return method_annotations_.get(); }
ParameterAnnotationVector* GetParameterAnnotations() { return parameter_annotations_.get(); }
@@ -718,10 +963,11 @@
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- std::unique_ptr<AnnotationSetItem> class_annotation_;
+ AnnotationSetItem* class_annotation_;
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
index 30f57d9..e6868d7 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -24,401 +24,6 @@
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 ReadArrayItemVariant(Header& header,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- ArrayItem::ArrayItemVariant* item);
-
-ArrayItem* ReadArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) {
- ArrayItem* item = new ArrayItem(type);
- ReadArrayItemVariant(header, data, type, length, item->GetArrayItemVariant());
- 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);
- ReadArrayItemVariant(header, data, type, encoded_value >> 5, item->GetArrayItemVariant());
- return item;
-}
-
-void ReadArrayItemVariant(Header& header,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- ArrayItem::ArrayItemVariant* item) {
- switch (type) {
- case DexFile::kDexAnnotationByte:
- item->u_.byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false));
- break;
- case DexFile::kDexAnnotationShort:
- item->u_.short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true));
- break;
- case DexFile::kDexAnnotationChar:
- item->u_.char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false));
- break;
- case DexFile::kDexAnnotationInt:
- item->u_.int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true));
- break;
- case DexFile::kDexAnnotationLong:
- item->u_.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->u_.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->u_.double_val_ = conv.d;
- break;
- }
- case DexFile::kDexAnnotationString: {
- const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->u_.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->u_.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->u_.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->u_.method_val_ = header.MethodIds()[method_index].get();
- break;
- }
- case DexFile::kDexAnnotationArray: {
- item->annotation_array_val_.reset(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_.reset(
- 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->u_.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_,
@@ -431,73 +36,37 @@
disk_header.link_off_,
disk_header.data_size_,
disk_header.data_off_);
+ Collections& collections = header->GetCollections();
// 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_);
+ collections.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));
+ collections.CreateStringId(dex_file, i);
}
// TypeId table.
- std::vector<std::unique_ptr<TypeId>>& type_ids = header->TypeIds();
- header->SetTypeIdsOffset(disk_header.type_ids_off_);
+ collections.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));
+ collections.CreateTypeId(dex_file, i);
}
// ProtoId table.
- std::vector<std::unique_ptr<ProtoId>>& proto_ids = header->ProtoIds();
- header->SetProtoIdsOffset(disk_header.proto_ids_off_);
+ collections.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));
+ collections.CreateProtoId(dex_file, i);
}
// FieldId table.
- std::vector<std::unique_ptr<FieldId>>& field_ids = header->FieldIds();
- header->SetFieldIdsOffset(disk_header.field_ids_off_);
+ collections.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));
+ collections.CreateFieldId(dex_file, i);
}
// MethodId table.
- std::vector<std::unique_ptr<MethodId>>& method_ids = header->MethodIds();
- header->SetMethodIdsOffset(disk_header.method_ids_off_);
+ collections.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));
+ collections.CreateMethodId(dex_file, i);
}
// ClassDef table.
- std::vector<std::unique_ptr<ClassDef>>& class_defs = header->ClassDefs();
- header->SetClassDefsOffset(disk_header.class_defs_off_);
+ collections.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));
+ collections.CreateClassDef(dex_file, i);
}
return header;
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 3a3f417..6f34a33 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -30,9 +30,11 @@
#include <sstream>
#include <vector>
+#include "base/unix_file/fd_file.h"
#include "dex_ir_builder.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
+#include "os.h"
#include "utils.h"
namespace art {
@@ -348,10 +350,26 @@
} // for
}
+// Forward declare to resolve circular dependence.
+static void DumpEncodedValue(const dex_ir::EncodedValue* data);
+
+/*
+ * Dumps encoded annotation.
+ */
+static void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation) {
+ fputs(annotation->GetType()->GetStringId()->Data(), out_file_);
+ // Display all name=value pairs.
+ for (auto& subannotation : *annotation->GetAnnotationElements()) {
+ fputc(' ', out_file_);
+ fputs(subannotation->GetName()->Data(), out_file_);
+ fputc('=', out_file_);
+ DumpEncodedValue(subannotation->GetValue());
+ }
+}
/*
* Dumps encoded value.
*/
-static void DumpEncodedValue(const dex_ir::ArrayItem* data) {
+static void DumpEncodedValue(const dex_ir::EncodedValue* data) {
switch (data->Type()) {
case DexFile::kDexAnnotationByte:
fprintf(out_file_, "%" PRId8, data->GetByte());
@@ -386,8 +404,8 @@
break;
}
case DexFile::kDexAnnotationType: {
- dex_ir::StringId* string_id = data->GetStringId();
- fputs(string_id->Data(), out_file_);
+ dex_ir::TypeId* type_id = data->GetTypeId();
+ fputs(type_id->GetStringId()->Data(), out_file_);
break;
}
case DexFile::kDexAnnotationField:
@@ -404,22 +422,15 @@
case DexFile::kDexAnnotationArray: {
fputc('{', out_file_);
// Display all elements.
- for (auto& array : *data->GetAnnotationArray()) {
+ for (auto& value : *data->GetEncodedArray()->GetEncodedValues()) {
fputc(' ', out_file_);
- DumpEncodedValue(array.get());
+ DumpEncodedValue(value.get());
}
fputs(" }", out_file_);
break;
}
case DexFile::kDexAnnotationAnnotation: {
- fputs(data->GetAnnotationAnnotationString()->Data(), out_file_);
- // Display all name=value pairs.
- for (auto& subannotation : *data->GetAnnotationAnnotationNameValuePairArray()) {
- fputc(' ', out_file_);
- fputs(subannotation->Name()->Data(), out_file_);
- fputc('=', out_file_);
- DumpEncodedValue(subannotation->Value());
- }
+ DumpEncodedAnnotation(data->GetEncodedAnnotation());
break;
}
case DexFile::kDexAnnotationNull:
@@ -437,8 +448,9 @@
/*
* Dumps the file header.
*/
-static void DumpFileHeader(const dex_ir::Header* header) {
+static void DumpFileHeader(dex_ir::Header* header) {
char sanitized[8 * 2 + 1];
+ dex_ir::Collections& collections = header->GetCollections();
fprintf(out_file_, "DEX file header:\n");
Asciify(sanitized, header->Magic(), 8);
fprintf(out_file_, "magic : '%s'\n", sanitized);
@@ -452,24 +464,24 @@
fprintf(out_file_, "link_size : %d\n", header->LinkSize());
fprintf(out_file_, "link_off : %d (0x%06x)\n",
header->LinkOffset(), header->LinkOffset());
- fprintf(out_file_, "string_ids_size : %d\n", header->StringIdsSize());
+ fprintf(out_file_, "string_ids_size : %d\n", collections.StringIdsSize());
fprintf(out_file_, "string_ids_off : %d (0x%06x)\n",
- header->StringIdsOffset(), header->StringIdsOffset());
- fprintf(out_file_, "type_ids_size : %d\n", header->TypeIdsSize());
+ collections.StringIdsOffset(), collections.StringIdsOffset());
+ fprintf(out_file_, "type_ids_size : %d\n", collections.TypeIdsSize());
fprintf(out_file_, "type_ids_off : %d (0x%06x)\n",
- header->TypeIdsOffset(), header->TypeIdsOffset());
- fprintf(out_file_, "proto_ids_size : %d\n", header->ProtoIdsSize());
+ collections.TypeIdsOffset(), collections.TypeIdsOffset());
+ fprintf(out_file_, "proto_ids_size : %d\n", collections.ProtoIdsSize());
fprintf(out_file_, "proto_ids_off : %d (0x%06x)\n",
- header->ProtoIdsOffset(), header->ProtoIdsOffset());
- fprintf(out_file_, "field_ids_size : %d\n", header->FieldIdsSize());
+ collections.ProtoIdsOffset(), collections.ProtoIdsOffset());
+ fprintf(out_file_, "field_ids_size : %d\n", collections.FieldIdsSize());
fprintf(out_file_, "field_ids_off : %d (0x%06x)\n",
- header->FieldIdsOffset(), header->FieldIdsOffset());
- fprintf(out_file_, "method_ids_size : %d\n", header->MethodIdsSize());
+ collections.FieldIdsOffset(), collections.FieldIdsOffset());
+ fprintf(out_file_, "method_ids_size : %d\n", collections.MethodIdsSize());
fprintf(out_file_, "method_ids_off : %d (0x%06x)\n",
- header->MethodIdsOffset(), header->MethodIdsOffset());
- fprintf(out_file_, "class_defs_size : %d\n", header->ClassDefsSize());
+ collections.MethodIdsOffset(), collections.MethodIdsOffset());
+ fprintf(out_file_, "class_defs_size : %d\n", collections.ClassDefsSize());
fprintf(out_file_, "class_defs_off : %d (0x%06x)\n",
- header->ClassDefsOffset(), header->ClassDefsOffset());
+ collections.ClassDefsOffset(), collections.ClassDefsOffset());
fprintf(out_file_, "data_size : %d\n", header->DataSize());
fprintf(out_file_, "data_off : %d (0x%06x)\n\n",
header->DataOffset(), header->DataOffset());
@@ -480,19 +492,19 @@
*/
static void DumpClassDef(dex_ir::Header* header, int idx) {
// General class information.
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
fprintf(out_file_, "Class #%d header:\n", idx);
- fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetOffset());
+ fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetIndex());
fprintf(out_file_, "access_flags : %d (0x%04x)\n",
class_def->GetAccessFlags(), class_def->GetAccessFlags());
uint32_t superclass_idx = class_def->Superclass() == nullptr ?
- DexFile::kDexNoIndex16 : class_def->Superclass()->GetOffset();
+ DexFile::kDexNoIndex16 : class_def->Superclass()->GetIndex();
fprintf(out_file_, "superclass_idx : %d\n", superclass_idx);
fprintf(out_file_, "interfaces_off : %d (0x%06x)\n",
class_def->InterfacesOffset(), class_def->InterfacesOffset());
uint32_t source_file_offset = 0xffffffffU;
if (class_def->SourceFile() != nullptr) {
- source_file_offset = class_def->SourceFile()->GetOffset();
+ source_file_offset = class_def->SourceFile()->GetIndex();
}
fprintf(out_file_, "source_file_idx : %d\n", source_file_offset);
uint32_t annotations_offset = 0;
@@ -541,7 +553,7 @@
fputs(" empty-annotation-set\n", out_file_);
return;
}
- for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : *set_item->GetItems()) {
+ for (dex_ir::AnnotationItem* annotation : *set_item->GetItems()) {
if (annotation == nullptr) {
continue;
}
@@ -552,10 +564,7 @@
case DexFile::kDexVisibilitySystem: fputs("VISIBILITY_SYSTEM ", out_file_); break;
default: fputs("VISIBILITY_UNKNOWN ", out_file_); break;
} // switch
- // Decode raw bytes in annotation.
- // const uint8_t* rData = annotation->annotation_;
- dex_ir::ArrayItem* data = annotation->GetItem();
- DumpEncodedValue(data);
+ DumpEncodedAnnotation(annotation->GetAnnotation());
fputc('\n', out_file_);
}
}
@@ -564,7 +573,7 @@
* Dumps class annotations.
*/
static void DumpClassAnnotations(dex_ir::Header* header, int idx) {
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
dex_ir::AnnotationsDirectoryItem* annotations_directory = class_def->Annotations();
if (annotations_directory == nullptr) {
return; // none
@@ -587,7 +596,7 @@
if (fields != nullptr) {
for (auto& field : *fields) {
const dex_ir::FieldId* field_id = field->GetFieldId();
- const uint32_t field_idx = field_id->GetOffset();
+ const uint32_t field_idx = field_id->GetIndex();
const char* field_name = field_id->Name()->Data();
fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
DumpAnnotationSetItem(field->GetAnnotationSetItem());
@@ -598,7 +607,7 @@
if (methods != nullptr) {
for (auto& method : *methods) {
const dex_ir::MethodId* method_id = method->GetMethodId();
- const uint32_t method_idx = method_id->GetOffset();
+ const uint32_t method_idx = method_id->GetIndex();
const char* method_name = method_id->Name()->Data();
fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
DumpAnnotationSetItem(method->GetAnnotationSetItem());
@@ -609,13 +618,13 @@
if (parameters != nullptr) {
for (auto& parameter : *parameters) {
const dex_ir::MethodId* method_id = parameter->GetMethodId();
- const uint32_t method_idx = method_id->GetOffset();
+ const uint32_t method_idx = method_id->GetIndex();
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()) {
+ for (dex_ir::AnnotationSetItem* annotation : *parameter->GetAnnotations()->GetItems()) {
fprintf(out_file_, "#%u\n", j);
- DumpAnnotationSetItem(annotation.get());
+ DumpAnnotationSetItem(annotation);
++j;
}
}
@@ -748,24 +757,24 @@
outSize = snprintf(buf.get(), buf_size, "<no-index>");
break;
case Instruction::kIndexTypeRef:
- if (index < header->TypeIdsSize()) {
- const char* tp = header->TypeIds()[index]->GetStringId()->Data();
+ if (index < header->GetCollections().TypeIdsSize()) {
+ const char* tp = header->GetCollections().GetTypeId(index)->GetStringId()->Data();
outSize = snprintf(buf.get(), buf_size, "%s // type@%0*x", tp, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<type?> // type@%0*x", width, index);
}
break;
case Instruction::kIndexStringRef:
- if (index < header->StringIdsSize()) {
- const char* st = header->StringIds()[index]->Data();
+ if (index < header->GetCollections().StringIdsSize()) {
+ const char* st = header->GetCollections().GetStringId(index)->Data();
outSize = snprintf(buf.get(), buf_size, "\"%s\" // string@%0*x", st, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<string?> // string@%0*x", width, index);
}
break;
case Instruction::kIndexMethodRef:
- if (index < header->MethodIdsSize()) {
- dex_ir::MethodId* method_id = header->MethodIds()[index].get();
+ if (index < header->GetCollections().MethodIdsSize()) {
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index);
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -776,8 +785,8 @@
}
break;
case Instruction::kIndexFieldRef:
- if (index < header->FieldIdsSize()) {
- dex_ir::FieldId* field_id = header->FieldIds()[index].get();
+ if (index < header->GetCollections().FieldIdsSize()) {
+ dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(index);
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -1028,7 +1037,7 @@
*/
static void DumpBytecodes(dex_ir::Header* header, uint32_t idx,
const dex_ir::CodeItem* code, uint32_t code_offset) {
- dex_ir::MethodId* method_id = header->MethodIds()[idx].get();
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(idx);
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1088,7 +1097,7 @@
return;
}
- dex_ir::MethodId* method_id = header->MethodIds()[idx].get();
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(idx);
const char* name = method_id->Name()->Data();
char* type_descriptor = strdup(GetSignatureForProtoId(method_id->Proto()).c_str());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1187,13 +1196,13 @@
* Dumps a static (class) field.
*/
static void DumpSField(dex_ir::Header* header, uint32_t idx, uint32_t flags,
- int i, dex_ir::ArrayItem* init) {
+ int i, dex_ir::EncodedValue* init) {
// Bail for anything private if export only requested.
if (options_.exports_only_ && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
}
- dex_ir::FieldId* field_id = header->FieldIds()[idx].get();
+ dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(idx);
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -1293,7 +1302,7 @@
dex_ir::Header* header,
int idx,
char** last_package) {
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
// Omitting non-public class.
if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) {
return;
@@ -1316,7 +1325,8 @@
// up the classes, sort them, and dump them alphabetically so the
// package name wouldn't jump around, but that's not a great plan
// for something that needs to run on the device.
- const char* class_descriptor = header->ClassDefs()[idx]->ClassType()->GetStringId()->Data();
+ const char* class_descriptor =
+ header->GetCollections().GetClassDef(idx)->ClassType()->GetStringId()->Data();
if (!(class_descriptor[0] == 'L' &&
class_descriptor[strlen(class_descriptor)-1] == ';')) {
// Arrays and primitives should not be defined explicitly. Keep going?
@@ -1386,7 +1396,7 @@
}
// Interfaces.
- dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
+ const dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
if (interfaces != nullptr) {
for (uint32_t i = 0; i < interfaces->size(); i++) {
DumpInterface((*interfaces)[i], i);
@@ -1396,8 +1406,10 @@
// Fields and methods.
dex_ir::ClassData* class_data = class_def->GetClassData();
// Prepare data for static fields.
- std::vector<std::unique_ptr<dex_ir::ArrayItem>>* static_values = class_def->StaticValues();
- const uint32_t static_values_size = (static_values == nullptr) ? 0 : static_values->size();
+ dex_ir::EncodedArrayItem* static_values = class_def->StaticValues();
+ dex_ir::EncodedValueVector* encoded_values =
+ static_values == nullptr ? nullptr : static_values->GetEncodedValues();
+ const uint32_t encoded_values_size = (encoded_values == nullptr) ? 0 : encoded_values->size();
// Static fields.
if (options_.output_format_ == kOutputPlain) {
@@ -1408,10 +1420,10 @@
if (static_fields != nullptr) {
for (uint32_t i = 0; i < static_fields->size(); i++) {
DumpSField(header,
- (*static_fields)[i]->GetFieldId()->GetOffset(),
+ (*static_fields)[i]->GetFieldId()->GetIndex(),
(*static_fields)[i]->GetAccessFlags(),
i,
- i < static_values_size ? (*static_values)[i].get() : nullptr);
+ i < encoded_values_size ? (*encoded_values)[i].get() : nullptr);
} // for
}
}
@@ -1425,7 +1437,7 @@
if (instance_fields != nullptr) {
for (uint32_t i = 0; i < instance_fields->size(); i++) {
DumpIField(header,
- (*instance_fields)[i]->GetFieldId()->GetOffset(),
+ (*instance_fields)[i]->GetFieldId()->GetIndex(),
(*instance_fields)[i]->GetAccessFlags(),
i);
} // for
@@ -1441,7 +1453,7 @@
if (direct_methods != nullptr) {
for (uint32_t i = 0; i < direct_methods->size(); i++) {
DumpMethod(header,
- (*direct_methods)[i]->GetMethodId()->GetOffset(),
+ (*direct_methods)[i]->GetMethodId()->GetIndex(),
(*direct_methods)[i]->GetAccessFlags(),
(*direct_methods)[i]->GetCodeItem(),
i);
@@ -1458,7 +1470,7 @@
if (virtual_methods != nullptr) {
for (uint32_t i = 0; i < virtual_methods->size(); i++) {
DumpMethod(header,
- (*virtual_methods)[i]->GetMethodId()->GetOffset(),
+ (*virtual_methods)[i]->GetMethodId()->GetIndex(),
(*virtual_methods)[i]->GetAccessFlags(),
(*virtual_methods)[i]->GetCodeItem(),
i);
@@ -1474,7 +1486,7 @@
}
const dex_ir::StringId* source_file = class_def->SourceFile();
fprintf(out_file_, " source_file_idx : %d (%s)\n\n",
- source_file == nullptr ? 0xffffffffU : source_file->GetOffset(), file_name);
+ source_file == nullptr ? 0xffffffffU : source_file->GetIndex(), file_name);
} else if (options_.output_format_ == kOutputXml) {
fprintf(out_file_, "</class>\n");
}
@@ -1483,6 +1495,96 @@
}
/*
+static uint32_t GetDataSectionOffset(dex_ir::Header& header) {
+ return dex_ir::Header::ItemSize() +
+ header.GetCollections().StringIdsSize() * dex_ir::StringId::ItemSize() +
+ header.GetCollections().TypeIdsSize() * dex_ir::TypeId::ItemSize() +
+ header.GetCollections().ProtoIdsSize() * dex_ir::ProtoId::ItemSize() +
+ header.GetCollections().FieldIdsSize() * dex_ir::FieldId::ItemSize() +
+ header.GetCollections().MethodIdsSize() * dex_ir::MethodId::ItemSize() +
+ header.GetCollections().ClassDefsSize() * dex_ir::ClassDef::ItemSize();
+}
+
+static bool Align(File* file, uint32_t& offset) {
+ uint8_t zero_buffer[] = { 0, 0, 0 };
+ uint32_t zeroes = (-offset) & 3;
+ if (zeroes > 0) {
+ if (!file->PwriteFully(zero_buffer, zeroes, offset)) {
+ return false;
+ }
+ offset += zeroes;
+ }
+ return true;
+}
+
+static bool WriteStrings(File* dex_file, dex_ir::Header& header,
+ uint32_t& index_offset, uint32_t& data_offset) {
+ uint32_t index = 0;
+ uint32_t index_buffer[1];
+ uint32_t string_length;
+ uint32_t length_length;
+ uint8_t length_buffer[8];
+ for (std::unique_ptr<dex_ir::StringId>& string_id : header.GetCollections().StringIds()) {
+ string_id->SetOffset(index);
+ index_buffer[0] = data_offset;
+ string_length = strlen(string_id->Data());
+ length_length = UnsignedLeb128Size(string_length);
+ EncodeUnsignedLeb128(length_buffer, string_length);
+
+ if (!dex_file->PwriteFully(index_buffer, 4, index_offset) ||
+ !dex_file->PwriteFully(length_buffer, length_length, data_offset) ||
+ !dex_file->PwriteFully(string_id->Data(), string_length, data_offset + length_length)) {
+ return false;
+ }
+
+ index++;
+ index_offset += 4;
+ data_offset += string_length + length_length;
+ }
+ return true;
+}
+
+static bool WriteTypes(File* dex_file, dex_ir::Header& header, uint32_t& index_offset) {
+ uint32_t index = 0;
+ uint32_t index_buffer[1];
+ for (std::unique_ptr<dex_ir::TypeId>& type_id : header.GetCollections().TypeIds()) {
+ type_id->SetIndex(index);
+ index_buffer[0] = type_id->GetStringId()->GetOffset();
+
+ if (!dex_file->PwriteFully(index_buffer, 4, index_offset)) {
+ return false;
+ }
+
+ index++;
+ index_offset += 4;
+ }
+ return true;
+}
+
+static bool WriteTypeLists(File* dex_file, dex_ir::Header& header, uint32_t& data_offset) {
+ if (!Align(dex_file, data_offset)) {
+ return false;
+ }
+
+ return true;
+}
+
+static void OutputDexFile(dex_ir::Header& header, const char* file_name) {
+ LOG(INFO) << "FILE NAME: " << file_name;
+ std::unique_ptr<File> dex_file(OS::CreateEmptyFileWriteOnly(file_name));
+ if (dex_file == nullptr) {
+ fprintf(stderr, "Can't open %s\n", file_name);
+ return;
+ }
+
+ uint32_t index_offset = dex_ir::Header::ItemSize();
+ uint32_t data_offset = GetDataSectionOffset(header);
+ WriteStrings(dex_file.get(), header, index_offset, data_offset);
+ WriteTypes(dex_file.get(), header, index_offset);
+}
+*/
+
+/*
* Dumps the requested sections of the file.
*/
static void ProcessDexFile(const char* file_name, const DexFile* dex_file) {
@@ -1504,7 +1606,7 @@
// Iterate over all classes.
char* package = nullptr;
- const uint32_t class_defs_size = header->ClassDefsSize();
+ const uint32_t class_defs_size = header->GetCollections().ClassDefsSize();
for (uint32_t i = 0; i < class_defs_size; i++) {
DumpClass(dex_file, header.get(), i, &package);
} // for
@@ -1519,6 +1621,14 @@
if (options_.output_format_ == kOutputXml) {
fprintf(out_file_, "</api>\n");
}
+
+ /*
+ // Output dex file.
+ if (options_.output_dex_files_) {
+ std::string output_dex_filename = dex_file->GetLocation() + ".out";
+ OutputDexFile(*header, output_dex_filename.c_str());
+ }
+ */
}
/*
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index bae587d..736d230 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -41,6 +41,7 @@
bool disassemble_;
bool exports_only_;
bool ignore_bad_checksum_;
+ bool output_dex_files_;
bool show_annotations_;
bool show_cfg_;
bool show_file_headers_;
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index 09fa0ef..ec5edf4 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -38,7 +38,7 @@
*/
static void Usage(void) {
fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
- fprintf(stderr, "%s: [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-l layout] [-o outfile]"
+ fprintf(stderr, "%s: [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-l layout] [-o outfile] [-w]"
" dexfile...\n\n", kProgramName);
fprintf(stderr, " -a : display annotations\n");
fprintf(stderr, " -b : build dex_ir\n");
@@ -51,6 +51,7 @@
fprintf(stderr, " -i : ignore checksum failures\n");
fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
fprintf(stderr, " -o : output file name (defaults to stdout)\n");
+ fprintf(stderr, " -w : output dex files\n");
}
/*
@@ -68,7 +69,7 @@
// Parse all arguments.
while (1) {
- const int ic = getopt(argc, argv, "abcdefghil:o:");
+ const int ic = getopt(argc, argv, "abcdefghil:o:w");
if (ic < 0) {
break; // done
}
@@ -113,6 +114,9 @@
case 'o': // output file
options_.output_file_name_ = optarg;
break;
+ case 'w': // output dex files
+ options_.output_dex_files_ = true;
+ break;
default:
want_usage = true;
break;