[llvm] abc7f68 - [Dsymutil][Debuginfo][NFC] Refactor dsymutil to separate DWARF optimizing part 2.

Alexey Lapshin via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 19 04:42:34 PST 2019


Author: Alexey Lapshin
Date: 2019-12-19T15:41:48+03:00
New Revision: abc7f6800df8a1f40e1e2c9ccce826abb0208284

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

LOG: [Dsymutil][Debuginfo][NFC] Refactor dsymutil to separate DWARF optimizing part 2.

That patch is extracted from the D70709. It moves CompileUnit, DeclContext
into llvm/DebugInfo/DWARF. It also adds new file DWARFOptimizer with
AddressesMap class. AddressesMap generalizes functionality
from RelocationManager.

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

Added: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h
    llvm/include/llvm/DebugInfo/DWARF/DWARFOptDeclContext.h
    llvm/include/llvm/DebugInfo/DWARF/DWARFOptimizer.h
    llvm/lib/DebugInfo/DWARF/DWARFOptCompileUnit.cpp
    llvm/lib/DebugInfo/DWARF/DWARFOptDeclContext.cpp
    llvm/lib/DebugInfo/DWARF/DWARFOptimizer.cpp

Modified: 
    llvm/lib/DebugInfo/DWARF/CMakeLists.txt
    llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
    llvm/tools/dsymutil/CMakeLists.txt
    llvm/tools/dsymutil/DwarfLinker.cpp
    llvm/tools/dsymutil/DwarfLinker.h
    llvm/tools/dsymutil/DwarfStreamer.cpp
    llvm/tools/dsymutil/DwarfStreamer.h

Removed: 
    llvm/tools/dsymutil/CompileUnit.cpp
    llvm/tools/dsymutil/CompileUnit.h
    llvm/tools/dsymutil/DeclContext.cpp
    llvm/tools/dsymutil/DeclContext.h


################################################################################
diff  --git a/llvm/tools/dsymutil/CompileUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h
similarity index 97%
rename from llvm/tools/dsymutil/CompileUnit.h
rename to llvm/include/llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h
index e0f5d3bc65b2..010862966846 100644
--- a/llvm/tools/dsymutil/CompileUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/CompileUnit.h - Dwarf debug info linker ---*- C++ -*-===//
+//===- DWARFOptCompileUnit.h ------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
-#define LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
+#ifndef LLVM_DEBUGINFO_DWARF_OPT_COMPILEUNIT_H
+#define LLVM_DEBUGINFO_DWARF_OPT_COMPILEUNIT_H
 
 #include "llvm/ADT/IntervalMap.h"
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/DataExtractor.h"
 
 namespace llvm {
-namespace dsymutil {
 
 class DeclContext;
 
@@ -46,7 +46,7 @@ struct PatchLocation {
 };
 
 /// Stores all information relating to a compile unit, be it in its original
-/// instance in the object file to its brand new cloned and linked DIE tree.
+/// instance in the object file to its brand new cloned and generated DIE tree.
 class CompileUnit {
 public:
   /// Information gathered about a DIE in the object file.
@@ -325,7 +325,6 @@ class CompileUnit {
   std::string ClangModuleName;
 };
 
-} // end namespace dsymutil
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
+#endif // LLVM_DEBUGINFO_DWARF_OPT_COMPILEUNIT_H

diff  --git a/llvm/tools/dsymutil/DeclContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptDeclContext.h
similarity index 95%
rename from llvm/tools/dsymutil/DeclContext.h
rename to llvm/include/llvm/DebugInfo/DWARF/DWARFOptDeclContext.h
index 36ef50944083..6045ed72b259 100644
--- a/llvm/tools/dsymutil/DeclContext.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptDeclContext.h
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/DeclContext.h - Dwarf debug info linker ---*- C++ -*-===//
+//===- llvm/DebugInfo/DWARF/DWARFOptDeclContext.h ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,20 +6,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
-#define LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
+#ifndef LLVM_DEBUGINFO_DWARF_OPT_DECLCONTEXT_H
+#define LLVM_DEBUGINFO_DWARF_OPT_DECLCONTEXT_H
 
-#include "CompileUnit.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h"
 #include "llvm/Support/Path.h"
 
 namespace llvm {
-namespace dsymutil {
 
 struct DeclMapInfo;
 
@@ -165,7 +164,6 @@ struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
   }
 };
 
-} // end namespace dsymutil
 } // end namespace llvm
 
