[llvm] adabfb5 - [DWARFLinker][NFC] Set the target DWARF version explicitly.

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 15 06:12:04 PDT 2022


Author: Alexey Lapshin
Date: 2022-09-15T16:06:10+03:00
New Revision: adabfb5e32fd208f7af6d9fd70bb5094d5fdaab6

URL: https://github.com/llvm/llvm-project/commit/adabfb5e32fd208f7af6d9fd70bb5094d5fdaab6
DIFF: https://github.com/llvm/llvm-project/commit/adabfb5e32fd208f7af6d9fd70bb5094d5fdaab6.diff

LOG: [DWARFLinker][NFC] Set the target DWARF version explicitly.

Currently, DWARFLinker determines the target DWARF version internally.
It examines incoming object files, detects maximal
DWARF version and uses that version for the output file.
This patch allows explicitly setting output DWARF version by the consumer
of DWARFLinker. So that DWARFLinker uses a specified version instead
of autodetected one. It allows consumers to use different logic for
setting the target DWARF version. f.e. instead of the maximally used version
someone could set a higher version to convert from DWARFv4 to DWARFv5
(This possibility is not supported yet, but it would be good if
the interface will support it). Or another variant is to set the target
version through the command line. In this patch, the autodetection is moved
into the consumers(DwarfLinkerForBinary.cpp, DebugInfoLinker.cpp).

Differential Revision: https://reviews.llvm.org/D132755

Added: 
    

Modified: 
    llvm/include/llvm/DWARFLinker/DWARFLinker.h
    llvm/lib/DWARFLinker/DWARFLinker.cpp
    llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
    llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 91a9e6b0526ba..6c202c6b8e5a5 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<LinkContext> ObjectContexts;
 
-  unsigned MaxDwarfVersion = 0;
-  unsigned MinDwarfVersion = std::numeric_limits<unsigned>::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 b7df288fe8491..9588528ca37fe 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<CompileUnit> 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 9c7f100948f79..b7cc05a28712c 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<void(const DWARFUnit &Unit)> 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<DWARFFile>(
           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 3e70f460bc58f..df17b010a7c3d 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<DWARFContext> Context = DWARFContext::create(File);
+
+  uint16_t MaxDWARFVersion = 0;
+  std::function<void(const DWARFUnit &Unit)> 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<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
   std::vector<std::string> EmptyWarnings;
 
-  std::unique_ptr<DWARFContext> 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())


        


More information about the llvm-commits mailing list