diff options
-rw-r--r-- | dex2oat/dex2oat_test.cc | 3 | ||||
-rw-r--r-- | dexlayout/dex_ir.cc | 78 | ||||
-rw-r--r-- | dexlayout/dex_ir.h | 72 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 10 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 43 | ||||
-rw-r--r-- | dexlayout/dex_writer.h | 2 | ||||
-rw-r--r-- | runtime/common_runtime_test.h | 6 | ||||
-rw-r--r-- | runtime/dex_file.h | 4 | ||||
-rw-r--r-- | runtime/runtime_callbacks_test.cc | 3 |
9 files changed, 215 insertions, 6 deletions
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index d546072f58..6420aa8759 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -430,6 +430,9 @@ class Dex2oatSwapUseTest : public Dex2oatSwapTest { }; TEST_F(Dex2oatSwapUseTest, CheckSwapUsage) { + // Native memory usage isn't correctly tracked under sanitization. + TEST_DISABLED_FOR_MEMORY_TOOL_ASAN(); + // The `native_alloc_2_ >= native_alloc_1_` assertion below may not // hold true on some x86 systems; disable this test while we // investigate (b/29259363). diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index f1c6f67a7c..cf453b9a16 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -281,6 +281,16 @@ void Collections::ReadEncodedValue( 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)); @@ -766,6 +776,64 @@ ClassData* Collections::CreateClassData( 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 = + reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset()); + 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.Begin() + disk_call_site_id.data_off_; + EncodedArrayItem* call_site_item = + CreateEncodedArrayItem(disk_call_item_ptr, disk_call_site_id.data_off_); + + CallSiteId* call_site_id = new CallSiteId(call_site_item); + call_site_ids_.AddIndexedItem(call_site_id, CallSiteIdsOffset() + i * CallSiteId::ItemSize(), i); +} + +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; + static_assert(DexFile::MethodHandleType::kLast == DexFile::MethodHandleType::kInvokeConstructor, + "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); + } + MethodHandleItem* method_handle = new MethodHandleItem(type, field_or_method_id); + method_handle_items_.AddIndexedItem( + method_handle, MethodHandleItemsOffset() + i * MethodHandleItem::ItemSize(), i); +} + static uint32_t HeaderOffset(const dex_ir::Collections& collections ATTRIBUTE_UNUSED) { return 0; } @@ -823,6 +891,16 @@ static const FileSectionDescriptor kFileSectionDescriptors[] = { &dex_ir::Collections::ClassDefsSize, &dex_ir::Collections::ClassDefsOffset }, { + "CallSiteId", + DexFile::kDexTypeCallSiteIdItem, + &dex_ir::Collections::CallSiteIdsSize, + &dex_ir::Collections::CallSiteIdsOffset + }, { + "MethodHandle", + DexFile::kDexTypeMethodHandleItem, + &dex_ir::Collections::MethodHandleItemsSize, + &dex_ir::Collections::MethodHandleItemsOffset + }, { "StringData", DexFile::kDexTypeStringDataItem, &dex_ir::Collections::StringDatasSize, diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index cad039550a..5692eb2b39 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -35,6 +35,7 @@ class AnnotationItem; class AnnotationsDirectoryItem; class AnnotationSetItem; class AnnotationSetRefList; +class CallSiteId; class ClassData; class ClassDef; class CodeItem; @@ -47,6 +48,7 @@ class FieldItem; class Header; class MapList; class MapItem; +class MethodHandleItem; class MethodId; class MethodItem; class ParameterAnnotation; @@ -65,6 +67,8 @@ static constexpr size_t kProtoIdItemSize = 12; static constexpr size_t kFieldIdItemSize = 8; static constexpr size_t kMethodIdItemSize = 8; static constexpr size_t kClassDefItemSize = 32; +static constexpr size_t kCallSiteIdItemSize = 4; +static constexpr size_t kMethodHandleItemSize = 8; // Visitor support class AbstractDispatcher { @@ -79,6 +83,8 @@ class AbstractDispatcher { virtual void Dispatch(const ProtoId* proto_id) = 0; virtual void Dispatch(const FieldId* field_id) = 0; virtual void Dispatch(const MethodId* method_id) = 0; + virtual void Dispatch(const CallSiteId* call_site_id) = 0; + virtual void Dispatch(const MethodHandleItem* method_handle_item) = 0; virtual void Dispatch(ClassData* class_data) = 0; virtual void Dispatch(ClassDef* class_def) = 0; virtual void Dispatch(FieldItem* field_item) = 0; @@ -165,6 +171,9 @@ 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<CallSiteId>>& CallSiteIds() { return call_site_ids_.Collection(); } + std::vector<std::unique_ptr<MethodHandleItem>>& MethodHandleItems() + { return method_handle_items_.Collection(); } std::map<uint32_t, std::unique_ptr<StringData>>& StringDatas() { return string_datas_.Collection(); } std::map<uint32_t, std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); } @@ -189,6 +198,10 @@ class Collections { 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 uint8_t* static_data, uint32_t offset); @@ -207,6 +220,8 @@ class Collections { FieldId* GetFieldId(uint32_t index) { return FieldIds()[index].get(); } MethodId* GetMethodId(uint32_t index) { return MethodIds()[index].get(); } ClassDef* GetClassDef(uint32_t index) { return ClassDefs()[index].get(); } + CallSiteId* GetCallSiteId(uint32_t index) { return CallSiteIds()[index].get(); } + MethodHandleItem* GetMethodHandle(uint32_t index) { return MethodHandleItems()[index].get(); } StringId* GetStringIdOrNullPtr(uint32_t index) { return index == DexFile::kDexNoIndex ? nullptr : GetStringId(index); @@ -221,6 +236,8 @@ class Collections { 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(); } @@ -240,6 +257,9 @@ class Collections { 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) @@ -262,6 +282,8 @@ 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 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(); } @@ -288,6 +310,8 @@ class Collections { CollectionVector<FieldId> field_ids_; CollectionVector<MethodId> method_ids_; CollectionVector<ClassDef> class_defs_; + CollectionVector<CallSiteId> call_site_ids_; + CollectionVector<MethodHandleItem> method_handle_items_; CollectionMap<StringData> string_datas_; CollectionMap<TypeList> type_lists_; @@ -603,8 +627,10 @@ class EncodedValue { void SetDouble(double d) { u_.double_val_ = d; } void SetStringId(StringId* string_id) { u_.string_val_ = string_id; } void SetTypeId(TypeId* type_id) { u_.type_val_ = type_id; } + void SetProtoId(ProtoId* proto_id) { u_.proto_val_ = proto_id; } void SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; } void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; } + void SetMethodHandle(MethodHandleItem* method_handle) { u_.method_handle_val_ = method_handle; } void SetEncodedArray(EncodedArrayItem* encoded_array) { encoded_array_.reset(encoded_array); } void SetEncodedAnnotation(EncodedAnnotation* encoded_annotation) { encoded_annotation_.reset(encoded_annotation); } @@ -619,8 +645,10 @@ class EncodedValue { double GetDouble() const { return u_.double_val_; } StringId* GetStringId() const { return u_.string_val_; } TypeId* GetTypeId() const { return u_.type_val_; } + ProtoId* GetProtoId() const { return u_.proto_val_; } FieldId* GetFieldId() const { return u_.field_val_; } MethodId* GetMethodId() const { return u_.method_val_; } + MethodHandleItem* GetMethodHandle() const { return u_.method_handle_val_; } EncodedArrayItem* GetEncodedArray() const { return encoded_array_.get(); } EncodedAnnotation* GetEncodedAnnotation() const { return encoded_annotation_.get(); } @@ -639,8 +667,10 @@ class EncodedValue { double double_val_; StringId* string_val_; TypeId* type_val_; + ProtoId* proto_val_; FieldId* field_val_; MethodId* method_val_; + MethodHandleItem* method_handle_val_; } u_; std::unique_ptr<EncodedArrayItem> encoded_array_; std::unique_ptr<EncodedAnnotation> encoded_annotation_; @@ -1087,6 +1117,48 @@ class AnnotationsDirectoryItem : public Item { DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem); }; +class CallSiteId : public IndexedItem { + public: + explicit CallSiteId(EncodedArrayItem* call_site_item) : call_site_item_(call_site_item) { + size_ = kCallSiteIdItemSize; + } + ~CallSiteId() OVERRIDE { } + + static size_t ItemSize() { return kCallSiteIdItemSize; } + + EncodedArrayItem* CallSiteItem() const { return call_site_item_; } + + void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } + + private: + EncodedArrayItem* call_site_item_; + + DISALLOW_COPY_AND_ASSIGN(CallSiteId); +}; + +class MethodHandleItem : public IndexedItem { + public: + MethodHandleItem(DexFile::MethodHandleType method_handle_type, IndexedItem* field_or_method_id) + : method_handle_type_(method_handle_type), + field_or_method_id_(field_or_method_id) { + size_ = kMethodHandleItemSize; + } + ~MethodHandleItem() OVERRIDE { } + + static size_t ItemSize() { return kMethodHandleItemSize; } + + DexFile::MethodHandleType GetMethodHandleType() const { return method_handle_type_; } + IndexedItem* GetFieldOrMethodId() const { return field_or_method_id_; } + + void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); } + + private: + DexFile::MethodHandleType method_handle_type_; + IndexedItem* field_or_method_id_; + + DISALLOW_COPY_AND_ASSIGN(MethodHandleItem); +}; + // TODO(sehr): implement MapList. class MapList : public Item { public: diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index d0c5bf964e..8eb726a64a 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -72,6 +72,8 @@ Header* DexIrBuilder(const DexFile& dex_file) { } // MapItem. collections.SetMapListOffset(disk_header.map_off_); + // CallSiteIds and MethodHandleItems. + collections.CreateCallSitesAndMethodHandles(dex_file); CheckAndSetRemainingOffsets(dex_file, &collections); @@ -115,6 +117,14 @@ static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* co CHECK_EQ(item->size_, collections->ClassDefsSize()); CHECK_EQ(item->offset_, collections->ClassDefsOffset()); break; + case DexFile::kDexTypeCallSiteIdItem: + CHECK_EQ(item->size_, collections->CallSiteIdsSize()); + CHECK_EQ(item->offset_, collections->CallSiteIdsOffset()); + break; + case DexFile::kDexTypeMethodHandleItem: + CHECK_EQ(item->size_, collections->MethodHandleItemsSize()); + CHECK_EQ(item->offset_, collections->MethodHandleItemsOffset()); + break; case DexFile::kDexTypeMapList: CHECK_EQ(item->size_, 1u); CHECK_EQ(item->offset_, disk_header.map_off_); diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index 7ffa38bfd4..e1b828ca52 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -151,6 +151,12 @@ size_t DexWriter::WriteEncodedValue(dex_ir::EncodedValue* encoded_value, size_t length = EncodeDoubleValue(encoded_value->GetDouble(), buffer); start = 8 - length; break; + case DexFile::kDexAnnotationMethodType: + length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer); + break; + case DexFile::kDexAnnotationMethodHandle: + length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer); + break; case DexFile::kDexAnnotationString: length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer); break; @@ -485,6 +491,27 @@ void DexWriter::WriteClasses() { } } +void DexWriter::WriteCallSites() { + uint32_t call_site_off[1]; + for (std::unique_ptr<dex_ir::CallSiteId>& call_site_id : + header_->GetCollections().CallSiteIds()) { + call_site_off[0] = call_site_id->CallSiteItem()->GetOffset(); + Write(call_site_off, call_site_id->GetSize(), call_site_id->GetOffset()); + } +} + +void DexWriter::WriteMethodHandles() { + uint16_t method_handle_buff[4]; + for (std::unique_ptr<dex_ir::MethodHandleItem>& method_handle : + header_->GetCollections().MethodHandleItems()) { + method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType()); + method_handle_buff[1] = 0; // unused. + method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex(); + method_handle_buff[3] = 0; // unused. + Write(method_handle_buff, method_handle->GetSize(), method_handle->GetOffset()); + } +} + struct MapItemContainer { MapItemContainer(uint32_t type, uint32_t size, uint32_t offset) : type_(type), size_(size), offset_(offset) { } @@ -528,6 +555,14 @@ void DexWriter::WriteMapItem() { queue.push(MapItemContainer(DexFile::kDexTypeClassDefItem, collection.ClassDefsSize(), collection.ClassDefsOffset())); } + if (collection.CallSiteIdsSize() != 0) { + queue.push(MapItemContainer(DexFile::kDexTypeCallSiteIdItem, collection.CallSiteIdsSize(), + collection.CallSiteIdsOffset())); + } + if (collection.MethodHandleItemsSize() != 0) { + queue.push(MapItemContainer(DexFile::kDexTypeMethodHandleItem, + collection.MethodHandleItemsSize(), collection.MethodHandleItemsOffset())); + } // Data section. queue.push(MapItemContainer(DexFile::kDexTypeMapList, 1, collection.MapListOffset())); @@ -618,10 +653,8 @@ void DexWriter::WriteHeader() { 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; + buffer[18] = header_->DataSize(); + buffer[19] = header_->DataOffset(); Write(buffer, 20 * sizeof(uint32_t), offset); } @@ -640,6 +673,8 @@ void DexWriter::WriteMemMap() { WriteDebugInfoItems(); WriteCodeItems(); WriteClasses(); + WriteCallSites(); + WriteMethodHandles(); WriteMapItem(); WriteHeader(); } diff --git a/dexlayout/dex_writer.h b/dexlayout/dex_writer.h index fb76e5ccfc..b396adf126 100644 --- a/dexlayout/dex_writer.h +++ b/dexlayout/dex_writer.h @@ -59,6 +59,8 @@ class DexWriter { void WriteDebugInfoItems(); void WriteCodeItems(); void WriteClasses(); + void WriteCallSites(); + void WriteMethodHandles(); void WriteMapItem(); void WriteHeader(); diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h index 56e8aa3685..a29cc6cd38 100644 --- a/runtime/common_runtime_test.h +++ b/runtime/common_runtime_test.h @@ -249,6 +249,12 @@ class CheckJniAbortCatcher { return; \ } +#define TEST_DISABLED_FOR_MEMORY_TOOL_ASAN() \ + if (RUNNING_ON_MEMORY_TOOL > 0 && !kMemoryToolIsValgrind) { \ + printf("WARNING: TEST DISABLED FOR MEMORY TOOL ASAN\n"); \ + return; \ + } + } // namespace art namespace std { diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 1b18d21cb1..36c734197a 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -92,8 +92,8 @@ class DexFile { uint32_t method_ids_off_; // file offset of MethodIds array uint32_t class_defs_size_; // number of ClassDefs uint32_t class_defs_off_; // file offset of ClassDef array - uint32_t data_size_; // unused - uint32_t data_off_; // unused + uint32_t data_size_; // size of data section + uint32_t data_off_; // file offset of data section // Decode the dex magic version uint32_t GetVersion() const; diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc index abe99e0d50..640f9ce848 100644 --- a/runtime/runtime_callbacks_test.cc +++ b/runtime/runtime_callbacks_test.cc @@ -335,6 +335,9 @@ class RuntimeSigQuitCallbackRuntimeCallbacksTest : public RuntimeCallbacksTest { }; TEST_F(RuntimeSigQuitCallbackRuntimeCallbacksTest, SigQuit) { + // SigQuit induces a dump. ASAN isn't happy with libunwind reading memory. + TEST_DISABLED_FOR_MEMORY_TOOL_ASAN(); + // The runtime needs to be started for the signal handler. Thread* self = Thread::Current(); |