diff options
-rw-r--r-- | dexlayout/Android.bp | 1 | ||||
-rw-r--r-- | dexlayout/dex_ir.cc | 167 | ||||
-rw-r--r-- | dexlayout/dex_ir.h | 144 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 2 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 651 | ||||
-rw-r--r-- | dexlayout/dex_writer.h | 74 | ||||
-rw-r--r-- | dexlayout/dexlayout.cc | 107 | ||||
-rw-r--r-- | dexlayout/dexlayout_test.cc | 48 |
8 files changed, 168 insertions, 1026 deletions
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp index 1e812a2844..296cdb6140 100644 --- a/dexlayout/Android.bp +++ b/dexlayout/Android.bp @@ -20,7 +20,6 @@ art_cc_binary { "dexlayout.cc", "dex_ir.cc", "dex_ir_builder.cc", - "dex_writer.cc", ], cflags: ["-Wall"], shared_libs: [ diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index b64ff8b2ec..aff03cd6ea 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -55,54 +55,6 @@ static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) { entry.end_address_, entry.reg_))); } -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; - } - } - } -} - EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) { const uint8_t encoded_value = *(*data)++; const uint8_t type = encoded_value & 0x1f; @@ -227,7 +179,7 @@ void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) { void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) { const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i); const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id); - TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_); + TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_, true); ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_), GetTypeId(disk_proto_id.return_type_idx_), @@ -258,7 +210,7 @@ void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) { const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_); const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def); - TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_); + TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_, false); const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_); // Annotations. @@ -280,8 +232,9 @@ void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) { class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i); } -TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, uint32_t offset) { - if (dex_type_list == nullptr) { +TypeList* Collections::CreateTypeList( + const DexFile::TypeList* dex_type_list, uint32_t offset, bool allow_empty) { + if (dex_type_list == nullptr && !allow_empty) { return nullptr; } // TODO: Create more efficient lookup for existing type lists. @@ -291,7 +244,7 @@ TypeList* Collections::CreateTypeList(const DexFile::TypeList* dex_type_list, ui } } TypeIdVector* type_vector = new TypeIdVector(); - uint32_t size = dex_type_list->Size(); + uint32_t size = dex_type_list == nullptr ? 0 : dex_type_list->Size(); for (uint32_t index = 0; index < size; ++index) { type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_)); } @@ -304,11 +257,6 @@ EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data if (static_data == nullptr) { return nullptr; } - for (std::unique_ptr<EncodedArrayItem>& existing_array_item : EncodedArrayItems()) { - if (existing_array_item->GetOffset() == offset) { - return existing_array_item.get(); - } - } uint32_t size = DecodeUnsignedLeb128(&static_data); EncodedValueVector* values = new EncodedValueVector(); for (uint32_t i = 0; i < size; ++i) { @@ -322,11 +270,6 @@ EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation, uint32_t offset) { - for (std::unique_ptr<AnnotationItem>& existing_annotation_item : AnnotationItems()) { - if (existing_annotation_item->GetOffset() == offset) { - return existing_annotation_item.get(); - } - } uint8_t visibility = annotation->visibility_; const uint8_t* annotation_data = annotation->annotation_; EncodedValue* encoded_value = @@ -341,14 +284,9 @@ AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file, const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset) { - if (disk_annotations_item.size_ == 0 && offset == 0) { + if (disk_annotations_item.size_ == 0) { return nullptr; } - for (std::unique_ptr<AnnotationSetItem>& existing_anno_set_item : AnnotationSetItems()) { - if (existing_anno_set_item->GetOffset() == offset) { - return existing_anno_set_item.get(); - } - } std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>(); for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) { const DexFile::AnnotationItem* annotation = @@ -367,11 +305,6 @@ AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file, AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file, const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) { - for (std::unique_ptr<AnnotationsDirectoryItem>& anno_dir_item : AnnotationsDirectoryItems()) { - if (anno_dir_item->GetOffset() == offset) { - return anno_dir_item.get(); - } - } const DexFile::AnnotationSetItem* class_set_item = dex_file.GetClassAnnotationSet(disk_annotations_item); AnnotationSetItem* class_annotation = nullptr; @@ -434,25 +367,16 @@ AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexF ParameterAnnotation* Collections::GenerateParameterAnnotation( const DexFile& dex_file, MethodId* method_id, const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) { - AnnotationSetRefList* set_ref_list = nullptr; - for (std::unique_ptr<AnnotationSetRefList>& existing_set_ref_list : AnnotationSetRefLists()) { - if (existing_set_ref_list->GetOffset() == offset) { - set_ref_list = existing_set_ref_list.get(); - break; - } + 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)); } - 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 = new AnnotationSetRefList(annotations); - annotation_set_ref_lists_.AddItem(set_ref_list, offset); - } - return new ParameterAnnotation(method_id, set_ref_list); + AnnotationSetRefList* new_ref_list = new AnnotationSetRefList(annotations); + annotation_set_ref_lists_.AddItem(new_ref_list, offset); + return new ParameterAnnotation(method_id, new_ref_list); } CodeItem* Collections::CreateCodeItem(const DexFile& dex_file, @@ -466,10 +390,7 @@ CodeItem* Collections::CreateCodeItem(const DexFile& dex_file, const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item); DebugInfoItem* debug_info = nullptr; if (debug_info_stream != 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 = new DebugInfoItem(debug_info_size, debug_info_buffer); + debug_info = new DebugInfoItem(); debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_); } @@ -478,41 +399,26 @@ CodeItem* Collections::CreateCodeItem(const DexFile& dex_file, memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t)); TryItemVector* tries = nullptr; - CatchHandlerVector* handler_list = nullptr; if (tries_size > 0) { tries = new TryItemVector(); - handler_list = new CatchHandlerVector(); for (uint32_t i = 0; i < tries_size; ++i) { const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i); uint32_t start_addr = disk_try_item->start_addr_; uint16_t insn_count = disk_try_item->insn_count_; - 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(); - } - } - if (handlers == nullptr) { - bool catch_all = false; - TypeAddrPairVector* addr_pairs = new TypeAddrPairVector(); - for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) { - const uint16_t type_index = it.GetHandlerTypeIndex(); - const TypeId* type_id = GetTypeIdOrNullPtr(type_index); - 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)); + CatchHandlerVector* handlers = new CatchHandlerVector(); + for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) { + const uint16_t type_index = it.GetHandlerTypeIndex(); + const TypeId* type_id = GetTypeIdOrNullPtr(type_index); + handlers->push_back(std::unique_ptr<const CatchHandler>( + new CatchHandler(type_id, it.GetHandlerAddress()))); } TryItem* try_item = new TryItem(start_addr, insn_count, handlers); tries->push_back(std::unique_ptr<const TryItem>(try_item)); } } // TODO: Calculate the size of the code item. - CodeItem* code_item = new CodeItem( - registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries, handler_list); + CodeItem* code_item = + new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries); code_items_.AddItem(code_item, offset); return code_item; } @@ -577,28 +483,5 @@ ClassData* Collections::CreateClassData( return class_data; } -template <class T> static uint32_t GetMinOffset(std::vector<std::unique_ptr<T>>& items) { - uint32_t offset = 0xffffffff; - for (std::unique_ptr<T>& item : items) { - if (item->GetOffset() != 0 && item->GetOffset() < offset) { - offset = item->GetOffset(); - } - } - return offset; -} - -void Collections::CalculateSectionOffsets() { - SetStringDatasOffset(GetMinOffset(StringDatas())); - SetTypeListsOffset(GetMinOffset(TypeLists())); - SetEncodedArrayItemsOffset(GetMinOffset(EncodedArrayItems())); - SetAnnotationItemsOffset(GetMinOffset(AnnotationItems())); - SetAnnotationSetItemsOffset(GetMinOffset(AnnotationSetItems())); - SetAnnotationSetRefListsOffset(GetMinOffset(AnnotationSetRefLists())); - SetAnnotationsDirectoryItemsOffset(GetMinOffset(AnnotationsDirectoryItems())); - SetDebugInfoItemsOffset(GetMinOffset(DebugInfoItems())); - SetCodeItemsOffset(GetMinOffset(CodeItems())); - SetClassDatasOffset(GetMinOffset(ClassDatas())); -} - } // namespace dex_ir } // namespace art diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 6c42bacf63..6ae9f1c938 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -24,7 +24,6 @@ #include "dex_file-inl.h" #include "leb128.h" -#include "utf.h" namespace art { namespace dex_ir { @@ -138,22 +137,10 @@ class Collections { std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); } std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); } std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); } - std::vector<std::unique_ptr<StringData>>& StringDatas() { return string_datas_.Collection(); } + std::vector<std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); } std::vector<std::unique_ptr<EncodedArrayItem>>& EncodedArrayItems() { return encoded_array_items_.Collection(); } - std::vector<std::unique_ptr<AnnotationItem>>& AnnotationItems() - { return annotation_items_.Collection(); } - std::vector<std::unique_ptr<AnnotationSetItem>>& AnnotationSetItems() - { return annotation_set_items_.Collection(); } - std::vector<std::unique_ptr<AnnotationSetRefList>>& AnnotationSetRefLists() - { return annotation_set_ref_lists_.Collection(); } - std::vector<std::unique_ptr<AnnotationsDirectoryItem>>& AnnotationsDirectoryItems() - { return annotations_directory_items_.Collection(); } - std::vector<std::unique_ptr<DebugInfoItem>>& DebugInfoItems() - { return debug_info_items_.Collection(); } - std::vector<std::unique_ptr<CodeItem>>& CodeItems() { return code_items_.Collection(); } - std::vector<std::unique_ptr<ClassData>>& ClassDatas() { return class_datas_.Collection(); } void CreateStringId(const DexFile& dex_file, uint32_t i); void CreateTypeId(const DexFile& dex_file, uint32_t i); @@ -162,7 +149,7 @@ class Collections { void CreateMethodId(const DexFile& dex_file, uint32_t i); void CreateClassDef(const DexFile& dex_file, uint32_t i); - TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset); + TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset, bool allow_empty); EncodedArrayItem* CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset); AnnotationItem* CreateAnnotationItem(const DexFile::AnnotationItem* annotation, uint32_t offset); AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file, @@ -195,16 +182,14 @@ class Collections { uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); } uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); } uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); } - uint32_t 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 EncodedArrayOffset() const { return encoded_array_items_.GetOffset(); } + uint32_t AnnotationOffset() const { return annotation_items_.GetOffset(); } + uint32_t AnnotationSetOffset() const { return annotation_set_items_.GetOffset(); } uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); } - uint32_t AnnotationsDirectoryItemsOffset() const - { return annotations_directory_items_.GetOffset(); } - uint32_t DebugInfoItemsOffset() const { return debug_info_items_.GetOffset(); } + uint32_t AnnotationsDirectoryOffset() const { return annotations_directory_items_.GetOffset(); } + uint32_t DebugInfoOffset() const { return debug_info_items_.GetOffset(); } uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); } uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); } - uint32_t MapItemOffset() const { return map_item_offset_; } void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); } void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); } @@ -214,21 +199,16 @@ class Collections { void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); } void SetStringDatasOffset(uint32_t new_offset) { string_datas_.SetOffset(new_offset); } void SetTypeListsOffset(uint32_t new_offset) { type_lists_.SetOffset(new_offset); } - void 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 SetEncodedArrayOffset(uint32_t new_offset) { encoded_array_items_.SetOffset(new_offset); } + void SetAnnotationOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); } + void SetAnnotationSetOffset(uint32_t new_offset) { annotation_set_items_.SetOffset(new_offset); } void SetAnnotationSetRefListsOffset(uint32_t new_offset) { annotation_set_ref_lists_.SetOffset(new_offset); } - void SetAnnotationsDirectoryItemsOffset(uint32_t new_offset) + void SetAnnotationsDirectoryOffset(uint32_t new_offset) { annotations_directory_items_.SetOffset(new_offset); } - void SetDebugInfoItemsOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); } + void SetDebugInfoOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); } void SetCodeItemsOffset(uint32_t new_offset) { code_items_.SetOffset(new_offset); } void SetClassDatasOffset(uint32_t new_offset) { class_datas_.SetOffset(new_offset); } - void SetMapItemOffset(uint32_t new_offset) { map_item_offset_ = new_offset; } - - void CalculateSectionOffsets(); uint32_t StringIdsSize() const { return string_ids_.Size(); } uint32_t TypeIdsSize() const { return type_ids_.Size(); } @@ -236,16 +216,6 @@ class Collections { 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 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(); } private: EncodedValue* ReadEncodedValue(const uint8_t** data); @@ -274,8 +244,6 @@ class Collections { CollectionWithOffset<CodeItem> code_items_; CollectionWithOffset<ClassData> class_datas_; - uint32_t map_item_offset_ = 0; - DISALLOW_COPY_AND_ASSIGN(Collections); }; @@ -385,7 +353,7 @@ class Header : public Item { class StringData : public Item { public: explicit StringData(const char* data) : data_(strdup(data)) { - size_ = UnsignedLeb128Size(CountModifiedUtf8Chars(data)) + strlen(data); + size_ = UnsignedLeb128Size(strlen(data)) + strlen(data); } const char* Data() const { return data_.get(); } @@ -393,7 +361,7 @@ class StringData : public Item { void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } private: - UniqueCPtr<const char> data_; + std::unique_ptr<const char> data_; DISALLOW_COPY_AND_ASSIGN(StringData); }; @@ -463,14 +431,14 @@ class ProtoId : public IndexedItem { const StringId* Shorty() const { return shorty_; } const TypeId* ReturnType() const { return return_type_; } - const TypeList* Parameters() const { return parameters_; } + const TypeIdVector& Parameters() const { return *parameters_->GetTypeList(); } void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } private: const StringId* shorty_; const TypeId* return_type_; - TypeList* parameters_; // This can be nullptr. + TypeList* parameters_; DISALLOW_COPY_AND_ASSIGN(ProtoId); }; @@ -554,7 +522,7 @@ class MethodItem : public Item { private: uint32_t access_flags_; const MethodId* method_id_; - const CodeItem* code_; // This can be nullptr. + const CodeItem* code_; DISALLOW_COPY_AND_ASSIGN(MethodItem); }; @@ -712,8 +680,8 @@ class ClassDef : public IndexedItem { interfaces_(interfaces), source_file_(source_file), annotations_(annotations), - class_data_(class_data), - static_values_(static_values) { size_ = kClassDefItemSize; } + static_values_(static_values), + class_data_(class_data) { size_ = kClassDefItemSize; } ~ClassDef() OVERRIDE { } @@ -727,8 +695,8 @@ class ClassDef : public IndexedItem { uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); } const StringId* SourceFile() const { return source_file_; } AnnotationsDirectoryItem* Annotations() const { return annotations_; } - ClassData* GetClassData() { return class_data_; } EncodedArrayItem* StaticValues() { return static_values_; } + ClassData* GetClassData() { return class_data_; } MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii); @@ -737,19 +705,19 @@ class ClassDef : public IndexedItem { private: const TypeId* class_type_; uint32_t access_flags_; - const TypeId* superclass_; // This can be nullptr. - TypeList* interfaces_; // This can be nullptr. - const StringId* source_file_; // This can be nullptr. - AnnotationsDirectoryItem* annotations_; // This can be nullptr. - ClassData* class_data_; // This can be nullptr. - EncodedArrayItem* static_values_; // This can be nullptr. + const TypeId* superclass_; + TypeList* interfaces_; + const StringId* source_file_; + AnnotationsDirectoryItem* annotations_; + EncodedArrayItem* static_values_; + ClassData* class_data_; DISALLOW_COPY_AND_ASSIGN(ClassDef); }; -class TypeAddrPair { +class CatchHandler { public: - TypeAddrPair(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { } + CatchHandler(const TypeId* type_id, uint32_t address) : type_id_(type_id), address_(address) { } const TypeId* GetTypeId() const { return type_id_; } uint32_t GetAddress() const { return address_; } @@ -758,25 +726,6 @@ class TypeAddrPair { const TypeId* type_id_; uint32_t address_; - DISALLOW_COPY_AND_ASSIGN(TypeAddrPair); -}; - -using TypeAddrPairVector = std::vector<std::unique_ptr<const TypeAddrPair>>; - -class CatchHandler { - public: - explicit CatchHandler(bool catch_all, uint16_t list_offset, TypeAddrPairVector* handlers) - : catch_all_(catch_all), list_offset_(list_offset), handlers_(handlers) { } - - bool HasCatchAll() const { return catch_all_; } - uint16_t GetListOffset() const { return list_offset_; } - TypeAddrPairVector* GetHandlers() const { return handlers_.get(); } - - private: - bool catch_all_; - uint16_t list_offset_; - std::unique_ptr<TypeAddrPairVector> handlers_; - DISALLOW_COPY_AND_ASSIGN(CatchHandler); }; @@ -784,20 +733,20 @@ using CatchHandlerVector = std::vector<std::unique_ptr<const CatchHandler>>; class TryItem : public Item { public: - TryItem(uint32_t start_addr, uint16_t insn_count, const CatchHandler* handlers) + TryItem(uint32_t start_addr, uint16_t insn_count, CatchHandlerVector* handlers) : start_addr_(start_addr), insn_count_(insn_count), handlers_(handlers) { } ~TryItem() OVERRIDE { } uint32_t StartAddr() const { return start_addr_; } uint16_t InsnCount() const { return insn_count_; } - const CatchHandler* GetHandlers() const { return handlers_; } + const CatchHandlerVector& GetHandlers() const { return *handlers_.get(); } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: uint32_t start_addr_; uint16_t insn_count_; - const CatchHandler* handlers_; + std::unique_ptr<CatchHandlerVector> handlers_; DISALLOW_COPY_AND_ASSIGN(TryItem); }; @@ -812,16 +761,14 @@ class CodeItem : public Item { DebugInfoItem* debug_info, uint32_t insns_size, uint16_t* insns, - TryItemVector* tries, - CatchHandlerVector* handlers) + TryItemVector* tries) : registers_size_(registers_size), ins_size_(ins_size), outs_size_(outs_size), debug_info_(debug_info), insns_size_(insns_size), insns_(insns), - tries_(tries), - handlers_(handlers) { } + tries_(tries) { } ~CodeItem() OVERRIDE { } @@ -833,7 +780,6 @@ class CodeItem : public Item { uint32_t InsnsSize() const { return insns_size_; } uint16_t* Insns() const { return insns_.get(); } TryItemVector* Tries() const { return tries_.get(); } - CatchHandlerVector* Handlers() const { return handlers_.get(); } void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } @@ -841,11 +787,10 @@ class CodeItem : public Item { uint16_t registers_size_; uint16_t ins_size_; uint16_t outs_size_; - DebugInfoItem* debug_info_; // This can be nullptr. + DebugInfoItem* debug_info_; uint32_t insns_size_; std::unique_ptr<uint16_t[]> insns_; - std::unique_ptr<TryItemVector> tries_; // This can be nullptr. - std::unique_ptr<CatchHandlerVector> handlers_; // This can be nullptr. + std::unique_ptr<TryItemVector> tries_; DISALLOW_COPY_AND_ASSIGN(CodeItem); }; @@ -885,19 +830,12 @@ using LocalInfoVector = std::vector<std::unique_ptr<LocalInfo>>; class DebugInfoItem : public Item { public: - DebugInfoItem(uint32_t debug_info_size, uint8_t* debug_info) - : debug_info_size_(debug_info_size), debug_info_(debug_info) { } - - uint32_t GetDebugInfoSize() const { return debug_info_size_; } - uint8_t* GetDebugInfo() const { return debug_info_.get(); } + DebugInfoItem() = default; PositionInfoVector& GetPositionInfo() { return positions_; } LocalInfoVector& GetLocalInfo() { return locals_; } private: - uint32_t debug_info_size_; - std::unique_ptr<uint8_t[]> debug_info_; - PositionInfoVector positions_; LocalInfoVector locals_; @@ -950,7 +888,7 @@ class AnnotationSetRefList : public Item { void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: - std::unique_ptr<std::vector<AnnotationSetItem*>> items_; // Elements of vector can be nullptr. + std::unique_ptr<std::vector<AnnotationSetItem*>> items_; DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList); }; @@ -1025,10 +963,10 @@ class AnnotationsDirectoryItem : public Item { void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); } private: - AnnotationSetItem* class_annotation_; // This can be nullptr. - std::unique_ptr<FieldAnnotationVector> field_annotations_; // This can be nullptr. - std::unique_ptr<MethodAnnotationVector> method_annotations_; // This can be nullptr. - std::unique_ptr<ParameterAnnotationVector> parameter_annotations_; // This can be nullptr. + AnnotationSetItem* class_annotation_; + std::unique_ptr<FieldAnnotationVector> field_annotations_; + std::unique_ptr<MethodAnnotationVector> method_annotations_; + std::unique_ptr<ParameterAnnotationVector> parameter_annotations_; DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem); }; diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index b86a6e2ee6..e6868d74bc 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -68,8 +68,6 @@ Header* DexIrBuilder(const DexFile& dex_file) { for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) { collections.CreateClassDef(dex_file, i); } - // MapItem. - collections.SetMapItemOffset(disk_header.map_off_); return header; } diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc deleted file mode 100644 index 721e7b3db1..0000000000 --- a/dexlayout/dex_writer.cc +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Header file of an in-memory representation of DEX files. - */ - -#include <stdint.h> - -#include <queue> -#include <vector> - -#include "dex_writer.h" -#include "utf.h" - -namespace art { - -size_t EncodeIntValue(int32_t value, uint8_t* buffer) { - size_t length = 0; - if (value >= 0) { - while (value > 0x7f) { - buffer[length++] = static_cast<uint8_t>(value); - value >>= 8; - } - } else { - while (value < -0x80) { - buffer[length++] = static_cast<uint8_t>(value); - value >>= 8; - } - } - buffer[length++] = static_cast<uint8_t>(value); - return length; -} - -size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) { - size_t length = 0; - do { - buffer[length++] = static_cast<uint8_t>(value); - value >>= 8; - } while (value != 0); - return length; -} - -size_t EncodeLongValue(int64_t value, uint8_t* buffer) { - size_t length = 0; - if (value >= 0) { - while (value > 0x7f) { - buffer[length++] = static_cast<uint8_t>(value); - value >>= 8; - } - } else { - while (value < -0x80) { - buffer[length++] = static_cast<uint8_t>(value); - value >>= 8; - } - } - buffer[length++] = static_cast<uint8_t>(value); - return length; -} - -union FloatUnion { - float f_; - uint32_t i_; -}; - -size_t EncodeFloatValue(float value, uint8_t* buffer) { - FloatUnion float_union; - float_union.f_ = value; - uint32_t int_value = float_union.i_; - size_t index = 3; - do { - buffer[index--] = int_value >> 24; - int_value <<= 8; - } while (int_value != 0); - return 3 - index; -} - -union DoubleUnion { - double d_; - uint64_t l_; -}; - -size_t EncodeDoubleValue(double value, uint8_t* buffer) { - DoubleUnion double_union; - double_union.d_ = value; - uint64_t long_value = double_union.l_; - size_t index = 7; - do { - buffer[index--] = long_value >> 56; - long_value <<= 8; - } while (long_value != 0); - return 7 - index; -} - -size_t DexWriter::Write(const void* buffer, size_t length, size_t offset) { - return dex_file_->PwriteFully(buffer, length, offset) ? length : 0; -} - -size_t DexWriter::WriteSleb128(uint32_t value, size_t offset) { - uint8_t buffer[8]; - EncodeSignedLeb128(buffer, value); - return Write(buffer, SignedLeb128Size(value), offset); -} - -size_t DexWriter::WriteUleb128(uint32_t value, size_t offset) { - uint8_t buffer[8]; - EncodeUnsignedLeb128(buffer, value); - return Write(buffer, UnsignedLeb128Size(value), offset); -} - -size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset) { - size_t original_offset = offset; - size_t start = 0; - size_t length; - uint8_t buffer[8]; - int8_t type = encoded_value->Type(); - switch (type) { - case DexFile::kDexAnnotationByte: - length = EncodeIntValue(encoded_value->GetByte(), buffer); - break; - case DexFile::kDexAnnotationShort: - length = EncodeIntValue(encoded_value->GetShort(), buffer); - break; - case DexFile::kDexAnnotationChar: - length = EncodeUIntValue(encoded_value->GetChar(), buffer); - break; - case DexFile::kDexAnnotationInt: - length = EncodeIntValue(encoded_value->GetInt(), buffer); - break; - case DexFile::kDexAnnotationLong: - length = EncodeLongValue(encoded_value->GetLong(), buffer); - break; - case DexFile::kDexAnnotationFloat: - length = EncodeFloatValue(encoded_value->GetFloat(), buffer); - start = 4 - length; - break; - case DexFile::kDexAnnotationDouble: - length = EncodeDoubleValue(encoded_value->GetDouble(), buffer); - start = 8 - length; - break; - case DexFile::kDexAnnotationString: - length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer); - break; - case DexFile::kDexAnnotationType: - length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer); - break; - case DexFile::kDexAnnotationField: - case DexFile::kDexAnnotationEnum: - length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer); - break; - case DexFile::kDexAnnotationMethod: - length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer); - break; - case DexFile::kDexAnnotationArray: - offset += WriteEncodedValueHeader(type, 0, offset); - offset += WriteEncodedArray(encoded_value->GetEncodedArray()->GetEncodedValues(), offset); - return offset - original_offset; - case DexFile::kDexAnnotationAnnotation: - offset += WriteEncodedValueHeader(type, 0, offset); - offset += WriteEncodedAnnotation(encoded_value->GetEncodedAnnotation(), offset); - return offset - original_offset; - case DexFile::kDexAnnotationNull: - return WriteEncodedValueHeader(type, 0, offset); - case DexFile::kDexAnnotationBoolean: - return WriteEncodedValueHeader(type, encoded_value->GetBoolean() ? 1 : 0, offset); - default: - return 0; - } - offset += WriteEncodedValueHeader(type, length - 1, offset); - offset += Write(buffer + start, length, offset); - return offset - original_offset; -} - -size_t DexWriter::WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset) { - uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) }; - return Write(buffer, sizeof(uint8_t), offset); -} - -size_t DexWriter::WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset) { - size_t original_offset = offset; - offset += WriteUleb128(values->size(), offset); - for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) { - offset += WriteEncodedValue(value.get(), offset); - } - return offset - original_offset; -} - -size_t DexWriter::WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset) { - size_t original_offset = offset; - offset += WriteUleb128(annotation->GetType()->GetIndex(), offset); - offset += WriteUleb128(annotation->GetAnnotationElements()->size(), offset); - for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element : - *annotation->GetAnnotationElements()) { - offset += WriteUleb128(annotation_element->GetName()->GetIndex(), offset); - offset += WriteEncodedValue(annotation_element->GetValue(), offset); - } - return offset - original_offset; -} - -size_t DexWriter::WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset) { - size_t original_offset = offset; - uint32_t prev_index = 0; - for (std::unique_ptr<dex_ir::FieldItem>& field : *fields) { - uint32_t index = field->GetFieldId()->GetIndex(); - offset += WriteUleb128(index - prev_index, offset); - offset += WriteUleb128(field->GetAccessFlags(), offset); - prev_index = index; - } - return offset - original_offset; -} - -size_t DexWriter::WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset) { - size_t original_offset = offset; - uint32_t prev_index = 0; - for (std::unique_ptr<dex_ir::MethodItem>& method : *methods) { - uint32_t index = method->GetMethodId()->GetIndex(); - uint32_t code_off = method->GetCodeItem() == nullptr ? 0 : method->GetCodeItem()->GetOffset(); - offset += WriteUleb128(index - prev_index, offset); - offset += WriteUleb128(method->GetAccessFlags(), offset); - offset += WriteUleb128(code_off, offset); - prev_index = index; - } - return offset - original_offset; -} - -void DexWriter::WriteStrings() { - uint32_t string_data_off[1]; - for (std::unique_ptr<dex_ir::StringId>& string_id : header_.GetCollections().StringIds()) { - string_data_off[0] = string_id->DataItem()->GetOffset(); - Write(string_data_off, string_id->GetSize(), string_id->GetOffset()); - } - - for (std::unique_ptr<dex_ir::StringData>& string_data : header_.GetCollections().StringDatas()) { - uint32_t offset = string_data->GetOffset(); - offset += WriteUleb128(CountModifiedUtf8Chars(string_data->Data()), offset); - Write(string_data->Data(), strlen(string_data->Data()), offset); - } -} - -void DexWriter::WriteTypes() { - uint32_t descriptor_idx[1]; - for (std::unique_ptr<dex_ir::TypeId>& type_id : header_.GetCollections().TypeIds()) { - descriptor_idx[0] = type_id->GetStringId()->GetIndex(); - Write(descriptor_idx, type_id->GetSize(), type_id->GetOffset()); - } -} - -void DexWriter::WriteTypeLists() { - uint32_t size[1]; - uint16_t list[1]; - for (std::unique_ptr<dex_ir::TypeList>& type_list : header_.GetCollections().TypeLists()) { - size[0] = type_list->GetTypeList()->size(); - uint32_t offset = type_list->GetOffset(); - offset += Write(size, sizeof(uint32_t), offset); - for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) { - list[0] = type_id->GetIndex(); - offset += Write(list, sizeof(uint16_t), offset); - } - } -} - -void DexWriter::WriteProtos() { - uint32_t buffer[3]; - for (std::unique_ptr<dex_ir::ProtoId>& proto_id : header_.GetCollections().ProtoIds()) { - buffer[0] = proto_id->Shorty()->GetIndex(); - buffer[1] = proto_id->ReturnType()->GetIndex(); - buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset(); - Write(buffer, proto_id->GetSize(), proto_id->GetOffset()); - } -} - -void DexWriter::WriteFields() { - uint16_t buffer[4]; - for (std::unique_ptr<dex_ir::FieldId>& field_id : header_.GetCollections().FieldIds()) { - buffer[0] = field_id->Class()->GetIndex(); - buffer[1] = field_id->Type()->GetIndex(); - buffer[2] = field_id->Name()->GetIndex(); - buffer[3] = field_id->Name()->GetIndex() >> 16; - Write(buffer, field_id->GetSize(), field_id->GetOffset()); - } -} - -void DexWriter::WriteMethods() { - uint16_t buffer[4]; - for (std::unique_ptr<dex_ir::MethodId>& method_id : header_.GetCollections().MethodIds()) { - buffer[0] = method_id->Class()->GetIndex(); - buffer[1] = method_id->Proto()->GetIndex(); - buffer[2] = method_id->Name()->GetIndex(); - buffer[3] = method_id->Name()->GetIndex() >> 16; - Write(buffer, method_id->GetSize(), method_id->GetOffset()); - } -} - -void DexWriter::WriteEncodedArrays() { - for (std::unique_ptr<dex_ir::EncodedArrayItem>& encoded_array : - header_.GetCollections().EncodedArrayItems()) { - WriteEncodedArray(encoded_array->GetEncodedValues(), encoded_array->GetOffset()); - } -} - -void DexWriter::WriteAnnotations() { - uint8_t visibility[1]; - for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : - header_.GetCollections().AnnotationItems()) { - visibility[0] = annotation->GetVisibility(); - size_t offset = annotation->GetOffset(); - offset += Write(visibility, sizeof(uint8_t), offset); - WriteEncodedAnnotation(annotation->GetAnnotation(), offset); - } -} - -void DexWriter::WriteAnnotationSets() { - uint32_t size[1]; - uint32_t annotation_off[1]; - for (std::unique_ptr<dex_ir::AnnotationSetItem>& annotation_set : - header_.GetCollections().AnnotationSetItems()) { - size[0] = annotation_set->GetItems()->size(); - size_t offset = annotation_set->GetOffset(); - offset += Write(size, sizeof(uint32_t), offset); - for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) { - annotation_off[0] = annotation->GetOffset(); - offset += Write(annotation_off, sizeof(uint32_t), offset); - } - } -} - -void DexWriter::WriteAnnotationSetRefs() { - uint32_t size[1]; - uint32_t annotations_off[1]; - for (std::unique_ptr<dex_ir::AnnotationSetRefList>& annotation_set_ref : - header_.GetCollections().AnnotationSetRefLists()) { - size[0] = annotation_set_ref->GetItems()->size(); - size_t offset = annotation_set_ref->GetOffset(); - offset += Write(size, sizeof(uint32_t), offset); - for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) { - annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset(); - offset += Write(annotations_off, sizeof(uint32_t), offset); - } - } -} - -void DexWriter::WriteAnnotationsDirectories() { - uint32_t directory_buffer[4]; - uint32_t annotation_buffer[2]; - for (std::unique_ptr<dex_ir::AnnotationsDirectoryItem>& annotations_directory : - header_.GetCollections().AnnotationsDirectoryItems()) { - directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 : - annotations_directory->GetClassAnnotation()->GetOffset(); - directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 : - annotations_directory->GetFieldAnnotations()->size(); - directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 : - annotations_directory->GetMethodAnnotations()->size(); - directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 : - annotations_directory->GetParameterAnnotations()->size(); - uint32_t offset = annotations_directory->GetOffset(); - offset += Write(directory_buffer, 4 * sizeof(uint32_t), offset); - if (annotations_directory->GetFieldAnnotations() != nullptr) { - for (std::unique_ptr<dex_ir::FieldAnnotation>& field : - *annotations_directory->GetFieldAnnotations()) { - annotation_buffer[0] = field->GetFieldId()->GetIndex(); - annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset(); - offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); - } - } - if (annotations_directory->GetMethodAnnotations() != nullptr) { - for (std::unique_ptr<dex_ir::MethodAnnotation>& method : - *annotations_directory->GetMethodAnnotations()) { - annotation_buffer[0] = method->GetMethodId()->GetIndex(); - annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset(); - offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); - } - } - if (annotations_directory->GetParameterAnnotations() != nullptr) { - for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter : - *annotations_directory->GetParameterAnnotations()) { - annotation_buffer[0] = parameter->GetMethodId()->GetIndex(); - annotation_buffer[1] = parameter->GetAnnotations()->GetOffset(); - offset += Write(annotation_buffer, 2 * sizeof(uint32_t), offset); - } - } - } -} - -void DexWriter::WriteDebugInfoItems() { - for (std::unique_ptr<dex_ir::DebugInfoItem>& info : header_.GetCollections().DebugInfoItems()) { - Write(info->GetDebugInfo(), info->GetDebugInfoSize(), info->GetOffset()); - } -} - -void DexWriter::WriteCodeItems() { - uint16_t uint16_buffer[4]; - uint32_t uint32_buffer[2]; - for (std::unique_ptr<dex_ir::CodeItem>& code_item : header_.GetCollections().CodeItems()) { - uint16_buffer[0] = code_item->RegistersSize(); - uint16_buffer[1] = code_item->InsSize(); - uint16_buffer[2] = code_item->OutsSize(); - uint16_buffer[3] = code_item->TriesSize(); - uint32_buffer[0] = code_item->DebugInfo() == nullptr ? 0 : code_item->DebugInfo()->GetOffset(); - uint32_buffer[1] = code_item->InsnsSize(); - size_t offset = code_item->GetOffset(); - offset += Write(uint16_buffer, 4 * sizeof(uint16_t), offset); - offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset); - offset += Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t), offset); - if (code_item->TriesSize() != 0) { - if (code_item->InsnsSize() % 2 != 0) { - uint16_t padding[1] = { 0 }; - offset += Write(padding, sizeof(uint16_t), offset); - } - uint32_t start_addr[1]; - uint16_t insn_count_and_handler_off[2]; - for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) { - start_addr[0] = try_item->StartAddr(); - insn_count_and_handler_off[0] = try_item->InsnCount(); - insn_count_and_handler_off[1] = try_item->GetHandlers()->GetListOffset(); - offset += Write(start_addr, sizeof(uint32_t), offset); - offset += Write(insn_count_and_handler_off, 2 * sizeof(uint16_t), offset); - } - // Leave offset pointing to the end of the try items. - WriteUleb128(code_item->Handlers()->size(), offset); - for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) { - size_t list_offset = offset + handlers->GetListOffset(); - uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 : - handlers->GetHandlers()->size(); - list_offset += WriteSleb128(size, list_offset); - for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) { - if (handler->GetTypeId() != nullptr) { - list_offset += WriteUleb128(handler->GetTypeId()->GetIndex(), list_offset); - } - list_offset += WriteUleb128(handler->GetAddress(), list_offset); - } - } - } - } -} - -void DexWriter::WriteClasses() { - uint32_t class_def_buffer[8]; - for (std::unique_ptr<dex_ir::ClassDef>& class_def : header_.GetCollections().ClassDefs()) { - class_def_buffer[0] = class_def->ClassType()->GetIndex(); - class_def_buffer[1] = class_def->GetAccessFlags(); - class_def_buffer[2] = class_def->Superclass() == nullptr ? DexFile::kDexNoIndex : - class_def->Superclass()->GetIndex(); - class_def_buffer[3] = class_def->InterfacesOffset(); - class_def_buffer[4] = class_def->SourceFile() == nullptr ? DexFile::kDexNoIndex : - class_def->SourceFile()->GetIndex(); - class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 : - class_def->Annotations()->GetOffset(); - class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 : - class_def->GetClassData()->GetOffset(); - class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 : - class_def->StaticValues()->GetOffset(); - size_t offset = class_def->GetOffset(); - Write(class_def_buffer, class_def->GetSize(), offset); - } - - for (std::unique_ptr<dex_ir::ClassData>& class_data : header_.GetCollections().ClassDatas()) { - size_t offset = class_data->GetOffset(); - offset += WriteUleb128(class_data->StaticFields()->size(), offset); - offset += WriteUleb128(class_data->InstanceFields()->size(), offset); - offset += WriteUleb128(class_data->DirectMethods()->size(), offset); - offset += WriteUleb128(class_data->VirtualMethods()->size(), offset); - offset += WriteEncodedFields(class_data->StaticFields(), offset); - offset += WriteEncodedFields(class_data->InstanceFields(), offset); - offset += WriteEncodedMethods(class_data->DirectMethods(), offset); - offset += WriteEncodedMethods(class_data->VirtualMethods(), offset); - } -} - -struct MapItemContainer { - MapItemContainer(uint32_t type, uint32_t size, uint32_t offset) - : type_(type), size_(size), offset_(offset) { } - - bool operator<(const MapItemContainer& other) const { - return offset_ > other.offset_; - } - - uint32_t type_; - uint32_t size_; - uint32_t offset_; -}; - -void DexWriter::WriteMapItem() { - dex_ir::Collections& collection = header_.GetCollections(); - std::priority_queue<MapItemContainer> queue; - - // Header and index section. - queue.push(MapItemContainer(DexFile::kDexTypeHeaderItem, 1, 0)); - if (collection.StringIdsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeStringIdItem, collection.StringIdsSize(), - collection.StringIdsOffset())); - } - if (collection.TypeIdsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeTypeIdItem, collection.TypeIdsSize(), - collection.TypeIdsOffset())); - } - if (collection.ProtoIdsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeProtoIdItem, collection.ProtoIdsSize(), - collection.ProtoIdsOffset())); - } - if (collection.FieldIdsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeFieldIdItem, collection.FieldIdsSize(), - collection.FieldIdsOffset())); - } - if (collection.MethodIdsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeMethodIdItem, collection.MethodIdsSize(), - collection.MethodIdsOffset())); - } - if (collection.ClassDefsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(), - collection.ClassDefsOffset())); - } - - // Data section. - queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapItemOffset())); - if (collection.TypeListsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeTypeList, collection.TypeListsSize(), - collection.TypeListsOffset())); - } - if (collection.AnnotationSetRefListsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetRefList, - collection.AnnotationSetRefListsSize(), collection.AnnotationSetRefListsOffset())); - } - if (collection.AnnotationSetItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeAnnotationSetItem, - collection.AnnotationSetItemsSize(), collection.AnnotationSetItemsOffset())); - } - if (collection.ClassDatasSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeClassDataItem, collection.ClassDatasSize(), - collection.ClassDatasOffset())); - } - if (collection.CodeItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeCodeItem, collection.CodeItemsSize(), - collection.CodeItemsOffset())); - } - if (collection.StringDatasSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeStringDataItem, collection.StringDatasSize(), - collection.StringDatasOffset())); - } - if (collection.DebugInfoItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeDebugInfoItem, collection.DebugInfoItemsSize(), - collection.DebugInfoItemsOffset())); - } - if (collection.AnnotationItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeAnnotationItem, collection.AnnotationItemsSize(), - collection.AnnotationItemsOffset())); - } - if (collection.EncodedArrayItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeEncodedArrayItem, - collection.EncodedArrayItemsSize(), collection.EncodedArrayItemsOffset())); - } - if (collection.AnnotationsDirectoryItemsSize() != 0) { - queue.push(MapItemContainer(DexFile::kDexTypeAnnotationsDirectoryItem, - collection.AnnotationsDirectoryItemsSize(), collection.AnnotationsDirectoryItemsOffset())); - } - - uint32_t offset = collection.MapItemOffset(); - uint16_t uint16_buffer[2]; - uint32_t uint32_buffer[2]; - uint16_buffer[1] = 0; - uint32_buffer[0] = queue.size(); - offset += Write(uint32_buffer, sizeof(uint32_t), offset); - while (!queue.empty()) { - const MapItemContainer& map_item = queue.top(); - uint16_buffer[0] = map_item.type_; - uint32_buffer[0] = map_item.size_; - uint32_buffer[1] = map_item.offset_; - offset += Write(uint16_buffer, 2 * sizeof(uint16_t), offset); - offset += Write(uint32_buffer, 2 * sizeof(uint32_t), offset); - queue.pop(); - } -} - -void DexWriter::WriteHeader() { - uint32_t buffer[20]; - dex_ir::Collections& collections = header_.GetCollections(); - size_t offset = 0; - offset += Write(header_.Magic(), 8 * sizeof(uint8_t), offset); - buffer[0] = header_.Checksum(); - offset += Write(buffer, sizeof(uint32_t), offset); - offset += Write(header_.Signature(), 20 * sizeof(uint8_t), offset); - uint32_t file_size = header_.FileSize(); - buffer[0] = file_size; - buffer[1] = header_.GetSize(); - buffer[2] = header_.EndianTag(); - buffer[3] = header_.LinkSize(); - buffer[4] = header_.LinkOffset(); - buffer[5] = collections.MapItemOffset(); - buffer[6] = collections.StringIdsSize(); - buffer[7] = collections.StringIdsOffset(); - buffer[8] = collections.TypeIdsSize(); - buffer[9] = collections.TypeIdsOffset(); - buffer[10] = collections.ProtoIdsSize(); - buffer[11] = collections.ProtoIdsOffset(); - buffer[12] = collections.FieldIdsSize(); - buffer[13] = collections.FieldIdsOffset(); - buffer[14] = collections.MethodIdsSize(); - buffer[15] = collections.MethodIdsOffset(); - uint32_t class_defs_size = collections.ClassDefsSize(); - uint32_t class_defs_off = collections.ClassDefsOffset(); - buffer[16] = class_defs_size; - buffer[17] = class_defs_off; - uint32_t data_off = class_defs_off + class_defs_size * dex_ir::ClassDef::ItemSize(); - uint32_t data_size = file_size - data_off; - buffer[18] = data_size; - buffer[19] = data_off; - Write(buffer, 20 * sizeof(uint32_t), offset); -} - -void DexWriter::WriteFile() { - if (dex_file_.get() == nullptr) { - fprintf(stderr, "Can't open output dex file\n"); - return; - } - - header_.GetCollections().CalculateSectionOffsets(); - - WriteStrings(); - WriteTypes(); - WriteTypeLists(); - WriteProtos(); - WriteFields(); - WriteMethods(); - WriteEncodedArrays(); - WriteAnnotations(); - WriteAnnotationSets(); - WriteAnnotationSetRefs(); - WriteAnnotationsDirectories(); - WriteDebugInfoItems(); - WriteCodeItems(); - WriteClasses(); - WriteMapItem(); - WriteHeader(); -} - -void DexWriter::OutputDexFile(dex_ir::Header& header, const char* file_name) { - LOG(INFO) << "FILE NAME: " << file_name; - (new DexWriter(header, file_name))->WriteFile(); -} - -} // namespace art diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h deleted file mode 100644 index 9104295472..0000000000 --- a/dexlayout/dex_writer.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Header file of an in-memory representation of DEX files. - */ - -#ifndef ART_DEXLAYOUT_DEX_WRITER_H_ -#define ART_DEXLAYOUT_DEX_WRITER_H_ - -#include "base/unix_file/fd_file.h" -#include "dex_ir.h" -#include "os.h" - -namespace art { - -class DexWriter { - public: - DexWriter(dex_ir::Header& header, const char* file_name) : header_(header), - dex_file_(OS::CreateEmptyFileWriteOnly(file_name)) { } - - static void OutputDexFile(dex_ir::Header& header, const char* file_name); - - private: - void WriteFile(); - - size_t Write(const void* buffer, size_t length, size_t offset); - size_t WriteSleb128(uint32_t value, size_t offset); - size_t WriteUleb128(uint32_t value, size_t offset); - size_t WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t offset); - size_t WriteEncodedValueHeader(int8_t value_type, size_t value_arg, size_t offset); - size_t WriteEncodedArray(dex_ir::EncodedValueVector* values, size_t offset); - size_t WriteEncodedAnnotation(dex_ir::EncodedAnnotation* annotation, size_t offset); - size_t WriteEncodedFields(dex_ir::FieldItemVector* fields, size_t offset); - size_t WriteEncodedMethods(dex_ir::MethodItemVector* methods, size_t offset); - - void WriteStrings(); - void WriteTypes(); - void WriteTypeLists(); - void WriteProtos(); - void WriteFields(); - void WriteMethods(); - void WriteEncodedArrays(); - void WriteAnnotations(); - void WriteAnnotationSets(); - void WriteAnnotationSetRefs(); - void WriteAnnotationsDirectories(); - void WriteDebugInfoItems(); - void WriteCodeItems(); - void WriteClasses(); - void WriteMapItem(); - void WriteHeader(); - - dex_ir::Header& header_; - std::unique_ptr<File> dex_file_; - - DISALLOW_COPY_AND_ASSIGN(DexWriter); -}; - - -} // namespace art - -#endif // ART_DEXLAYOUT_DEX_WRITER_H_ diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index a23db38632..6f34a33ed7 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -30,10 +30,11 @@ #include <sstream> #include <vector> +#include "base/unix_file/fd_file.h" #include "dex_ir_builder.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" -#include "dex_writer.h" +#include "os.h" #include "utils.h" namespace art { @@ -243,12 +244,10 @@ static std::string GetSignatureForProtoId(const dex_ir::ProtoId* proto) { return "<no signature>"; } + const std::vector<const dex_ir::TypeId*>& params = proto->Parameters(); std::string result("("); - const dex_ir::TypeList* type_list = proto->Parameters(); - if (type_list != nullptr) { - for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) { - result += type_id->GetStringId()->Data(); - } + for (uint32_t i = 0; i < params.size(); ++i) { + result += params[i]->GetStringId()->Data(); } result += ")"; result += proto->ReturnType()->GetStringId()->Data(); @@ -667,7 +666,7 @@ static void DumpCatches(const dex_ir::CodeItem* code) { const uint32_t start = try_item->StartAddr(); const uint32_t end = start + try_item->InsnCount(); fprintf(out_file_, " 0x%04x - 0x%04x\n", start, end); - for (auto& handler : *try_item->GetHandlers()->GetHandlers()) { + for (auto& handler : try_item->GetHandlers()) { const dex_ir::TypeId* type_id = handler->GetTypeId(); const char* descriptor = (type_id == nullptr) ? "<any>" : type_id->GetStringId()->Data(); fprintf(out_file_, " %s -> 0x%04x\n", descriptor, handler->GetAddress()); @@ -1496,6 +1495,96 @@ static void DumpClass(const DexFile* dex_file, } /* +static uint32_t GetDataSectionOffset(dex_ir::Header& header) { + return dex_ir::Header::ItemSize() + + header.GetCollections().StringIdsSize() * dex_ir::StringId::ItemSize() + + header.GetCollections().TypeIdsSize() * dex_ir::TypeId::ItemSize() + + header.GetCollections().ProtoIdsSize() * dex_ir::ProtoId::ItemSize() + + header.GetCollections().FieldIdsSize() * dex_ir::FieldId::ItemSize() + + header.GetCollections().MethodIdsSize() * dex_ir::MethodId::ItemSize() + + header.GetCollections().ClassDefsSize() * dex_ir::ClassDef::ItemSize(); +} + +static bool Align(File* file, uint32_t& offset) { + uint8_t zero_buffer[] = { 0, 0, 0 }; + uint32_t zeroes = (-offset) & 3; + if (zeroes > 0) { + if (!file->PwriteFully(zero_buffer, zeroes, offset)) { + return false; + } + offset += zeroes; + } + return true; +} + +static bool WriteStrings(File* dex_file, dex_ir::Header& header, + uint32_t& index_offset, uint32_t& data_offset) { + uint32_t index = 0; + uint32_t index_buffer[1]; + uint32_t string_length; + uint32_t length_length; + uint8_t length_buffer[8]; + for (std::unique_ptr<dex_ir::StringId>& string_id : header.GetCollections().StringIds()) { + string_id->SetOffset(index); + index_buffer[0] = data_offset; + string_length = strlen(string_id->Data()); + length_length = UnsignedLeb128Size(string_length); + EncodeUnsignedLeb128(length_buffer, string_length); + + if (!dex_file->PwriteFully(index_buffer, 4, index_offset) || + !dex_file->PwriteFully(length_buffer, length_length, data_offset) || + !dex_file->PwriteFully(string_id->Data(), string_length, data_offset + length_length)) { + return false; + } + + index++; + index_offset += 4; + data_offset += string_length + length_length; + } + return true; +} + +static bool WriteTypes(File* dex_file, dex_ir::Header& header, uint32_t& index_offset) { + uint32_t index = 0; + uint32_t index_buffer[1]; + for (std::unique_ptr<dex_ir::TypeId>& type_id : header.GetCollections().TypeIds()) { + type_id->SetIndex(index); + index_buffer[0] = type_id->GetStringId()->GetOffset(); + + if (!dex_file->PwriteFully(index_buffer, 4, index_offset)) { + return false; + } + + index++; + index_offset += 4; + } + return true; +} + +static bool WriteTypeLists(File* dex_file, dex_ir::Header& header, uint32_t& data_offset) { + if (!Align(dex_file, data_offset)) { + return false; + } + + return true; +} + +static void OutputDexFile(dex_ir::Header& header, const char* file_name) { + LOG(INFO) << "FILE NAME: " << file_name; + std::unique_ptr<File> dex_file(OS::CreateEmptyFileWriteOnly(file_name)); + if (dex_file == nullptr) { + fprintf(stderr, "Can't open %s\n", file_name); + return; + } + + uint32_t index_offset = dex_ir::Header::ItemSize(); + uint32_t data_offset = GetDataSectionOffset(header); + WriteStrings(dex_file.get(), header, index_offset, data_offset); + WriteTypes(dex_file.get(), header, index_offset); +} +*/ + +/* * Dumps the requested sections of the file. */ static void ProcessDexFile(const char* file_name, const DexFile* dex_file) { @@ -1533,11 +1622,13 @@ static void ProcessDexFile(const char* file_name, const DexFile* dex_file) { fprintf(out_file_, "</api>\n"); } + /* // Output dex file. if (options_.output_dex_files_) { std::string output_dex_filename = dex_file->GetLocation() + ".out"; - DexWriter::OutputDexFile(*header, output_dex_filename.c_str()); + OutputDexFile(*header, output_dex_filename.c_str()); } + */ } /* diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 63dc9728f1..42b64c3888 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -36,8 +36,8 @@ class DexLayoutTest : public CommonRuntimeTest { dex_file_ = GetLibCoreDexFileNames()[0]; } - // Runs FullPlainOutput test. - bool FullPlainOutputExec(std::string* error_msg) { + // Runs test with given arguments. + bool Exec(std::string* error_msg) { // TODO: dexdump2 -> dexdump ? ScratchFile dexdump_output; std::string dexdump_filename = dexdump_output.GetFilename(); @@ -67,41 +67,6 @@ class DexLayoutTest : public CommonRuntimeTest { return true; } - // Runs FullPlainOutput test. - bool DexFileOutputExec(std::string* error_msg) { - ScratchFile dexlayout_output; - std::string dexlayout_filename = dexlayout_output.GetFilename(); - std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout"; - EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path"; - std::vector<std::string> dexlayout_exec_argv = - { dexlayout, "-d", "-f", "-h", "-l", "plain", "-w", "-o", dexlayout_filename, dex_file_ }; - - if (!::art::Exec(dexlayout_exec_argv, error_msg)) { - return false; - } - - size_t last_slash = dexlayout_filename.rfind("/"); - std::string scratch_directory = dexlayout_filename.substr(0, last_slash + 1); - std::vector<std::string> unzip_exec_argv = - { "/usr/bin/unzip", dex_file_, "classes.dex", "-d", scratch_directory}; - if (!::art::Exec(unzip_exec_argv, error_msg)) { - return false; - } - - std::vector<std::string> diff_exec_argv = - { "/usr/bin/diff", scratch_directory + "classes.dex" , dex_file_ + ".out" }; - if (!::art::Exec(diff_exec_argv, error_msg)) { - return false; - } - - std::vector<std::string> rm_exec_argv = { "/bin/rm", scratch_directory + "classes.dex" }; - if (!::art::Exec(rm_exec_argv, error_msg)) { - return false; - } - - return true; - } - std::string dex_file_; }; @@ -110,14 +75,7 @@ TEST_F(DexLayoutTest, FullPlainOutput) { // Disable test on target. TEST_DISABLED_FOR_TARGET(); std::string error_msg; - ASSERT_TRUE(FullPlainOutputExec(&error_msg)) << error_msg; -} - -TEST_F(DexLayoutTest, DexFileOutput) { - // Disable test on target. - TEST_DISABLED_FOR_TARGET(); - std::string error_msg; - ASSERT_TRUE(DexFileOutputExec(&error_msg)) << error_msg; + ASSERT_TRUE(Exec(&error_msg)) << error_msg; } } // namespace art |