summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
authorAlexey Lapshin <a.v.lapshin@mail.ru>2019-12-20 19:23:31 +0300
committerAlexey Lapshin <a.v.lapshin@mail.ru>2020-01-08 14:15:31 +0300
commit1cf11a4c67a15ab5493ef424c898accf49012caa (patch)
tree725e9007d55d84e3ad27af22222ebbcda6ef6043 /llvm/tools
parent96d2d96b03ff590867cd6578eb7f6d32770cbbf0 (diff)
downloadbcm5719-llvm-1cf11a4c67a15ab5493ef424c898accf49012caa.tar.gz
bcm5719-llvm-1cf11a4c67a15ab5493ef424c898accf49012caa.zip
[Dsymutil][Debuginfo][NFC] Reland: Refactor dsymutil to separate DWARF optimizing part. #2.
Summary: This patch relands D71271. The problem with D71271 is that it has cyclic dependency: CodeGen->AsmPrinter->DebugInfoDWARF->CodeGen. To avoid cyclic dependency this patch puts implementation for DWARFOptimizer into separate library: lib/DWARFLinker. Thus the difference between this patch and D71271 is in that DWARFOptimizer renamed into DWARFLinker and it`s files are put into lib/DWARFLinker. Reviewers: JDevlieghere, friss, dblaikie, aprantl Reviewed By: JDevlieghere Subscribers: thegameg, merge_guards_bot, probinson, mgorny, hiraditya, llvm-commits Tags: #llvm, #debug-info Differential Revision: https://reviews.llvm.org/D71839
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/dsymutil/CMakeLists.txt5
-rw-r--r--llvm/tools/dsymutil/CompileUnit.cpp146
-rw-r--r--llvm/tools/dsymutil/CompileUnit.h331
-rw-r--r--llvm/tools/dsymutil/DeclContext.cpp210
-rw-r--r--llvm/tools/dsymutil/DeclContext.h171
-rw-r--r--llvm/tools/dsymutil/DwarfLinkerForBinary.cpp (renamed from llvm/tools/dsymutil/DwarfLinker.cpp)254
-rw-r--r--llvm/tools/dsymutil/DwarfLinkerForBinary.h (renamed from llvm/tools/dsymutil/DwarfLinker.h)118
-rw-r--r--llvm/tools/dsymutil/DwarfStreamer.cpp2
-rw-r--r--llvm/tools/dsymutil/DwarfStreamer.h2
-rw-r--r--llvm/tools/dsymutil/LLVMBuild.txt2
10 files changed, 193 insertions, 1048 deletions
diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt
index b8466baa634..fecd8a61ad0 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
AllTargetsInfos
AsmPrinter
DebugInfoDWARF
+ DWARFLinker
MC
Object
CodeGen
@@ -22,10 +23,8 @@ add_llvm_tool(dsymutil
dsymutil.cpp
BinaryHolder.cpp
CFBundle.cpp
- CompileUnit.cpp
DebugMap.cpp
- DeclContext.cpp
- DwarfLinker.cpp
+ DwarfLinkerForBinary.cpp
DwarfStreamer.cpp
MachODebugMapParser.cpp
MachOUtils.cpp
diff --git a/llvm/tools/dsymutil/CompileUnit.cpp b/llvm/tools/dsymutil/CompileUnit.cpp
deleted file mode 100644
index 036c61a6b92..00000000000
--- a/llvm/tools/dsymutil/CompileUnit.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===//
-//
-// 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 "CompileUnit.h"
-#include "DeclContext.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) {
- while (Idx) {
- if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
- return true;
- Idx = U.getInfo(Idx).ParentIdx;
- }
- return false;
-}
-
-uint16_t CompileUnit::getLanguage() {
- if (!Language) {
- DWARFDie CU = getOrigUnit().getUnitDIE();
- Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
- }
- return Language;
-}
-
-void CompileUnit::markEverythingAsKept() {
- unsigned Idx = 0;
-
- setHasInterestingContent();
-
- for (auto &I : Info) {
- // Mark everything that wasn't explicit marked for pruning.
- I.Keep = !I.Prune;
- auto DIE = OrigUnit.getDIEAtIndex(Idx++);
-
- // Try to guess which DIEs must go to the accelerator tables. We do that
- // just for variables, because functions will be handled depending on
- // whether they carry a DW_AT_low_pc attribute or not.
- if (DIE.getTag() != dwarf::DW_TAG_variable &&
- DIE.getTag() != dwarf::DW_TAG_constant)
- continue;
-
- Optional<DWARFFormValue> Value;
- if (!(Value = DIE.find(dwarf::DW_AT_location))) {
- if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
- !inFunctionScope(*this, I.ParentIdx))
- I.InDebugMap = true;
- continue;
- }
- if (auto Block = Value->getAsBlock()) {
- if (Block->size() > OrigUnit.getAddressByteSize() &&
- (*Block)[0] == dwarf::DW_OP_addr)
- I.InDebugMap = true;
- }
- }
-}
-
-uint64_t CompileUnit::computeNextUnitOffset() {
- NextUnitOffset = StartOffset;
- if (NewUnit) {
- NextUnitOffset += 11 /* Header size */;
- NextUnitOffset += NewUnit->getUnitDie().getSize();
- }
- return NextUnitOffset;
-}
-
-/// Keep track of a forward cross-cu reference from this unit
-/// to \p Die that lives in \p RefUnit.
-void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
- DeclContext *Ctxt, PatchLocation Attr) {
- ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
-}
-
-void CompileUnit::fixupForwardReferences() {
- for (const auto &Ref : ForwardDIEReferences) {
- DIE *RefDie;
- const CompileUnit *RefUnit;
- PatchLocation Attr;
- DeclContext *Ctxt;
- std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
- if (Ctxt && Ctxt->getCanonicalDIEOffset())
- Attr.set(Ctxt->getCanonicalDIEOffset());
- else
- Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
- }
-}
-
-void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
- Labels.insert({LabelLowPc, PcOffset});
-}
-
-void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
- int64_t PcOffset) {
- // Don't add empty ranges to the interval map. They are a problem because
- // the interval map expects half open intervals. This is safe because they
- // are empty anyway.
- if (FuncHighPc != FuncLowPc)
- Ranges.insert(FuncLowPc, FuncHighPc, PcOffset);
- this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
- this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
-}
-
-void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
- if (Die.getTag() != dwarf::DW_TAG_compile_unit)
- RangeAttributes.push_back(Attr);
- else
- UnitRangeAttribute = Attr;
-}
-
-void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
- LocationAttributes.emplace_back(Attr, PcOffset);
-}
-
-void CompileUnit::addNamespaceAccelerator(const DIE *Die,
- DwarfStringPoolEntryRef Name) {
- Namespaces.emplace_back(Name, Die);
-}
-
-void CompileUnit::addObjCAccelerator(const DIE *Die,
- DwarfStringPoolEntryRef Name,
- bool SkipPubSection) {
- ObjC.emplace_back(Name, Die, SkipPubSection);
-}
-
-void CompileUnit::addNameAccelerator(const DIE *Die,
- DwarfStringPoolEntryRef Name,
- bool SkipPubSection) {
- Pubnames.emplace_back(Name, Die, SkipPubSection);
-}
-
-void CompileUnit::addTypeAccelerator(const DIE *Die,
- DwarfStringPoolEntryRef Name,
- bool ObjcClassImplementation,
- uint32_t QualifiedNameHash) {
- Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
-}
-
-} // namespace dsymutil
-} // namespace llvm
diff --git a/llvm/tools/dsymutil/CompileUnit.h b/llvm/tools/dsymutil/CompileUnit.h
deleted file mode 100644
index e0f5d3bc65b..00000000000
--- a/llvm/tools/dsymutil/CompileUnit.h
+++ /dev/null
@@ -1,331 +0,0 @@
-//===- tools/dsymutil/CompileUnit.h - Dwarf debug info linker ---*- 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_TOOLS_DSYMUTIL_COMPILEUNIT_H
-#define LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
-
-#include "llvm/ADT/IntervalMap.h"
-#include "llvm/CodeGen/DIE.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-
-namespace llvm {
-namespace dsymutil {
-
-class DeclContext;
-
-template <typename KeyT, typename ValT>
-using HalfOpenIntervalMap =
- IntervalMap<KeyT, ValT, IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
- IntervalMapHalfOpenInfo<KeyT>>;
-
-using FunctionIntervals = HalfOpenIntervalMap<uint64_t, int64_t>;
-
-// FIXME: Delete this structure.
-struct PatchLocation {
- DIE::value_iterator I;
-
- PatchLocation() = default;
- PatchLocation(DIE::value_iterator I) : I(I) {}
-
- void set(uint64_t New) const {
- assert(I);
- const auto &Old = *I;
- assert(Old.getType() == DIEValue::isInteger);
- *I = DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New));
- }
-
- uint64_t get() const {
- assert(I);
- return I->getDIEInteger().getValue();
- }
-};
-
-/// 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.
-class CompileUnit {
-public:
- /// Information gathered about a DIE in the object file.
- struct DIEInfo {
- /// Address offset to apply to the described entity.
- int64_t AddrAdjust;
-
- /// ODR Declaration context.
- DeclContext *Ctxt;
-
- /// Cloned version of that DIE.
- DIE *Clone;
-
- /// The index of this DIE's parent.
- uint32_t ParentIdx;
-
- /// Is the DIE part of the linked output?
- bool Keep : 1;
-
- /// Was this DIE's entity found in the map?
- bool InDebugMap : 1;
-
- /// Is this a pure forward declaration we can strip?
- bool Prune : 1;
-
- /// Does DIE transitively refer an incomplete decl?
- bool Incomplete : 1;
- };
-
- CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
- StringRef ClangModuleName)
- : OrigUnit(OrigUnit), ID(ID), Ranges(RangeAlloc),
- ClangModuleName(ClangModuleName) {
- Info.resize(OrigUnit.getNumDIEs());
-
- auto CUDie = OrigUnit.getUnitDIE(false);
- if (!CUDie) {
- HasODR = false;
- return;
- }
- if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
- HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
- *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
- *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
- *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
- *Lang == dwarf::DW_LANG_ObjC_plus_plus);
- else
- HasODR = false;
- }
-
- DWARFUnit &getOrigUnit() const { return OrigUnit; }
-
- unsigned getUniqueID() const { return ID; }
-
- void createOutputDIE() {
- NewUnit.emplace(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(),
- OrigUnit.getUnitDIE().getTag());
- }
-
- DIE *getOutputUnitDIE() const {
- if (NewUnit)
- return &const_cast<BasicDIEUnit &>(*NewUnit).getUnitDie();
- return nullptr;
- }
-
- bool hasODR() const { return HasODR; }
- bool isClangModule() const { return !ClangModuleName.empty(); }
- uint16_t getLanguage();
-
- const std::string &getClangModuleName() const { return ClangModuleName; }
-
- DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
- const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
-
- uint64_t getStartOffset() const { return StartOffset; }
- uint64_t getNextUnitOffset() const { return NextUnitOffset; }
- void setStartOffset(uint64_t DebugInfoSize) { StartOffset = DebugInfoSize; }
-
- uint64_t getLowPc() const { return LowPc; }
- uint64_t getHighPc() const { return HighPc; }
- bool hasLabelAt(uint64_t Addr) const { return Labels.count(Addr); }
-
- Optional<PatchLocation> getUnitRangesAttribute() const {
- return UnitRangeAttribute;
- }
-
- const FunctionIntervals &getFunctionRanges() const { return Ranges; }
-
- const std::vector<PatchLocation> &getRangesAttributes() const {
- return RangeAttributes;
- }
-
- const std::vector<std::pair<PatchLocation, int64_t>> &
- getLocationAttributes() const {
- return LocationAttributes;
- }
-
- void setHasInterestingContent() { HasInterestingContent = true; }
- bool hasInterestingContent() { return HasInterestingContent; }
-
- /// Mark every DIE in this unit as kept. This function also
- /// marks variables as InDebugMap so that they appear in the
- /// reconstructed accelerator tables.
- void markEverythingAsKept();
-
- /// Compute the end offset for this unit. Must be called after the CU's DIEs
- /// have been cloned. \returns the next unit offset (which is also the
- /// current debug_info section size).
- uint64_t computeNextUnitOffset();
-
- /// Keep track of a forward reference to DIE \p Die in \p RefUnit by \p
- /// Attr. The attribute should be fixed up later to point to the absolute
- /// offset of \p Die in the debug_info section or to the canonical offset of
- /// \p Ctxt if it is non-null.
- void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
- DeclContext *Ctxt, PatchLocation Attr);
-
- /// Apply all fixups recorded by noteForwardReference().
- void fixupForwardReferences();
-
- /// Add the low_pc of a label that is relocated by applying
- /// offset \p PCOffset.
- void addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset);
-
- /// Add a function range [\p LowPC, \p HighPC) that is relocated by applying
- /// offset \p PCOffset.
- void addFunctionRange(uint64_t LowPC, uint64_t HighPC, int64_t PCOffset);
-
- /// Keep track of a DW_AT_range attribute that we will need to patch up later.
- void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
-
- /// Keep track of a location attribute pointing to a location list in the
- /// debug_loc section.
- void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
-
- /// Add a name accelerator entry for \a Die with \a Name.
- void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name);
-
- /// Add a name accelerator entry for \a Die with \a Name.
- void addNameAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
- bool SkipPubnamesSection = false);
-
- /// Add various accelerator entries for \p Die with \p Name which is stored
- /// in the string table at \p Offset. \p Name must be an Objective-C
- /// selector.
- void addObjCAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
- bool SkipPubnamesSection = false);
-
- /// Add a type accelerator entry for \p Die with \p Name which is stored in
- /// the string table at \p Offset.
- void addTypeAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name,
- bool ObjcClassImplementation,
- uint32_t QualifiedNameHash);
-
- struct AccelInfo {
- /// Name of the entry.
- DwarfStringPoolEntryRef Name;
-
- /// DIE this entry describes.
- const DIE *Die;
-
- /// Hash of the fully qualified name.
- uint32_t QualifiedNameHash;
-
- /// Emit this entry only in the apple_* sections.
- bool SkipPubSection;
-
- /// Is this an ObjC class implementation?
- bool ObjcClassImplementation;
-
- AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
- bool SkipPubSection = false)
- : Name(Name), Die(Die), SkipPubSection(SkipPubSection) {}
-
- AccelInfo(DwarfStringPoolEntryRef Name, const DIE *Die,
- uint32_t QualifiedNameHash, bool ObjCClassIsImplementation)
- : Name(Name), Die(Die), QualifiedNameHash(QualifiedNameHash),
- SkipPubSection(false),
- ObjcClassImplementation(ObjCClassIsImplementation) {}
- };
-
- const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
- const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
- const std::vector<AccelInfo> &getNamespaces() const { return Namespaces; }
- const std::vector<AccelInfo> &getObjC() const { return ObjC; }
-
- /// Get the full path for file \a FileNum in the line table
- StringRef getResolvedPath(unsigned FileNum) {
- if (FileNum >= ResolvedPaths.size())
- return StringRef();
- return ResolvedPaths[FileNum];
- }
-
- /// Set the fully resolved path for the line-table's file \a FileNum
- /// to \a Path.
- void setResolvedPath(unsigned FileNum, StringRef Path) {
- if (ResolvedPaths.size() <= FileNum)
- ResolvedPaths.resize(FileNum + 1);
- ResolvedPaths[FileNum] = Path;
- }
-
- MCSymbol *getLabelBegin() { return LabelBegin; }
- void setLabelBegin(MCSymbol *S) { LabelBegin = S; }
-
-private:
- DWARFUnit &OrigUnit;
- unsigned ID;
- std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
- Optional<BasicDIEUnit> NewUnit;
- MCSymbol *LabelBegin = nullptr;
-
- uint64_t StartOffset;
- uint64_t NextUnitOffset;
-
- uint64_t LowPc = std::numeric_limits<uint64_t>::max();
- uint64_t HighPc = 0;
-
- /// A list of attributes to fixup with the absolute offset of
- /// a DIE in the debug_info section.
- ///
- /// The offsets for the attributes in this array couldn't be set while
- /// cloning because for cross-cu forward references the target DIE's offset
- /// isn't known you emit the reference attribute.
- std::vector<
- std::tuple<DIE *, const CompileUnit *, DeclContext *, PatchLocation>>
- ForwardDIEReferences;
-
- FunctionIntervals::Allocator RangeAlloc;
-
- /// The ranges in that interval map are the PC ranges for
- /// functions in this unit, associated with the PC offset to apply
- /// to the addresses to get the linked address.
- FunctionIntervals Ranges;
-
- /// The DW_AT_low_pc of each DW_TAG_label.
- SmallDenseMap<uint64_t, uint64_t, 1> Labels;
-
- /// DW_AT_ranges attributes to patch after we have gathered
- /// all the unit's function addresses.
- /// @{
- std::vector<PatchLocation> RangeAttributes;
- Optional<PatchLocation> UnitRangeAttribute;
- /// @}
-
- /// Location attributes that need to be transferred from the
- /// original debug_loc section to the liked one. They are stored
- /// along with the PC offset that is to be applied to their
- /// function's address.
- std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes;
-
- /// Accelerator entries for the unit, both for the pub*
- /// sections and the apple* ones.
- /// @{
- std::vector<AccelInfo> Pubnames;
- std::vector<AccelInfo> Pubtypes;
- std::vector<AccelInfo> Namespaces;
- std::vector<AccelInfo> ObjC;
- /// @}
-
- /// Cached resolved paths from the line table.
- /// Note, the StringRefs here point in to the intern (uniquing) string pool.
- /// This means that a StringRef returned here doesn't need to then be uniqued
- /// for the purposes of getting a unique address for each string.
- std::vector<StringRef> ResolvedPaths;
-
- /// Is this unit subject to the ODR rule?
- bool HasODR;
-
- /// Did a DIE actually contain a valid reloc?
- bool HasInterestingContent;
-
- /// The DW_AT_language of this unit.
- uint16_t Language = 0;
-
- /// If this is a Clang module, this holds the module's name.
- std::string ClangModuleName;
-};
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H
diff --git a/llvm/tools/dsymutil/DeclContext.cpp b/llvm/tools/dsymutil/DeclContext.cpp
deleted file mode 100644
index 1c33b672c26..00000000000
--- a/llvm/tools/dsymutil/DeclContext.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-//===- tools/dsymutil/DeclContext.cpp - Declaration context ---------------===//
-//
-// 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 "DeclContext.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.
-///
-/// In the current implementation, we don't handle overloaded functions well,
-/// because the argument types are not taken into account when computing the
-/// DeclContext tree.
-///
-/// Some of this is mitigated byt using mangled names that do contain the
-/// arguments types, but sometimes (e.g. with function templates) we don't have
-/// that. In that case, just do not unique anything that refers to the contexts
-/// we are not able to distinguish.
-///
-/// If a context that is not a namespace appears twice in the same CU, we know
-/// it is ambiguous. Make it invalid.
-bool DeclContext::setLastSeenDIE(CompileUnit &U, const DWARFDie &Die) {
- if (LastSeenCompileUnitID == U.getUniqueID()) {
- DWARFUnit &OrigUnit = U.getOrigUnit();
- uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE);
- U.getInfo(FirstIdx).Ctxt = nullptr;
- return false;
- }
-
- LastSeenCompileUnitID = U.getUniqueID();
- LastSeenDIE = Die;
- return true;
-}
-
-PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
- DeclContext &Context, const DWARFDie &DIE, CompileUnit &U,
- UniquingStringPool &StringPool, bool InClangModule) {
- unsigned Tag = DIE.getTag();
-
- // FIXME: dsymutil-classic compat: We should bail out here if we
- // have a specification or an abstract_origin. We will get the
- // parent context wrong here.
-
- switch (Tag) {
- default:
- // By default stop gathering child contexts.
- return PointerIntPair<DeclContext *, 1>(nullptr);
- case dwarf::DW_TAG_module:
- break;
- case dwarf::DW_TAG_compile_unit:
- return PointerIntPair<DeclContext *, 1>(&Context);
- case dwarf::DW_TAG_subprogram:
- // Do not unique anything inside CU local functions.
- if ((Context.getTag() == dwarf::DW_TAG_namespace ||
- Context.getTag() == dwarf::DW_TAG_compile_unit) &&
- !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0))
- return PointerIntPair<DeclContext *, 1>(nullptr);
- LLVM_FALLTHROUGH;
- case dwarf::DW_TAG_member:
- case dwarf::DW_TAG_namespace:
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_class_type:
- case dwarf::DW_TAG_union_type:
- case dwarf::DW_TAG_enumeration_type:
- case dwarf::DW_TAG_typedef:
- // Artificial things might be ambiguous, because they might be created on
- // demand. For example implicitly defined constructors are ambiguous
- // because of the way we identify contexts, and they won't be generated
- // every time everywhere.
- if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0))
- return PointerIntPair<DeclContext *, 1>(nullptr);
- break;
- }
-
- const char *Name = DIE.getName(DINameKind::LinkageName);
- const char *ShortName = DIE.getName(DINameKind::ShortName);
- StringRef NameRef;
- StringRef ShortNameRef;
- StringRef FileRef;
-
- if (Name)
- NameRef = StringPool.internString(Name);
- else if (Tag == dwarf::DW_TAG_namespace)
- // FIXME: For dsymutil-classic compatibility. I think uniquing within
- // anonymous namespaces is wrong. There is no ODR guarantee there.
- NameRef = StringPool.internString("(anonymous namespace)");
-
- if (ShortName && ShortName != Name)
- ShortNameRef = StringPool.internString(ShortName);
- else
- ShortNameRef = NameRef;
-
- if (Tag != dwarf::DW_TAG_class_type && Tag != dwarf::DW_TAG_structure_type &&
- Tag != dwarf::DW_TAG_union_type &&
- Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty())
- return PointerIntPair<DeclContext *, 1>(nullptr);
-
- unsigned Line = 0;
- unsigned ByteSize = std::numeric_limits<uint32_t>::max();
-
- if (!InClangModule) {
- // Gather some discriminating data about the DeclContext we will be
- // creating: File, line number and byte size. This shouldn't be necessary,
- // because the ODR is just about names, but given that we do some
- // approximations with overloaded functions and anonymous namespaces, use
- // these additional data points to make the process safer.
- //
- // This is disabled for clang modules, because forward declarations of
- // module-defined types do not have a file and line.
- ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size),
- std::numeric_limits<uint64_t>::max());
- if (Tag != dwarf::DW_TAG_namespace || !Name) {
- if (unsigned FileNum =
- dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) {
- if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
- &U.getOrigUnit())) {
- // FIXME: dsymutil-classic compatibility. I'd rather not
- // unique anything in anonymous namespaces, but if we do, then
- // verify that the file and line correspond.
- if (!Name && Tag == dwarf::DW_TAG_namespace)
- FileNum = 1;
-
- if (LT->hasFileAtIndex(FileNum)) {
- Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0);
- // Cache the resolved paths based on the index in the line table,
- // because calling realpath is expansive.
- StringRef ResolvedPath = U.getResolvedPath(FileNum);
- if (!ResolvedPath.empty()) {
- FileRef = ResolvedPath;
- } else {
- std::string File;
- bool FoundFileName = LT->getFileNameByIndex(
- FileNum, U.getOrigUnit().getCompilationDir(),
- DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
- File);
- (void)FoundFileName;
- assert(FoundFileName && "Must get file name from line table");
- // Second level of caching, this time based on the file's parent
- // path.
- FileRef = PathResolver.resolve(File, StringPool);
- U.setResolvedPath(FileNum, FileRef);
- }
- }
- }
- }
- }
- }
-
- if (!Line && NameRef.empty())
- return PointerIntPair<DeclContext *, 1>(nullptr);
-
- // We hash NameRef, which is the mangled name, in order to get most
- // overloaded functions resolve correctly.
- //
- // Strictly speaking, hashing the Tag is only necessary for a
- // DW_TAG_module, to prevent uniquing of a module and a namespace
- // with the same name.
- //
- // FIXME: dsymutil-classic won't unique the same type presented
- // once as a struct and once as a class. Using the Tag in the fully
- // qualified name hash to get the same effect.
- unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag, NameRef);
-
- // FIXME: dsymutil-classic compatibility: when we don't have a name,
- // use the filename.
- if (Tag == dwarf::DW_TAG_namespace && NameRef == "(anonymous namespace)")
- Hash = hash_combine(Hash, FileRef);
-
- // Now look if this context already exists.
- DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context);
- auto ContextIter = Contexts.find(&Key);
-
- if (ContextIter == Contexts.end()) {
- // The context wasn't found.
- bool Inserted;
- DeclContext *NewContext =
- new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef, FileRef,
- Context, DIE, U.getUniqueID());
- std::tie(ContextIter, Inserted) = Contexts.insert(NewContext);
- assert(Inserted && "Failed to insert DeclContext");
- (void)Inserted;
- } else if (Tag != dwarf::DW_TAG_namespace &&
- !(*ContextIter)->setLastSeenDIE(U, DIE)) {
- // The context was found, but it is ambiguous with another context
- // in the same file. Mark it invalid.
- return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
- }
-
- assert(ContextIter != Contexts.end());
- // FIXME: dsymutil-classic compatibility. Union types aren't
- // uniques, but their children might be.
- if ((Tag == dwarf::DW_TAG_subprogram &&
- Context.getTag() != dwarf::DW_TAG_structure_type &&
- Context.getTag() != dwarf::DW_TAG_class_type) ||
- (Tag == dwarf::DW_TAG_union_type))
- return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */ 1);
-
- return PointerIntPair<DeclContext *, 1>(*ContextIter);
-}
-} // namespace dsymutil
-} // namespace llvm
diff --git a/llvm/tools/dsymutil/DeclContext.h b/llvm/tools/dsymutil/DeclContext.h
deleted file mode 100644
index 36ef5094408..00000000000
--- a/llvm/tools/dsymutil/DeclContext.h
+++ /dev/null
@@ -1,171 +0,0 @@
-//===- tools/dsymutil/DeclContext.h - Dwarf debug info linker ---*- 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_TOOLS_DSYMUTIL_DECLCONTEXT_H
-#define LLVM_TOOLS_DSYMUTIL_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/Support/Path.h"
-
-namespace llvm {
-namespace dsymutil {
-
-struct DeclMapInfo;
-
-/// Small helper that resolves and caches file paths. This helps reduce the
-/// number of calls to realpath which is expensive. We assume the input are
-/// files, and cache the realpath of their parent. This way we can quickly
-/// resolve different files under the same path.
-class CachedPathResolver {
-public:
- /// Resolve a path by calling realpath and cache its result. The returned
- /// StringRef is interned in the given \p StringPool.
- StringRef resolve(std::string Path, NonRelocatableStringpool &StringPool) {
- StringRef FileName = sys::path::filename(Path);
- SmallString<256> ParentPath = sys::path::parent_path(Path);
-
- // If the ParentPath has not yet been resolved, resolve and cache it for
- // future look-ups.
- if (!ResolvedPaths.count(ParentPath)) {
- SmallString<256> RealPath;
- sys::fs::real_path(ParentPath, RealPath);
- ResolvedPaths.insert({ParentPath, StringRef(RealPath).str()});
- }
-
- // Join the file name again with the resolved path.
- SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
- sys::path::append(ResolvedPath, FileName);
- return StringPool.internString(ResolvedPath);
- }
-
-private:
- StringMap<std::string> ResolvedPaths;
-};
-
-/// A DeclContext is a named program scope that is used for ODR uniquing of
-/// types.
-///
-/// The set of DeclContext for the ODR-subject parts of a Dwarf link is
-/// expanded (and uniqued) with each new object file processed. We need to
-/// determine the context of each DIE in an linked object file to see if the
-/// corresponding type has already been emitted.
-///
-/// The contexts are conceptually organized as a tree (eg. a function scope is
-/// contained in a namespace scope that contains other scopes), but
-/// storing/accessing them in an actual tree is too inefficient: we need to be
-/// able to very quickly query a context for a given child context by name.
-/// Storing a StringMap in each DeclContext would be too space inefficient.
-///
-/// The solution here is to give each DeclContext a link to its parent (this
-/// allows to walk up the tree), but to query the existence of a specific
-/// DeclContext using a separate DenseMap keyed on the hash of the fully
-/// qualified name of the context.
-class DeclContext {
-public:
- using Map = DenseSet<DeclContext *, DeclMapInfo>;
-
- DeclContext() : DefinedInClangModule(0), Parent(*this) {}
-
- DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
- StringRef Name, StringRef File, const DeclContext &Parent,
- DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
- : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
- DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
- LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
-
- uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
-
- bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
-
- uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
- void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
-
- bool isDefinedInClangModule() const { return DefinedInClangModule; }
- void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
-
- uint16_t getTag() const { return Tag; }
- StringRef getName() const { return Name; }
-
-private:
- friend DeclMapInfo;
-
- unsigned QualifiedNameHash = 0;
- uint32_t Line = 0;
- uint32_t ByteSize = 0;
- uint16_t Tag = dwarf::DW_TAG_compile_unit;
- unsigned DefinedInClangModule : 1;
- StringRef Name;
- StringRef File;
- const DeclContext &Parent;
- DWARFDie LastSeenDIE;
- uint32_t LastSeenCompileUnitID = 0;
- uint32_t CanonicalDIEOffset = 0;
-};
-
-/// This class gives a tree-like API to the DenseMap that stores the
-/// DeclContext objects. It holds the BumpPtrAllocator where these objects will
-/// be allocated.
-class DeclContextTree {
-public:
- /// Get the child of \a Context described by \a DIE in \a Unit. The
- /// required strings will be interned in \a StringPool.
- /// \returns The child DeclContext along with one bit that is set if
- /// this context is invalid.
- ///
- /// An invalid context means it shouldn't be considered for uniquing, but its
- /// not returning null, because some children of that context might be
- /// uniquing candidates.
- ///
- /// FIXME: The invalid bit along the return value is to emulate some
- /// dsymutil-classic functionality.
- PointerIntPair<DeclContext *, 1>
- getChildDeclContext(DeclContext &Context, const DWARFDie &DIE,
- CompileUnit &Unit, UniquingStringPool &StringPool,
- bool InClangModule);
-
- DeclContext &getRoot() { return Root; }
-
-private:
- BumpPtrAllocator Allocator;
- DeclContext Root;
- DeclContext::Map Contexts;
-
- /// Cache resolved paths from the line table.
- CachedPathResolver PathResolver;
-};
-
-/// Info type for the DenseMap storing the DeclContext pointers.
-struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
- using DenseMapInfo<DeclContext *>::getEmptyKey;
- using DenseMapInfo<DeclContext *>::getTombstoneKey;
-
- static unsigned getHashValue(const DeclContext *Ctxt) {
- return Ctxt->QualifiedNameHash;
- }
-
- static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
- if (RHS == getEmptyKey() || RHS == getTombstoneKey())
- return RHS == LHS;
- return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
- LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
- LHS->Name.data() == RHS->Name.data() &&
- LHS->File.data() == RHS->File.data() &&
- LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
- }
-};
-
-} // end namespace dsymutil
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 53f6b2899b0..b42fc1a1d50 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker -----------===//
+//===- tools/dsymutil/DwarfLinkerForBinary.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,10 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "DwarfLinker.h"
+#include "DwarfLinkerForBinary.h"
#include "BinaryHolder.h"
#include "DebugMap.h"
-#include "DeclContext.h"
#include "DwarfStreamer.h"
#include "MachOUtils.h"
#include "dsymutil.h"
@@ -37,6 +36,7 @@
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/Config/config.h"
+#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -119,7 +119,7 @@ static CompileUnit *getUnitForOffset(const UnitListTy &Units, uint64_t Offset) {
/// Resolve the DIE attribute reference that has been extracted in \p RefValue.
/// The resulting DIE might be in another CompileUnit which is stored into \p
/// ReferencedCU. \returns null if resolving fails for any reason.
-static DWARFDie resolveDIEReference(const DwarfLinker &Linker,
+static DWARFDie resolveDIEReference(const DwarfLinkerForBinary &Linker,
const DebugMapObject &DMO,
const UnitListTy &Units,
const DWARFFormValue &RefValue,
@@ -188,7 +188,8 @@ static bool isTypeTag(uint16_t Tag) {
return false;
}
-static Error remarksErrorHandler(const DebugMapObject &DMO, DwarfLinker &Linker,
+static Error remarksErrorHandler(const DebugMapObject &DMO,
+ DwarfLinkerForBinary &Linker,
std::unique_ptr<FileError> FE) {
bool IsArchive = DMO.getObjectFilename().endswith(")");
// Don't report errors for missing remark files from static
@@ -212,10 +213,10 @@ static Error remarksErrorHandler(const DebugMapObject &DMO, DwarfLinker &Linker,
return createFileError(FE->getFileName(), std::move(NewE));
}
-bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
- AttributesInfo &Info,
- OffsetsStringPool &StringPool,
- bool StripTemplate) {
+bool DwarfLinkerForBinary::DIECloner::getDIENames(const DWARFDie &Die,
+ AttributesInfo &Info,
+ OffsetsStringPool &StringPool,
+ bool StripTemplate) {
// This function will be called on DIEs having low_pcs and
// ranges. As getting the name might be more expansive, filter out
// blocks directly.
@@ -244,8 +245,9 @@ bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
/// Report a warning to the user, optionally including information about a
/// specific \p DIE related to the warning.
-void DwarfLinker::reportWarning(const Twine &Warning, const DebugMapObject &DMO,
- const DWARFDie *DIE) const {
+void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
+ const DebugMapObject &DMO,
+ const DWARFDie *DIE) const {
StringRef Context = DMO.getObjectFilename();
warn(Warning, Context);
@@ -260,8 +262,8 @@ void DwarfLinker::reportWarning(const Twine &Warning, const DebugMapObject &DMO,
DIE->dump(errs(), 6 /* Indent */, DumpOpts);
}
-bool DwarfLinker::createStreamer(const Triple &TheTriple,
- raw_fd_ostream &OutFile) {
+bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
+ raw_fd_ostream &OutFile) {
if (Options.NoOutput)
return true;
@@ -397,34 +399,9 @@ static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) {
llvm_unreachable("Invalid 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 differences:
- //
- // 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 DwarfLinkerForBinary::startDebugObject(LinkContext &Context) {}
-void DwarfLinker::endDebugObject(LinkContext &Context) {
+void DwarfLinkerForBinary::endDebugObject(LinkContext &Context) {
Context.Clear();
for (auto I = DIEBlocks.begin(), E = DIEBlocks.end(); I != E; ++I)
@@ -460,7 +437,7 @@ static bool isMachOPairedReloc(uint64_t RelocType, uint64_t Arch) {
/// Iterate over the relocations of the given \p Section and
/// store the ones that correspond to debug map entries into the
/// ValidRelocs array.
-void DwarfLinker::RelocationManager::findValidRelocsMachO(
+void DwarfLinkerForBinary::RelocationManager::findValidRelocsMachO(
const object::SectionRef &Section, const object::MachOObjectFile &Obj,
const DebugMapObject &DMO) {
Expected<StringRef> ContentsOrErr = Section.getContents();
@@ -534,7 +511,7 @@ void DwarfLinker::RelocationManager::findValidRelocsMachO(
/// Dispatch the valid relocation finding logic to the
/// appropriate handler depending on the object file format.
-bool DwarfLinker::RelocationManager::findValidRelocs(
+bool DwarfLinkerForBinary::RelocationManager::findValidRelocs(
const object::SectionRef &Section, const object::ObjectFile &Obj,
const DebugMapObject &DMO) {
// Dispatch to the right handler depending on the file type.
@@ -560,7 +537,7 @@ bool DwarfLinker::RelocationManager::findValidRelocs(
/// link by indicating which DIEs refer to symbols present in the
/// linked binary.
/// \returns whether there are any valid relocations in the debug info.
-bool DwarfLinker::RelocationManager::findValidRelocsInDebugInfo(
+bool DwarfLinkerForBinary::RelocationManager::findValidRelocsInDebugInfo(
const object::ObjectFile &Obj, const DebugMapObject &DMO) {
// Find the debug_info section.
for (const object::SectionRef &Section : Obj.sections()) {
@@ -584,7 +561,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 DwarfLinkerForBinary::RelocationManager::hasValidRelocationAt(
uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
assert(NextValidReloc == 0 ||
StartOffset > ValidRelocs[NextValidReloc - 1].Offset);
@@ -645,11 +622,9 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
/// Check if a variable describing DIE should be kept.
/// \returns updated TraversalFlags.
-unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
- const DWARFDie &DIE,
- CompileUnit &Unit,
- CompileUnit::DIEInfo &MyInfo,
- unsigned Flags) {
+unsigned DwarfLinkerForBinary::shouldKeepVariableDIE(
+ RelocationManager &RelocMgr, const DWARFDie &DIE, CompileUnit &Unit,
+ CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
// Global variables with constant value can always be kept.
@@ -675,7 +650,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;
@@ -692,7 +668,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
/// Check if a function describing DIE should be kept.
/// \returns updated TraversalFlags.
-unsigned DwarfLinker::shouldKeepSubprogramDIE(
+unsigned DwarfLinkerForBinary::shouldKeepSubprogramDIE(
RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE,
const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
@@ -713,7 +689,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) {
@@ -748,19 +724,17 @@ 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;
}
/// Check if a DIE should be kept.
/// \returns updated TraversalFlags.
-unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
- RangesTy &Ranges, const DWARFDie &DIE,
- const DebugMapObject &DMO,
- CompileUnit &Unit,
- CompileUnit::DIEInfo &MyInfo,
- unsigned Flags) {
+unsigned DwarfLinkerForBinary::shouldKeepDIE(
+ RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE,
+ const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
+ unsigned Flags) {
switch (DIE.getTag()) {
case dwarf::DW_TAG_constant:
case dwarf::DW_TAG_variable:
@@ -885,11 +859,11 @@ static void lookForChildDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
// the parent chain). There are however a set of DIE types for which we want
// to ignore that directive and still walk their children.
if (dieNeedsChildrenToBeMeaningful(Die.getTag()))
- Flags &= ~DwarfLinker::TF_ParentWalk;
+ Flags &= ~DwarfLinkerForBinary::TF_ParentWalk;
// We're finished if this DIE has no children or we're walking the parent
// chain.
- if (!Die.hasChildren() || (Flags & DwarfLinker::TF_ParentWalk))
+ if (!Die.hasChildren() || (Flags & DwarfLinkerForBinary::TF_ParentWalk))
return;
// Add children in reverse order to the worklist to effectively process them
@@ -908,12 +882,12 @@ static void lookForChildDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
/// Look at DIEs referenced by the given DIE and decide whether they should be
/// kept. All DIEs referenced though attributes should be kept.
static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
- unsigned Flags, DwarfLinker &Linker,
+ unsigned Flags, DwarfLinkerForBinary &Linker,
const UnitListTy &Units,
const DebugMapObject &DMO,
SmallVectorImpl<WorklistItem> &Worklist) {
- bool UseOdr = (Flags & DwarfLinker::TF_DependencyWalk)
- ? (Flags & DwarfLinker::TF_ODR)
+ bool UseOdr = (Flags & DwarfLinkerForBinary::TF_DependencyWalk)
+ ? (Flags & DwarfLinkerForBinary::TF_ODR)
: CU.hasODR();
DWARFUnit &Unit = CU.getOrigUnit();
DWARFDataExtractor Data = Unit.getDebugInfoExtractor();
@@ -962,7 +936,7 @@ static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
}
}
- unsigned ODRFlag = UseOdr ? DwarfLinker::TF_ODR : 0;
+ unsigned ODRFlag = UseOdr ? DwarfLinkerForBinary::TF_ODR : 0;
// Add referenced DIEs in reverse order to the worklist to effectively
// process them in order.
@@ -974,8 +948,9 @@ static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
&Info);
Worklist.emplace_back(P.first, P.second,
- DwarfLinker::TF_Keep |
- DwarfLinker::TF_DependencyWalk | ODRFlag);
+ DwarfLinkerForBinary::TF_Keep |
+ DwarfLinkerForBinary::TF_DependencyWalk |
+ ODRFlag);
}
}
@@ -1018,11 +993,12 @@ static void lookForParentDIEsToKeep(unsigned AncestorIdx, CompileUnit &CU,
/// UpdateRefIncompleteness).
///
/// The return value indicates whether the DIE is incomplete.
-void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
- RangesTy &Ranges, const UnitListTy &Units,
- const DWARFDie &Die,
- const DebugMapObject &DMO, CompileUnit &Cu,
- unsigned Flags) {
+void DwarfLinkerForBinary::lookForDIEsToKeep(RelocationManager &RelocMgr,
+ RangesTy &Ranges,
+ const UnitListTy &Units,
+ const DWARFDie &Die,
+ const DebugMapObject &DMO,
+ CompileUnit &Cu, unsigned Flags) {
// LIFO work list.
SmallVector<WorklistItem, 4> Worklist;
Worklist.emplace_back(Die, Cu, Flags);
@@ -1113,7 +1089,7 @@ void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
/// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to
/// the instances hold by the DIEs. When we encounter an abbreviation
/// that we don't know, we create a permanent copy of it.
-void DwarfLinker::AssignAbbrev(DIEAbbrev &Abbrev) {
+void DwarfLinkerForBinary::assignAbbrev(DIEAbbrev &Abbrev) {
// Check the set for priors.
FoldingSetNodeID ID;
Abbrev.Profile(ID);
@@ -1137,7 +1113,7 @@ void DwarfLinker::AssignAbbrev(DIEAbbrev &Abbrev) {
}
}
-unsigned DwarfLinker::DIECloner::cloneStringAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneStringAttribute(
DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
const DWARFUnit &U, OffsetsStringPool &StringPool, AttributesInfo &Info) {
// Switch everything to out of line strings.
@@ -1157,7 +1133,7 @@ unsigned DwarfLinker::DIECloner::cloneStringAttribute(
return 4;
}
-unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneDieReferenceAttribute(
DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
unsigned AttrSize, const DWARFFormValue &Val, const DebugMapObject &DMO,
CompileUnit &Unit) {
@@ -1228,7 +1204,7 @@ unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute(
return AttrSize;
}
-void DwarfLinker::DIECloner::cloneExpression(
+void DwarfLinkerForBinary::DIECloner::cloneExpression(
DataExtractor &Data, DWARFExpression Expression, const DebugMapObject &DMO,
CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) {
using Encoding = DWARFExpression::Operation::Encoding;
@@ -1288,7 +1264,7 @@ void DwarfLinker::DIECloner::cloneExpression(
}
}
-unsigned DwarfLinker::DIECloner::cloneBlockAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneBlockAttribute(
DIE &Die, const DebugMapObject &DMO, CompileUnit &Unit,
AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize,
bool IsLittleEndian) {
@@ -1346,7 +1322,7 @@ unsigned DwarfLinker::DIECloner::cloneBlockAttribute(
return AttrSize;
}
-unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneAddressAttribute(
DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
const CompileUnit &Unit, AttributesInfo &Info) {
uint64_t Addr = *Val.getAsAddress();
@@ -1394,7 +1370,7 @@ unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
return Unit.getOrigUnit().getAddressByteSize();
}
-unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneScalarAttribute(
DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO,
CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
unsigned AttrSize, AttributesInfo &Info) {
@@ -1451,7 +1427,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
// location list.
// FIXME: use DWARFAttribute::mayHaveLocationDescription().
else if (AttrSpec.Attr == dwarf::DW_AT_location ||
- AttrSpec.Attr == dwarf::DW_AT_frame_base)
+ AttrSpec.Attr == dwarf::DW_AT_frame_base)
Unit.noteLocationAttribute(Patch, Info.PCOffset);
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
Info.IsDeclaration = true;
@@ -1462,7 +1438,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
/// Clone \p InputDIE's attribute described by \p AttrSpec with
/// value \p Val, and add it to \p Die.
/// \returns the size of the cloned attribute.
-unsigned DwarfLinker::DIECloner::cloneAttribute(
+unsigned DwarfLinkerForBinary::DIECloner::cloneAttribute(
DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO,
CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val,
const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info,
@@ -1517,7 +1493,7 @@ unsigned DwarfLinker::DIECloner::cloneAttribute(
/// monotonic \p BaseOffset values.
///
/// \returns whether any reloc has been applied.
-bool DwarfLinker::RelocationManager::applyValidRelocs(
+bool DwarfLinkerForBinary::RelocationManager::applyValidRelocs(
MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
assert((NextValidReloc == 0 ||
BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) &&
@@ -1558,11 +1534,9 @@ static bool isObjCSelector(StringRef Name) {
(Name[1] == '[');
}
-void DwarfLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
- const DIE *Die,
- DwarfStringPoolEntryRef Name,
- OffsetsStringPool &StringPool,
- bool SkipPubSection) {
+void DwarfLinkerForBinary::DIECloner::addObjCAccelerator(
+ CompileUnit &Unit, const DIE *Die, DwarfStringPoolEntryRef Name,
+ OffsetsStringPool &StringPool, bool SkipPubSection) {
assert(isObjCSelector(Name.getString()) && "not an objc selector");
// Objective C method or class function.
// "- [Class(Category) selector :withArg ...]"
@@ -1624,7 +1598,7 @@ shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
}
}
-DIE *DwarfLinker::DIECloner::cloneDIE(
+DIE *DwarfLinkerForBinary::DIECloner::cloneDIE(
const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &Unit,
OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset,
unsigned Flags, bool IsLittleEndian, DIE *Die) {
@@ -1675,7 +1649,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
@@ -1793,7 +1768,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
if (HasChildren)
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
// Assign a permanent abbrev number
- Linker.AssignAbbrev(NewAbbrev);
+ Linker.assignAbbrev(NewAbbrev);
Die->setAbbrevNumber(NewAbbrev.getNumber());
// Add the size of the abbreviation number to the output offset.
@@ -1824,9 +1799,9 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
/// Patch the input object file relevant debug_ranges entries
/// and emit them in the output file. Update the relevant attributes
/// to point at the new entries.
-void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
- DWARFContext &OrigDwarf,
- const DebugMapObject &DMO) const {
+void DwarfLinkerForBinary::patchRangesForUnit(const CompileUnit &Unit,
+ DWARFContext &OrigDwarf,
+ const DebugMapObject &DMO) const {
DWARFDebugRangeList RangeList;
const auto &FunctionRanges = Unit.getFunctionRanges();
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
@@ -1879,7 +1854,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
/// FIXME: this could actually be done right in patchRangesForUnit,
/// but for the sake of initial bit-for-bit compatibility with legacy
/// dsymutil, we have to do it in a delayed pass.
-void DwarfLinker::generateUnitRanges(CompileUnit &Unit) const {
+void DwarfLinkerForBinary::generateUnitRanges(CompileUnit &Unit) const {
auto Attr = Unit.getUnitRangesAttribute();
if (Attr)
Attr->set(Streamer->getRangesSectionSize());
@@ -1931,10 +1906,10 @@ static void patchStmtList(DIE &Die, DIEInteger Offset) {
/// Extract the line table for \p Unit from \p OrigDwarf, and
/// recreate a relocated version of these for the address ranges that
/// are present in the binary.
-void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
- DWARFContext &OrigDwarf,
- RangesTy &Ranges,
- const DebugMapObject &DMO) {
+void DwarfLinkerForBinary::patchLineTableForUnit(CompileUnit &Unit,
+ DWARFContext &OrigDwarf,
+ RangesTy &Ranges,
+ const DebugMapObject &DMO) {
DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
if (!StmtList)
@@ -2071,7 +2046,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
}
}
-void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
+void DwarfLinkerForBinary::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
switch (Options.TheAccelTableKind) {
case AccelTableKind::Apple:
emitAppleAcceleratorEntriesForUnit(Unit);
@@ -2085,7 +2060,8 @@ void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
}
}
-void DwarfLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) {
+void DwarfLinkerForBinary::emitAppleAcceleratorEntriesForUnit(
+ CompileUnit &Unit) {
// Add namespaces.
for (const auto &Namespace : Unit.getNamespaces())
AppleNamespaces.addName(Namespace.Name,
@@ -2114,7 +2090,8 @@ void DwarfLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) {
AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset());
}
-void DwarfLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) {
+void DwarfLinkerForBinary::emitDwarfAcceleratorEntriesForUnit(
+ CompileUnit &Unit) {
for (const auto &Namespace : Unit.getNamespaces())
DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
Namespace.Die->getTag(), Unit.getUniqueID());
@@ -2132,10 +2109,10 @@ void DwarfLinker::emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit) {
/// This is actually pretty easy as the data of the CIEs and FDEs can
/// be considered as black boxes and moved as is. The only thing to do
/// is to patch the addresses in the headers.
-void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
- RangesTy &Ranges,
- DWARFContext &OrigDwarf,
- unsigned AddrSize) {
+void DwarfLinkerForBinary::patchFrameInfoForObject(const DebugMapObject &DMO,
+ RangesTy &Ranges,
+ DWARFContext &OrigDwarf,
+ unsigned AddrSize) {
StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
if (FrameData.empty())
return;
@@ -2212,25 +2189,24 @@ void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
}
}
-void DwarfLinker::DIECloner::copyAbbrev(
- const DWARFAbbreviationDeclaration &Abbrev, bool hasODR) {
+void DwarfLinkerForBinary::DIECloner::copyAbbrev(
+ const DWARFAbbreviationDeclaration &Abbrev, bool HasODR) {
DIEAbbrev Copy(dwarf::Tag(Abbrev.getTag()),
dwarf::Form(Abbrev.hasChildren()));
for (const auto &Attr : Abbrev.attributes()) {
uint16_t Form = Attr.Form;
- if (hasODR && isODRAttribute(Attr.Attr))
+ if (HasODR && isODRAttribute(Attr.Attr))
Form = dwarf::DW_FORM_ref_addr;
Copy.AddAttribute(dwarf::Attribute(Attr.Attr), dwarf::Form(Form));
}
- Linker.AssignAbbrev(Copy);
+ Linker.assignAbbrev(Copy);
}
-uint32_t
-DwarfLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
- const DebugMapObject &DMO,
- int ChildRecurseDepth) {
+uint32_t DwarfLinkerForBinary::DIECloner::hashFullyQualifiedName(
+ DWARFDie DIE, CompileUnit &U, const DebugMapObject &DMO,
+ int ChildRecurseDepth) {
const char *Name = nullptr;
DWARFUnit *OrigUnit = &U.getOrigUnit();
CompileUnit *CU = &U;
@@ -2281,7 +2257,7 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) {
return 0;
}
-bool DwarfLinker::registerModuleReference(
+bool DwarfLinkerForBinary::registerModuleReference(
DWARFDie CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap,
const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool,
UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
@@ -2339,7 +2315,8 @@ bool DwarfLinker::registerModuleReference(
}
ErrorOr<const object::ObjectFile &>
-DwarfLinker::loadObject(const DebugMapObject &Obj, const DebugMap &Map) {
+DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
+ const DebugMap &Map) {
auto ObjectEntry =
BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
if (!ObjectEntry) {
@@ -2360,7 +2337,7 @@ DwarfLinker::loadObject(const DebugMapObject &Obj, const DebugMap &Map) {
return *Object;
}
-Error DwarfLinker::loadClangModule(
+Error DwarfLinkerForBinary::loadClangModule(
DWARFDie CUDie, StringRef Filename, StringRef ModuleName, uint64_t DwoId,
DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges,
OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool,
@@ -2417,7 +2394,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());
@@ -2454,7 +2431,7 @@ Error DwarfLinker::loadClangModule(
// Add this module.
Unit = std::make_unique<CompileUnit>(*CU, UnitID++, !Options.NoODR,
- ModuleName);
+ ModuleName);
Unit->setHasInterestingContent();
analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(),
UniquingStringPool, ODRContexts, ModulesEndOffset,
@@ -2481,7 +2458,7 @@ Error DwarfLinker::loadClangModule(
return Error::success();
}
-void DwarfLinker::DIECloner::cloneAllCompileUnits(
+void DwarfLinkerForBinary::DIECloner::cloneAllCompileUnits(
DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges,
OffsetsStringPool &StringPool, bool IsLittleEndian) {
if (!Linker.Streamer)
@@ -2550,7 +2527,7 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(
}
}
-void DwarfLinker::updateAccelKind(DWARFContext &Dwarf) {
+void DwarfLinkerForBinary::updateAccelKind(DWARFContext &Dwarf) {
if (Options.TheAccelTableKind != AccelTableKind::Default)
return;
@@ -2564,15 +2541,14 @@ void DwarfLinker::updateAccelKind(DWARFContext &Dwarf) {
AtLeastOneAppleAccelTable = true;
}
- if (!AtLeastOneDwarfAccelTable &&
- !DwarfObj.getNamesSection().Data.empty()) {
+ if (!AtLeastOneDwarfAccelTable && !DwarfObj.getNamesSection().Data.empty()) {
AtLeastOneDwarfAccelTable = true;
}
}
-bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO,
- const DebugMap &Map,
- OffsetsStringPool &StringPool) {
+bool DwarfLinkerForBinary::emitPaperTrailWarnings(
+ const DebugMapObject &DMO, const DebugMap &Map,
+ OffsetsStringPool &StringPool) {
if (DMO.getWarnings().empty() || !DMO.empty())
return false;
@@ -2606,13 +2582,13 @@ bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO,
DMO.getWarnings().size() * (4 + 1 + 4) +
1 /* End of children */;
DIEAbbrev Abbrev = CUDie->generateAbbrev();
- AssignAbbrev(Abbrev);
+ assignAbbrev(Abbrev);
CUDie->setAbbrevNumber(Abbrev.getNumber());
Size += getULEB128Size(Abbrev.getNumber());
// Abbreviation ordering needed for classic compatibility.
for (auto &Child : CUDie->children()) {
Abbrev = Child.generateAbbrev();
- AssignAbbrev(Abbrev);
+ assignAbbrev(Abbrev);
Child.setAbbrevNumber(Abbrev.getNumber());
Size += getULEB128Size(Abbrev.getNumber());
}
@@ -2657,17 +2633,15 @@ static Error copySwiftInterfaces(
// copy_file attempts an APFS clone first, so this should be cheap.
if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
- warn(Twine("cannot copy parseable Swift interface ") +
- InterfaceFile + ": " +
- toString(errorCodeToError(EC)));
+ warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
+ ": " + toString(errorCodeToError(EC)));
Path.resize(BaseLength);
}
return Error::success();
}
static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
- StringRef ArchName,
- const remarks::RemarkLinker &RL) {
+ StringRef ArchName, const remarks::RemarkLinker &RL) {
// Make sure we don't create the directories and the file if there is nothing
// to serialize.
if (RL.empty())
@@ -2701,7 +2675,7 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
return Error::success();
}
-bool DwarfLinker::link(const DebugMap &Map) {
+bool DwarfLinkerForBinary::link(const DebugMap &Map) {
if (!createStreamer(Map.getTriple(), OutFile))
return false;
@@ -2798,8 +2772,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";
@@ -2916,7 +2889,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);
@@ -2925,10 +2898,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());
@@ -3074,7 +3046,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
const DebugMap &DM, LinkOptions Options) {
- DwarfLinker Linker(OutFile, BinHolder, std::move(Options));
+ DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
return Linker.link(DM);
}
diff --git a/llvm/tools/dsymutil/DwarfLinker.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index b8d8e9d02e3..133e28e7fea 100644
--- a/llvm/tools/dsymutil/DwarfLinker.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -1,4 +1,4 @@
-//===- tools/dsymutil/DwarfLinker.h - Dwarf debug info linker ---*- C++ -*-===//
+//===- tools/dsymutil/DwarfLinkerForBinary.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.
@@ -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/DWARFLinker/DWARFLinker.h"
+#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
+#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.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.
@@ -53,10 +37,10 @@ using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
/// a function, the location for a variable). These relocations are
/// called ValidRelocs in the DwarfLinker and are gathered as a very
/// first step when we start processing a DebugMapObject.
-class DwarfLinker {
+class DwarfLinkerForBinary {
public:
- DwarfLinker(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- LinkOptions Options)
+ DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
+ LinkOptions Options)
: OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
/// Link the contents of the DebugMap.
@@ -74,6 +58,7 @@ public:
TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
TF_SkipPC = 1 << 5, ///< Skip all location attributes.
};
+
private:
/// Remembers the oldest and newest DWARF version we've seen in a unit.
void updateDwarfVersion(unsigned Version) {
@@ -89,7 +74,7 @@ private:
OffsetsStringPool &StringPool);
/// Keeps track of relocations.
- class RelocationManager {
+ class RelocationManager : public AddressesMap {
struct ValidReloc {
uint64_t Offset;
uint32_t Size;
@@ -105,7 +90,7 @@ private:
}
};
- const DwarfLinker &Linker;
+ const DwarfLinkerForBinary &Linker;
/// The valid relocations for the current DebugMapObject.
/// This vector is sorted by relocation offset.
@@ -117,13 +102,48 @@ private:
/// cheap lookup during the root DIE selection and during DIE cloning.
unsigned NextValidReloc = 0;
+ RangesTy AddressRanges;
+
public:
- RelocationManager(DwarfLinker &Linker) : Linker(Linker) {}
+ RelocationManager(DwarfLinkerForBinary &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 differences:
+ //
+ // 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 +161,44 @@ private:
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 {
+ DwarfLinkerForBinary &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) {
+ LinkContext(const DebugMap &Map, DwarfLinkerForBinary &Linker,
+ DebugMapObject &DMO)
+ : 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 @@ private:
DwarfContext.reset(nullptr);
CompileUnits.clear();
Ranges.clear();
+ RelocMgr->clear();
}
};
@@ -224,7 +257,6 @@ private:
unsigned &UnitID, bool IsLittleEndian,
unsigned Indent = 0, bool Quiet = false);
-
/// Mark the passed DIE as well as all the ones it depends on as kept.
void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
const UnitListTy &Units, const DWARFDie &DIE,
@@ -258,7 +290,7 @@ private:
/// @{
class DIECloner {
- DwarfLinker &Linker;
+ DwarfLinkerForBinary &Linker;
RelocationManager &RelocMgr;
/// Allocator used for all the DIEValue objects.
@@ -268,7 +300,7 @@ private:
LinkOptions Options;
public:
- DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr,
+ DIECloner(DwarfLinkerForBinary &Linker, RelocationManager &RelocMgr,
BumpPtrAllocator &DIEAlloc,
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
LinkOptions &Options)
@@ -409,7 +441,7 @@ private:
};
/// Assign an abbreviation number to \p Abbrev
- void AssignAbbrev(DIEAbbrev &Abbrev);
+ void assignAbbrev(DIEAbbrev &Abbrev);
/// Compute and emit debug_ranges section for \p Unit, and
/// patch the attributes referencing it.
diff --git a/llvm/tools/dsymutil/DwarfStreamer.cpp b/llvm/tools/dsymutil/DwarfStreamer.cpp
index 8747aee458f..54cec3c4f68 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.cpp
+++ b/llvm/tools/dsymutil/DwarfStreamer.cpp
@@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//
#include "DwarfStreamer.h"
-#include "CompileUnit.h"
#include "LinkUtils.h"
#include "MachOUtils.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
diff --git a/llvm/tools/dsymutil/DwarfStreamer.h b/llvm/tools/dsymutil/DwarfStreamer.h
index baf215ac131..8479970a4f7 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.h
+++ b/llvm/tools/dsymutil/DwarfStreamer.h
@@ -9,12 +9,12 @@
#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"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h"
+#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/MC/MCAsmBackend.h"
diff --git a/llvm/tools/dsymutil/LLVMBuild.txt b/llvm/tools/dsymutil/LLVMBuild.txt
index 61bc07b81d3..819d3c4b30d 100644
--- a/llvm/tools/dsymutil/LLVMBuild.txt
+++ b/llvm/tools/dsymutil/LLVMBuild.txt
@@ -18,4 +18,4 @@
type = Tool
name = dsymutil
parent = Tools
-required_libraries = AsmPrinter DebugInfoDWARF MC Object CodeGen Support all-targets
+required_libraries = AsmPrinter DebugInfoDWARF DWARFLinker MC Object CodeGen Support all-targets
OpenPOWER on IntegriCloud