[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