diff options
author | 2018-06-14 15:13:04 -0700 | |
---|---|---|
committer | 2018-06-15 10:55:56 -0700 | |
commit | 2b5a38f8fbdecf9c82f06ec108c7ee7463bd8093 (patch) | |
tree | 51e3648106f2f74196f9476209a7a649e7885dcb | |
parent | 5f7c6a1fc35e04b75e1154620c5fd0ab8758e62c (diff) |
Refactor ownership in dex_ir
Remove some unnecessary generality, consolidating and simplifying the
interface to Header and moving all the construction code out of dex_ir.
This makes item ownership exclusively controlled by the collections
themselves, preparing for in-place construction.
Bug: 33017139
Test: make -j 40 test-art-host-gtest
Change-Id: Ice461ae89ef9f8bed3350780e8dd6283bc6eca1b
-rw-r--r-- | dexlayout/compact_dex_writer.cc | 56 | ||||
-rw-r--r-- | dexlayout/dex_ir.cc | 947 | ||||
-rw-r--r-- | dexlayout/dex_ir.h | 583 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 1110 | ||||
-rw-r--r-- | dexlayout/dex_verify.cc | 81 | ||||
-rw-r--r-- | dexlayout/dex_verify.h | 8 | ||||
-rw-r--r-- | dexlayout/dex_visualize.cc | 4 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 190 | ||||
-rw-r--r-- | dexlayout/dexlayout.cc | 116 |
9 files changed, 1552 insertions, 1543 deletions
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc index 3f5dbcfce5..00fb0af710 100644 --- a/dexlayout/compact_dex_writer.cc +++ b/dexlayout/compact_dex_writer.cc @@ -40,9 +40,8 @@ CompactDexWriter::Container::Container(bool dedupe_code_items) uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) { const uint32_t start_offset = stream->Tell(); - const dex_ir::Collections& collections = header_->GetCollections(); // Debug offsets for method indexes. 0 means no debug info. - std::vector<uint32_t> debug_info_offsets(collections.MethodIdsSize(), 0u); + std::vector<uint32_t> debug_info_offsets(header_->MethodIds().Size(), 0u); static constexpr InvokeType invoke_types[] = { kDirect, @@ -50,7 +49,7 @@ uint32_t CompactDexWriter::WriteDebugInfoOffsetTable(Stream* stream) { }; for (InvokeType invoke_type : invoke_types) { - for (const std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { // Skip classes that are not defined in this dex file. dex_ir::ClassData* class_data = class_def->GetClassData(); if (class_data == nullptr) { @@ -232,14 +231,13 @@ uint32_t CompactDexWriter::Deduper::Dedupe(uint32_t data_start, } void CompactDexWriter::SortDebugInfosByMethodIndex() { - dex_ir::Collections& collections = header_->GetCollections(); static constexpr InvokeType invoke_types[] = { kDirect, kVirtual }; std::map<const dex_ir::DebugInfoItem*, uint32_t> method_idx_map; for (InvokeType invoke_type : invoke_types) { - for (std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { // Skip classes that are not defined in this dex file. dex_ir::ClassData* class_data = class_def->GetClassData(); if (class_data == nullptr) { @@ -257,8 +255,8 @@ void CompactDexWriter::SortDebugInfosByMethodIndex() { } } } - std::sort(collections.DebugInfoItems().begin(), - collections.DebugInfoItems().end(), + std::sort(header_->DebugInfoItems().begin(), + header_->DebugInfoItems().end(), [&](const std::unique_ptr<dex_ir::DebugInfoItem>& a, const std::unique_ptr<dex_ir::DebugInfoItem>& b) { auto it_a = method_idx_map.find(a.get()); @@ -282,20 +280,19 @@ void CompactDexWriter::WriteHeader(Stream* stream) { header.endian_tag_ = header_->EndianTag(); header.link_size_ = header_->LinkSize(); header.link_off_ = header_->LinkOffset(); - const dex_ir::Collections& collections = header_->GetCollections(); - header.map_off_ = collections.MapListOffset(); - header.string_ids_size_ = collections.StringIdsSize(); - header.string_ids_off_ = collections.StringIdsOffset(); - header.type_ids_size_ = collections.TypeIdsSize(); - header.type_ids_off_ = collections.TypeIdsOffset(); - header.proto_ids_size_ = collections.ProtoIdsSize(); - header.proto_ids_off_ = collections.ProtoIdsOffset(); - header.field_ids_size_ = collections.FieldIdsSize(); - header.field_ids_off_ = collections.FieldIdsOffset(); - header.method_ids_size_ = collections.MethodIdsSize(); - header.method_ids_off_ = collections.MethodIdsOffset(); - header.class_defs_size_ = collections.ClassDefsSize(); - header.class_defs_off_ = collections.ClassDefsOffset(); + header.map_off_ = header_->MapListOffset(); + header.string_ids_size_ = header_->StringIds().Size(); + header.string_ids_off_ = header_->StringIds().GetOffset(); + header.type_ids_size_ = header_->TypeIds().Size(); + header.type_ids_off_ = header_->TypeIds().GetOffset(); + header.proto_ids_size_ = header_->ProtoIds().Size(); + header.proto_ids_off_ = header_->ProtoIds().GetOffset(); + header.field_ids_size_ = header_->FieldIds().Size(); + header.field_ids_off_ = header_->FieldIds().GetOffset(); + header.method_ids_size_ = header_->MethodIds().Size(); + header.method_ids_off_ = header_->MethodIds().GetOffset(); + header.class_defs_size_ = header_->ClassDefs().Size(); + header.class_defs_off_ = header_->ClassDefs().GetOffset(); header.data_size_ = header_->DataSize(); header.data_off_ = header_->DataOffset(); header.owned_data_begin_ = owned_data_begin_; @@ -332,16 +329,15 @@ void CompactDexWriter::WriteStringData(Stream* stream, dex_ir::StringData* strin } bool CompactDexWriter::CanGenerateCompactDex(std::string* error_msg) { - dex_ir::Collections& collections = header_->GetCollections(); static constexpr InvokeType invoke_types[] = { kDirect, kVirtual }; - std::vector<bool> saw_method_id(collections.MethodIdsSize(), false); - std::vector<dex_ir::CodeItem*> method_id_code_item(collections.MethodIdsSize(), nullptr); - std::vector<dex_ir::DebugInfoItem*> method_id_debug_info(collections.MethodIdsSize(), nullptr); + std::vector<bool> saw_method_id(header_->MethodIds().Size(), false); + std::vector<dex_ir::CodeItem*> method_id_code_item(header_->MethodIds().Size(), nullptr); + std::vector<dex_ir::DebugInfoItem*> method_id_debug_info(header_->MethodIds().Size(), nullptr); for (InvokeType invoke_type : invoke_types) { - for (std::unique_ptr<dex_ir::ClassDef>& class_def : collections.ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { // Skip classes that are not defined in this dex file. dex_ir::ClassData* class_data = class_def->GetClassData(); if (class_data == nullptr) { @@ -407,8 +403,6 @@ bool CompactDexWriter::Write(DexContainer* output, std::string* error_msg) { // Starting offset is right after the header. main_stream->Seek(GetHeaderSize()); - dex_ir::Collections& collection = header_->GetCollections(); - // Based on: https://source.android.com/devices/tech/dalvik/dex-format // Since the offsets may not be calculated already, the writing must be done in the correct order. const uint32_t string_ids_offset = main_stream->Tell(); @@ -469,16 +463,16 @@ bool CompactDexWriter::Write(DexContainer* output, std::string* error_msg) { // Write the map list. if (compute_offsets_) { data_stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList)); - collection.SetMapListOffset(data_stream->Tell()); + header_->SetMapListOffset(data_stream->Tell()); } else { - data_stream->Seek(collection.MapListOffset()); + data_stream->Seek(header_->MapListOffset()); } // Map items are included in the data section. GenerateAndWriteMapItems(data_stream); // Write link data if it exists. - const std::vector<uint8_t>& link_data = collection.LinkData(); + const std::vector<uint8_t>& link_data = header_->LinkData(); if (link_data.size() > 0) { CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size())); if (compute_offsets_) { diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index 15e3baf18a..3917847ea7 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -30,873 +30,11 @@ 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 uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) { - const uint8_t* stream = debug_info_stream; - DecodeUnsignedLeb128(&stream); // line_start - uint32_t parameters_size = DecodeUnsignedLeb128(&stream); - for (uint32_t i = 0; i < parameters_size; ++i) { - DecodeUnsignedLeb128P1(&stream); // Parameter name. - } - - for (;;) { - uint8_t opcode = *stream++; - switch (opcode) { - case DexFile::DBG_END_SEQUENCE: - return stream - debug_info_stream; // end of stream. - case DexFile::DBG_ADVANCE_PC: - DecodeUnsignedLeb128(&stream); // addr_diff - break; - case DexFile::DBG_ADVANCE_LINE: - DecodeSignedLeb128(&stream); // line_diff - break; - case DexFile::DBG_START_LOCAL: - DecodeUnsignedLeb128(&stream); // register_num - DecodeUnsignedLeb128P1(&stream); // name_idx - DecodeUnsignedLeb128P1(&stream); // type_idx - break; - case DexFile::DBG_START_LOCAL_EXTENDED: - DecodeUnsignedLeb128(&stream); // register_num - DecodeUnsignedLeb128P1(&stream); // name_idx - DecodeUnsignedLeb128P1(&stream); // type_idx - DecodeUnsignedLeb128P1(&stream); // sig_idx - break; - case DexFile::DBG_END_LOCAL: - case DexFile::DBG_RESTART_LOCAL: - DecodeUnsignedLeb128(&stream); // register_num - break; - case DexFile::DBG_SET_PROLOGUE_END: - case DexFile::DBG_SET_EPILOGUE_BEGIN: - break; - case DexFile::DBG_SET_FILE: { - DecodeUnsignedLeb128P1(&stream); // name_idx - break; - } - default: { - break; - } - } - } -} - -static bool GetIdFromInstruction(Collections& collections, - const Instruction* dec_insn, - std::vector<TypeId*>* type_ids, - std::vector<StringId*>* string_ids, - std::vector<MethodId*>* method_ids, - std::vector<FieldId*>* field_ids) { - // Determine index and width of the string. - uint32_t index = 0; - switch (Instruction::FormatOf(dec_insn->Opcode())) { - // SOME NOT SUPPORTED: - // case Instruction::k20bc: - case Instruction::k21c: - case Instruction::k35c: - // case Instruction::k35ms: - case Instruction::k3rc: - // case Instruction::k3rms: - // case Instruction::k35mi: - // case Instruction::k3rmi: - case Instruction::k45cc: - case Instruction::k4rcc: - index = dec_insn->VRegB(); - break; - case Instruction::k31c: - index = dec_insn->VRegB(); - break; - case Instruction::k22c: - // case Instruction::k22cs: - index = dec_insn->VRegC(); - break; - default: - break; - } // switch - - // Determine index type, and add reference to the appropriate collection. - switch (Instruction::IndexTypeOf(dec_insn->Opcode())) { - case Instruction::kIndexTypeRef: - if (index < collections.TypeIdsSize()) { - type_ids->push_back(collections.GetTypeId(index)); - return true; - } - break; - case Instruction::kIndexStringRef: - if (index < collections.StringIdsSize()) { - string_ids->push_back(collections.GetStringId(index)); - return true; - } - break; - case Instruction::kIndexMethodRef: - case Instruction::kIndexMethodAndProtoRef: - if (index < collections.MethodIdsSize()) { - method_ids->push_back(collections.GetMethodId(index)); - return true; - } - break; - case Instruction::kIndexFieldRef: - if (index < collections.FieldIdsSize()) { - field_ids->push_back(collections.GetFieldId(index)); - return true; - } - break; - case Instruction::kIndexUnknown: - case Instruction::kIndexNone: - case Instruction::kIndexVtableOffset: - case Instruction::kIndexFieldOffset: - default: - break; - } // switch - return false; -} - -/* - * Get all the types, strings, methods, and fields referred to from bytecode. - */ -static bool GetIdsFromByteCode(Collections& collections, - const CodeItem* code, - std::vector<TypeId*>* type_ids, - std::vector<StringId*>* string_ids, - std::vector<MethodId*>* method_ids, - std::vector<FieldId*>* field_ids) { - bool has_id = false; - IterationRange<DexInstructionIterator> instructions = code->Instructions(); - SafeDexInstructionIterator it(instructions.begin(), instructions.end()); - for (; !it.IsErrorState() && it < instructions.end(); ++it) { - // In case the instruction goes past the end of the code item, make sure to not process it. - SafeDexInstructionIterator next = it; - ++next; - if (next.IsErrorState()) { - break; - } - has_id |= GetIdFromInstruction(collections, - &it.Inst(), - type_ids, - string_ids, - method_ids, - field_ids); - } // for - return has_id; -} - -EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) { - const uint8_t encoded_value = *(*data)++; - const uint8_t type = encoded_value & 0x1f; - EncodedValue* item = new EncodedValue(type); - ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item); - return item; -} - -EncodedValue* Collections::ReadEncodedValue(const DexFile& dex_file, - const uint8_t** data, - uint8_t type, - uint8_t length) { - EncodedValue* item = new EncodedValue(type); - ReadEncodedValue(dex_file, data, type, length, item); - return item; -} - -void Collections::ReadEncodedValue(const DexFile& dex_file, - 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::kDexAnnotationMethodType: { - const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item->SetProtoId(GetProtoId(proto_index)); - break; - } - case DexFile::kDexAnnotationMethodHandle: { - const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); - item->SetMethodHandle(GetMethodHandle(method_handle_index)); - 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 offset = *data - dex_file.DataBegin(); - 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(dex_file, data))); - } - EncodedArrayItem* array_item = new EncodedArrayItem(values); - if (eagerly_assign_offsets_) { - array_item->SetOffset(offset); - } - item->SetEncodedArray(array_item); - 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(dex_file, 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(dex::StringIndex(i)); - StringData* string_data = CreateAndAddItem(string_datas_map_, - string_datas_, - disk_string_id.string_data_off_, - dex_file.GetStringData(disk_string_id)); - CreateAndAddIndexedItem(string_ids_, - StringIdsOffset() + i * StringId::ItemSize(), - i, - string_data); -} - -void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) { - const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i)); - CreateAndAddIndexedItem(type_ids_, - TypeIdsOffset() + i * TypeId::ItemSize(), - i, - GetStringId(disk_type_id.descriptor_idx_.index_)); -} - -void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) { - const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i)); - const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id); - TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_); - - CreateAndAddIndexedItem(proto_ids_, - ProtoIdsOffset() + i * ProtoId::ItemSize(), - i, - GetStringId(disk_proto_id.shorty_idx_.index_), - GetTypeId(disk_proto_id.return_type_idx_.index_), - parameter_type_list); -} - -void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) { - const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i); - CreateAndAddIndexedItem(field_ids_, - FieldIdsOffset() + i * FieldId::ItemSize(), - i, - GetTypeId(disk_field_id.class_idx_.index_), - GetTypeId(disk_field_id.type_idx_.index_), - GetStringId(disk_field_id.name_idx_.index_)); -} - -void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) { - const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i); - CreateAndAddIndexedItem(method_ids_, - MethodIdsOffset() + i * MethodId::ItemSize(), - i, - GetTypeId(disk_method_id.class_idx_.index_), - GetProtoId(disk_method_id.proto_idx_.index_), - GetStringId(disk_method_id.name_idx_.index_)); -} - -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_.index_); - uint32_t access_flags = disk_class_def.access_flags_; - const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_); - - const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def); - TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_); - - const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_); - // 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(dex_file, 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_); - CreateAndAddIndexedItem(class_defs_, - ClassDefsOffset() + i * ClassDef::ItemSize(), - i, - class_type, - access_flags, - superclass, - interfaces_type_list, - source_file, - annotations, - static_values, - class_data); -} - -TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) { - if (dex_type_list == nullptr) { - return nullptr; - } - TypeList* type_list = type_lists_map_.GetExistingObject(offset); - if (type_list == nullptr) { - TypeIdVector* type_vector = new TypeIdVector(); - uint32_t size = dex_type_list->Size(); - for (uint32_t index = 0; index < size; ++index) { - type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_.index_)); - } - type_list = CreateAndAddItem(type_lists_map_, type_lists_, offset, type_vector); - } - return type_list; -} - -EncodedArrayItem* Collections::CreateEncodedArrayItem(const DexFile& dex_file, - const uint8_t* static_data, - uint32_t offset) { - if (static_data == nullptr) { - return nullptr; - } - EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset); - if (encoded_array_item == 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(dex_file, &static_data))); - } - // TODO: Calculate the size of the encoded array. - encoded_array_item = CreateAndAddItem(encoded_array_items_map_, - encoded_array_items_, - offset, - values); - } - return encoded_array_item; -} - -void Collections::AddAnnotationsFromMapListSection(const DexFile& dex_file, - uint32_t start_offset, - uint32_t count) { - uint32_t current_offset = start_offset; - for (size_t i = 0; i < count; ++i) { - // Annotation that we didn't process already, add it to the set. - const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset); - AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation); - DCHECK(annotation_item != nullptr); - current_offset += annotation_item->GetSize(); - } -} - -AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file, - const DexFile::AnnotationItem* annotation) { - const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation); - const uint32_t offset = start_data - dex_file.DataBegin(); - AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset); - if (annotation_item == nullptr) { - uint8_t visibility = annotation->visibility_; - const uint8_t* annotation_data = annotation->annotation_; - std::unique_ptr<EncodedValue> encoded_value( - ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0)); - annotation_item = CreateAndAddItem(annotation_items_map_, - annotation_items_, - offset, - visibility, - encoded_value->ReleaseEncodedAnnotation()); - annotation_item->SetSize(annotation_data - start_data); - } - return annotation_item; -} - - -AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file, - const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) { - if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) { - return nullptr; - } - AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset); - if (annotation_set_item == 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(dex_file, annotation); - items->push_back(annotation_item); - } - annotation_set_item = CreateAndAddItem(annotation_set_items_map_, - annotation_set_items_, - offset, - items); - } - return annotation_set_item; -} - -AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file, - const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) { - AnnotationsDirectoryItem* annotations_directory_item = - annotations_directory_items_map_.GetExistingObject(offset); - if (annotations_directory_item != nullptr) { - return annotations_directory_item; - } - const DexFile::AnnotationSetItem* class_set_item = - dex_file.GetClassAnnotationSet(disk_annotations_item); - AnnotationSetItem* class_annotation = nullptr; - if (class_set_item != nullptr) { - uint32_t item_offset = disk_annotations_item->class_annotations_off_; - class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, 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. - return CreateAndAddItem(annotations_directory_items_map_, - annotations_directory_items_, - offset, - class_annotation, - field_annotations, - method_annotations, - parameter_annotations); -} - -ParameterAnnotation* Collections::GenerateParameterAnnotation( - const DexFile& dex_file, MethodId* method_id, - const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) { - AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset); - if (set_ref_list == nullptr) { - 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)); - } - set_ref_list = CreateAndAddItem(annotation_set_ref_lists_map_, - annotation_set_ref_lists_, - offset, - annotations); - } - return new ParameterAnnotation(method_id, set_ref_list); -} - -CodeItem* Collections::DedupeOrCreateCodeItem(const DexFile& dex_file, - const DexFile::CodeItem* disk_code_item, - uint32_t offset, - uint32_t dex_method_index) { - if (disk_code_item == nullptr) { - return nullptr; - } - CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index); - const uint32_t debug_info_offset = accessor.DebugInfoOffset(); - - // Create the offsets pair and dedupe based on it. - std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset); - auto existing = code_items_map_.find(offsets_pair); - if (existing != code_items_map_.end()) { - return existing->second; - } - - const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset); - DebugInfoItem* debug_info = nullptr; - if (debug_info_stream != nullptr) { - debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset); - if (debug_info == nullptr) { - uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream); - uint8_t* debug_info_buffer = new uint8_t[debug_info_size]; - memcpy(debug_info_buffer, debug_info_stream, debug_info_size); - debug_info = CreateAndAddItem(debug_info_items_map_, - debug_info_items_, - debug_info_offset, - debug_info_size, - debug_info_buffer); - } - } - - uint32_t insns_size = accessor.InsnsSizeInCodeUnits(); - uint16_t* insns = new uint16_t[insns_size]; - memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t)); - - TryItemVector* tries = nullptr; - CatchHandlerVector* handler_list = nullptr; - if (accessor.TriesSize() > 0) { - tries = new TryItemVector(); - handler_list = new CatchHandlerVector(); - for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) { - uint32_t start_addr = disk_try_item.start_addr_; - uint16_t insn_count = disk_try_item.insn_count_; - uint16_t handler_off = disk_try_item.handler_off_; - const CatchHandler* handlers = nullptr; - for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { - if (handler_off == existing_handlers->GetListOffset()) { - handlers = existing_handlers.get(); - break; - } - } - if (handlers == nullptr) { - bool catch_all = false; - TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); - for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) { - const dex::TypeIndex type_index = it.GetHandlerTypeIndex(); - const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_); - catch_all |= type_id == nullptr; - addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>( - new TypeAddrPair(type_id, it.GetHandlerAddress()))); - } - handlers = new CatchHandler(catch_all, handler_off, addr_pairs); - handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers)); - } - TryItem* try_item = new TryItem(start_addr, insn_count, handlers); - tries->push_back(std::unique_ptr<const TryItem>(try_item)); - } - // Manually walk catch handlers list and add any missing handlers unreferenced by try items. - const uint8_t* handlers_base = accessor.GetCatchHandlerData(); - const uint8_t* handlers_data = handlers_base; - uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data); - while (handlers_size > handler_list->size()) { - bool already_added = false; - uint16_t handler_off = handlers_data - handlers_base; - for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { - if (handler_off == existing_handlers->GetListOffset()) { - already_added = true; - break; - } - } - int32_t size = DecodeSignedLeb128(&handlers_data); - bool has_catch_all = size <= 0; - if (has_catch_all) { - size = -size; - } - if (already_added) { - for (int32_t i = 0; i < size; i++) { - DecodeUnsignedLeb128(&handlers_data); - DecodeUnsignedLeb128(&handlers_data); - } - if (has_catch_all) { - DecodeUnsignedLeb128(&handlers_data); - } - continue; - } - TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); - for (int32_t i = 0; i < size; i++) { - const TypeId* type_id = GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data)); - uint32_t addr = DecodeUnsignedLeb128(&handlers_data); - addr_pairs->push_back( - std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr))); - } - if (has_catch_all) { - uint32_t addr = DecodeUnsignedLeb128(&handlers_data); - addr_pairs->push_back( - std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr))); - } - const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs); - handler_list->push_back(std::unique_ptr<const CatchHandler>(handler)); - } - } - - uint32_t size = dex_file.GetCodeItemSize(*disk_code_item); - CodeItem* code_item = code_items_.CreateAndAddItem(accessor.RegistersSize(), - accessor.InsSize(), - accessor.OutsSize(), - debug_info, - insns_size, - insns, - tries, - handler_list); - code_item->SetSize(size); - - // Add the code item to the map. - DCHECK(!code_item->OffsetAssigned()); - if (eagerly_assign_offsets_) { - code_item->SetOffset(offset); - } - code_items_map_.emplace(offsets_pair, code_item); - - // Add "fixup" references to types, strings, methods, and fields. - // This is temporary, as we will probably want more detailed parsing of the - // instructions here. - std::vector<TypeId*> type_ids; - std::vector<StringId*> string_ids; - std::vector<MethodId*> method_ids; - std::vector<FieldId*> field_ids; - if (GetIdsFromByteCode(*this, - code_item, - /*out*/ &type_ids, - /*out*/ &string_ids, - /*out*/ &method_ids, - /*out*/ &field_ids)) { - CodeFixups* fixups = new CodeFixups(std::move(type_ids), - std::move(string_ids), - std::move(method_ids), - std::move(field_ids)); - code_item->SetCodeFixups(fixups); - } - - return code_item; -} - -MethodItem Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { - MethodId* method_id = GetMethodId(cdii.GetMemberIndex()); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); - // Temporary hack to prevent incorrectly deduping code items if they have the same offset since - // they may have different debug info streams. - CodeItem* code_item = DedupeOrCreateCodeItem(dex_file, - disk_code_item, - cdii.GetMethodCodeItemOffset(), - cdii.GetMemberIndex()); - return MethodItem(access_flags, method_id, 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 = class_datas_map_.GetExistingObject(offset); - if (class_data == nullptr && encoded_data != nullptr) { - ClassDataItemIterator cdii(dex_file, encoded_data); - // Static fields. - FieldItemVector* static_fields = new FieldItemVector(); - for (; cdii.HasNextStaticField(); cdii.Next()) { - FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - static_fields->emplace_back(access_flags, field_item); - } - // Instance fields. - FieldItemVector* instance_fields = new FieldItemVector(); - for (; cdii.HasNextInstanceField(); cdii.Next()) { - FieldId* field_item = GetFieldId(cdii.GetMemberIndex()); - uint32_t access_flags = cdii.GetRawMemberAccessFlags(); - instance_fields->emplace_back(access_flags, field_item); - } - // Direct methods. - MethodItemVector* direct_methods = new MethodItemVector(); - for (; cdii.HasNextDirectMethod(); cdii.Next()) { - direct_methods->push_back(GenerateMethodItem(dex_file, cdii)); - } - // Virtual methods. - MethodItemVector* virtual_methods = new MethodItemVector(); - for (; cdii.HasNextVirtualMethod(); cdii.Next()) { - virtual_methods->push_back(GenerateMethodItem(dex_file, cdii)); - } - class_data = CreateAndAddItem(class_datas_map_, - class_datas_, - offset, - static_fields, - instance_fields, - direct_methods, - virtual_methods); - class_data->SetSize(cdii.EndDataPointer() - encoded_data); - } - return class_data; -} - -void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) { - // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems. - const DexFile::MapList* map = dex_file.GetMapList(); - for (uint32_t i = 0; i < map->size_; ++i) { - const DexFile::MapItem* item = map->list_ + i; - switch (item->type_) { - case DexFile::kDexTypeCallSiteIdItem: - SetCallSiteIdsOffset(item->offset_); - break; - case DexFile::kDexTypeMethodHandleItem: - SetMethodHandleItemsOffset(item->offset_); - break; - default: - break; - } - } - // Populate MethodHandleItems first (CallSiteIds may depend on them). - for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) { - CreateMethodHandleItem(dex_file, i); - } - // Populate CallSiteIds. - for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) { - CreateCallSiteId(dex_file, i); - } -} - -void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) { - const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i); - const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_; - EncodedArrayItem* call_site_item = - CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_); - - CreateAndAddIndexedItem(call_site_ids_, - CallSiteIdsOffset() + i * CallSiteId::ItemSize(), - i, - call_site_item); -} - -void Collections::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) { - const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i); - uint16_t index = disk_method_handle.field_or_method_idx_; - DexFile::MethodHandleType type = - static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_); - bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic || - type == DexFile::MethodHandleType::kInvokeInstance || - type == DexFile::MethodHandleType::kInvokeConstructor || - type == DexFile::MethodHandleType::kInvokeDirect || - type == DexFile::MethodHandleType::kInvokeInterface; - static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface, - "Unexpected method handle types."); - IndexedItem* field_or_method_id; - if (is_invoke) { - field_or_method_id = GetMethodId(index); - } else { - field_or_method_id = GetFieldId(index); - } - CreateAndAddIndexedItem(method_handle_items_, - MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), - i, - type, - field_or_method_id); -} - -void Collections::SortVectorsByMapOrder() { - string_datas_.SortByMapOrder(string_datas_map_.Collection()); - type_lists_.SortByMapOrder(type_lists_map_.Collection()); - encoded_array_items_.SortByMapOrder(encoded_array_items_map_.Collection()); - annotation_items_.SortByMapOrder(annotation_items_map_.Collection()); - annotation_set_items_.SortByMapOrder(annotation_set_items_map_.Collection()); - annotation_set_ref_lists_.SortByMapOrder(annotation_set_ref_lists_map_.Collection()); - annotations_directory_items_.SortByMapOrder(annotations_directory_items_map_.Collection()); - debug_info_items_.SortByMapOrder(debug_info_items_map_.Collection()); - code_items_.SortByMapOrder(code_items_map_); - class_datas_.SortByMapOrder(class_datas_map_.Collection()); -} - -void Collections::ClearMaps() { - string_datas_map_.Collection().clear(); - type_lists_map_.Collection().clear(); - encoded_array_items_map_.Collection().clear(); - annotation_items_map_.Collection().clear(); - annotation_set_items_map_.Collection().clear(); - annotation_set_ref_lists_map_.Collection().clear(); - annotations_directory_items_map_.Collection().clear(); - debug_info_items_map_.Collection().clear(); - code_items_map_.clear(); - class_datas_map_.Collection().clear(); -} - -static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { +static uint32_t HeaderOffset(const dex_ir::Header* header ATTRIBUTE_UNUSED) { return 0; } -static uint32_t HeaderSize(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { +static uint32_t HeaderSize(const dex_ir::Header* header ATTRIBUTE_UNUSED) { // Size is in elements, so there is only one header. return 1; } @@ -907,9 +45,9 @@ struct FileSectionDescriptor { std::string name; uint16_t type; // A function that when applied to a collection object, gives the size of the section. - std::function<uint32_t(const dex_ir::Collections&)> size_fn; + std::function<uint32_t(dex_ir::Header*)> size_fn; // A function that when applied to a collection object, gives the offset of the section. - std::function<uint32_t(const dex_ir::Collections&)> offset_fn; + std::function<uint32_t(dex_ir::Header*)> offset_fn; }; static const FileSectionDescriptor kFileSectionDescriptors[] = { @@ -921,106 +59,105 @@ static const FileSectionDescriptor kFileSectionDescriptors[] = { }, { "StringId", DexFile::kDexTypeStringIdItem, - &dex_ir::Collections::StringIdsSize, - &dex_ir::Collections::StringIdsOffset + [](const dex_ir::Header* h) { return h->StringIds().Size(); }, + [](const dex_ir::Header* h) { return h->StringIds().GetOffset(); } }, { "TypeId", DexFile::kDexTypeTypeIdItem, - &dex_ir::Collections::TypeIdsSize, - &dex_ir::Collections::TypeIdsOffset + [](const dex_ir::Header* h) { return h->TypeIds().Size(); }, + [](const dex_ir::Header* h) { return h->TypeIds().GetOffset(); } }, { "ProtoId", DexFile::kDexTypeProtoIdItem, - &dex_ir::Collections::ProtoIdsSize, - &dex_ir::Collections::ProtoIdsOffset + [](const dex_ir::Header* h) { return h->ProtoIds().Size(); }, + [](const dex_ir::Header* h) { return h->ProtoIds().GetOffset(); } }, { "FieldId", DexFile::kDexTypeFieldIdItem, - &dex_ir::Collections::FieldIdsSize, - &dex_ir::Collections::FieldIdsOffset + [](const dex_ir::Header* h) { return h->FieldIds().Size(); }, + [](const dex_ir::Header* h) { return h->FieldIds().GetOffset(); } }, { "MethodId", DexFile::kDexTypeMethodIdItem, - &dex_ir::Collections::MethodIdsSize, - &dex_ir::Collections::MethodIdsOffset + [](const dex_ir::Header* h) { return h->MethodIds().Size(); }, + [](const dex_ir::Header* h) { return h->MethodIds().GetOffset(); } }, { "ClassDef", DexFile::kDexTypeClassDefItem, - &dex_ir::Collections::ClassDefsSize, - &dex_ir::Collections::ClassDefsOffset + [](const dex_ir::Header* h) { return h->ClassDefs().Size(); }, + [](const dex_ir::Header* h) { return h->ClassDefs().GetOffset(); } }, { "CallSiteId", DexFile::kDexTypeCallSiteIdItem, - &dex_ir::Collections::CallSiteIdsSize, - &dex_ir::Collections::CallSiteIdsOffset + [](const dex_ir::Header* h) { return h->CallSiteIds().Size(); }, + [](const dex_ir::Header* h) { return h->CallSiteIds().GetOffset(); } }, { "MethodHandle", DexFile::kDexTypeMethodHandleItem, - &dex_ir::Collections::MethodHandleItemsSize, - &dex_ir::Collections::MethodHandleItemsOffset + [](const dex_ir::Header* h) { return h->MethodHandleItems().Size(); }, + [](const dex_ir::Header* h) { return h->MethodHandleItems().GetOffset(); } }, { "StringData", DexFile::kDexTypeStringDataItem, - &dex_ir::Collections::StringDatasSize, - &dex_ir::Collections::StringDatasOffset + [](const dex_ir::Header* h) { return h->StringDatas().Size(); }, + [](const dex_ir::Header* h) { return h->StringDatas().GetOffset(); } }, { "TypeList", DexFile::kDexTypeTypeList, - &dex_ir::Collections::TypeListsSize, - &dex_ir::Collections::TypeListsOffset + [](const dex_ir::Header* h) { return h->TypeLists().Size(); }, + [](const dex_ir::Header* h) { return h->TypeLists().GetOffset(); } }, { "EncArr", DexFile::kDexTypeEncodedArrayItem, - &dex_ir::Collections::EncodedArrayItemsSize, - &dex_ir::Collections::EncodedArrayItemsOffset + [](const dex_ir::Header* h) { return h->EncodedArrayItems().Size(); }, + [](const dex_ir::Header* h) { return h->EncodedArrayItems().GetOffset(); } }, { "Annotation", DexFile::kDexTypeAnnotationItem, - &dex_ir::Collections::AnnotationItemsSize, - &dex_ir::Collections::AnnotationItemsOffset + [](const dex_ir::Header* h) { return h->AnnotationItems().Size(); }, + [](const dex_ir::Header* h) { return h->AnnotationItems().GetOffset(); } }, { "AnnoSet", DexFile::kDexTypeAnnotationSetItem, - &dex_ir::Collections::AnnotationSetItemsSize, - &dex_ir::Collections::AnnotationSetItemsOffset + [](const dex_ir::Header* h) { return h->AnnotationSetItems().Size(); }, + [](const dex_ir::Header* h) { return h->AnnotationSetItems().GetOffset(); } }, { "AnnoSetRL", DexFile::kDexTypeAnnotationSetRefList, - &dex_ir::Collections::AnnotationSetRefListsSize, - &dex_ir::Collections::AnnotationSetRefListsOffset + [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().Size(); }, + [](const dex_ir::Header* h) { return h->AnnotationSetRefLists().GetOffset(); } }, { "AnnoDir", DexFile::kDexTypeAnnotationsDirectoryItem, - &dex_ir::Collections::AnnotationsDirectoryItemsSize, - &dex_ir::Collections::AnnotationsDirectoryItemsOffset + [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().Size(); }, + [](const dex_ir::Header* h) { return h->AnnotationsDirectoryItems().GetOffset(); } }, { "DebugInfo", DexFile::kDexTypeDebugInfoItem, - &dex_ir::Collections::DebugInfoItemsSize, - &dex_ir::Collections::DebugInfoItemsOffset + [](const dex_ir::Header* h) { return h->DebugInfoItems().Size(); }, + [](const dex_ir::Header* h) { return h->DebugInfoItems().GetOffset(); } }, { "CodeItem", DexFile::kDexTypeCodeItem, - &dex_ir::Collections::CodeItemsSize, - &dex_ir::Collections::CodeItemsOffset + [](const dex_ir::Header* h) { return h->CodeItems().Size(); }, + [](const dex_ir::Header* h) { return h->CodeItems().GetOffset(); } }, { "ClassData", DexFile::kDexTypeClassDataItem, - &dex_ir::Collections::ClassDatasSize, - &dex_ir::Collections::ClassDatasOffset + [](const dex_ir::Header* h) { return h->ClassDatas().Size(); }, + [](const dex_ir::Header* h) { return h->ClassDatas().GetOffset(); } } }; std::vector<dex_ir::DexFileSection> GetSortedDexFileSections(dex_ir::Header* header, dex_ir::SortDirection direction) { - const dex_ir::Collections& collections = header->GetCollections(); std::vector<dex_ir::DexFileSection> sorted_sections; // Build the table that will map from offset to color for (const FileSectionDescriptor& s : kFileSectionDescriptors) { sorted_sections.push_back(dex_ir::DexFileSection(s.name, s.type, - s.size_fn(collections), - s.offset_fn(collections))); + s.size_fn(header), + s.offset_fn(header))); } // Sort by offset. std::sort(sorted_sections.begin(), diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 54ff105820..9f355ba9e8 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -24,6 +24,7 @@ #include <map> #include <vector> +#include "base/iteration_range.h" #include "base/leb128.h" #include "base/stl_util.h" #include "dex/dex_file-inl.h" @@ -107,37 +108,153 @@ class AbstractDispatcher { DISALLOW_COPY_AND_ASSIGN(AbstractDispatcher); }; -// Collections become owners of the objects added by moving them into unique pointers. -template<class T> class CollectionBase { +template<class T> class Iterator : public std::iterator<std::random_access_iterator_tag, T> { public: - CollectionBase() = default; + using value_type = typename std::iterator<std::random_access_iterator_tag, T>::value_type; + using difference_type = + typename std::iterator<std::random_access_iterator_tag, value_type>::difference_type; + using pointer = typename std::iterator<std::random_access_iterator_tag, value_type>::pointer; + using reference = typename std::iterator<std::random_access_iterator_tag, value_type>::reference; + + Iterator(const Iterator&) = default; + Iterator(Iterator&&) = default; + Iterator& operator=(const Iterator&) = default; + Iterator& operator=(Iterator&&) = default; + + Iterator(const std::vector<T>& vector, + uint32_t position, + uint32_t iterator_end) + : vector_(&vector), + position_(position), + iterator_end_(iterator_end) { } + Iterator() : vector_(nullptr), position_(0U), iterator_end_(0U) { } + + bool IsValid() const { return position_ < iterator_end_; } + + bool operator==(const Iterator& rhs) const { return position_ == rhs.position_; } + bool operator!=(const Iterator& rhs) const { return !(*this == rhs); } + bool operator<(const Iterator& rhs) const { return position_ < rhs.position_; } + bool operator>(const Iterator& rhs) const { return rhs < *this; } + bool operator<=(const Iterator& rhs) const { return !(rhs < *this); } + bool operator>=(const Iterator& rhs) const { return !(*this < rhs); } + + Iterator& operator++() { // Value after modification. + ++position_; + return *this; + } - uint32_t GetOffset() const { - return offset_; + Iterator operator++(int) { + Iterator temp = *this; + ++position_; + return temp; + } + + Iterator& operator+=(difference_type delta) { + position_ += delta; + return *this; + } + + Iterator operator+(difference_type delta) const { + Iterator temp = *this; + temp += delta; + return temp; + } + + Iterator& operator--() { // Value after modification. + --position_; + return *this; + } + + Iterator operator--(int) { + Iterator temp = *this; + --position_; + return temp; } - void SetOffset(uint32_t new_offset) { - offset_ = new_offset; + + Iterator& operator-=(difference_type delta) { + position_ -= delta; + return *this; + } + + Iterator operator-(difference_type delta) const { + Iterator temp = *this; + temp -= delta; + return temp; + } + + difference_type operator-(const Iterator& rhs) { + return position_ - rhs.position_; + } + + reference operator*() const { + return const_cast<reference>((*vector_)[position_]); + } + + pointer operator->() const { + return const_cast<pointer>(&((*vector_)[position_])); + } + + reference operator[](difference_type n) const { + return (*vector_)[position_ + n]; } private: + const std::vector<T>* vector_; + uint32_t position_; + uint32_t iterator_end_; + + template <typename U> + friend bool operator<(const Iterator<U>& lhs, const Iterator<U>& rhs); +}; + +// Collections become owners of the objects added by moving them into unique pointers. +class CollectionBase { + public: + CollectionBase() = default; + virtual ~CollectionBase() { } + + uint32_t GetOffset() const { return offset_; } + void SetOffset(uint32_t new_offset) { offset_ = new_offset; } + virtual uint32_t Size() const { return 0U; } + + private: // Start out unassigned. uint32_t offset_ = 0u; DISALLOW_COPY_AND_ASSIGN(CollectionBase); }; -template<class T> class CollectionVector : public CollectionBase<T> { +template<class T> class CollectionVector : public CollectionBase { public: - using Vector = std::vector<std::unique_ptr<T>>; + using ElementType = std::unique_ptr<T>; + CollectionVector() { } explicit CollectionVector(size_t size) { // Preallocate so that assignment does not invalidate pointers into the vector. collection_.reserve(size); } + virtual ~CollectionVector() OVERRIDE { } - uint32_t Size() const { return collection_.size(); } - Vector& Collection() { return collection_; } - const Vector& Collection() const { return collection_; } + template<class... Args> + T* CreateAndAddItem(Args&&... args) { + T* object = new T(std::forward<Args>(args)...); + collection_.push_back(std::unique_ptr<T>(object)); + return object; + } + + virtual uint32_t Size() const OVERRIDE { return collection_.size(); } + + Iterator<ElementType> begin() const { return Iterator<ElementType>(collection_, 0U, Size()); } + Iterator<ElementType> end() const { return Iterator<ElementType>(collection_, Size(), Size()); } + + const ElementType& operator[](size_t index) const { + DCHECK_LT(index, Size()); + return collection_[index]; + } + ElementType& operator[](size_t index) { + DCHECK_LT(index, Size()); + return collection_[index]; + } // Sort the vector by copying pointers over. template <typename MapType> @@ -147,24 +264,16 @@ template<class T> class CollectionVector : public CollectionBase<T> { for (size_t i = 0; i < Size(); ++i) { // There are times when the array will temporarily contain the same pointer twice, doing the // release here sure there is no double free errors. - Collection()[i].release(); - Collection()[i].reset(it->second); + collection_[i].release(); + collection_[i].reset(it->second); ++it; } } protected: - Vector collection_; - - template<class... Args> - T* CreateAndAddItem(Args&&... args) { - T* object = new T(std::forward<Args>(args)...); - collection_.push_back(std::unique_ptr<T>(object)); - return object; - } + std::vector<ElementType> collection_; private: - friend class Collections; DISALLOW_COPY_AND_ASSIGN(CollectionVector); }; @@ -174,7 +283,6 @@ template<class T> class IndexedCollectionVector : public CollectionVector<T> { IndexedCollectionVector() = default; explicit IndexedCollectionVector(size_t size) : CollectionVector<T>(size) { } - private: template <class... Args> T* CreateAndAddIndexedItem(uint32_t index, Args&&... args) { T* object = CollectionVector<T>::CreateAndAddItem(std::forward<Args>(args)...); @@ -182,330 +290,13 @@ template<class T> class IndexedCollectionVector : public CollectionVector<T> { return object; } - T* GetElement(uint32_t index) { - DCHECK_LT(index, CollectionVector<T>::Size()); + T* operator[](size_t index) const { DCHECK_NE(CollectionVector<T>::collection_[index].get(), static_cast<T*>(nullptr)); return CollectionVector<T>::collection_[index].get(); } - friend class Collections; - DISALLOW_COPY_AND_ASSIGN(IndexedCollectionVector); -}; - -template<class T> class CollectionMap : public CollectionBase<T> { - public: - CollectionMap() = default; - - // Returns the existing item if it is already inserted, null otherwise. - T* GetExistingObject(uint32_t offset) { - auto it = collection_.find(offset); - return it != collection_.end() ? it->second : nullptr; - } - - // Lower case for template interop with std::map. - uint32_t size() const { return collection_.size(); } - std::map<uint32_t, T*>& Collection() { return collection_; } - private: - std::map<uint32_t, T*> collection_; - - // CollectionMaps do not own the objects they contain, therefore AddItem is supported - // rather than CreateAndAddItem. - void AddItem(T* object, uint32_t offset) { - auto it = collection_.emplace(offset, object); - CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " " - << " and address " << it.first->second; - } - - friend class Collections; - DISALLOW_COPY_AND_ASSIGN(CollectionMap); -}; - -class Collections { - public: - Collections() = default; - Collections(uint32_t num_string_ids, - uint32_t num_type_ids, - uint32_t num_proto_ids, - uint32_t num_field_ids, - uint32_t num_method_ids, - uint32_t num_class_defs) - : string_ids_(num_string_ids), - type_ids_(num_type_ids), - proto_ids_(num_proto_ids), - field_ids_(num_field_ids), - method_ids_(num_method_ids), - class_defs_(num_class_defs) { } - - IndexedCollectionVector<StringId>::Vector& StringIds() { return string_ids_.Collection(); } - IndexedCollectionVector<TypeId>::Vector& TypeIds() { return type_ids_.Collection(); } - IndexedCollectionVector<ProtoId>::Vector& ProtoIds() { return proto_ids_.Collection(); } - IndexedCollectionVector<FieldId>::Vector& FieldIds() { return field_ids_.Collection(); } - IndexedCollectionVector<MethodId>::Vector& MethodIds() { return method_ids_.Collection(); } - IndexedCollectionVector<ClassDef>::Vector& ClassDefs() { return class_defs_.Collection(); } - CollectionVector<CallSiteId>::Vector& CallSiteIds() { return call_site_ids_.Collection(); } - CollectionVector<MethodHandleItem>::Vector& MethodHandleItems() - { return method_handle_items_.Collection(); } - CollectionVector<StringData>::Vector& StringDatas() { return string_datas_.Collection(); } - CollectionVector<TypeList>::Vector& TypeLists() { return type_lists_.Collection(); } - CollectionVector<EncodedArrayItem>::Vector& EncodedArrayItems() - { return encoded_array_items_.Collection(); } - CollectionVector<AnnotationItem>::Vector& AnnotationItems() - { return annotation_items_.Collection(); } - CollectionVector<AnnotationSetItem>::Vector& AnnotationSetItems() - { return annotation_set_items_.Collection(); } - CollectionVector<AnnotationSetRefList>::Vector& AnnotationSetRefLists() - { return annotation_set_ref_lists_.Collection(); } - CollectionVector<AnnotationsDirectoryItem>::Vector& AnnotationsDirectoryItems() - { return annotations_directory_items_.Collection(); } - CollectionVector<DebugInfoItem>::Vector& DebugInfoItems() - { return debug_info_items_.Collection(); } - CollectionVector<CodeItem>::Vector& CodeItems() { return code_items_.Collection(); } - CollectionVector<ClassData>::Vector& ClassDatas() { return class_datas_.Collection(); } - - const CollectionVector<ClassDef>::Vector& ClassDefs() const { return class_defs_.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); - void CreateCallSiteId(const DexFile& dex_file, uint32_t i); - void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i); - - void CreateCallSitesAndMethodHandles(const DexFile& dex_file); - - TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset); - EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file, - const uint8_t* static_data, - uint32_t offset); - AnnotationItem* CreateAnnotationItem(const DexFile& dex_file, - const DexFile::AnnotationItem* annotation); - 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* DedupeOrCreateCodeItem(const DexFile& dex_file, - const DexFile::CodeItem* disk_code_item, - uint32_t offset, - uint32_t dex_method_index); - ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset); - void AddAnnotationsFromMapListSection(const DexFile& dex_file, - uint32_t start_offset, - uint32_t count); - - StringId* GetStringId(uint32_t index) { - return string_ids_.GetElement(index); - } - TypeId* GetTypeId(uint32_t index) { - return type_ids_.GetElement(index); - } - ProtoId* GetProtoId(uint32_t index) { - return proto_ids_.GetElement(index); - } - FieldId* GetFieldId(uint32_t index) { - return field_ids_.GetElement(index); - } - MethodId* GetMethodId(uint32_t index) { - return method_ids_.GetElement(index); - } - ClassDef* GetClassDef(uint32_t index) { - return class_defs_.GetElement(index); - } - CallSiteId* GetCallSiteId(uint32_t index) { - CHECK_LT(index, CallSiteIdsSize()); - return CallSiteIds()[index].get(); - } - MethodHandleItem* GetMethodHandle(uint32_t index) { - CHECK_LT(index, MethodHandleItemsSize()); - return MethodHandleItems()[index].get(); - } - - StringId* GetStringIdOrNullPtr(uint32_t index) { - return index == dex::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 CallSiteIdsOffset() const { return call_site_ids_.GetOffset(); } - uint32_t MethodHandleItemsOffset() const { return method_handle_items_.GetOffset(); } - uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); } - uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); } - uint32_t EncodedArrayItemsOffset() const { return encoded_array_items_.GetOffset(); } - uint32_t AnnotationItemsOffset() const { return annotation_items_.GetOffset(); } - uint32_t AnnotationSetItemsOffset() const { return annotation_set_items_.GetOffset(); } - uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); } - uint32_t AnnotationsDirectoryItemsOffset() const - { return annotations_directory_items_.GetOffset(); } - uint32_t DebugInfoItemsOffset() const { return debug_info_items_.GetOffset(); } - uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); } - uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); } - uint32_t MapListOffset() const { return map_list_offset_; } - - 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 SetCallSiteIdsOffset(uint32_t new_offset) { call_site_ids_.SetOffset(new_offset); } - void SetMethodHandleItemsOffset(uint32_t new_offset) - { method_handle_items_.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 SetEncodedArrayItemsOffset(uint32_t new_offset) - { encoded_array_items_.SetOffset(new_offset); } - void SetAnnotationItemsOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); } - void SetAnnotationSetItemsOffset(uint32_t new_offset) - { annotation_set_items_.SetOffset(new_offset); } - void SetAnnotationSetRefListsOffset(uint32_t new_offset) - { annotation_set_ref_lists_.SetOffset(new_offset); } - void SetAnnotationsDirectoryItemsOffset(uint32_t new_offset) - { annotations_directory_items_.SetOffset(new_offset); } - void SetDebugInfoItemsOffset(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); } - void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = 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(); } - uint32_t CallSiteIdsSize() const { return call_site_ids_.Size(); } - uint32_t MethodHandleItemsSize() const { return method_handle_items_.Size(); } - uint32_t StringDatasSize() const { return string_datas_.Size(); } - uint32_t TypeListsSize() const { return type_lists_.Size(); } - uint32_t EncodedArrayItemsSize() const { return encoded_array_items_.Size(); } - uint32_t AnnotationItemsSize() const { return annotation_items_.Size(); } - uint32_t AnnotationSetItemsSize() const { return annotation_set_items_.Size(); } - uint32_t AnnotationSetRefListsSize() const { return annotation_set_ref_lists_.Size(); } - uint32_t AnnotationsDirectoryItemsSize() const { return annotations_directory_items_.Size(); } - uint32_t DebugInfoItemsSize() const { return debug_info_items_.Size(); } - uint32_t CodeItemsSize() const { return code_items_.Size(); } - uint32_t ClassDatasSize() const { return class_datas_.Size(); } - - // Sort the vectors buy map order (same order that was used in the input file). - void SortVectorsByMapOrder(); - // Empty the maps, which are only used for IR construction. - void ClearMaps(); - - template <typename Type, class... Args> - Type* CreateAndAddItem(CollectionMap<Type>& map, - CollectionVector<Type>& vector, - uint32_t offset, - Args&&... args) { - Type* item = vector.CreateAndAddItem(std::forward<Args>(args)...); - DCHECK(!map.GetExistingObject(offset)); - DCHECK(!item->OffsetAssigned()); - if (eagerly_assign_offsets_) { - item->SetOffset(offset); - } - map.AddItem(item, offset); - return item; - } - - template <typename Type, class... Args> - Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector, - uint32_t offset, - uint32_t index, - Args&&... args) { - Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...); - DCHECK(!item->OffsetAssigned()); - if (eagerly_assign_offsets_) { - item->SetOffset(offset); - } - return item; - } - - void SetEagerlyAssignOffsets(bool eagerly_assign_offsets) { - eagerly_assign_offsets_ = eagerly_assign_offsets; - } - - void SetLinkData(std::vector<uint8_t>&& link_data) { - link_data_ = std::move(link_data); - } - - const std::vector<uint8_t>& LinkData() const { - return link_data_; - } - - private: - EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data); - EncodedValue* ReadEncodedValue(const DexFile& dex_file, - const uint8_t** data, - uint8_t type, - uint8_t length); - void ReadEncodedValue(const DexFile& dex_file, - 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); - - // Collection vectors own the IR data. - IndexedCollectionVector<StringId> string_ids_; - IndexedCollectionVector<TypeId> type_ids_; - IndexedCollectionVector<ProtoId> proto_ids_; - IndexedCollectionVector<FieldId> field_ids_; - IndexedCollectionVector<MethodId> method_ids_; - IndexedCollectionVector<ClassDef> class_defs_; - IndexedCollectionVector<CallSiteId> call_site_ids_; - IndexedCollectionVector<MethodHandleItem> method_handle_items_; - IndexedCollectionVector<StringData> string_datas_; - IndexedCollectionVector<TypeList> type_lists_; - IndexedCollectionVector<EncodedArrayItem> encoded_array_items_; - IndexedCollectionVector<AnnotationItem> annotation_items_; - IndexedCollectionVector<AnnotationSetItem> annotation_set_items_; - IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_; - IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_; - // The order of the vectors controls the layout of the output file by index order, to change the - // layout just sort the vector. Note that you may only change the order of the non indexed vectors - // below. Indexed vectors are accessed by indices in other places, changing the sorting order will - // invalidate the existing indices and is not currently supported. - CollectionVector<DebugInfoItem> debug_info_items_; - CollectionVector<CodeItem> code_items_; - CollectionVector<ClassData> class_datas_; - - // Note that the maps do not have ownership, the vectors do. - // TODO: These maps should only be required for building the IR and should be put in a separate - // IR builder class. - CollectionMap<StringData> string_datas_map_; - CollectionMap<TypeList> type_lists_map_; - CollectionMap<EncodedArrayItem> encoded_array_items_map_; - CollectionMap<AnnotationItem> annotation_items_map_; - CollectionMap<AnnotationSetItem> annotation_set_items_map_; - CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_; - CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_; - CollectionMap<DebugInfoItem> debug_info_items_map_; - // Code item maps need to check both the debug info offset and debug info offset, do not use - // CollectionMap. - // First offset is the code item offset, second is the debug info offset. - std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_; - CollectionMap<ClassData> class_datas_map_; - - uint32_t map_list_offset_ = 0; - - // Link data. - std::vector<uint8_t> link_data_; - - // If we eagerly assign offsets during IR building or later after layout. Must be false if - // changing the layout is enabled. - bool eagerly_assign_offsets_; - - DISALLOW_COPY_AND_ASSIGN(Collections); + DISALLOW_COPY_AND_ASSIGN(IndexedCollectionVector); }; class Item { @@ -598,12 +389,12 @@ class Header : public Item { uint32_t num_class_defs) : Item(0, kHeaderItemSize), support_default_methods_(support_default_methods), - collections_(num_string_ids, - num_type_ids, - num_proto_ids, - num_field_ids, - num_method_ids, - num_class_defs) { + string_ids_(num_string_ids), + type_ids_(num_type_ids), + proto_ids_(num_proto_ids), + field_ids_(num_field_ids), + method_ids_(num_method_ids), + class_defs_(num_class_defs) { ConstructorHelper(magic, checksum, signature, @@ -641,7 +432,69 @@ class Header : public Item { 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& GetCollections() { return collections_; } + IndexedCollectionVector<StringId>& StringIds() { return string_ids_; } + const IndexedCollectionVector<StringId>& StringIds() const { return string_ids_; } + IndexedCollectionVector<TypeId>& TypeIds() { return type_ids_; } + const IndexedCollectionVector<TypeId>& TypeIds() const { return type_ids_; } + IndexedCollectionVector<ProtoId>& ProtoIds() { return proto_ids_; } + const IndexedCollectionVector<ProtoId>& ProtoIds() const { return proto_ids_; } + IndexedCollectionVector<FieldId>& FieldIds() { return field_ids_; } + const IndexedCollectionVector<FieldId>& FieldIds() const { return field_ids_; } + IndexedCollectionVector<MethodId>& MethodIds() { return method_ids_; } + const IndexedCollectionVector<MethodId>& MethodIds() const { return method_ids_; } + IndexedCollectionVector<ClassDef>& ClassDefs() { return class_defs_; } + const IndexedCollectionVector<ClassDef>& ClassDefs() const { return class_defs_; } + IndexedCollectionVector<CallSiteId>& CallSiteIds() { return call_site_ids_; } + const IndexedCollectionVector<CallSiteId>& CallSiteIds() const { return call_site_ids_; } + IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() { return method_handle_items_; } + const IndexedCollectionVector<MethodHandleItem>& MethodHandleItems() const { + return method_handle_items_; + } + CollectionVector<StringData>& StringDatas() { return string_datas_; } + const CollectionVector<StringData>& StringDatas() const { return string_datas_; } + CollectionVector<TypeList>& TypeLists() { return type_lists_; } + const CollectionVector<TypeList>& TypeLists() const { return type_lists_; } + CollectionVector<EncodedArrayItem>& EncodedArrayItems() { return encoded_array_items_; } + const CollectionVector<EncodedArrayItem>& EncodedArrayItems() const { + return encoded_array_items_; + } + CollectionVector<AnnotationItem>& AnnotationItems() { return annotation_items_; } + const CollectionVector<AnnotationItem>& AnnotationItems() const { return annotation_items_; } + CollectionVector<AnnotationSetItem>& AnnotationSetItems() { return annotation_set_items_; } + const CollectionVector<AnnotationSetItem>& AnnotationSetItems() const { + return annotation_set_items_; + } + CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() { + return annotation_set_ref_lists_; + } + const CollectionVector<AnnotationSetRefList>& AnnotationSetRefLists() const { + return annotation_set_ref_lists_; + } + CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() { + return annotations_directory_items_; + } + const CollectionVector<AnnotationsDirectoryItem>& AnnotationsDirectoryItems() const { + return annotations_directory_items_; + } + CollectionVector<DebugInfoItem>& DebugInfoItems() { return debug_info_items_; } + const CollectionVector<DebugInfoItem>& DebugInfoItems() const { return debug_info_items_; } + CollectionVector<CodeItem>& CodeItems() { return code_items_; } + const CollectionVector<CodeItem>& CodeItems() const { return code_items_; } + CollectionVector<ClassData>& ClassDatas() { return class_datas_; } + const CollectionVector<ClassData>& ClassDatas() const { return class_datas_; } + + StringId* GetStringIdOrNullPtr(uint32_t index) { + return index == dex::kDexNoIndex ? nullptr : StringIds()[index]; + } + TypeId* GetTypeIdOrNullPtr(uint16_t index) { + return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index]; + } + + uint32_t MapListOffset() const { return map_list_offset_; } + void SetMapListOffset(uint32_t new_offset) { map_list_offset_ = new_offset; } + + const std::vector<uint8_t>& LinkData() const { return link_data_; } + void SetLinkData(std::vector<uint8_t>&& link_data) { link_data_ = std::move(link_data); } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } @@ -683,7 +536,35 @@ class Header : public Item { memcpy(magic_, magic, sizeof(magic_)); memcpy(signature_, signature, sizeof(signature_)); } - Collections collections_; + + // Collection vectors own the IR data. + IndexedCollectionVector<StringId> string_ids_; + IndexedCollectionVector<TypeId> type_ids_; + IndexedCollectionVector<ProtoId> proto_ids_; + IndexedCollectionVector<FieldId> field_ids_; + IndexedCollectionVector<MethodId> method_ids_; + IndexedCollectionVector<ClassDef> class_defs_; + IndexedCollectionVector<CallSiteId> call_site_ids_; + IndexedCollectionVector<MethodHandleItem> method_handle_items_; + IndexedCollectionVector<StringData> string_datas_; + IndexedCollectionVector<TypeList> type_lists_; + IndexedCollectionVector<EncodedArrayItem> encoded_array_items_; + IndexedCollectionVector<AnnotationItem> annotation_items_; + IndexedCollectionVector<AnnotationSetItem> annotation_set_items_; + IndexedCollectionVector<AnnotationSetRefList> annotation_set_ref_lists_; + IndexedCollectionVector<AnnotationsDirectoryItem> annotations_directory_items_; + // The order of the vectors controls the layout of the output file by index order, to change the + // layout just sort the vector. Note that you may only change the order of the non indexed vectors + // below. Indexed vectors are accessed by indices in other places, changing the sorting order will + // invalidate the existing indices and is not currently supported. + CollectionVector<DebugInfoItem> debug_info_items_; + CollectionVector<CodeItem> code_items_; + CollectionVector<ClassData> class_datas_; + + uint32_t map_list_offset_ = 0; + + // Link data. + std::vector<uint8_t> link_data_; DISALLOW_COPY_AND_ASSIGN(Header); }; diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index 9468f763d6..a04a2349c4 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -20,14 +20,226 @@ #include <vector> #include "dex_ir_builder.h" + +#include "dex/code_item_accessors-inl.h" +#include "dex/dex_file_exception_helpers.h" #include "dexlayout.h" namespace art { namespace dex_ir { -static void CheckAndSetRemainingOffsets(const DexFile& dex_file, - Collections* collections, - const Options& options); +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 uint32_t GetDebugInfoStreamSize(const uint8_t* debug_info_stream) { + const uint8_t* stream = debug_info_stream; + DecodeUnsignedLeb128(&stream); // line_start + uint32_t parameters_size = DecodeUnsignedLeb128(&stream); + for (uint32_t i = 0; i < parameters_size; ++i) { + DecodeUnsignedLeb128P1(&stream); // Parameter name. + } + + for (;;) { + uint8_t opcode = *stream++; + switch (opcode) { + case DexFile::DBG_END_SEQUENCE: + return stream - debug_info_stream; // end of stream. + case DexFile::DBG_ADVANCE_PC: + DecodeUnsignedLeb128(&stream); // addr_diff + break; + case DexFile::DBG_ADVANCE_LINE: + DecodeSignedLeb128(&stream); // line_diff + break; + case DexFile::DBG_START_LOCAL: + DecodeUnsignedLeb128(&stream); // register_num + DecodeUnsignedLeb128P1(&stream); // name_idx + DecodeUnsignedLeb128P1(&stream); // type_idx + break; + case DexFile::DBG_START_LOCAL_EXTENDED: + DecodeUnsignedLeb128(&stream); // register_num + DecodeUnsignedLeb128P1(&stream); // name_idx + DecodeUnsignedLeb128P1(&stream); // type_idx + DecodeUnsignedLeb128P1(&stream); // sig_idx + break; + case DexFile::DBG_END_LOCAL: + case DexFile::DBG_RESTART_LOCAL: + DecodeUnsignedLeb128(&stream); // register_num + break; + case DexFile::DBG_SET_PROLOGUE_END: + case DexFile::DBG_SET_EPILOGUE_BEGIN: + break; + case DexFile::DBG_SET_FILE: { + DecodeUnsignedLeb128P1(&stream); // name_idx + break; + } + default: { + break; + } + } + } +} + +template<class T> class CollectionMap : public CollectionBase { + public: + CollectionMap() = default; + virtual ~CollectionMap() OVERRIDE { } + + template <class... Args> + T* CreateAndAddItem(CollectionVector<T>& vector, + bool eagerly_assign_offsets, + uint32_t offset, + Args&&... args) { + T* item = vector.CreateAndAddItem(std::forward<Args>(args)...); + DCHECK(!GetExistingObject(offset)); + DCHECK(!item->OffsetAssigned()); + if (eagerly_assign_offsets) { + item->SetOffset(offset); + } + AddItem(item, offset); + return item; + } + + // Returns the existing item if it is already inserted, null otherwise. + T* GetExistingObject(uint32_t offset) { + auto it = collection_.find(offset); + return it != collection_.end() ? it->second : nullptr; + } + + // Lower case for template interop with std::map. + uint32_t size() const { return collection_.size(); } + std::map<uint32_t, T*>& Collection() { return collection_; } + + private: + std::map<uint32_t, T*> collection_; + + // CollectionMaps do not own the objects they contain, therefore AddItem is supported + // rather than CreateAndAddItem. + void AddItem(T* object, uint32_t offset) { + auto it = collection_.emplace(offset, object); + CHECK(it.second) << "CollectionMap already has an object with offset " << offset << " " + << " and address " << it.first->second; + } + + DISALLOW_COPY_AND_ASSIGN(CollectionMap); +}; + +class BuilderMaps { + public: + BuilderMaps(Header* header, bool eagerly_assign_offsets) + : header_(header), eagerly_assign_offsets_(eagerly_assign_offsets) { } + + 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); + void CreateCallSiteId(const DexFile& dex_file, uint32_t i); + void CreateMethodHandleItem(const DexFile& dex_file, uint32_t i); + + void CreateCallSitesAndMethodHandles(const DexFile& dex_file); + + TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset); + EncodedArrayItem* CreateEncodedArrayItem(const DexFile& dex_file, + const uint8_t* static_data, + uint32_t offset); + AnnotationItem* CreateAnnotationItem(const DexFile& dex_file, + const DexFile::AnnotationItem* annotation); + 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* DedupeOrCreateCodeItem(const DexFile& dex_file, + const DexFile::CodeItem* disk_code_item, + uint32_t offset, + uint32_t dex_method_index); + ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset); + + void AddAnnotationsFromMapListSection(const DexFile& dex_file, + uint32_t start_offset, + uint32_t count); + + void CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options); + + // Sort the vectors buy map order (same order that was used in the input file). + void SortVectorsByMapOrder(); + + private: + bool GetIdsFromByteCode(const CodeItem* code, + std::vector<TypeId*>* type_ids, + std::vector<StringId*>* string_ids, + std::vector<MethodId*>* method_ids, + std::vector<FieldId*>* field_ids); + + bool GetIdFromInstruction(const Instruction* dec_insn, + std::vector<TypeId*>* type_ids, + std::vector<StringId*>* string_ids, + std::vector<MethodId*>* method_ids, + std::vector<FieldId*>* field_ids); + + EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data); + EncodedValue* ReadEncodedValue(const DexFile& dex_file, + const uint8_t** data, + uint8_t type, + uint8_t length); + void ReadEncodedValue(const DexFile& dex_file, + const uint8_t** data, + uint8_t type, + uint8_t length, + EncodedValue* item); + + MethodItem GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii); + + ParameterAnnotation* GenerateParameterAnnotation( + const DexFile& dex_file, + MethodId* method_id, + const DexFile::AnnotationSetRefList* annotation_set_ref_list, + uint32_t offset); + + template <typename Type, class... Args> + Type* CreateAndAddIndexedItem(IndexedCollectionVector<Type>& vector, + uint32_t offset, + uint32_t index, + Args&&... args) { + Type* item = vector.CreateAndAddIndexedItem(index, std::forward<Args>(args)...); + DCHECK(!item->OffsetAssigned()); + if (eagerly_assign_offsets_) { + item->SetOffset(offset); + } + return item; + } + + Header* header_; + // If we eagerly assign offsets during IR building or later after layout. Must be false if + // changing the layout is enabled. + bool eagerly_assign_offsets_; + + // Note: maps do not have ownership. + CollectionMap<StringData> string_datas_map_; + CollectionMap<TypeList> type_lists_map_; + CollectionMap<EncodedArrayItem> encoded_array_items_map_; + CollectionMap<AnnotationItem> annotation_items_map_; + CollectionMap<AnnotationSetItem> annotation_set_items_map_; + CollectionMap<AnnotationSetRefList> annotation_set_ref_lists_map_; + CollectionMap<AnnotationsDirectoryItem> annotations_directory_items_map_; + CollectionMap<DebugInfoItem> debug_info_items_map_; + // Code item maps need to check both the debug info offset and debug info offset, do not use + // CollectionMap. + // First offset is the code item offset, second is the debug info offset. + std::map<std::pair<uint32_t, uint32_t>, CodeItem*> code_items_map_; + CollectionMap<ClassData> class_datas_map_; + + DISALLOW_COPY_AND_ASSIGN(BuilderMaps); +}; Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets, @@ -50,36 +262,35 @@ Header* DexIrBuilder(const DexFile& dex_file, dex_file.NumFieldIds(), dex_file.NumMethodIds(), dex_file.NumClassDefs()); - Collections& collections = header->GetCollections(); - collections.SetEagerlyAssignOffsets(eagerly_assign_offsets); + BuilderMaps builder_maps(header, eagerly_assign_offsets); // Walk the rest of the header fields. // StringId table. - collections.SetStringIdsOffset(disk_header.string_ids_off_); + header->StringIds().SetOffset(disk_header.string_ids_off_); for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) { - collections.CreateStringId(dex_file, i); + builder_maps.CreateStringId(dex_file, i); } // TypeId table. - collections.SetTypeIdsOffset(disk_header.type_ids_off_); + header->TypeIds().SetOffset(disk_header.type_ids_off_); for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) { - collections.CreateTypeId(dex_file, i); + builder_maps.CreateTypeId(dex_file, i); } // ProtoId table. - collections.SetProtoIdsOffset(disk_header.proto_ids_off_); + header->ProtoIds().SetOffset(disk_header.proto_ids_off_); for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) { - collections.CreateProtoId(dex_file, i); + builder_maps.CreateProtoId(dex_file, i); } // FieldId table. - collections.SetFieldIdsOffset(disk_header.field_ids_off_); + header->FieldIds().SetOffset(disk_header.field_ids_off_); for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) { - collections.CreateFieldId(dex_file, i); + builder_maps.CreateFieldId(dex_file, i); } // MethodId table. - collections.SetMethodIdsOffset(disk_header.method_ids_off_); + header->MethodIds().SetOffset(disk_header.method_ids_off_); for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) { - collections.CreateMethodId(dex_file, i); + builder_maps.CreateMethodId(dex_file, i); } // ClassDef table. - collections.SetClassDefsOffset(disk_header.class_defs_off_); + header->ClassDefs().SetOffset(disk_header.class_defs_off_); for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) { if (!options.class_filter_.empty()) { // If the filter is enabled (not empty), filter out classes that don't have a matching @@ -90,29 +301,29 @@ Header* DexIrBuilder(const DexFile& dex_file, continue; } } - collections.CreateClassDef(dex_file, i); + builder_maps.CreateClassDef(dex_file, i); } // MapItem. - collections.SetMapListOffset(disk_header.map_off_); + header->SetMapListOffset(disk_header.map_off_); // CallSiteIds and MethodHandleItems. - collections.CreateCallSitesAndMethodHandles(dex_file); - CheckAndSetRemainingOffsets(dex_file, &collections, options); + builder_maps.CreateCallSitesAndMethodHandles(dex_file); + builder_maps.CheckAndSetRemainingOffsets(dex_file, options); // Sort the vectors by the map order (same order as the file). - collections.SortVectorsByMapOrder(); - collections.ClearMaps(); + builder_maps.SortVectorsByMapOrder(); // Load the link data if it exists. - collections.SetLinkData(std::vector<uint8_t>( + header->SetLinkData(std::vector<uint8_t>( dex_file.DataBegin() + dex_file.GetHeader().link_off_, dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_)); return header; } -static void CheckAndSetRemainingOffsets(const DexFile& dex_file, - Collections* collections, - const Options& options) { +/* + * Get all the types, strings, methods, and fields referred to from bytecode. + */ +void BuilderMaps::CheckAndSetRemainingOffsets(const DexFile& dex_file, const Options& options) { const DexFile::Header& disk_header = dex_file.GetHeader(); // Read MapItems and validate/set remaining offsets. const DexFile::MapList* map = dex_file.GetMapList(); @@ -125,74 +336,74 @@ static void CheckAndSetRemainingOffsets(const DexFile& dex_file, CHECK_EQ(item->offset_, 0u); break; case DexFile::kDexTypeStringIdItem: - CHECK_EQ(item->size_, collections->StringIdsSize()); - CHECK_EQ(item->offset_, collections->StringIdsOffset()); + CHECK_EQ(item->size_, header_->StringIds().Size()); + CHECK_EQ(item->offset_, header_->StringIds().GetOffset()); break; case DexFile::kDexTypeTypeIdItem: - CHECK_EQ(item->size_, collections->TypeIdsSize()); - CHECK_EQ(item->offset_, collections->TypeIdsOffset()); + CHECK_EQ(item->size_, header_->TypeIds().Size()); + CHECK_EQ(item->offset_, header_->TypeIds().GetOffset()); break; case DexFile::kDexTypeProtoIdItem: - CHECK_EQ(item->size_, collections->ProtoIdsSize()); - CHECK_EQ(item->offset_, collections->ProtoIdsOffset()); + CHECK_EQ(item->size_, header_->ProtoIds().Size()); + CHECK_EQ(item->offset_, header_->ProtoIds().GetOffset()); break; case DexFile::kDexTypeFieldIdItem: - CHECK_EQ(item->size_, collections->FieldIdsSize()); - CHECK_EQ(item->offset_, collections->FieldIdsOffset()); + CHECK_EQ(item->size_, header_->FieldIds().Size()); + CHECK_EQ(item->offset_, header_->FieldIds().GetOffset()); break; case DexFile::kDexTypeMethodIdItem: - CHECK_EQ(item->size_, collections->MethodIdsSize()); - CHECK_EQ(item->offset_, collections->MethodIdsOffset()); + CHECK_EQ(item->size_, header_->MethodIds().Size()); + CHECK_EQ(item->offset_, header_->MethodIds().GetOffset()); break; case DexFile::kDexTypeClassDefItem: if (options.class_filter_.empty()) { // The filter may have removed some classes, this will get fixed up during writing. - CHECK_EQ(item->size_, collections->ClassDefsSize()); + CHECK_EQ(item->size_, header_->ClassDefs().Size()); } - CHECK_EQ(item->offset_, collections->ClassDefsOffset()); + CHECK_EQ(item->offset_, header_->ClassDefs().GetOffset()); break; case DexFile::kDexTypeCallSiteIdItem: - CHECK_EQ(item->size_, collections->CallSiteIdsSize()); - CHECK_EQ(item->offset_, collections->CallSiteIdsOffset()); + CHECK_EQ(item->size_, header_->CallSiteIds().Size()); + CHECK_EQ(item->offset_, header_->CallSiteIds().GetOffset()); break; case DexFile::kDexTypeMethodHandleItem: - CHECK_EQ(item->size_, collections->MethodHandleItemsSize()); - CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset()); + CHECK_EQ(item->size_, header_->MethodHandleItems().Size()); + CHECK_EQ(item->offset_, header_->MethodHandleItems().GetOffset()); break; case DexFile::kDexTypeMapList: CHECK_EQ(item->size_, 1u); CHECK_EQ(item->offset_, disk_header.map_off_); break; case DexFile::kDexTypeTypeList: - collections->SetTypeListsOffset(item->offset_); + header_->TypeLists().SetOffset(item->offset_); break; case DexFile::kDexTypeAnnotationSetRefList: - collections->SetAnnotationSetRefListsOffset(item->offset_); + header_->AnnotationSetRefLists().SetOffset(item->offset_); break; case DexFile::kDexTypeAnnotationSetItem: - collections->SetAnnotationSetItemsOffset(item->offset_); + header_->AnnotationSetItems().SetOffset(item->offset_); break; case DexFile::kDexTypeClassDataItem: - collections->SetClassDatasOffset(item->offset_); + header_->ClassDatas().SetOffset(item->offset_); break; case DexFile::kDexTypeCodeItem: - collections->SetCodeItemsOffset(item->offset_); + header_->CodeItems().SetOffset(item->offset_); break; case DexFile::kDexTypeStringDataItem: - collections->SetStringDatasOffset(item->offset_); + header_->StringDatas().SetOffset(item->offset_); break; case DexFile::kDexTypeDebugInfoItem: - collections->SetDebugInfoItemsOffset(item->offset_); + header_->DebugInfoItems().SetOffset(item->offset_); break; case DexFile::kDexTypeAnnotationItem: - collections->SetAnnotationItemsOffset(item->offset_); - collections->AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_); + header_->AnnotationItems().SetOffset(item->offset_); + AddAnnotationsFromMapListSection(dex_file, item->offset_, item->size_); break; case DexFile::kDexTypeEncodedArrayItem: - collections->SetEncodedArrayItemsOffset(item->offset_); + header_->EncodedArrayItems().SetOffset(item->offset_); break; case DexFile::kDexTypeAnnotationsDirectoryItem: - collections->SetAnnotationsDirectoryItemsOffset(item->offset_); + header_->AnnotationsDirectoryItems().SetOffset(item->offset_); break; default: LOG(ERROR) << "Unknown map list item type."; @@ -200,5 +411,798 @@ static void CheckAndSetRemainingOffsets(const DexFile& dex_file, } } +void BuilderMaps::CreateStringId(const DexFile& dex_file, uint32_t i) { + const DexFile::StringId& disk_string_id = dex_file.GetStringId(dex::StringIndex(i)); + StringData* string_data = + string_datas_map_.CreateAndAddItem(header_->StringDatas(), + eagerly_assign_offsets_, + disk_string_id.string_data_off_, + dex_file.GetStringData(disk_string_id)); + CreateAndAddIndexedItem(header_->StringIds(), + header_->StringIds().GetOffset() + i * StringId::ItemSize(), + i, + string_data); +} + +void BuilderMaps::CreateTypeId(const DexFile& dex_file, uint32_t i) { + const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(dex::TypeIndex(i)); + CreateAndAddIndexedItem(header_->TypeIds(), + header_->TypeIds().GetOffset() + i * TypeId::ItemSize(), + i, + header_->StringIds()[disk_type_id.descriptor_idx_.index_]); +} + +void BuilderMaps::CreateProtoId(const DexFile& dex_file, uint32_t i) { + const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(dex::ProtoIndex(i)); + const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id); + TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_); + + CreateAndAddIndexedItem(header_->ProtoIds(), + header_->ProtoIds().GetOffset() + i * ProtoId::ItemSize(), + i, + header_->StringIds()[disk_proto_id.shorty_idx_.index_], + header_->TypeIds()[disk_proto_id.return_type_idx_.index_], + parameter_type_list); +} + +void BuilderMaps::CreateFieldId(const DexFile& dex_file, uint32_t i) { + const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i); + CreateAndAddIndexedItem(header_->FieldIds(), + header_->FieldIds().GetOffset() + i * FieldId::ItemSize(), + i, + header_->TypeIds()[disk_field_id.class_idx_.index_], + header_->TypeIds()[disk_field_id.type_idx_.index_], + header_->StringIds()[disk_field_id.name_idx_.index_]); +} + +void BuilderMaps::CreateMethodId(const DexFile& dex_file, uint32_t i) { + const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i); + CreateAndAddIndexedItem(header_->MethodIds(), + header_->MethodIds().GetOffset() + i * MethodId::ItemSize(), + i, + header_->TypeIds()[disk_method_id.class_idx_.index_], + header_->ProtoIds()[disk_method_id.proto_idx_.index_], + header_->StringIds()[disk_method_id.name_idx_.index_]); +} + +void BuilderMaps::CreateClassDef(const DexFile& dex_file, uint32_t i) { + const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i); + const TypeId* class_type = header_->TypeIds()[disk_class_def.class_idx_.index_]; + uint32_t access_flags = disk_class_def.access_flags_; + const TypeId* superclass = header_->GetTypeIdOrNullPtr(disk_class_def.superclass_idx_.index_); + + const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def); + TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_); + + const StringId* source_file = + header_->GetStringIdOrNullPtr(disk_class_def.source_file_idx_.index_); + // 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(dex_file, 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_); + CreateAndAddIndexedItem(header_->ClassDefs(), + header_->ClassDefs().GetOffset() + i * ClassDef::ItemSize(), + i, + class_type, + access_flags, + superclass, + interfaces_type_list, + source_file, + annotations, + static_values, + class_data); +} + +void BuilderMaps::CreateCallSiteId(const DexFile& dex_file, uint32_t i) { + const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i); + const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_; + EncodedArrayItem* call_site_item = + CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_); + + CreateAndAddIndexedItem(header_->CallSiteIds(), + header_->CallSiteIds().GetOffset() + i * CallSiteId::ItemSize(), + i, + call_site_item); +} + +void BuilderMaps::CreateMethodHandleItem(const DexFile& dex_file, uint32_t i) { + const DexFile::MethodHandleItem& disk_method_handle = dex_file.GetMethodHandle(i); + uint16_t index = disk_method_handle.field_or_method_idx_; + DexFile::MethodHandleType type = + static_cast<DexFile::MethodHandleType>(disk_method_handle.method_handle_type_); + bool is_invoke = type == DexFile::MethodHandleType::kInvokeStatic || + type == DexFile::MethodHandleType::kInvokeInstance || + type == DexFile::MethodHandleType::kInvokeConstructor || + type == DexFile::MethodHandleType::kInvokeDirect || + type == DexFile::MethodHandleType::kInvokeInterface; + static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeInterface, + "Unexpected method handle types."); + IndexedItem* field_or_method_id; + if (is_invoke) { + field_or_method_id = header_->MethodIds()[index]; + } else { + field_or_method_id = header_->FieldIds()[index]; + } + CreateAndAddIndexedItem(header_->MethodHandleItems(), + header_->MethodHandleItems().GetOffset() + + i * MethodHandleItem::ItemSize(), + i, + type, + field_or_method_id); +} + +void BuilderMaps::CreateCallSitesAndMethodHandles(const DexFile& dex_file) { + // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems. + const DexFile::MapList* map = dex_file.GetMapList(); + for (uint32_t i = 0; i < map->size_; ++i) { + const DexFile::MapItem* item = map->list_ + i; + switch (item->type_) { + case DexFile::kDexTypeCallSiteIdItem: + header_->CallSiteIds().SetOffset(item->offset_); + break; + case DexFile::kDexTypeMethodHandleItem: + header_->MethodHandleItems().SetOffset(item->offset_); + break; + default: + break; + } + } + // Populate MethodHandleItems first (CallSiteIds may depend on them). + for (uint32_t i = 0; i < dex_file.NumMethodHandles(); i++) { + CreateMethodHandleItem(dex_file, i); + } + // Populate CallSiteIds. + for (uint32_t i = 0; i < dex_file.NumCallSiteIds(); i++) { + CreateCallSiteId(dex_file, i); + } +} + +TypeList* BuilderMaps::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) { + if (dex_type_list == nullptr) { + return nullptr; + } + TypeList* type_list = type_lists_map_.GetExistingObject(offset); + if (type_list == nullptr) { + TypeIdVector* type_vector = new TypeIdVector(); + uint32_t size = dex_type_list->Size(); + for (uint32_t index = 0; index < size; ++index) { + type_vector->push_back(header_->TypeIds()[ + dex_type_list->GetTypeItem(index).type_idx_.index_]); + } + type_list = type_lists_map_.CreateAndAddItem(header_->TypeLists(), + eagerly_assign_offsets_, + offset, + type_vector); + } + return type_list; +} + +EncodedArrayItem* BuilderMaps::CreateEncodedArrayItem(const DexFile& dex_file, + const uint8_t* static_data, + uint32_t offset) { + if (static_data == nullptr) { + return nullptr; + } + EncodedArrayItem* encoded_array_item = encoded_array_items_map_.GetExistingObject(offset); + if (encoded_array_item == 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(dex_file, &static_data))); + } + // TODO: Calculate the size of the encoded array. + encoded_array_item = encoded_array_items_map_.CreateAndAddItem(header_->EncodedArrayItems(), + eagerly_assign_offsets_, + offset, + values); + } + return encoded_array_item; +} + +void BuilderMaps::AddAnnotationsFromMapListSection(const DexFile& dex_file, + uint32_t start_offset, + uint32_t count) { + uint32_t current_offset = start_offset; + for (size_t i = 0; i < count; ++i) { + // Annotation that we didn't process already, add it to the set. + const DexFile::AnnotationItem* annotation = dex_file.GetAnnotationItemAtOffset(current_offset); + AnnotationItem* annotation_item = CreateAnnotationItem(dex_file, annotation); + DCHECK(annotation_item != nullptr); + current_offset += annotation_item->GetSize(); + } +} + +AnnotationItem* BuilderMaps::CreateAnnotationItem(const DexFile& dex_file, + const DexFile::AnnotationItem* annotation) { + const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation); + const uint32_t offset = start_data - dex_file.DataBegin(); + AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset); + if (annotation_item == nullptr) { + uint8_t visibility = annotation->visibility_; + const uint8_t* annotation_data = annotation->annotation_; + std::unique_ptr<EncodedValue> encoded_value( + ReadEncodedValue(dex_file, &annotation_data, DexFile::kDexAnnotationAnnotation, 0)); + annotation_item = + annotation_items_map_.CreateAndAddItem(header_->AnnotationItems(), + eagerly_assign_offsets_, + offset, + visibility, + encoded_value->ReleaseEncodedAnnotation()); + annotation_item->SetSize(annotation_data - start_data); + } + return annotation_item; +} + + +AnnotationSetItem* BuilderMaps::CreateAnnotationSetItem(const DexFile& dex_file, + const DexFile::AnnotationSetItem* disk_annotations_item, uint32_t offset) { + if (disk_annotations_item == nullptr || (disk_annotations_item->size_ == 0 && offset == 0)) { + return nullptr; + } + AnnotationSetItem* annotation_set_item = annotation_set_items_map_.GetExistingObject(offset); + if (annotation_set_item == 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(dex_file, annotation); + items->push_back(annotation_item); + } + annotation_set_item = + annotation_set_items_map_.CreateAndAddItem(header_->AnnotationSetItems(), + eagerly_assign_offsets_, + offset, + items); + } + return annotation_set_item; +} + +AnnotationsDirectoryItem* BuilderMaps::CreateAnnotationsDirectoryItem(const DexFile& dex_file, + const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) { + AnnotationsDirectoryItem* annotations_directory_item = + annotations_directory_items_map_.GetExistingObject(offset); + if (annotations_directory_item != nullptr) { + return annotations_directory_item; + } + const DexFile::AnnotationSetItem* class_set_item = + dex_file.GetClassAnnotationSet(disk_annotations_item); + AnnotationSetItem* class_annotation = nullptr; + if (class_set_item != nullptr) { + uint32_t item_offset = disk_annotations_item->class_annotations_off_; + class_annotation = CreateAnnotationSetItem(dex_file, class_set_item, 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 = header_->FieldIds()[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 = header_->MethodIds()[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 = header_->MethodIds()[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. + return annotations_directory_items_map_.CreateAndAddItem(header_->AnnotationsDirectoryItems(), + eagerly_assign_offsets_, + offset, + class_annotation, + field_annotations, + method_annotations, + parameter_annotations); +} + +CodeItem* BuilderMaps::DedupeOrCreateCodeItem(const DexFile& dex_file, + const DexFile::CodeItem* disk_code_item, + uint32_t offset, + uint32_t dex_method_index) { + if (disk_code_item == nullptr) { + return nullptr; + } + CodeItemDebugInfoAccessor accessor(dex_file, disk_code_item, dex_method_index); + const uint32_t debug_info_offset = accessor.DebugInfoOffset(); + + // Create the offsets pair and dedupe based on it. + std::pair<uint32_t, uint32_t> offsets_pair(offset, debug_info_offset); + auto existing = code_items_map_.find(offsets_pair); + if (existing != code_items_map_.end()) { + return existing->second; + } + + const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset); + DebugInfoItem* debug_info = nullptr; + if (debug_info_stream != nullptr) { + debug_info = debug_info_items_map_.GetExistingObject(debug_info_offset); + if (debug_info == nullptr) { + uint32_t debug_info_size = GetDebugInfoStreamSize(debug_info_stream); + uint8_t* debug_info_buffer = new uint8_t[debug_info_size]; + memcpy(debug_info_buffer, debug_info_stream, debug_info_size); + debug_info = debug_info_items_map_.CreateAndAddItem(header_->DebugInfoItems(), + eagerly_assign_offsets_, + debug_info_offset, + debug_info_size, + debug_info_buffer); + } + } + + uint32_t insns_size = accessor.InsnsSizeInCodeUnits(); + uint16_t* insns = new uint16_t[insns_size]; + memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t)); + + TryItemVector* tries = nullptr; + CatchHandlerVector* handler_list = nullptr; + if (accessor.TriesSize() > 0) { + tries = new TryItemVector(); + handler_list = new CatchHandlerVector(); + for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) { + uint32_t start_addr = disk_try_item.start_addr_; + uint16_t insn_count = disk_try_item.insn_count_; + uint16_t handler_off = disk_try_item.handler_off_; + const CatchHandler* handlers = nullptr; + for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { + if (handler_off == existing_handlers->GetListOffset()) { + handlers = existing_handlers.get(); + break; + } + } + if (handlers == nullptr) { + bool catch_all = false; + TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); + for (CatchHandlerIterator it(accessor, disk_try_item); it.HasNext(); it.Next()) { + const dex::TypeIndex type_index = it.GetHandlerTypeIndex(); + const TypeId* type_id = header_->GetTypeIdOrNullPtr(type_index.index_); + catch_all |= type_id == nullptr; + addr_pairs->push_back(std::unique_ptr<const TypeAddrPair>( + new TypeAddrPair(type_id, it.GetHandlerAddress()))); + } + handlers = new CatchHandler(catch_all, handler_off, addr_pairs); + handler_list->push_back(std::unique_ptr<const CatchHandler>(handlers)); + } + TryItem* try_item = new TryItem(start_addr, insn_count, handlers); + tries->push_back(std::unique_ptr<const TryItem>(try_item)); + } + // Manually walk catch handlers list and add any missing handlers unreferenced by try items. + const uint8_t* handlers_base = accessor.GetCatchHandlerData(); + const uint8_t* handlers_data = handlers_base; + uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data); + while (handlers_size > handler_list->size()) { + bool already_added = false; + uint16_t handler_off = handlers_data - handlers_base; + for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) { + if (handler_off == existing_handlers->GetListOffset()) { + already_added = true; + break; + } + } + int32_t size = DecodeSignedLeb128(&handlers_data); + bool has_catch_all = size <= 0; + if (has_catch_all) { + size = -size; + } + if (already_added) { + for (int32_t i = 0; i < size; i++) { + DecodeUnsignedLeb128(&handlers_data); + DecodeUnsignedLeb128(&handlers_data); + } + if (has_catch_all) { + DecodeUnsignedLeb128(&handlers_data); + } + continue; + } + TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); + for (int32_t i = 0; i < size; i++) { + const TypeId* type_id = + header_->GetTypeIdOrNullPtr(DecodeUnsignedLeb128(&handlers_data)); + uint32_t addr = DecodeUnsignedLeb128(&handlers_data); + addr_pairs->push_back( + std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(type_id, addr))); + } + if (has_catch_all) { + uint32_t addr = DecodeUnsignedLeb128(&handlers_data); + addr_pairs->push_back( + std::unique_ptr<const TypeAddrPair>(new TypeAddrPair(nullptr, addr))); + } + const CatchHandler* handler = new CatchHandler(has_catch_all, handler_off, addr_pairs); + handler_list->push_back(std::unique_ptr<const CatchHandler>(handler)); + } + } + + uint32_t size = dex_file.GetCodeItemSize(*disk_code_item); + CodeItem* code_item = header_->CodeItems().CreateAndAddItem(accessor.RegistersSize(), + accessor.InsSize(), + accessor.OutsSize(), + debug_info, + insns_size, + insns, + tries, + handler_list); + code_item->SetSize(size); + + // Add the code item to the map. + DCHECK(!code_item->OffsetAssigned()); + if (eagerly_assign_offsets_) { + code_item->SetOffset(offset); + } + code_items_map_.emplace(offsets_pair, code_item); + + // Add "fixup" references to types, strings, methods, and fields. + // This is temporary, as we will probably want more detailed parsing of the + // instructions here. + std::vector<TypeId*> type_ids; + std::vector<StringId*> string_ids; + std::vector<MethodId*> method_ids; + std::vector<FieldId*> field_ids; + if (GetIdsFromByteCode(code_item, + /*out*/ &type_ids, + /*out*/ &string_ids, + /*out*/ &method_ids, + /*out*/ &field_ids)) { + CodeFixups* fixups = new CodeFixups(std::move(type_ids), + std::move(string_ids), + std::move(method_ids), + std::move(field_ids)); + code_item->SetCodeFixups(fixups); + } + + return code_item; +} + +ClassData* BuilderMaps::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 = class_datas_map_.GetExistingObject(offset); + if (class_data == nullptr && encoded_data != nullptr) { + ClassDataItemIterator cdii(dex_file, encoded_data); + // Static fields. + FieldItemVector* static_fields = new FieldItemVector(); + for (; cdii.HasNextStaticField(); cdii.Next()) { + FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()]; + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + static_fields->emplace_back(access_flags, field_item); + } + // Instance fields. + FieldItemVector* instance_fields = new FieldItemVector(); + for (; cdii.HasNextInstanceField(); cdii.Next()) { + FieldId* field_item = header_->FieldIds()[cdii.GetMemberIndex()]; + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + instance_fields->emplace_back(access_flags, field_item); + } + // Direct methods. + MethodItemVector* direct_methods = new MethodItemVector(); + for (; cdii.HasNextDirectMethod(); cdii.Next()) { + direct_methods->push_back(GenerateMethodItem(dex_file, cdii)); + } + // Virtual methods. + MethodItemVector* virtual_methods = new MethodItemVector(); + for (; cdii.HasNextVirtualMethod(); cdii.Next()) { + virtual_methods->push_back(GenerateMethodItem(dex_file, cdii)); + } + class_data = class_datas_map_.CreateAndAddItem(header_->ClassDatas(), + eagerly_assign_offsets_, + offset, + static_fields, + instance_fields, + direct_methods, + virtual_methods); + class_data->SetSize(cdii.EndDataPointer() - encoded_data); + } + return class_data; +} + +void BuilderMaps::SortVectorsByMapOrder() { + header_->StringDatas().SortByMapOrder(string_datas_map_.Collection()); + header_->TypeLists().SortByMapOrder(type_lists_map_.Collection()); + header_->EncodedArrayItems().SortByMapOrder(encoded_array_items_map_.Collection()); + header_->AnnotationItems().SortByMapOrder(annotation_items_map_.Collection()); + header_->AnnotationSetItems().SortByMapOrder(annotation_set_items_map_.Collection()); + header_->AnnotationSetRefLists().SortByMapOrder(annotation_set_ref_lists_map_.Collection()); + header_->AnnotationsDirectoryItems().SortByMapOrder( + annotations_directory_items_map_.Collection()); + header_->DebugInfoItems().SortByMapOrder(debug_info_items_map_.Collection()); + header_->CodeItems().SortByMapOrder(code_items_map_); + header_->ClassDatas().SortByMapOrder(class_datas_map_.Collection()); +} + +bool BuilderMaps::GetIdsFromByteCode(const CodeItem* code, + std::vector<TypeId*>* type_ids, + std::vector<StringId*>* string_ids, + std::vector<MethodId*>* method_ids, + std::vector<FieldId*>* field_ids) { + bool has_id = false; + IterationRange<DexInstructionIterator> instructions = code->Instructions(); + SafeDexInstructionIterator it(instructions.begin(), instructions.end()); + for (; !it.IsErrorState() && it < instructions.end(); ++it) { + // In case the instruction goes past the end of the code item, make sure to not process it. + SafeDexInstructionIterator next = it; + ++next; + if (next.IsErrorState()) { + break; + } + has_id |= GetIdFromInstruction(&it.Inst(), type_ids, string_ids, method_ids, field_ids); + } // for + return has_id; +} + +bool BuilderMaps::GetIdFromInstruction(const Instruction* dec_insn, + std::vector<TypeId*>* type_ids, + std::vector<StringId*>* string_ids, + std::vector<MethodId*>* method_ids, + std::vector<FieldId*>* field_ids) { + // Determine index and width of the string. + uint32_t index = 0; + switch (Instruction::FormatOf(dec_insn->Opcode())) { + // SOME NOT SUPPORTED: + // case Instruction::k20bc: + case Instruction::k21c: + case Instruction::k35c: + // case Instruction::k35ms: + case Instruction::k3rc: + // case Instruction::k3rms: + // case Instruction::k35mi: + // case Instruction::k3rmi: + case Instruction::k45cc: + case Instruction::k4rcc: + index = dec_insn->VRegB(); + break; + case Instruction::k31c: + index = dec_insn->VRegB(); + break; + case Instruction::k22c: + // case Instruction::k22cs: + index = dec_insn->VRegC(); + break; + default: + break; + } // switch + + // Determine index type, and add reference to the appropriate collection. + switch (Instruction::IndexTypeOf(dec_insn->Opcode())) { + case Instruction::kIndexTypeRef: + if (index < header_->TypeIds().Size()) { + type_ids->push_back(header_->TypeIds()[index]); + return true; + } + break; + case Instruction::kIndexStringRef: + if (index < header_->StringIds().Size()) { + string_ids->push_back(header_->StringIds()[index]); + return true; + } + break; + case Instruction::kIndexMethodRef: + case Instruction::kIndexMethodAndProtoRef: + if (index < header_->MethodIds().Size()) { + method_ids->push_back(header_->MethodIds()[index]); + return true; + } + break; + case Instruction::kIndexFieldRef: + if (index < header_->FieldIds().Size()) { + field_ids->push_back(header_->FieldIds()[index]); + return true; + } + break; + case Instruction::kIndexUnknown: + case Instruction::kIndexNone: + case Instruction::kIndexVtableOffset: + case Instruction::kIndexFieldOffset: + default: + break; + } // switch + return false; +} + +EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file, const uint8_t** data) { + const uint8_t encoded_value = *(*data)++; + const uint8_t type = encoded_value & 0x1f; + EncodedValue* item = new EncodedValue(type); + ReadEncodedValue(dex_file, data, type, encoded_value >> 5, item); + return item; +} + +EncodedValue* BuilderMaps::ReadEncodedValue(const DexFile& dex_file, + const uint8_t** data, + uint8_t type, + uint8_t length) { + EncodedValue* item = new EncodedValue(type); + ReadEncodedValue(dex_file, data, type, length, item); + return item; +} + +void BuilderMaps::ReadEncodedValue(const DexFile& dex_file, + 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::kDexAnnotationMethodType: { + const uint32_t proto_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetProtoId(header_->ProtoIds()[proto_index]); + break; + } + case DexFile::kDexAnnotationMethodHandle: { + const uint32_t method_handle_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetMethodHandle(header_->MethodHandleItems()[method_handle_index]); + break; + } + case DexFile::kDexAnnotationString: { + const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetStringId(header_->StringIds()[string_index]); + break; + } + case DexFile::kDexAnnotationType: { + const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetTypeId(header_->TypeIds()[string_index]); + break; + } + case DexFile::kDexAnnotationField: + case DexFile::kDexAnnotationEnum: { + const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetFieldId(header_->FieldIds()[field_index]); + break; + } + case DexFile::kDexAnnotationMethod: { + const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false)); + item->SetMethodId(header_->MethodIds()[method_index]); + break; + } + case DexFile::kDexAnnotationArray: { + EncodedValueVector* values = new EncodedValueVector(); + const uint32_t offset = *data - dex_file.DataBegin(); + 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(dex_file, data))); + } + EncodedArrayItem* array_item = new EncodedArrayItem(values); + if (eagerly_assign_offsets_) { + array_item->SetOffset(offset); + } + item->SetEncodedArray(array_item); + 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(header_->StringIds()[name_index], + ReadEncodedValue(dex_file, data)))); + } + item->SetEncodedAnnotation(new EncodedAnnotation(header_->TypeIds()[type_idx], elements)); + break; + } + case DexFile::kDexAnnotationNull: + break; + case DexFile::kDexAnnotationBoolean: + item->SetBoolean(length != 0); + break; + default: + break; + } +} + +MethodItem BuilderMaps::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) { + MethodId* method_id = header_->MethodIds()[cdii.GetMemberIndex()]; + uint32_t access_flags = cdii.GetRawMemberAccessFlags(); + const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem(); + // Temporary hack to prevent incorrectly deduping code items if they have the same offset since + // they may have different debug info streams. + CodeItem* code_item = DedupeOrCreateCodeItem(dex_file, + disk_code_item, + cdii.GetMethodCodeItemOffset(), + cdii.GetMemberIndex()); + return MethodItem(access_flags, method_id, code_item); +} + +ParameterAnnotation* BuilderMaps::GenerateParameterAnnotation( + const DexFile& dex_file, + MethodId* method_id, + const DexFile::AnnotationSetRefList* annotation_set_ref_list, + uint32_t offset) { + AnnotationSetRefList* set_ref_list = annotation_set_ref_lists_map_.GetExistingObject(offset); + if (set_ref_list == nullptr) { + 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)); + } + set_ref_list = + annotation_set_ref_lists_map_.CreateAndAddItem(header_->AnnotationSetRefLists(), + eagerly_assign_offsets_, + offset, + annotations); + } + return new ParameterAnnotation(method_id, set_ref_list); +} + } // namespace dex_ir } // namespace art diff --git a/dexlayout/dex_verify.cc b/dexlayout/dex_verify.cc index 2e4756b482..962798d6f4 100644 --- a/dexlayout/dex_verify.cc +++ b/dexlayout/dex_verify.cc @@ -31,38 +31,42 @@ using android::base::StringPrintf; bool VerifyOutputDexFile(dex_ir::Header* orig_header, dex_ir::Header* output_header, std::string* error_msg) { - dex_ir::Collections& orig = orig_header->GetCollections(); - dex_ir::Collections& output = output_header->GetCollections(); - // Compare all id sections. They have a defined order that can't be changed by dexlayout. - if (!VerifyIds(orig.StringIds(), output.StringIds(), "string ids", error_msg) || - !VerifyIds(orig.TypeIds(), output.TypeIds(), "type ids", error_msg) || - !VerifyIds(orig.ProtoIds(), output.ProtoIds(), "proto ids", error_msg) || - !VerifyIds(orig.FieldIds(), output.FieldIds(), "field ids", error_msg) || - !VerifyIds(orig.MethodIds(), output.MethodIds(), "method ids", error_msg)) { + if (!VerifyIds(orig_header->StringIds(), output_header->StringIds(), "string ids", error_msg) || + !VerifyIds(orig_header->TypeIds(), output_header->TypeIds(), "type ids", error_msg) || + !VerifyIds(orig_header->ProtoIds(), output_header->ProtoIds(), "proto ids", error_msg) || + !VerifyIds(orig_header->FieldIds(), output_header->FieldIds(), "field ids", error_msg) || + !VerifyIds(orig_header->MethodIds(), output_header->MethodIds(), "method ids", error_msg)) { return false; } // Compare class defs. The order may have been changed by dexlayout. - if (!VerifyClassDefs(orig.ClassDefs(), output.ClassDefs(), error_msg)) { + if (!VerifyClassDefs(orig_header->ClassDefs(), output_header->ClassDefs(), error_msg)) { return false; } return true; } -template<class T> bool VerifyIds(std::vector<std::unique_ptr<T>>& orig, - std::vector<std::unique_ptr<T>>& output, +template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig, + dex_ir::CollectionVector<T>& output, const char* section_name, std::string* error_msg) { - if (orig.size() != output.size()) { - *error_msg = StringPrintf( - "Mismatched size for %s section: %zu vs %zu.", section_name, orig.size(), output.size()); - return false; - } - for (size_t i = 0; i < orig.size(); ++i) { - if (!VerifyId(orig[i].get(), output[i].get(), error_msg)) { + auto orig_iter = orig.begin(); + auto output_iter = output.begin(); + for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) { + if (!VerifyId(orig_iter->get(), output_iter->get(), error_msg)) { return false; } } + if (orig_iter != orig.end() || output_iter != output.end()) { + const char* longer; + if (orig_iter == orig.end()) { + longer = "output"; + } else { + longer = "original"; + } + *error_msg = StringPrintf("Mismatch for %s section: %s is longer.", section_name, longer); + return false; + } return true; } @@ -181,29 +185,36 @@ struct ClassDefCompare { // The class defs may have a new order due to dexlayout. Use the class's class_idx to uniquely // identify them and sort them for comparison. -bool VerifyClassDefs(std::vector<std::unique_ptr<dex_ir::ClassDef>>& orig, - std::vector<std::unique_ptr<dex_ir::ClassDef>>& output, +bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig, + dex_ir::CollectionVector<dex_ir::ClassDef>& output, std::string* error_msg) { - if (orig.size() != output.size()) { - *error_msg = StringPrintf( - "Mismatched size for class defs section: %zu vs %zu.", orig.size(), output.size()); - return false; - } // Store the class defs into sets sorted by the class's type index. std::set<dex_ir::ClassDef*, ClassDefCompare> orig_set; std::set<dex_ir::ClassDef*, ClassDefCompare> output_set; - for (size_t i = 0; i < orig.size(); ++i) { - orig_set.insert(orig[i].get()); - output_set.insert(output[i].get()); - } - auto orig_iter = orig_set.begin(); - auto output_iter = output_set.begin(); - while (orig_iter != orig_set.end() && output_iter != output_set.end()) { - if (!VerifyClassDef(*orig_iter, *output_iter, error_msg)) { + auto orig_iter = orig.begin(); + auto output_iter = output.begin(); + for (; orig_iter != orig.end() && output_iter != output.end(); ++orig_iter, ++output_iter) { + orig_set.insert(orig_iter->get()); + output_set.insert(output_iter->get()); + } + if (orig_iter != orig.end() || output_iter != output.end()) { + const char* longer; + if (orig_iter == orig.end()) { + longer = "output"; + } else { + longer = "original"; + } + *error_msg = StringPrintf("Mismatch for class defs section: %s is longer.", longer); + return false; + } + auto orig_set_iter = orig_set.begin(); + auto output_set_iter = output_set.begin(); + while (orig_set_iter != orig_set.end() && output_set_iter != output_set.end()) { + if (!VerifyClassDef(*orig_set_iter, *output_set_iter, error_msg)) { return false; } - orig_iter++; - output_iter++; + orig_set_iter++; + output_set_iter++; } return true; } diff --git a/dexlayout/dex_verify.h b/dexlayout/dex_verify.h index 998939bbce..4943defe16 100644 --- a/dexlayout/dex_verify.h +++ b/dexlayout/dex_verify.h @@ -30,8 +30,8 @@ bool VerifyOutputDexFile(dex_ir::Header* orig_header, dex_ir::Header* output_header, std::string* error_msg); -template<class T> bool VerifyIds(std::vector<std::unique_ptr<T>>& orig, - std::vector<std::unique_ptr<T>>& output, +template<class T> bool VerifyIds(dex_ir::CollectionVector<T>& orig, + dex_ir::CollectionVector<T>& output, const char* section_name, std::string* error_msg); bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg); @@ -40,8 +40,8 @@ bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg); bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg); -bool VerifyClassDefs(std::vector<std::unique_ptr<dex_ir::ClassDef>>& orig, - std::vector<std::unique_ptr<dex_ir::ClassDef>>& output, +bool VerifyClassDefs(dex_ir::CollectionVector<dex_ir::ClassDef>& orig, + dex_ir::CollectionVector<dex_ir::ClassDef>& output, std::string* error_msg); bool VerifyClassDef(dex_ir::ClassDef* orig, dex_ir::ClassDef* output, std::string* error_msg); diff --git a/dexlayout/dex_visualize.cc b/dexlayout/dex_visualize.cc index 0e04c587e7..abcaffc434 100644 --- a/dexlayout/dex_visualize.cc +++ b/dexlayout/dex_visualize.cc @@ -252,9 +252,9 @@ void VisualizeDexLayout(dex_ir::Header* header, return; } - const uint32_t class_defs_size = header->GetCollections().ClassDefsSize(); + const uint32_t class_defs_size = header->ClassDefs().Size(); for (uint32_t class_index = 0; class_index < class_defs_size; class_index++) { - dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(class_index); + dex_ir::ClassDef* class_def = header->ClassDefs()[class_index]; dex::TypeIndex type_idx(class_def->ClassType()->GetIndex()); if (profile_info != nullptr && !profile_info->ContainsClass(*dex_file, type_idx)) { continue; diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index 9ed1312983..a4c5cda4ba 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -231,7 +231,7 @@ void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* me // function that takes a CollectionVector<T> and uses overloading. void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) { const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::StringId>& string_id : header_->GetCollections().StringIds()) { + for (auto& string_id : header_->StringIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringIdItem)); if (reserve_only) { stream->Skip(string_id->GetSize()); @@ -241,7 +241,7 @@ void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetStringIdsOffset(start); + header_->StringIds().SetOffset(start); } } @@ -256,25 +256,25 @@ void DexWriter::WriteStringData(Stream* stream, dex_ir::StringData* string_data) void DexWriter::WriteStringDatas(Stream* stream) { const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::StringData>& string_data : header_->GetCollections().StringDatas()) { + for (auto& string_data : header_->StringDatas()) { WriteStringData(stream, string_data.get()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetStringDatasOffset(start); + header_->StringDatas().SetOffset(start); } } void DexWriter::WriteTypeIds(Stream* stream) { uint32_t descriptor_idx[1]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::TypeId>& type_id : header_->GetCollections().TypeIds()) { + for (auto& type_id : header_->TypeIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeIdItem)); ProcessOffset(stream, type_id.get()); descriptor_idx[0] = type_id->GetStringId()->GetIndex(); stream->Write(descriptor_idx, type_id->GetSize()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetTypeIdsOffset(start); + header_->TypeIds().SetOffset(start); } } @@ -282,7 +282,7 @@ void DexWriter::WriteTypeLists(Stream* stream) { uint32_t size[1]; uint16_t list[1]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::TypeList>& type_list : header_->GetCollections().TypeLists()) { + for (auto& type_list : header_->TypeLists()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeList)); size[0] = type_list->GetTypeList()->size(); ProcessOffset(stream, type_list.get()); @@ -293,14 +293,14 @@ void DexWriter::WriteTypeLists(Stream* stream) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetTypeListsOffset(start); + header_->TypeLists().SetOffset(start); } } void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) { uint32_t buffer[3]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_->GetCollections().ProtoIds()) { + for (auto& proto_id : header_->ProtoIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeProtoIdItem)); ProcessOffset(stream, proto_id.get()); if (reserve_only) { @@ -313,14 +313,14 @@ void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetProtoIdsOffset(start); + header_->ProtoIds().SetOffset(start); } } void DexWriter::WriteFieldIds(Stream* stream) { uint16_t buffer[4]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::FieldId>& field_id : header_->GetCollections().FieldIds()) { + for (auto& field_id : header_->FieldIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeFieldIdItem)); ProcessOffset(stream, field_id.get()); buffer[0] = field_id->Class()->GetIndex(); @@ -330,14 +330,14 @@ void DexWriter::WriteFieldIds(Stream* stream) { stream->Write(buffer, field_id->GetSize()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetFieldIdsOffset(start); + header_->FieldIds().SetOffset(start); } } void DexWriter::WriteMethodIds(Stream* stream) { uint16_t buffer[4]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::MethodId>& method_id : header_->GetCollections().MethodIds()) { + for (auto& method_id : header_->MethodIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodIdItem)); ProcessOffset(stream, method_id.get()); buffer[0] = method_id->Class()->GetIndex(); @@ -347,28 +347,26 @@ void DexWriter::WriteMethodIds(Stream* stream) { stream->Write(buffer, method_id->GetSize()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetMethodIdsOffset(start); + header_->MethodIds().SetOffset(start); } } void DexWriter::WriteEncodedArrays(Stream* stream) { const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array : - header_->GetCollections().EncodedArrayItems()) { + for (auto& encoded_array : header_->EncodedArrayItems()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeEncodedArrayItem)); ProcessOffset(stream, encoded_array.get()); WriteEncodedArray(stream, encoded_array->GetEncodedValues()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetEncodedArrayItemsOffset(start); + header_->EncodedArrayItems().SetOffset(start); } } void DexWriter::WriteAnnotations(Stream* stream) { uint8_t visibility[1]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : - header_->GetCollections().AnnotationItems()) { + for (auto& annotation : header_->AnnotationItems()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationItem)); visibility[0] = annotation->GetVisibility(); ProcessOffset(stream, annotation.get()); @@ -376,7 +374,7 @@ void DexWriter::WriteAnnotations(Stream* stream) { WriteEncodedAnnotation(stream, annotation->GetAnnotation()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetAnnotationItemsOffset(start); + header_->AnnotationItems().SetOffset(start); } } @@ -384,8 +382,7 @@ void DexWriter::WriteAnnotationSets(Stream* stream) { uint32_t size[1]; uint32_t annotation_off[1]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set : - header_->GetCollections().AnnotationSetItems()) { + for (auto& annotation_set : header_->AnnotationSetItems()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetItem)); size[0] = annotation_set->GetItems()->size(); ProcessOffset(stream, annotation_set.get()); @@ -396,7 +393,7 @@ void DexWriter::WriteAnnotationSets(Stream* stream) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetAnnotationSetItemsOffset(start); + header_->AnnotationSetItems().SetOffset(start); } } @@ -404,8 +401,7 @@ void DexWriter::WriteAnnotationSetRefs(Stream* stream) { uint32_t size[1]; uint32_t annotations_off[1]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref : - header_->GetCollections().AnnotationSetRefLists()) { + for (auto& annotation_set_ref : header_->AnnotationSetRefLists()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetRefList)); size[0] = annotation_set_ref->GetItems()->size(); ProcessOffset(stream, annotation_set_ref.get()); @@ -416,7 +412,7 @@ void DexWriter::WriteAnnotationSetRefs(Stream* stream) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetAnnotationSetRefListsOffset(start); + header_->AnnotationSetRefLists().SetOffset(start); } } @@ -424,8 +420,7 @@ void DexWriter::WriteAnnotationsDirectories(Stream* stream) { uint32_t directory_buffer[4]; uint32_t annotation_buffer[2]; const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory : - header_->GetCollections().AnnotationsDirectoryItems()) { + for (auto& annotations_directory : header_->AnnotationsDirectoryItems()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem)); ProcessOffset(stream, annotations_directory.get()); directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 : @@ -463,7 +458,7 @@ void DexWriter::WriteAnnotationsDirectories(Stream* stream) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetAnnotationsDirectoryItemsOffset(start); + header_->AnnotationsDirectoryItems().SetOffset(start); } } @@ -475,12 +470,11 @@ void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_ void DexWriter::WriteDebugInfoItems(Stream* stream) { const uint32_t start = stream->Tell(); - for (std::unique_ptr<dex_ir::DebugInfoItem>& debug_info : - header_->GetCollections().DebugInfoItems()) { + for (auto& debug_info : header_->DebugInfoItems()) { WriteDebugInfoItem(stream, debug_info.get()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetDebugInfoItemsOffset(start); + header_->DebugInfoItems().SetOffset(start); } } @@ -558,7 +552,7 @@ void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) { DexLayoutSections::SectionType::kSectionTypeCode)]; } const uint32_t start = stream->Tell(); - for (auto& code_item : header_->GetCollections().CodeItems()) { + for (auto& code_item : header_->CodeItems()) { uint32_t start_offset = stream->Tell(); WriteCodeItem(stream, code_item.get(), reserve_only); // Only add the section hotness info once. @@ -573,14 +567,14 @@ void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) { } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetCodeItemsOffset(start); + header_->CodeItems().SetOffset(start); } } void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) { const uint32_t start = stream->Tell(); uint32_t class_def_buffer[8]; - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem)); if (reserve_only) { stream->Skip(class_def->GetSize()); @@ -602,14 +596,14 @@ void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetClassDefsOffset(start); + header_->ClassDefs().SetOffset(start); } } void DexWriter::WriteClassDatas(Stream* stream) { const uint32_t start = stream->Tell(); for (const std::unique_ptr<dex_ir::ClassData>& class_data : - header_->GetCollections().ClassDatas()) { + header_->ClassDatas()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDataItem)); ProcessOffset(stream, class_data.get()); stream->WriteUleb128(class_data->StaticFields()->size()); @@ -622,15 +616,14 @@ void DexWriter::WriteClassDatas(Stream* stream) { WriteEncodedMethods(stream, class_data->VirtualMethods()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetClassDatasOffset(start); + header_->ClassDatas().SetOffset(start); } } void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) { const uint32_t start = stream->Tell(); uint32_t call_site_off[1]; - for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id : - header_->GetCollections().CallSiteIds()) { + for (auto& call_site_id : header_->CallSiteIds()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem)); if (reserve_only) { stream->Skip(call_site_id->GetSize()); @@ -640,15 +633,14 @@ void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) { } } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetCallSiteIdsOffset(start); + header_->CallSiteIds().SetOffset(start); } } void DexWriter::WriteMethodHandles(Stream* stream) { const uint32_t start = stream->Tell(); uint16_t method_handle_buff[4]; - for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle : - header_->GetCollections().MethodHandleItems()) { + for (auto& method_handle : header_->MethodHandleItems()) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem)); method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType()); method_handle_buff[1] = 0; // unused. @@ -657,7 +649,7 @@ void DexWriter::WriteMethodHandles(Stream* stream) { stream->Write(method_handle_buff, method_handle->GetSize()); } if (compute_offsets_ && start != stream->Tell()) { - header_->GetCollections().SetMethodHandleItemsOffset(start); + header_->MethodHandleItems().SetOffset(start); } } @@ -678,67 +670,66 @@ void DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) { } void DexWriter::GenerateAndWriteMapItems(Stream* stream) { - dex_ir::Collections& collection = header_->GetCollections(); MapItemQueue queue; // Header and index section. queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0)); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem, - collection.StringIdsSize(), - collection.StringIdsOffset())); + header_->StringIds().Size(), + header_->StringIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem, - collection.TypeIdsSize(), - collection.TypeIdsOffset())); + header_->TypeIds().Size(), + header_->TypeIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem, - collection.ProtoIdsSize(), - collection.ProtoIdsOffset())); + header_->ProtoIds().Size(), + header_->ProtoIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem, - collection.FieldIdsSize(), - collection.FieldIdsOffset())); + header_->FieldIds().Size(), + header_->FieldIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem, - collection.MethodIdsSize(), - collection.MethodIdsOffset())); + header_->MethodIds().Size(), + header_->MethodIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem, - collection.ClassDefsSize(), - collection.ClassDefsOffset())); + header_->ClassDefs().Size(), + header_->ClassDefs().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem, - collection.CallSiteIdsSize(), - collection.CallSiteIdsOffset())); + header_->CallSiteIds().Size(), + header_->CallSiteIds().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem, - collection.MethodHandleItemsSize(), - collection.MethodHandleItemsOffset())); + header_->MethodHandleItems().Size(), + header_->MethodHandleItems().GetOffset())); // Data section. - queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, collection.MapListOffset())); + queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList, - collection.TypeListsSize(), - collection.TypeListsOffset())); + header_->TypeLists().Size(), + header_->TypeLists().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList, - collection.AnnotationSetRefListsSize(), - collection.AnnotationSetRefListsOffset())); + header_->AnnotationSetRefLists().Size(), + header_->AnnotationSetRefLists().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem, - collection.AnnotationSetItemsSize(), - collection.AnnotationSetItemsOffset())); + header_->AnnotationSetItems().Size(), + header_->AnnotationSetItems().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem, - collection.ClassDatasSize(), - collection.ClassDatasOffset())); + header_->ClassDatas().Size(), + header_->ClassDatas().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem, - collection.CodeItemsSize(), - collection.CodeItemsOffset())); + header_->CodeItems().Size(), + header_->CodeItems().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem, - collection.StringDatasSize(), - collection.StringDatasOffset())); + header_->StringDatas().Size(), + header_->StringDatas().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem, - collection.DebugInfoItemsSize(), - collection.DebugInfoItemsOffset())); + header_->DebugInfoItems().Size(), + header_->DebugInfoItems().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem, - collection.AnnotationItemsSize(), - collection.AnnotationItemsOffset())); + header_->AnnotationItems().Size(), + header_->AnnotationItems().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem, - collection.EncodedArrayItemsSize(), - collection.EncodedArrayItemsOffset())); + header_->EncodedArrayItems().Size(), + header_->EncodedArrayItems().GetOffset())); queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem, - collection.AnnotationsDirectoryItemsSize(), - collection.AnnotationsDirectoryItemsOffset())); + header_->AnnotationsDirectoryItems().Size(), + header_->AnnotationsDirectoryItems().GetOffset())); WriteMapItems(stream, &queue); } @@ -761,20 +752,19 @@ void DexWriter::WriteHeader(Stream* stream) { header.endian_tag_ = header_->EndianTag(); header.link_size_ = header_->LinkSize(); header.link_off_ = header_->LinkOffset(); - const dex_ir::Collections& collections = header_->GetCollections(); - header.map_off_ = collections.MapListOffset(); - header.string_ids_size_ = collections.StringIdsSize(); - header.string_ids_off_ = collections.StringIdsOffset(); - header.type_ids_size_ = collections.TypeIdsSize(); - header.type_ids_off_ = collections.TypeIdsOffset(); - header.proto_ids_size_ = collections.ProtoIdsSize(); - header.proto_ids_off_ = collections.ProtoIdsOffset(); - header.field_ids_size_ = collections.FieldIdsSize(); - header.field_ids_off_ = collections.FieldIdsOffset(); - header.method_ids_size_ = collections.MethodIdsSize(); - header.method_ids_off_ = collections.MethodIdsOffset(); - header.class_defs_size_ = collections.ClassDefsSize(); - header.class_defs_off_ = collections.ClassDefsOffset(); + header.map_off_ = header_->MapListOffset(); + header.string_ids_size_ = header_->StringIds().Size(); + header.string_ids_off_ = header_->StringIds().GetOffset(); + header.type_ids_size_ = header_->TypeIds().Size(); + header.type_ids_off_ = header_->TypeIds().GetOffset(); + header.proto_ids_size_ = header_->ProtoIds().Size(); + header.proto_ids_off_ = header_->ProtoIds().GetOffset(); + header.field_ids_size_ = header_->FieldIds().Size(); + header.field_ids_off_ = header_->FieldIds().GetOffset(); + header.method_ids_size_ = header_->MethodIds().Size(); + header.method_ids_off_ = header_->MethodIds().GetOffset(); + header.class_defs_size_ = header_->ClassDefs().Size(); + header.class_defs_off_ = header_->ClassDefs().GetOffset(); header.data_size_ = header_->DataSize(); header.data_off_ = header_->DataOffset(); @@ -797,8 +787,6 @@ bool DexWriter::Write(DexContainer* output, std::string* error_msg) { // Starting offset is right after the header. stream->Seek(GetHeaderSize()); - dex_ir::Collections& collection = header_->GetCollections(); - // Based on: https://source.android.com/devices/tech/dalvik/dex-format // Since the offsets may not be calculated already, the writing must be done in the correct order. const uint32_t string_ids_offset = stream->Tell(); @@ -863,9 +851,9 @@ bool DexWriter::Write(DexContainer* output, std::string* error_msg) { // Write the map list. if (compute_offsets_) { stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList)); - collection.SetMapListOffset(stream->Tell()); + header_->SetMapListOffset(stream->Tell()); } else { - stream->Seek(collection.MapListOffset()); + stream->Seek(header_->MapListOffset()); } GenerateAndWriteMapItems(stream); stream->AlignTo(kDataSectionAlignment); @@ -882,7 +870,7 @@ bool DexWriter::Write(DexContainer* output, std::string* error_msg) { } // Write link data if it exists. - const std::vector<uint8_t>& link_data = collection.LinkData(); + const std::vector<uint8_t>& link_data = header_->LinkData(); if (link_data.size() > 0) { CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size())); if (compute_offsets_) { diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 39d93bfc77..d6dd9d1829 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -417,24 +417,24 @@ static std::unique_ptr<char[]> IndexString(dex_ir::Header* header, outSize = snprintf(buf.get(), buf_size, "<no-index>"); break; case Instruction::kIndexTypeRef: - if (index < header->GetCollections().TypeIdsSize()) { - const char* tp = header->GetCollections().GetTypeId(index)->GetStringId()->Data(); + if (index < header->TypeIds().Size()) { + const char* tp = header->TypeIds()[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->GetCollections().StringIdsSize()) { - const char* st = header->GetCollections().GetStringId(index)->Data(); + if (index < header->StringIds().Size()) { + const char* st = header->StringIds()[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->GetCollections().MethodIdsSize()) { - dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index); + if (index < header->MethodIds().Size()) { + dex_ir::MethodId* method_id = header->MethodIds()[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(); @@ -445,8 +445,8 @@ static std::unique_ptr<char[]> IndexString(dex_ir::Header* header, } break; case Instruction::kIndexFieldRef: - if (index < header->GetCollections().FieldIdsSize()) { - dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(index); + if (index < header->FieldIds().Size()) { + dex_ir::FieldId* field_id = header->FieldIds()[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(); @@ -466,15 +466,15 @@ static std::unique_ptr<char[]> IndexString(dex_ir::Header* header, case Instruction::kIndexMethodAndProtoRef: { std::string method("<method?>"); std::string proto("<proto?>"); - if (index < header->GetCollections().MethodIdsSize()) { - dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index); + if (index < header->MethodIds().Size()) { + dex_ir::MethodId* method_id = header->MethodIds()[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(); method = StringPrintf("%s.%s:%s", back_descriptor, name, type_descriptor.c_str()); } - if (secondary_index < header->GetCollections().ProtoIdsSize()) { - dex_ir::ProtoId* proto_id = header->GetCollections().GetProtoId(secondary_index); + if (secondary_index < header->ProtoIds().Size()) { + dex_ir::ProtoId* proto_id = header->ProtoIds()[secondary_index]; proto = GetSignatureForProtoId(proto_id); } outSize = snprintf(buf.get(), buf_size, "%s, %s // method@%0*x, proto@%0*x", @@ -596,7 +596,6 @@ void DexLayout::DumpEncodedValue(const dex_ir::EncodedValue* data) { */ void DexLayout::DumpFileHeader() { 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); @@ -610,24 +609,24 @@ void DexLayout::DumpFileHeader() { 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", collections.StringIdsSize()); + fprintf(out_file_, "string_ids_size : %d\n", header_->StringIds().Size()); fprintf(out_file_, "string_ids_off : %d (0x%06x)\n", - collections.StringIdsOffset(), collections.StringIdsOffset()); - fprintf(out_file_, "type_ids_size : %d\n", collections.TypeIdsSize()); + header_->StringIds().GetOffset(), header_->StringIds().GetOffset()); + fprintf(out_file_, "type_ids_size : %d\n", header_->TypeIds().Size()); fprintf(out_file_, "type_ids_off : %d (0x%06x)\n", - collections.TypeIdsOffset(), collections.TypeIdsOffset()); - fprintf(out_file_, "proto_ids_size : %d\n", collections.ProtoIdsSize()); + header_->TypeIds().GetOffset(), header_->TypeIds().GetOffset()); + fprintf(out_file_, "proto_ids_size : %d\n", header_->ProtoIds().Size()); fprintf(out_file_, "proto_ids_off : %d (0x%06x)\n", - collections.ProtoIdsOffset(), collections.ProtoIdsOffset()); - fprintf(out_file_, "field_ids_size : %d\n", collections.FieldIdsSize()); + header_->ProtoIds().GetOffset(), header_->ProtoIds().GetOffset()); + fprintf(out_file_, "field_ids_size : %d\n", header_->FieldIds().Size()); fprintf(out_file_, "field_ids_off : %d (0x%06x)\n", - collections.FieldIdsOffset(), collections.FieldIdsOffset()); - fprintf(out_file_, "method_ids_size : %d\n", collections.MethodIdsSize()); + header_->FieldIds().GetOffset(), header_->FieldIds().GetOffset()); + fprintf(out_file_, "method_ids_size : %d\n", header_->MethodIds().Size()); fprintf(out_file_, "method_ids_off : %d (0x%06x)\n", - collections.MethodIdsOffset(), collections.MethodIdsOffset()); - fprintf(out_file_, "class_defs_size : %d\n", collections.ClassDefsSize()); + header_->MethodIds().GetOffset(), header_->MethodIds().GetOffset()); + fprintf(out_file_, "class_defs_size : %d\n", header_->ClassDefs().Size()); fprintf(out_file_, "class_defs_off : %d (0x%06x)\n", - collections.ClassDefsOffset(), collections.ClassDefsOffset()); + header_->ClassDefs().GetOffset(), header_->ClassDefs().GetOffset()); fprintf(out_file_, "data_size : %d\n", header_->DataSize()); fprintf(out_file_, "data_off : %d (0x%06x)\n\n", header_->DataOffset(), header_->DataOffset()); @@ -638,7 +637,7 @@ void DexLayout::DumpFileHeader() { */ void DexLayout::DumpClassDef(int idx) { // General class information. - dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx); + dex_ir::ClassDef* class_def = header_->ClassDefs()[idx]; fprintf(out_file_, "Class #%d header:\n", idx); fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetIndex()); fprintf(out_file_, "access_flags : %d (0x%04x)\n", @@ -719,7 +718,7 @@ void DexLayout::DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item) { * Dumps class annotations. */ void DexLayout::DumpClassAnnotations(int idx) { - dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx); + dex_ir::ClassDef* class_def = header_->ClassDefs()[idx]; dex_ir::AnnotationsDirectoryItem* annotations_directory = class_def->Annotations(); if (annotations_directory == nullptr) { return; // none @@ -1039,7 +1038,7 @@ void DexLayout::DumpInstruction(const dex_ir::CodeItem* code, * Dumps a bytecode disassembly. */ void DexLayout::DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32_t code_offset) { - dex_ir::MethodId* method_id = header_->GetCollections().GetMethodId(idx); + dex_ir::MethodId* method_id = header_->MethodIds()[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(); @@ -1083,16 +1082,16 @@ static void DumpLocalsCb(void* context, const DexFile::LocalInfo& entry) { /* * Lookup functions. */ -static const char* StringDataByIdx(uint32_t idx, dex_ir::Collections& collections) { - dex_ir::StringId* string_id = collections.GetStringIdOrNullPtr(idx); +static const char* StringDataByIdx(uint32_t idx, dex_ir::Header* header) { + dex_ir::StringId* string_id = header->GetStringIdOrNullPtr(idx); if (string_id == nullptr) { return nullptr; } return string_id->Data(); } -static const char* StringDataByTypeIdx(uint16_t idx, dex_ir::Collections& collections) { - dex_ir::TypeId* type_id = collections.GetTypeIdOrNullPtr(idx); +static const char* StringDataByTypeIdx(uint16_t idx, dex_ir::Header* header) { + dex_ir::TypeId* type_id = header->GetTypeIdOrNullPtr(idx); if (type_id == nullptr) { return nullptr; } @@ -1134,7 +1133,7 @@ void DexLayout::DumpCode(uint32_t idx, if (debug_info != nullptr) { DexFile::DecodeDebugPositionInfo(debug_info->GetDebugInfo(), [this](uint32_t idx) { - return StringDataByIdx(idx, this->header_->GetCollections()); + return StringDataByIdx(idx, this->header_); }, DumpPositionsCb, out_file_); @@ -1161,12 +1160,12 @@ void DexLayout::DumpCode(uint32_t idx, code->InsSize(), code->InsnsSize(), [this](uint32_t idx) { - return StringDataByIdx(idx, this->header_->GetCollections()); + return StringDataByIdx(idx, this->header_); }, [this](uint32_t idx) { return StringDataByTypeIdx(dchecked_integral_cast<uint16_t>(idx), - this->header_->GetCollections()); + this->header_); }, DumpLocalsCb, out_file_); @@ -1182,7 +1181,7 @@ void DexLayout::DumpMethod(uint32_t idx, uint32_t flags, const dex_ir::CodeItem* return; } - dex_ir::MethodId* method_id = header_->GetCollections().GetMethodId(idx); + dex_ir::MethodId* method_id = header_->MethodIds()[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(); @@ -1292,7 +1291,7 @@ void DexLayout::DumpSField(uint32_t idx, uint32_t flags, int i, dex_ir::EncodedV return; } - dex_ir::FieldId* field_id = header_->GetCollections().GetFieldId(idx); + dex_ir::FieldId* field_id = header_->FieldIds()[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(); @@ -1346,7 +1345,7 @@ void DexLayout::DumpIField(uint32_t idx, uint32_t flags, int i) { * the value will be replaced with a newly-allocated string. */ void DexLayout::DumpClass(int idx, char** last_package) { - dex_ir::ClassDef* class_def = header_->GetCollections().GetClassDef(idx); + dex_ir::ClassDef* class_def = header_->ClassDefs()[idx]; // Omitting non-public class. if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) { return; @@ -1364,8 +1363,7 @@ void DexLayout::DumpClass(int idx, char** last_package) { // 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_->GetCollections().GetClassDef(idx)->ClassType()->GetStringId()->Data(); + const char* class_descriptor = header_->ClassDefs()[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? @@ -1543,7 +1541,7 @@ void DexLayout::DumpDexFile() { // Iterate over all classes. char* package = nullptr; - const uint32_t class_defs_size = header_->GetCollections().ClassDefsSize(); + const uint32_t class_defs_size = header_->ClassDefs().Size(); for (uint32_t i = 0; i < class_defs_size; i++) { DumpClass(i, &package); } // for @@ -1562,13 +1560,13 @@ void DexLayout::DumpDexFile() { void DexLayout::LayoutClassDefsAndClassData(const DexFile* dex_file) { std::vector<dex_ir::ClassDef*> new_class_def_order; - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { dex::TypeIndex type_idx(class_def->ClassType()->GetIndex()); if (info_->ContainsClass(*dex_file, type_idx)) { new_class_def_order.push_back(class_def.get()); } } - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { dex::TypeIndex type_idx(class_def->ClassType()->GetIndex()); if (!info_->ContainsClass(*dex_file, type_idx)) { new_class_def_order.push_back(class_def.get()); @@ -1576,8 +1574,7 @@ void DexLayout::LayoutClassDefsAndClassData(const DexFile* dex_file) { } std::unordered_set<dex_ir::ClassData*> visited_class_data; size_t class_data_index = 0; - dex_ir::CollectionVector<dex_ir::ClassData>::Vector& class_datas = - header_->GetCollections().ClassDatas(); + auto& class_datas = header_->ClassDatas(); for (dex_ir::ClassDef* class_def : new_class_def_order) { dex_ir::ClassData* class_data = class_def->GetClassData(); if (class_data != nullptr && visited_class_data.find(class_data) == visited_class_data.end()) { @@ -1590,15 +1587,14 @@ void DexLayout::LayoutClassDefsAndClassData(const DexFile* dex_file) { ++class_data_index; } } - CHECK_EQ(class_data_index, class_datas.size()); + CHECK_EQ(class_data_index, class_datas.Size()); if (DexLayout::kChangeClassDefOrder) { // This currently produces dex files that violate the spec since the super class class_def is // supposed to occur before any subclasses. - dex_ir::CollectionVector<dex_ir::ClassDef>::Vector& class_defs = - header_->GetCollections().ClassDefs(); - CHECK_EQ(new_class_def_order.size(), class_defs.size()); - for (size_t i = 0; i < class_defs.size(); ++i) { + dex_ir::CollectionVector<dex_ir::ClassDef>& class_defs = header_->ClassDefs(); + CHECK_EQ(new_class_def_order.size(), class_defs.Size()); + for (size_t i = 0; i < class_defs.Size(); ++i) { // Overwrite the existing vector with the new ordering, note that the sets of objects are // equivalent, but the order changes. This is why this is not a memory leak. // TODO: Consider cleaning this up with a shared_ptr. @@ -1609,10 +1605,10 @@ void DexLayout::LayoutClassDefsAndClassData(const DexFile* dex_file) { } void DexLayout::LayoutStringData(const DexFile* dex_file) { - const size_t num_strings = header_->GetCollections().StringIds().size(); + const size_t num_strings = header_->StringIds().Size(); std::vector<bool> is_shorty(num_strings, false); std::vector<bool> from_hot_method(num_strings, false); - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { // A name of a profile class is probably going to get looked up by ClassTable::Lookup, mark it // as hot. Add its super class and interfaces as well, which can be used during initialization. const bool is_profile_class = @@ -1678,7 +1674,7 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) { } // Sort string data by specified order. std::vector<dex_ir::StringId*> string_ids; - for (auto& string_id : header_->GetCollections().StringIds()) { + for (auto& string_id : header_->StringIds()) { string_ids.push_back(string_id.get()); } std::sort(string_ids.begin(), @@ -1699,8 +1695,7 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) { // Order by index by default. return a->GetIndex() < b->GetIndex(); }); - dex_ir::CollectionVector<dex_ir::StringData>::Vector& string_datas = - header_->GetCollections().StringDatas(); + auto& string_datas = header_->StringDatas(); // Now we know what order we want the string data, reorder them. size_t data_index = 0; for (dex_ir::StringId* string_id : string_ids) { @@ -1713,11 +1708,11 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) { for (const std::unique_ptr<dex_ir::StringData>& data : string_datas) { visited.insert(data.get()); } - for (auto& string_id : header_->GetCollections().StringIds()) { + for (auto& string_id : header_->StringIds()) { CHECK(visited.find(string_id->DataItem()) != visited.end()); } } - CHECK_EQ(data_index, string_datas.size()); + CHECK_EQ(data_index, string_datas.Size()); } // Orders code items according to specified class data ordering. @@ -1732,7 +1727,7 @@ void DexLayout::LayoutCodeItems(const DexFile* dex_file) { // Assign hotness flags to all code items. for (InvokeType invoke_type : invoke_types) { - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_->GetCollections().ClassDefs()) { + for (auto& class_def : header_->ClassDefs()) { const bool is_profile_class = info_->ContainsClass(*dex_file, dex::TypeIndex(class_def->ClassType()->GetIndex())); @@ -1778,8 +1773,7 @@ void DexLayout::LayoutCodeItems(const DexFile* dex_file) { } } - dex_ir::CollectionVector<dex_ir::CodeItem>::Vector& code_items = - header_->GetCollections().CodeItems(); + const auto& code_items = header_->CodeItems(); if (VLOG_IS_ON(dex)) { size_t layout_count[static_cast<size_t>(LayoutType::kLayoutTypeCount)] = {}; for (const std::unique_ptr<dex_ir::CodeItem>& code_item : code_items) { @@ -1871,7 +1865,7 @@ bool DexLayout::ProcessDexFile(const char* file_name, const bool has_output_container = dex_container != nullptr; const bool output = options_.output_dex_directory_ != nullptr || has_output_container; - // Try to avoid eagerly assigning offsets to find bugs since GetOffset will abort if the offset + // Try to avoid eagerly assigning offsets to find bugs since Offset will abort if the offset // is unassigned. bool eagerly_assign_offsets = false; if (options_.visualize_pattern_ || options_.show_section_statistics_ || options_.dump_) { |