-#endif // LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
+#endif // LLVM_DEBUGINFO_DWARF_OPT_DECLCONTEXT_H

diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFOptimizer.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptimizer.h
new file mode 100644
index 000000000000..5700c97a92fe
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFOptimizer.h
@@ -0,0 +1,86 @@
+//===- llvm/DebugInfo/DWARF/DWARFOptimizer.h --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFOPTIMIZER_H
+#define LLVM_DEBUGINFO_DWARFOPTIMIZER_H
+
+#include "llvm/CodeGen/NonRelocatableStringpool.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptDeclContext.h"
+#include <map>
+
+namespace llvm {
+
+enum class DwarfOptimizerClient { Dsymutil, LLD, General };
+
+/// Partial address range. Besides an offset, only the
+/// HighPC is stored. The structure is stored in a map where the LowPC is the
+/// key.
+struct ObjFileAddressRange {
+  /// Function HighPC.
+  uint64_t HighPC;
+  /// Offset to apply to the linked address.
+  /// should be 0 for not-linked object file.
+  int64_t Offset;
+
+  ObjFileAddressRange(uint64_t EndPC, int64_t Offset)
+      : HighPC(EndPC), Offset(Offset) {}
+
+  ObjFileAddressRange() : HighPC(0), Offset(0) {}
+};
+
+/// Map LowPC to ObjFileAddressRange.
+using RangesTy = std::map<uint64_t, ObjFileAddressRange>;
+
+/// AddressesMap represents information about valid addresses used
+/// by debug information. Valid addresses are those which points to
+/// live code sections. i.e. relocations for these addresses point
+/// into sections which would be/are placed into resulting binary.
+class AddressesMap {
+public:
+  virtual ~AddressesMap();
+
+  /// Returns true if represented addresses are from linked file.
+  /// Returns false if represented addresses are from not-linked
+  /// object file.
+  virtual bool areRelocationsResolved() const = 0;
+
+  /// Checks that there are valid relocations against a .debug_info
+  /// section. Reset current relocation pointer if neccessary.
+  virtual bool hasValidRelocs(bool resetRelocsPtr = true) = 0;
+
+  /// Checks that there is a relocation against .debug_info
+  /// table between \p StartOffset and \p NextOffset.
+  ///
+  /// This function must be called with offsets in strictly ascending
+  /// order because it never looks back at relocations it already 'went past'.
+  /// \returns true and sets Info.InDebugMap if it is the case.
+  virtual bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
+                                    CompileUnit::DIEInfo &Info) = 0;
+
+  /// Apply the valid relocations to the buffer \p Data, taking into
+  /// account that Data is at \p BaseOffset in the debug_info section.
+  ///
+  /// This function must be called with monotonic \p BaseOffset values.
+  ///
+  /// \returns true whether any reloc has been applied.
+  virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
+                                bool IsLittleEndian) = 0;
+
+  /// Returns all valid functions address ranges(i.e., those ranges
+  /// which points to sections with code).
+  virtual RangesTy &getValidAddressRanges() = 0;
+
+  /// Erases all data.
+  virtual void clear() = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFOPTIMIZER_H

