From f9e7b620ffb99d6e3eaf3e8a95834904538dde4b Mon Sep 17 00:00:00 2001 From: Hsin-Yi Chen Date: Fri, 20 Mar 2020 20:00:05 +0800 Subject: [PATCH] Store the sdump path for each type definition when linking ABI dumps This commit adds sdump paths to ModuleIR::odr_list_map_. It maps type ID to list of TypeDefinitions. A TypeDefinition consists of a TypeIR and the sdump path where the type is defined. The path is used to distinguish the definitions of the type in different source files. When header-abi-linker merges modules, the compilation unit paths are copied to the merged module. Thus, the paths are not lost when the merged module is merged to another one. Test: ./test.py Bug: 147396457 Change-Id: I72a9502b4e81f8ead10c8439af76aea86e3bc3f3 --- .../header-checker/src/diff/abi_diff.cpp | 2 +- .../src/linker/module_merger.cpp | 12 ++++-- .../src/repr/ir_representation.cpp | 34 +++++++++++++++-- .../src/repr/ir_representation.h | 38 ++++++++++++++----- .../libmerge_multi_definitions.so.lsdump | 8 ++-- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/vndk/tools/header-checker/src/diff/abi_diff.cpp b/vndk/tools/header-checker/src/diff/abi_diff.cpp index 3136e1ed6..0dd4439c8 100644 --- a/vndk/tools/header-checker/src/diff/abi_diff.cpp +++ b/vndk/tools/header-checker/src/diff/abi_diff.cpp @@ -113,7 +113,7 @@ HeaderAbiDiff::ExtractUserDefinedTypes(const repr::ModuleIR &tu) { if (odr_list.size() != 1) { continue; } - const repr::TypeIR *type = *(odr_list.begin()); + const repr::TypeIR *type = odr_list.begin()->type_ir_; const repr::RecordTypeIR *record_type = nullptr; switch (type->GetKind()) { case repr::RecordTypeKind: diff --git a/vndk/tools/header-checker/src/linker/module_merger.cpp b/vndk/tools/header-checker/src/linker/module_merger.cpp index 85ad5de19..54e13af64 100644 --- a/vndk/tools/header-checker/src/linker/module_merger.cpp +++ b/vndk/tools/header-checker/src/linker/module_merger.cpp @@ -67,7 +67,8 @@ MergeStatus ModuleMerger::LookupUserDefinedType( // Compare each user-defined type with the latest input user-defined type. // If there is a match, re-use the existing user-defined type. - for (auto &contender_ud : it->second) { + for (auto &definition : it->second) { + const TypeIR *contender_ud = definition.type_ir_; DiffStatus result = diff_helper.CompareAndDumpTypeDiff( contender_ud->GetSelfType(), ud_type->GetSelfType()); if (result == DiffStatus::no_diff) { @@ -81,7 +82,7 @@ MergeStatus ModuleMerger::LookupUserDefinedType( #ifdef DEBUG llvm::errs() << "ODR violation detected for: " << ud_type->GetName() << "\n"; #endif - return MergeStatus(true, (*(it->second.begin()))->GetSelfType()); + return MergeStatus(true, it->second.begin()->type_ir_->GetSelfType()); } @@ -199,10 +200,13 @@ ModuleMerger::UpdateUDTypeAccounting( const T *addend_node, const ModuleIR &addend, AbiElementMap *local_to_global_type_id_map, AbiElementMap *specific_type_map) { + const std::string addend_compilation_unit_path = + addend.GetCompilationUnitPath(addend_node); + assert(addend_compilation_unit_path != ""); std::string added_type_id = addend_node->GetSelfType(); auto type_id_it = module_->type_graph_.find(added_type_id); if (type_id_it != module_->type_graph_.end()) { - added_type_id = AllocateNewTypeId(added_type_id, addend); + added_type_id = added_type_id + "#ODR:" + addend_compilation_unit_path; } // Add the ud-type with type-id to the type_graph_, since if there are generic @@ -217,7 +221,7 @@ ModuleMerger::UpdateUDTypeAccounting( // Add to facilitate ODR checking. const std::string &key = GetODRListMapKey(&(it->second)); MergeStatus type_merge_status = MergeStatus(true, added_type_id); - module_->AddToODRListMap(key, &(it->second)); + module_->AddToODRListMap(key, &(it->second), addend_compilation_unit_path); local_to_global_type_id_map->emplace(addend_node->GetSelfType(), type_merge_status); return {type_merge_status, it}; diff --git a/vndk/tools/header-checker/src/repr/ir_representation.cpp b/vndk/tools/header-checker/src/repr/ir_representation.cpp index 50d1bf974..6f512fdaa 100644 --- a/vndk/tools/header-checker/src/repr/ir_representation.cpp +++ b/vndk/tools/header-checker/src/repr/ir_representation.cpp @@ -109,7 +109,7 @@ void ModuleIR::AddRecordType(RecordTypeIR &&record_type) { auto it = AddToMapAndTypeGraph( std::move(record_type), &record_types_, &type_graph_); const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); + AddToODRListMap(key, &(it->second), compilation_unit_path_); } @@ -120,7 +120,7 @@ void ModuleIR::AddFunctionType(FunctionTypeIR &&function_type) { auto it = AddToMapAndTypeGraph( std::move(function_type), &function_types_, &type_graph_); const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, &(it->second)); + AddToODRListMap(key, &(it->second), compilation_unit_path_); } @@ -131,7 +131,7 @@ void ModuleIR::AddEnumType(EnumTypeIR &&enum_type) { auto it = AddToMapAndTypeGraph( std::move(enum_type), &enum_types_, &type_graph_); const std::string &key = GetODRListMapKey(&(it->second)); - AddToODRListMap(key, (&it->second)); + AddToODRListMap(key, (&it->second), compilation_unit_path_); } @@ -197,6 +197,34 @@ void ModuleIR::AddElfObject(ElfObjectIR &&elf_object) { } +std::string ModuleIR::GetCompilationUnitPath(const TypeIR *type_ir) const { + std::string key; + switch (type_ir->GetKind()) { + case RecordTypeKind: + key = GetODRListMapKey(static_cast(type_ir)); + break; + case EnumTypeKind: + key = GetODRListMapKey(static_cast(type_ir)); + break; + case FunctionTypeKind: + key = GetODRListMapKey(static_cast(type_ir)); + break; + default: + return ""; + } + auto it = odr_list_map_.find(key); + if (it == odr_list_map_.end()) { + return ""; + } + for (const auto &definition : it->second) { + if (definition.type_ir_ == type_ir) { + return definition.compilation_unit_path_; + } + } + return ""; +} + + bool ModuleIR::IsLinkableMessageInExportedHeaders( const LinkableMessageIR *linkable_message) const { if (exported_headers_ == nullptr || exported_headers_->empty()) { diff --git a/vndk/tools/header-checker/src/repr/ir_representation.h b/vndk/tools/header-checker/src/repr/ir_representation.h index 12ba97a24..f74d3b7a7 100644 --- a/vndk/tools/header-checker/src/repr/ir_representation.h +++ b/vndk/tools/header-checker/src/repr/ir_representation.h @@ -37,9 +37,6 @@ using AbiElementMap = std::map; template using AbiElementUnorderedMap = std::unordered_map; -template -using AbiElementList = std::list; - enum TextFormatIR { ProtobufTextFormat = 0, Json = 1, @@ -759,6 +756,16 @@ class ElfObjectIR : public ElfSymbolIR { } }; +class TypeDefinition { + public: + TypeDefinition(const TypeIR *type_ir, + const std::string *compilation_unit_path) + : type_ir_(type_ir), compilation_unit_path_(*compilation_unit_path) {} + + const TypeIR *type_ir_; + const std::string &compilation_unit_path_; +}; + class ModuleIR { public: ModuleIR(const std::set *exported_headers) @@ -828,7 +835,7 @@ class ModuleIR { return type_graph_; } - const AbiElementUnorderedMap> & + const AbiElementUnorderedMap> & GetODRListMap() const { return odr_list_map_; } @@ -864,10 +871,19 @@ class ModuleIR { void AddElfObject(ElfObjectIR &&elf_object); - void AddToODRListMap(const std::string &key, const TypeIR *value) { + // Find the compilation unit path of a RecordTypeIR, FunctionTypeIR, or + // EnumTypeIR in odr_list_map_. Return an empty string if the type is not in + // the map. + std::string GetCompilationUnitPath(const TypeIR *type_ir) const; + + void AddToODRListMap(const std::string &key, const TypeIR *type_ir, + const std::string &compilation_unit_path) { + auto compilation_unit_path_it = + compilation_unit_paths_.emplace(compilation_unit_path).first; auto map_it = odr_list_map_.find(key); + TypeDefinition value(type_ir, &*compilation_unit_path_it); if (map_it == odr_list_map_.end()) { - odr_list_map_.emplace(key, std::list({value})); + odr_list_map_.emplace(key, std::list({value})); return; } odr_list_map_[key].emplace_back(value); @@ -883,7 +899,6 @@ class ModuleIR { // File path to the compilation unit (*.sdump) std::string compilation_unit_path_; - AbiElementList record_types_list_; AbiElementMap functions_; AbiElementMap global_variables_; AbiElementMap record_types_; @@ -904,8 +919,13 @@ class ModuleIR { AbiElementMap elf_objects_; // type-id -> LinkableMessageIR * map AbiElementMap type_graph_; - // maps unique_id + source_file -> const TypeIR * - AbiElementUnorderedMap> odr_list_map_; + // maps unique_id + source_file -> TypeDefinition + AbiElementUnorderedMap> odr_list_map_; + + + private: + // The compilation unit paths referenced by odr_list_map_; + std::set compilation_unit_paths_; const std::set *exported_headers_; }; diff --git a/vndk/tools/header-checker/tests/reference_dumps/arm64/libmerge_multi_definitions.so.lsdump b/vndk/tools/header-checker/tests/reference_dumps/arm64/libmerge_multi_definitions.so.lsdump index ff2627da9..fa5cfe5f3 100644 --- a/vndk/tools/header-checker/tests/reference_dumps/arm64/libmerge_multi_definitions.so.lsdump +++ b/vndk/tools/header-checker/tests/reference_dumps/arm64/libmerge_multi_definitions.so.lsdump @@ -66,7 +66,7 @@ "alignment" : 8, "linker_set_key" : "_ZTIP6Struct", "name" : "Struct *", - "referenced_type" : "_ZTI6Struct#ODR:", + "referenced_type" : "_ZTI6Struct#ODR:/def2.h.sdump", "self_type" : "_ZTIP6Struct#ODR:", "size" : 8, "source_file" : "/development/vndk/tools/header-checker/tests/integration/merge_multi_definitions/include/def2.h" @@ -123,7 +123,7 @@ "is_const" : true, "linker_set_key" : "_ZTIK6Struct", "name" : "const Struct", - "referenced_type" : "_ZTI6Struct#ODR:", + "referenced_type" : "_ZTI6Struct#ODR:/def2.h.sdump", "self_type" : "_ZTIK6Struct#ODR:", "size" : 8, "source_file" : "/development/vndk/tools/header-checker/tests/integration/merge_multi_definitions/include/def2.h" @@ -168,8 +168,8 @@ ], "linker_set_key" : "_ZTI6Struct", "name" : "Struct", - "referenced_type" : "_ZTI6Struct#ODR:", - "self_type" : "_ZTI6Struct#ODR:", + "referenced_type" : "_ZTI6Struct#ODR:/def2.h.sdump", + "self_type" : "_ZTI6Struct#ODR:/def2.h.sdump", "size" : 8, "source_file" : "/development/vndk/tools/header-checker/tests/integration/merge_multi_definitions/include/def2.h" }