diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -31,11 +31,9 @@ /// The kind of accelerator tables we should emit. enum class DwarfLinkerAccelTableKind : uint8_t { - None, Apple, ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc. - Dwarf, ///< DWARF v5 .debug_names. - Default, ///< Dwarf for DWARF5 or later, Apple otherwise. - Pub, ///< .debug_pubnames, .debug_pubtypes + DWARFv4, ///< .debug_pubnames, .debug_pubtypes + DWARFv5 ///< .debug_names. }; /// AddressesMap represents information about valid addresses used @@ -275,9 +273,11 @@ /// Use specified number of threads for parallel files linking. void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; } - /// Set kind of accelerator tables to be generated. - void setAccelTableKind(DwarfLinkerAccelTableKind Kind) { - Options.TheAccelTableKind = Kind; + /// Add kind of accelerator tables to be generated. + void addAccelTableKind(DwarfLinkerAccelTableKind Kind) { + assert(std::find(Options.AccelTables.begin(), Options.AccelTables.end(), + Kind) == Options.AccelTables.end()); + Options.AccelTables.emplace_back(Kind); } /// Set prepend path for clang modules. @@ -401,9 +401,6 @@ MinDwarfVersion = std::min(MinDwarfVersion, Version); } - /// Remembers the kinds of accelerator tables we've seen in a unit. - void updateAccelKind(DWARFContext &Dwarf); - /// Emit warnings as Dwarf compile units to leave a trail after linking. bool emitPaperTrailWarnings(const DWARFFile &File, OffsetsStringPool &StringPool); @@ -704,9 +701,6 @@ /// Emit the accelerator entries for \p Unit. void emitAcceleratorEntriesForUnit(CompileUnit &Unit); - void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit); - void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit); - void emitPubAcceleratorEntriesForUnit(CompileUnit &Unit); /// Patch the frame info for an object file and emit it. void patchFrameInfoForObject(const DWARFFile &, RangesTy &Ranges, @@ -736,9 +730,6 @@ unsigned MaxDwarfVersion = 0; unsigned MinDwarfVersion = std::numeric_limits::max(); - bool AtLeastOneAppleAccelTable = false; - bool AtLeastOneDwarfAccelTable = false; - /// The CIEs that have been emitted in the output section. The actual CIE /// data serves a the key to this StringMap, this takes care of comparing the /// semantics of CIEs defined in different object files. @@ -789,9 +780,8 @@ /// Number of threads. unsigned Threads = 1; - /// The accelerator table kind - DwarfLinkerAccelTableKind TheAccelTableKind = - DwarfLinkerAccelTableKind::Default; + /// The accelerator table kinds + SmallVector AccelTables; /// Prepend path for the clang modules. std::string PrependPath; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -1811,67 +1811,49 @@ } void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { - switch (Options.TheAccelTableKind) { - case DwarfLinkerAccelTableKind::None: - // Nothing to do. - break; - case DwarfLinkerAccelTableKind::Apple: - emitAppleAcceleratorEntriesForUnit(Unit); - break; - case DwarfLinkerAccelTableKind::Dwarf: - emitDwarfAcceleratorEntriesForUnit(Unit); - break; - case DwarfLinkerAccelTableKind::Pub: - emitPubAcceleratorEntriesForUnit(Unit); - break; - case DwarfLinkerAccelTableKind::Default: - llvm_unreachable("The default must be updated to a concrete value."); - break; + for (DwarfLinkerAccelTableKind AccelTableKind : Options.AccelTables) { + switch (AccelTableKind) { + case DwarfLinkerAccelTableKind::Apple: { + // Add namespaces. + for (const auto &Namespace : Unit.getNamespaces()) + AppleNamespaces.addName(Namespace.Name, Namespace.Die->getOffset() + + Unit.getStartOffset()); + // Add names. + for (const auto &Pubname : Unit.getPubnames()) + AppleNames.addName(Pubname.Name, + Pubname.Die->getOffset() + Unit.getStartOffset()); + // Add types. + for (const auto &Pubtype : Unit.getPubtypes()) + AppleTypes.addName( + Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(), + Pubtype.Die->getTag(), + Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation + : 0, + Pubtype.QualifiedNameHash); + // Add ObjC names. + for (const auto &ObjC : Unit.getObjC()) + AppleObjc.addName(ObjC.Name, + ObjC.Die->getOffset() + Unit.getStartOffset()); + } break; + case DwarfLinkerAccelTableKind::DWARFv4: { + TheDwarfEmitter->emitPubNamesForUnit(Unit); + TheDwarfEmitter->emitPubTypesForUnit(Unit); + } break; + case DwarfLinkerAccelTableKind::DWARFv5: { + for (const auto &Namespace : Unit.getNamespaces()) + DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), + Namespace.Die->getTag(), Unit.getUniqueID()); + for (const auto &Pubname : Unit.getPubnames()) + DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(), + Pubname.Die->getTag(), Unit.getUniqueID()); + for (const auto &Pubtype : Unit.getPubtypes()) + DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(), + Pubtype.Die->getTag(), Unit.getUniqueID()); + } break; + } } } -void DWARFLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) { - // Add namespaces. - for (const auto &Namespace : Unit.getNamespaces()) - AppleNamespaces.addName(Namespace.Name, - Namespace.Die->getOffset() + Unit.getStartOffset()); - - /// Add names. - for (const auto &Pubname : Unit.getPubnames()) - AppleNames.addName(Pubname.Name, - Pubname.Die->getOffset() + Unit.getStartOffset()); - - /// Add types. - for (const auto &Pubtype : Unit.getPubtypes()) - AppleTypes.addName( - Pubtype.Name, Pubtype.Die->getOffset() + Unit.getStartOffset(), - Pubtype.Die->getTag(), - Pubtype.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation - : 0, - Pubtype.QualifiedNameHash); - - /// Add ObjC names. - for (const auto &ObjC : Unit.getObjC()) - AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset()); -} - -void DWARFLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) { - for (const auto &Namespace : Unit.getNamespaces()) - DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), - Namespace.Die->getTag(), Unit.getUniqueID()); - for (const auto &Pubname : Unit.getPubnames()) - DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(), - Pubname.Die->getTag(), Unit.getUniqueID()); - for (const auto &Pubtype : Unit.getPubtypes()) - DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(), - Pubtype.Die->getTag(), Unit.getUniqueID()); -} - -void DWARFLinker::emitPubAcceleratorEntriesForUnit(CompileUnit &Unit) { - TheDwarfEmitter->emitPubNamesForUnit(Unit); - TheDwarfEmitter->emitPubTypesForUnit(Unit); -} - /// Read the frame info stored in the object, and emit the /// patched frame descriptions for the resulting file. /// @@ -2240,25 +2222,6 @@ return OutputDebugInfoSize - StartOutputDebugInfoSize; } -void DWARFLinker::updateAccelKind(DWARFContext &Dwarf) { - if (Options.TheAccelTableKind != DwarfLinkerAccelTableKind::Default) - return; - - auto &DwarfObj = Dwarf.getDWARFObj(); - - if (!AtLeastOneDwarfAccelTable && - (!DwarfObj.getAppleNamesSection().Data.empty() || - !DwarfObj.getAppleTypesSection().Data.empty() || - !DwarfObj.getAppleNamespacesSection().Data.empty() || - !DwarfObj.getAppleObjCSection().Data.empty())) { - AtLeastOneAppleAccelTable = true; - } - - if (!AtLeastOneDwarfAccelTable && !DwarfObj.getNamesSection().Data.empty()) { - AtLeastOneDwarfAccelTable = true; - } -} - bool DWARFLinker::emitPaperTrailWarnings(const DWARFFile &File, OffsetsStringPool &StringPool) { @@ -2338,9 +2301,6 @@ void DWARFLinker::addObjectFile(DWARFFile &File) { ObjectContexts.emplace_back(LinkContext(File)); - - if (ObjectContexts.back().File.Dwarf) - updateAccelKind(*ObjectContexts.back().File.Dwarf); } Error DWARFLinker::link() { @@ -2361,19 +2321,6 @@ // ODR Contexts for the optimize. DeclContextTree ODRContexts; - // If we haven't decided on an accelerator table kind yet, we base ourselves - // on the DWARF we have seen so far. At this point we haven't pulled in debug - // information from modules yet, so it is technically possible that they - // would affect the decision. However, as they're built with the same - // compiler and flags, it is safe to assume that they will follow the - // decision made here. - if (Options.TheAccelTableKind == DwarfLinkerAccelTableKind::Default) { - if (AtLeastOneDwarfAccelTable && !AtLeastOneAppleAccelTable) - Options.TheAccelTableKind = DwarfLinkerAccelTableKind::Dwarf; - else - Options.TheAccelTableKind = DwarfLinkerAccelTableKind::Apple; - } - for (LinkContext &OptContext : ObjectContexts) { if (Options.Verbose) { if (DwarfLinkerClientID == DwarfLinkerClient::Dsymutil) @@ -2601,25 +2548,22 @@ if (!Options.NoOutput) { TheDwarfEmitter->emitAbbrevs(Abbreviations, MaxDwarfVersion); TheDwarfEmitter->emitStrings(OffsetsStringPool); - switch (Options.TheAccelTableKind) { - case DwarfLinkerAccelTableKind::None: - // Nothing to do. - break; - case DwarfLinkerAccelTableKind::Apple: - TheDwarfEmitter->emitAppleNames(AppleNames); - TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces); - TheDwarfEmitter->emitAppleTypes(AppleTypes); - TheDwarfEmitter->emitAppleObjc(AppleObjc); - break; - case DwarfLinkerAccelTableKind::Dwarf: - TheDwarfEmitter->emitDebugNames(DebugNames); - break; - case DwarfLinkerAccelTableKind::Pub: - // Already emitted by emitPubAcceleratorEntriesForUnit. - break; - case DwarfLinkerAccelTableKind::Default: - llvm_unreachable("Default should have already been resolved."); - break; + for (DwarfLinkerAccelTableKind TableKind : Options.AccelTables) { + switch (TableKind) { + case DwarfLinkerAccelTableKind::Apple: + TheDwarfEmitter->emitAppleNamespaces(AppleNamespaces); + TheDwarfEmitter->emitAppleNames(AppleNames); + TheDwarfEmitter->emitAppleTypes(AppleTypes); + TheDwarfEmitter->emitAppleObjc(AppleObjc); + break; + case DwarfLinkerAccelTableKind::DWARFv4: + // Already emitted by emitAcceleratorEntriesForUnit. + // Already emitted by emitAcceleratorEntriesForUnit. + break; + case DwarfLinkerAccelTableKind::DWARFv5: + TheDwarfEmitter->emitDebugNames(DebugNames); + break; + } } } }; diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -571,6 +571,9 @@ return Options.Translator(Input); }; + bool AtLeastOneDwarfAccelTable = false; + bool AtLeastOneAppleAccelTable = false; + GeneralLinker.setVerbosity(Options.Verbose); GeneralLinker.setStatistics(Options.Statistics); GeneralLinker.setVerifyInputDWARF(Options.VerifyInputDWARF); @@ -578,7 +581,6 @@ GeneralLinker.setNoODR(Options.NoODR); GeneralLinker.setUpdate(Options.Update); GeneralLinker.setNumThreads(Options.Threads); - GeneralLinker.setAccelTableKind(Options.TheAccelTableKind); GeneralLinker.setPrependPath(Options.PrependPath); GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic); if (Options.Translator) @@ -702,9 +704,25 @@ continue; } - if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) + if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) { GeneralLinker.addObjectFile(*ErrorOrObj); - else { + + if (Options.TheAccelTableKind == DsymutilAccelTableKind::Default && + ErrorOrObj->Dwarf) { + auto &DwarfObj = ErrorOrObj->Dwarf->getDWARFObj(); + + if (!AtLeastOneDwarfAccelTable && + (!DwarfObj.getAppleNamesSection().Data.empty() || + !DwarfObj.getAppleTypesSection().Data.empty() || + !DwarfObj.getAppleNamespacesSection().Data.empty() || + !DwarfObj.getAppleObjCSection().Data.empty())) + AtLeastOneAppleAccelTable = true; + + if (!AtLeastOneDwarfAccelTable && + !DwarfObj.getNamesSection().Data.empty()) + AtLeastOneDwarfAccelTable = true; + } + } else { ObjectsForLinking.push_back(std::make_unique( Obj->getObjectFilename(), nullptr, nullptr, Obj->empty() ? Obj->getWarnings() : EmptyWarnings)); @@ -712,6 +730,34 @@ } } + switch (Options.TheAccelTableKind) { + case DsymutilAccelTableKind::Apple: + GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple); + break; + case DsymutilAccelTableKind::Dwarf: + GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DWARFv5); + break; + case DsymutilAccelTableKind::Pub: + GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DWARFv4); + break; + case DsymutilAccelTableKind::Default: + // If we haven't decided on an accelerator table kind yet, we base ourselves + // on the DWARF we have seen so far. At this point we haven't pulled in + // debug information from modules yet, so it is technically possible that + // they would affect the decision. However, as they're built with the same + // compiler and flags, it is safe to assume that they will follow the + // decision made here. + + if (AtLeastOneDwarfAccelTable && !AtLeastOneAppleAccelTable) + GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DWARFv5); + else + GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple); + break; + case DsymutilAccelTableKind::None: + // Nothing to do. + break; + } + // link debug info for loaded object files. if (Error E = GeneralLinker.link()) return error(toString(std::move(E))); diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h --- a/llvm/tools/dsymutil/LinkUtils.h +++ b/llvm/tools/dsymutil/LinkUtils.h @@ -23,6 +23,14 @@ namespace llvm { namespace dsymutil { +enum class DsymutilAccelTableKind : uint8_t { + None, + Apple, ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc. + Dwarf, ///< DWARF v5 .debug_names. + Default, ///< Dwarf for DWARF5 or later, Apple otherwise. + Pub, ///< .debug_pubnames, .debug_pubtypes +}; + struct LinkOptions { /// Verbosity bool Verbose = false; @@ -56,7 +64,7 @@ OutputFileType FileType = OutputFileType::Object; /// The accelerator table kind - DwarfLinkerAccelTableKind TheAccelTableKind; + DsymutilAccelTableKind TheAccelTableKind; /// -oso-prepend-path std::string PrependPath; diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp --- a/llvm/tools/dsymutil/dsymutil.cpp +++ b/llvm/tools/dsymutil/dsymutil.cpp @@ -206,26 +206,26 @@ return Error::success(); } -static Expected +static Expected getAccelTableKind(opt::InputArgList &Args) { if (opt::Arg *Accelerator = Args.getLastArg(OPT_accelerator)) { StringRef S = Accelerator->getValue(); if (S == "Apple") - return DwarfLinkerAccelTableKind::Apple; + return DsymutilAccelTableKind::Apple; if (S == "Dwarf") - return DwarfLinkerAccelTableKind::Dwarf; + return DsymutilAccelTableKind::Dwarf; if (S == "Pub") - return DwarfLinkerAccelTableKind::Pub; + return DsymutilAccelTableKind::Pub; if (S == "Default") - return DwarfLinkerAccelTableKind::Default; + return DsymutilAccelTableKind::Default; if (S == "None") - return DwarfLinkerAccelTableKind::None; + return DsymutilAccelTableKind::None; return make_error("invalid accelerator type specified: '" + S + "'. Supported values are 'Apple', " "'Dwarf', 'Pub', 'Default' and 'None'.", inconvertibleErrorCode()); } - return DwarfLinkerAccelTableKind::Default; + return DsymutilAccelTableKind::Default; } static Expected getReproducerMode(opt::InputArgList &Args) { @@ -310,7 +310,7 @@ } } - if (Expected AccelKind = getAccelTableKind(Args)) { + if (Expected AccelKind = getAccelTableKind(Args)) { Options.LinkOpts.TheAccelTableKind = *AccelKind; } else { return AccelKind.takeError(); diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -267,7 +267,6 @@ DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD); DebugInfoLinker.setEstimatedObjfilesAmount(1); - DebugInfoLinker.setAccelTableKind(DwarfLinkerAccelTableKind::None); DebugInfoLinker.setErrorHandler(ReportErr); DebugInfoLinker.setWarningHandler(ReportWarn); DebugInfoLinker.setNumThreads(Options.NumThreads);