diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h index 91a9e6b0526ba2..6c202c6b8e5a56 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h @@ -323,6 +323,17 @@ class DWARFLinker { Options.ObjectPrefixMap = Map; } + /// Set target DWARF version. + Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) { + if (TargetDWARFVersion < 1 || TargetDWARFVersion > 5) + return createStringError(std::errc::invalid_argument, + "unsupported DWARF version: %d", + TargetDWARFVersion); + + Options.TargetDWARFVersion = TargetDWARFVersion; + return Error::success(); + } + private: /// Flags passed to DwarfLinker::lookForDIEsToKeep enum TraversalFlags { @@ -398,12 +409,6 @@ class DWARFLinker { Options.ErrorHandler(Warning, File.FileName, DIE); } - /// Remembers the oldest and newest DWARF version we've seen in a unit. - void updateDwarfVersion(unsigned Version) { - MaxDwarfVersion = std::max(MaxDwarfVersion, Version); - MinDwarfVersion = std::min(MinDwarfVersion, Version); - } - /// Remembers the kinds of accelerator tables we've seen in a unit. void updateAccelKind(DWARFContext &Dwarf); @@ -759,9 +764,6 @@ class DWARFLinker { DwarfEmitter *TheDwarfEmitter; std::vector ObjectContexts; - unsigned MaxDwarfVersion = 0; - unsigned MinDwarfVersion = std::numeric_limits::max(); - bool AtLeastOneAppleAccelTable = false; bool AtLeastOneDwarfAccelTable = false; @@ -793,6 +795,9 @@ class DWARFLinker { /// linking options struct DWARFLinkerOptions { + /// DWARF version for the output. + uint16_t TargetDWARFVersion = 0; + /// Generate processing log to the standard output. bool Verbose = false; diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp index b7df288fe84915..9588528ca37fe9 100644 --- a/llvm/lib/DWARFLinker/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp @@ -2136,7 +2136,6 @@ Error DWARFLinker::loadClangModule(objFileLoader Loader, const DWARFDie &CUDie, std::unique_ptr Unit; for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { OnCUDieLoaded(*CU); - updateDwarfVersion(CU->getVersion()); // Recursively get all modules imported by this one. auto ChildCUDie = CU->getUnitDIE(); if (!ChildCUDie) @@ -2378,6 +2377,8 @@ void DWARFLinker::addObjectFile(DWARFFile &File, objFileLoader Loader, Error DWARFLinker::link() { assert(Options.NoOutput || TheDwarfEmitter); + assert((Options.TargetDWARFVersion != 0) && + "TargetDWARFVersion should be set"); // First populate the data structure we need for each iteration of the // parallel loop. @@ -2497,7 +2498,6 @@ Error DWARFLinker::link() { OptContext.File.Dwarf->getNumCompileUnits()); for (const auto &CU : OptContext.File.Dwarf->compile_units()) { - updateDwarfVersion(CU->getVersion()); auto CUDie = CU->getUnitDIE(false); if (Options.Verbose) { outs() << "Input compilation unit:"; @@ -2515,10 +2515,6 @@ Error DWARFLinker::link() { } } - // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. - if (MaxDwarfVersion == 0) - MaxDwarfVersion = 3; - // At this point we know how much data we have emitted. We use this value to // compare canonical DIE offsets in analyzeContextInfo to see if a definition // is already emitted, without being affected by canonical die offsets set @@ -2542,7 +2538,6 @@ Error DWARFLinker::link() { return; for (const auto &CU : Context.File.Dwarf->compile_units()) { - updateDwarfVersion(CU->getVersion()); // The !isClangModuleRef condition effectively skips over fully resolved // skeleton units. auto CUDie = CU->getUnitDIE(); @@ -2627,7 +2622,7 @@ Error DWARFLinker::link() { auto EmitLambda = [&]() { // Emit everything that's global. if (!Options.NoOutput) { - TheDwarfEmitter->emitAbbrevs(Abbreviations, MaxDwarfVersion); + TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion); TheDwarfEmitter->emitStrings(OffsetsStringPool); switch (Options.TheAccelTableKind) { case DwarfLinkerAccelTableKind::None: diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index 9c7f100948f79e..b7cc05a28712cc 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -661,6 +661,12 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) { SectionToOffsetInDwarf, RelocationsToApply); } + uint16_t MaxDWARFVersion = 0; + std::function OnCUDieLoaded = + [&MaxDWARFVersion](const DWARFUnit &Unit) { + MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); + }; + for (const auto &Obj : Map.objects()) { // N_AST objects (swiftmodule files) should get dumped directly into the // appropriate DWARF section. @@ -704,7 +710,7 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) { } if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) - GeneralLinker.addObjectFile(*ErrorOrObj, Loader); + GeneralLinker.addObjectFile(*ErrorOrObj, Loader, OnCUDieLoaded); else { ObjectsForLinking.push_back(std::make_unique( Obj->getObjectFilename(), nullptr, nullptr, @@ -713,6 +719,13 @@ bool DwarfLinkerForBinary::link(const DebugMap &Map) { } } + // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. + if (MaxDWARFVersion == 0) + MaxDWARFVersion = 3; + + if (Error E = GeneralLinker.setTargetDWARFVersion(MaxDWARFVersion)) + return error(toString(std::move(E))); + // link debug info for loaded object files. if (Error E = GeneralLinker.link()) return error(toString(std::move(E))); diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp index 3e70f460bc58f8..df17b010a7c3dc 100644 --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -263,6 +263,14 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options, .str())) return createStringError(std::errc::invalid_argument, ""); + std::unique_ptr Context = DWARFContext::create(File); + + uint16_t MaxDWARFVersion = 0; + std::function OnCUDieLoaded = + [&MaxDWARFVersion](const DWARFUnit &Unit) { + MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion); + }; + // Create DWARF linker. DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD); @@ -279,8 +287,6 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options, std::vector> AddresssMapForLinking(1); std::vector EmptyWarnings; - std::unique_ptr Context = DWARFContext::create(File); - // Unknown debug sections would be removed. Display warning // for such sections. for (SectionName Sec : Context->getDWARFObj().getSectionNames()) { @@ -300,7 +306,15 @@ Error linkDebugInfo(object::ObjectFile &File, const Options &Options, EmptyWarnings); for (size_t I = 0; I < ObjectsForLinking.size(); I++) - DebugInfoLinker.addObjectFile(*ObjectsForLinking[I]); + DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr, + OnCUDieLoaded); + + // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway. + if (MaxDWARFVersion == 0) + MaxDWARFVersion = 3; + + if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion)) + return Err; // Link debug info. if (Error Err = DebugInfoLinker.link())