diff  --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index 3fe9904f221b..d51fe2653631 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -27,6 +27,9 @@ add_llvm_component_library(LLVMDebugInfoDWARF
   DWARFUnitIndex.cpp
   DWARFUnit.cpp
   DWARFVerifier.cpp
+  DWARFOptCompileUnit.cpp
+  DWARFOptDeclContext.cpp
+  DWARFOptimizer.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/DWARF

diff  --git a/llvm/tools/dsymutil/CompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFOptCompileUnit.cpp
similarity index 96%
rename from llvm/tools/dsymutil/CompileUnit.cpp
rename to llvm/lib/DebugInfo/DWARF/DWARFOptCompileUnit.cpp
index 036c61a6b926..6ca5f1289283 100644
--- a/llvm/tools/dsymutil/CompileUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFOptCompileUnit.cpp
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===//
+//===- llvm/DebugInfo/DWARF/DWARFOptCompileUnit.cpp -----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,11 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "CompileUnit.h"
-#include "DeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptDeclContext.h"
 
 namespace llvm {
-namespace dsymutil {
 
 /// Check if the DIE at \p Idx is in the scope of a function.
 static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
@@ -142,5 +141,4 @@ void CompileUnit::addTypeAccelerator(const DIE *Die,
   Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
 }
 
-} // namespace dsymutil
 } // namespace llvm

diff  --git a/llvm/tools/dsymutil/DeclContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFOptDeclContext.cpp
similarity index 98%
rename from llvm/tools/dsymutil/DeclContext.cpp
rename to llvm/lib/DebugInfo/DWARF/DWARFOptDeclContext.cpp
index 1c33b672c26b..95cf58444e1a 100644
--- a/llvm/tools/dsymutil/DeclContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFOptDeclContext.cpp
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/DeclContext.cpp - Declaration context ---------------===//
+//===- llvm/DebugInfo/DWARF/DWARFOptDeclContext.cpp -----------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,13 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "DeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptDeclContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 
 namespace llvm {
-namespace dsymutil {
 
 /// Set the last DIE/CU a context was seen in and, possibly invalidate the
 /// context if it is ambiguous.
@@ -206,5 +205,5 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
 
   return PointerIntPair<DeclContext *, 1>(*ContextIter);
 }
-} // namespace dsymutil
+
 } // namespace llvm

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFOptimizer.cpp b/llvm/lib/DebugInfo/DWARF/DWARFOptimizer.cpp
new file mode 100644
index 000000000000..535d2a047076
--- /dev/null
+++ b/llvm/lib/DebugInfo/DWARF/DWARFOptimizer.cpp
@@ -0,0 +1,15 @@
+//=== llvm/DebugInfo/DWARF/DWARFOptimizer.cpp -----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFOptimizer.h"
+
+namespace llvm {
+
+AddressesMap::~AddressesMap() {}
+
+} // namespace llvm

diff  --git a/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt b/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
index 182be10f0b4c..e72360deaf88 100644
--- a/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
+++ b/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
@@ -18,4 +18,4 @@
 type = Library
 name = DebugInfoDWARF
 parent = DebugInfo
-required_libraries = BinaryFormat Object MC Support
+required_libraries = BinaryFormat Object MC Support CodeGen

