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 @@ -320,6 +320,17 @@ 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 { @@ -395,12 +406,6 @@ 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); @@ -733,9 +738,6 @@ DwarfEmitter *TheDwarfEmitter; std::vector ObjectContexts; - unsigned MaxDwarfVersion = 0; - unsigned MinDwarfVersion = std::numeric_limits::max(); - bool AtLeastOneAppleAccelTable = false; bool AtLeastOneDwarfAccelTable = false; @@ -764,6 +766,9 @@ /// linking options struct DWARFLinkerOptions { + /// DWARF version for the output. + uint16_t TargetDWARFVersion = 3; + /// Generate processing log to the standard output. bool Verbose = false; 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 @@ -2102,7 +2102,6 @@ std::unique_ptr Unit; for (const auto &CU : ErrOrObj->Dwarf->compile_units()) { - updateDwarfVersion(CU->getVersion()); // Recursively get all modules imported by this one. auto CUDie = CU->getUnitDIE(false); if (!CUDie) @@ -2470,7 +2469,6 @@ 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:"; @@ -2486,10 +2484,6 @@ } } - // 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 @@ -2513,7 +2507,6 @@ return; for (const auto &CU : Context.File.Dwarf->compile_units()) { - updateDwarfVersion(CU->getVersion()); // The !registerModuleReference() condition effectively skips // over fully resolved skeleton units. This second pass of // registerModuleReferences doesn't do any new work, but it @@ -2602,7 +2595,7 @@ 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 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -571,6 +571,8 @@ return Options.Translator(Input); }; + uint16_t MaxDWARFVersion = 3; + GeneralLinker.setVerbosity(Options.Verbose); GeneralLinker.setStatistics(Options.Statistics); GeneralLinker.setVerifyInputDWARF(Options.VerifyInputDWARF); @@ -702,9 +704,13 @@ continue; } - if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) + if (auto ErrorOrObj = loadObject(*Obj, Map, RL)) { GeneralLinker.addObjectFile(*ErrorOrObj); - else { + + for (auto &CU : ErrorOrObj->Dwarf->compile_units()) + MaxDWARFVersion = std::max(CU->getVersion(), MaxDWARFVersion); + + } else { ObjectsForLinking.push_back(std::make_unique( Obj->getObjectFilename(), nullptr, nullptr, Obj->empty() ? Obj->getWarnings() : EmptyWarnings)); @@ -712,6 +718,9 @@ } } + 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 --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -263,6 +263,12 @@ .str())) return createStringError(std::errc::invalid_argument, ""); + std::unique_ptr Context = DWARFContext::create(File); + + uint16_t MaxDWARFVersion = 3; + for (auto &CU : Context->compile_units()) + MaxDWARFVersion = std::max(CU->getVersion(), MaxDWARFVersion); + // Create DWARF linker. DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD); @@ -275,12 +281,13 @@ DebugInfoLinker.setVerbosity(Options.Verbose); DebugInfoLinker.setUpdate(!Options.DoGarbageCollection); + if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion)) + return Err; + std::vector> ObjectsForLinking(1); 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()) {