diff  --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index b8466baa6346..e21215b2417d 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -22,9 +22,7 @@ add_llvm_tool(dsymutil
   dsymutil.cpp
   BinaryHolder.cpp
   CFBundle.cpp
-  CompileUnit.cpp
   DebugMap.cpp
-  DeclContext.cpp
   DwarfLinker.cpp
   DwarfStreamer.cpp
   MachODebugMapParser.cpp

diff  --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
index 64acab698434..521d3635dab2 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
@@ -9,7 +9,6 @@
 #include "DwarfLinker.h"
 #include "BinaryHolder.h"
 #include "DebugMap.h"
-#include "DeclContext.h"
 #include "DwarfStreamer.h"
 #include "MachOUtils.h"
 #include "dsymutil.h"
@@ -45,6 +44,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptDeclContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/MC/MCAsmBackend.h"
@@ -374,30 +374,6 @@ static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) {
 }
 
 void DwarfLinker::startDebugObject(LinkContext &Context) {
-  // Iterate over the debug map entries and put all the ones that are
-  // functions (because they have a size) into the Ranges map. This map is
-  // very similar to the FunctionRanges that are stored in each unit, with 2
-  // notable 
diff erences:
-  //
-  //  1. Obviously this one is global, while the other ones are per-unit.
-  //
-  //  2. This one contains not only the functions described in the DIE
-  //     tree, but also the ones that are only in the debug map.
-  //
-  // The latter information is required to reproduce dsymutil's logic while
-  // linking line tables. The cases where this information matters look like
-  // bugs that need to be investigated, but for now we need to reproduce
-  // dsymutil's behavior.
-  // FIXME: Once we understood exactly if that information is needed,
-  // maybe totally remove this (or try to use it to do a real
-  // -gline-tables-only on Darwin.
-  for (const auto &Entry : Context.DMO.symbols()) {
-    const auto &Mapping = Entry.getValue();
-    if (Mapping.Size && Mapping.ObjectAddress)
-      Context.Ranges[*Mapping.ObjectAddress] = DebugMapObjectRange(
-          *Mapping.ObjectAddress + Mapping.Size,
-          int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
-  }
 }
 
 void DwarfLinker::endDebugObject(LinkContext &Context) {
@@ -560,7 +536,7 @@ bool DwarfLinker::RelocationManager::findValidRelocsInDebugInfo(
 /// This function must be called with offsets in strictly ascending
 /// order because it never looks back at relocations it already 'went past'.
 /// \returns true and sets Info.InDebugMap if it is the case.
-bool DwarfLinker::RelocationManager::hasValidRelocation(
+bool DwarfLinker::RelocationManager::hasValidRelocationAt(
     uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
   assert(NextValidReloc == 0 ||
          StartOffset > ValidRelocs[NextValidReloc - 1].Offset);
@@ -651,7 +627,8 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
   // always check if the variable has a valid relocation, so that the
   // DIEInfo is filled. However, we don't want a static variable in a
   // function to force us to keep the enclosing function.
-  if (!RelocMgr.hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) ||
+  if (!RelocMgr.hasValidRelocationAt(LocationOffset, LocationEndOffset,
+                                     MyInfo) ||
       (Flags & TF_InFunctionScope))
     return Flags;
 
@@ -689,7 +666,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
   auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
   assert(LowPc.hasValue() && "low_pc attribute is not an address.");
   if (!LowPc ||
-      !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
+      !RelocMgr.hasValidRelocationAt(LowPcOffset, LowPcEndOffset, MyInfo))
     return Flags;
 
   if (Options.Verbose) {
@@ -724,7 +701,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
   }
 
   // Replace the debug map range with a more accurate one.
-  Ranges[*LowPc] = DebugMapObjectRange(*HighPc, MyInfo.AddrAdjust);
+  Ranges[*LowPc] = ObjFileAddressRange(*HighPc, MyInfo.AddrAdjust);
   Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
   return Flags;
 }
@@ -1651,7 +1628,8 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
   Data =
       DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
   // Modify the copy with relocated addresses.
-  if (RelocMgr.applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
+  if (RelocMgr.areRelocationsResolved() &&
+      RelocMgr.applyValidRelocs(DIECopy, Offset, Data.isLittleEndian())) {
     // If we applied relocations, we store the value of high_pc that was
     // potentially stored in the input DIE. If high_pc is an address
     // (Dwarf version == 2), then it might have been relocated to a
@@ -2393,7 +2371,7 @@ Error DwarfLinker::loadClangModule(
 
   // Setup access to the debug info.
   auto DwarfContext = DWARFContext::create(*ErrOrObj);
-  RelocationManager RelocMgr(*this);
+  RelocationManager RelocMgr(*this, *ErrOrObj, DMO);
 
   for (const auto &CU : DwarfContext->compile_units()) {
     updateDwarfVersion(CU->getVersion());
@@ -2774,8 +2752,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
     // Look for relocations that correspond to debug map entries.
 
     if (LLVM_LIKELY(!Options.Update) &&
-        !LinkContext.RelocMgr.findValidRelocsInDebugInfo(
-            *LinkContext.ObjectFile, LinkContext.DMO)) {
+        !LinkContext.RelocMgr->hasValidRelocs()) {
       if (Options.Verbose)
         outs() << "No valid relocations found. Skipping.\n";
 
@@ -2892,7 +2869,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
       Streamer->copyInvariantDebugSection(*LinkContext.ObjectFile);
     } else {
       for (auto &CurrentUnit : LinkContext.CompileUnits)
-        lookForDIEsToKeep(LinkContext.RelocMgr, LinkContext.Ranges,
+        lookForDIEsToKeep(*LinkContext.RelocMgr, LinkContext.Ranges,
                           LinkContext.CompileUnits,
                           CurrentUnit->getOrigUnit().getUnitDIE(),
                           LinkContext.DMO, *CurrentUnit, 0);
@@ -2901,10 +2878,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
     // The calls to applyValidRelocs inside cloneDIE will walk the reloc
     // array again (in the same way findValidRelocsInDebugInfo() did). We
     // need to reset the NextValidReloc index to the beginning.
-    LinkContext.RelocMgr.resetValidRelocs();
-    if (LinkContext.RelocMgr.hasValidRelocs() || LLVM_UNLIKELY(Options.Update))
-      DIECloner(*this, LinkContext.RelocMgr, DIEAlloc, LinkContext.CompileUnits,
-                Options)
+    if (LinkContext.RelocMgr->hasValidRelocs() || LLVM_UNLIKELY(Options.Update))
+      DIECloner(*this, *LinkContext.RelocMgr, DIEAlloc,
+                LinkContext.CompileUnits, Options)
           .cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO,
                                 LinkContext.Ranges, OffsetsStringPool,
                                 LinkContext.DwarfContext->isLittleEndian());

diff  --git a/llvm/tools/dsymutil/DwarfLinker.h b/llvm/tools/dsymutil/DwarfLinker.h
index b8d8e9d02e32..748377f802b3 100644
--- a/llvm/tools/dsymutil/DwarfLinker.h
+++ b/llvm/tools/dsymutil/DwarfLinker.h
@@ -10,33 +10,17 @@
 #define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
 
 #include "BinaryHolder.h"
-#include "CompileUnit.h"
 #include "DebugMap.h"
-#include "DeclContext.h"
 #include "DwarfStreamer.h"
 #include "LinkUtils.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptDeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptimizer.h"
 
 namespace llvm {
 namespace dsymutil {
 
-/// Partial address range for debug map objects. Besides an offset, only the
-/// HighPC is stored. The structure is stored in a map where the LowPC is the
-/// key.
-struct DebugMapObjectRange {
-  /// Function HighPC.
-  uint64_t HighPC;
-  /// Offset to apply to the linked address.
-  int64_t Offset;
-
-  DebugMapObjectRange(uint64_t EndPC, int64_t Offset)
-      : HighPC(EndPC), Offset(Offset) {}
-
-  DebugMapObjectRange() : HighPC(0), Offset(0) {}
-};
-
-/// Map LowPC to DebugMapObjectRange.
-using RangesTy = std::map<uint64_t, DebugMapObjectRange>;
 using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
 
 /// The core of the Dwarf linking logic.
@@ -89,7 +73,7 @@ class DwarfLinker {
                               OffsetsStringPool &StringPool);
 
   /// Keeps track of relocations.
-  class RelocationManager {
+  class RelocationManager : public AddressesMap {
     struct ValidReloc {
       uint64_t Offset;
       uint32_t Size;
@@ -117,13 +101,50 @@ class DwarfLinker {
     /// cheap lookup during the root DIE selection and during DIE cloning.
     unsigned NextValidReloc = 0;
 
+    RangesTy AddressRanges;
+
   public:
-    RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
+    RelocationManager(DwarfLinker &Linker, const object::ObjectFile &Obj,
+                      const DebugMapObject &DMO)
+        : Linker(Linker) {
+      findValidRelocsInDebugInfo(Obj, DMO);
+
+      // Iterate over the debug map entries and put all the ones that are
+      // functions (because they have a size) into the Ranges map. This map is
+      // very similar to the FunctionRanges that are stored in each unit, with 2
+      // notable 
diff erences:
+      //
+      //  1. Obviously this one is global, while the other ones are per-unit.
+      //
+      //  2. This one contains not only the functions described in the DIE
+      //     tree, but also the ones that are only in the debug map.
+      //
+      // The latter information is required to reproduce dsymutil's logic while
+      // linking line tables. The cases where this information matters look like
+      // bugs that need to be investigated, but for now we need to reproduce
+      // dsymutil's behavior.
+      // FIXME: Once we understood exactly if that information is needed,
+      // maybe totally remove this (or try to use it to do a real
+      // -gline-tables-only on Darwin.
+      for (const auto &Entry : DMO.symbols()) {
+        const auto &Mapping = Entry.getValue();
+        if (Mapping.Size && Mapping.ObjectAddress)
+          AddressRanges[*Mapping.ObjectAddress] = ObjFileAddressRange(
+              *Mapping.ObjectAddress + Mapping.Size,
+              int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
+      }
+    }
+    virtual ~RelocationManager () override {
+        clear();
+    }
 
-    bool hasValidRelocs() const { return !ValidRelocs.empty(); }
+    virtual bool areRelocationsResolved() const override { return true; }
 
-    /// Reset the NextValidReloc counter.
-    void resetValidRelocs() { NextValidReloc = 0; }
+    bool hasValidRelocs(bool resetRelocsPtr = true) override {
+      if (resetRelocsPtr)
+        NextValidReloc = 0;
+      return !ValidRelocs.empty();
+    }
 
     /// \defgroup FindValidRelocations Translate debug map into a list
     /// of relevant relocations
@@ -141,32 +162,43 @@ class DwarfLinker {
                               const DebugMapObject &DMO);
     /// @}
 
-    bool hasValidRelocation(uint64_t StartOffset, uint64_t EndOffset,
-                            CompileUnit::DIEInfo &Info);
+    bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
+                              CompileUnit::DIEInfo &Info) override;
 
     bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
-                          bool IsLittleEndian);
+                          bool IsLittleEndian) override;
+
+    RangesTy &getValidAddressRanges() override { return AddressRanges; }
+
+    void clear() override {
+      AddressRanges.clear();
+      ValidRelocs.clear();
+      NextValidReloc = 0;
+    }
   };
 
   /// Keeps track of data associated with one object during linking.
   struct LinkContext {
+    DwarfLinker &Linker;
     DebugMapObject &DMO;
-    const object::ObjectFile *ObjectFile;
-    RelocationManager RelocMgr;
+    const object::ObjectFile *ObjectFile = nullptr;
+    std::unique_ptr<RelocationManager> RelocMgr;
     std::unique_ptr<DWARFContext> DwarfContext;
     RangesTy Ranges;
     UnitListTy CompileUnits;
 
     LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO)
-        : DMO(DMO), RelocMgr(Linker) {
+        : Linker(Linker), DMO(DMO) {
       // Swift ASTs are not object files.
       if (DMO.getType() == MachO::N_AST) {
         ObjectFile = nullptr;
         return;
       }
-      auto ErrOrObj = Linker.loadObject(DMO, Map);
-      ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr;
-      DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr;
+      if (auto ErrOrObj = Linker.loadObject(DMO, Map)) {
+        ObjectFile = &*ErrOrObj;
+        DwarfContext = DWARFContext::create(*ObjectFile);
+        RelocMgr.reset(new RelocationManager(Linker, *ObjectFile, DMO));
+      }
     }
 
     /// Clear part of the context that's no longer needed when we're done with
@@ -175,6 +207,7 @@ class DwarfLinker {
       DwarfContext.reset(nullptr);
       CompileUnits.clear();
       Ranges.clear();
+      RelocMgr->clear();
     }
   };
 

diff  --git a/llvm/tools/dsymutil/DwarfStreamer.cpp b/llvm/tools/dsymutil/DwarfStreamer.cpp
index 8747aee458fd..33dc9fc850b5 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.cpp
+++ b/llvm/tools/dsymutil/DwarfStreamer.cpp
@@ -7,11 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "DwarfStreamer.h"
-#include "CompileUnit.h"
 #include "LinkUtils.h"
 #include "MachOUtils.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h"
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/MCTargetOptionsCommandFlags.inc"
 #include "llvm/Support/LEB128.h"

diff  --git a/llvm/tools/dsymutil/DwarfStreamer.h b/llvm/tools/dsymutil/DwarfStreamer.h
index baf215ac1315..85e3d48b7581 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.h
+++ b/llvm/tools/dsymutil/DwarfStreamer.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
 #define LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
 
-#include "CompileUnit.h"
 #include "DebugMap.h"
 #include "LinkUtils.h"
 #include "llvm/CodeGen/AccelTable.h"
@@ -17,6 +16,7 @@
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFOptCompileUnit.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"


        


More information about the llvm-commits mailing list