From 076ea9fc780fbe5d1148f44c2ef8939e9982025b Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Fri, 20 Dec 2019 19:23:31 +0300 Subject: [PATCH] [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 --- .../llvm/CodeGen/NonRelocatableStringpool.h | 2 +- include/llvm/DWARFLinker/DWARFLinker.h | 86 ++++++ .../llvm/DWARFLinker/DWARFLinkerCompileUnit.h | 13 +- .../llvm/DWARFLinker/DWARFLinkerDeclContext.h | 12 +- lib/CMakeLists.txt | 1 + lib/CodeGen/NonRelocatableStringpool.cpp | 2 +- lib/DWARFLinker/CMakeLists.txt | 6 + lib/DWARFLinker/DWARFLinker.cpp | 15 ++ .../DWARFLinker/DWARFLinkerCompileUnit.cpp | 8 +- .../DWARFLinker/DWARFLinkerDeclContext.cpp | 7 +- lib/DWARFLinker/LLVMBuild.txt | 21 ++ lib/LLVMBuild.txt | 1 + tools/dsymutil/CMakeLists.txt | 5 +- ...arfLinker.cpp => DwarfLinkerForBinary.cpp} | 254 ++++++++---------- .../{DwarfLinker.h => DwarfLinkerForBinary.h} | 118 +++++--- tools/dsymutil/DwarfStreamer.cpp | 2 +- tools/dsymutil/DwarfStreamer.h | 2 +- tools/dsymutil/LLVMBuild.txt | 2 +- 18 files changed, 342 insertions(+), 215 deletions(-) create mode 100644 include/llvm/DWARFLinker/DWARFLinker.h rename tools/dsymutil/CompileUnit.h => include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h (97%) rename tools/dsymutil/DeclContext.h => include/llvm/DWARFLinker/DWARFLinkerDeclContext.h (95%) create mode 100644 lib/DWARFLinker/CMakeLists.txt create mode 100644 lib/DWARFLinker/DWARFLinker.cpp rename tools/dsymutil/CompileUnit.cpp => lib/DWARFLinker/DWARFLinkerCompileUnit.cpp (96%) rename tools/dsymutil/DeclContext.cpp => lib/DWARFLinker/DWARFLinkerDeclContext.cpp (98%) create mode 100644 lib/DWARFLinker/LLVMBuild.txt rename tools/dsymutil/{DwarfLinker.cpp => DwarfLinkerForBinary.cpp} (93%) rename tools/dsymutil/{DwarfLinker.h => DwarfLinkerForBinary.h} (85%) diff --git a/include/llvm/CodeGen/NonRelocatableStringpool.h b/include/llvm/CodeGen/NonRelocatableStringpool.h index f7d082e2a2b..56db30ff7d6 100644 --- a/include/llvm/CodeGen/NonRelocatableStringpool.h +++ b/include/llvm/CodeGen/NonRelocatableStringpool.h @@ -1,4 +1,4 @@ -//===- llvm/CodeGen/NonRelocatableStringpool.h - A simple stringpool -----===// +//===- NonRelocatableStringpool.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. diff --git a/include/llvm/DWARFLinker/DWARFLinker.h b/include/llvm/DWARFLinker/DWARFLinker.h new file mode 100644 index 00000000000..218c9641bfb --- /dev/null +++ b/include/llvm/DWARFLinker/DWARFLinker.h @@ -0,0 +1,86 @@ +//===- DWARFLinker.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_DWARFLINKER_DWARFLINKER_H +#define LLVM_DWARFLINKER_DWARFLINKER_H + +#include "llvm/CodeGen/NonRelocatableStringpool.h" +#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include + +namespace llvm { + +enum class DwarfLinkerClient { 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; + +/// 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 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_DWARFLINKER_DWARFLINKER_H diff --git a/tools/dsymutil/CompileUnit.h b/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h similarity index 97% rename from tools/dsymutil/CompileUnit.h rename to include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h index e0f5d3bc65b..7873a16fea5 100644 --- a/tools/dsymutil/CompileUnit.h +++ b/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h @@ -1,4 +1,4 @@ -//===- tools/dsymutil/CompileUnit.h - Dwarf debug info linker ---*- C++ -*-===// +//===- DWARFLinkerCompileUnit.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_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H +#define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_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 @@ private: std::string ClangModuleName; }; -} // end namespace dsymutil } // end namespace llvm -#endif // LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H +#endif // LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H diff --git a/tools/dsymutil/DeclContext.h b/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h similarity index 95% rename from tools/dsymutil/DeclContext.h rename to include/llvm/DWARFLinker/DWARFLinkerDeclContext.h index 36ef5094408..db40254bf60 100644 --- a/tools/dsymutil/DeclContext.h +++ b/include/llvm/DWARFLinker/DWARFLinkerDeclContext.h @@ -1,4 +1,4 @@ -//===- tools/dsymutil/DeclContext.h - Dwarf debug info linker ---*- C++ -*-===// +//===- DWARFLinkerDeclContext.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_DWARFLINKER_DWARFLINKERDECLCONTEXT_H +#define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_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/DWARFLinker/DWARFLinkerCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/Support/Path.h" namespace llvm { -namespace dsymutil { struct DeclMapInfo; @@ -165,7 +164,6 @@ struct DeclMapInfo : private DenseMapInfo { } }; -} // end namespace dsymutil } // end namespace llvm -#endif // LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H +#endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f7e08a68e67..8f8d417124c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(CodeGen) add_subdirectory(BinaryFormat) add_subdirectory(Bitcode) add_subdirectory(Bitstream) +add_subdirectory(DWARFLinker) add_subdirectory(Frontend) add_subdirectory(Transforms) add_subdirectory(Linker) diff --git a/lib/CodeGen/NonRelocatableStringpool.cpp b/lib/CodeGen/NonRelocatableStringpool.cpp index d28399f239c..9ed3471c0fc 100644 --- a/lib/CodeGen/NonRelocatableStringpool.cpp +++ b/lib/CodeGen/NonRelocatableStringpool.cpp @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/NonRelocatableStringpool.cpp - A simple stringpool --===// +//===-- NonRelocatableStringpool.cpp --------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/DWARFLinker/CMakeLists.txt b/lib/DWARFLinker/CMakeLists.txt new file mode 100644 index 00000000000..09610f006fd --- /dev/null +++ b/lib/DWARFLinker/CMakeLists.txt @@ -0,0 +1,6 @@ +add_llvm_component_library(LLVMDWARFLinker + DWARFLinkerCompileUnit.cpp + DWARFLinkerDeclContext.cpp + DWARFLinker.cpp + + ) diff --git a/lib/DWARFLinker/DWARFLinker.cpp b/lib/DWARFLinker/DWARFLinker.cpp new file mode 100644 index 00000000000..e26148a1096 --- /dev/null +++ b/lib/DWARFLinker/DWARFLinker.cpp @@ -0,0 +1,15 @@ +//=== DWARFLinker.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/DWARFLinker/DWARFLinker.h" + +namespace llvm { + +AddressesMap::~AddressesMap() {} + +} // namespace llvm diff --git a/tools/dsymutil/CompileUnit.cpp b/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp similarity index 96% rename from tools/dsymutil/CompileUnit.cpp rename to lib/DWARFLinker/DWARFLinkerCompileUnit.cpp index 036c61a6b92..e4de01676dc 100644 --- a/tools/dsymutil/CompileUnit.cpp +++ b/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp @@ -1,4 +1,4 @@ -//===- tools/dsymutil/CompileUnit.h - Dwarf compile unit ------------------===// +//===- DWARFLinkerCompileUnit.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/DWARFLinker/DWARFLinkerCompileUnit.h" +#include "llvm/DWARFLinker/DWARFLinkerDeclContext.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/tools/dsymutil/DeclContext.cpp b/lib/DWARFLinker/DWARFLinkerDeclContext.cpp similarity index 98% rename from tools/dsymutil/DeclContext.cpp rename to lib/DWARFLinker/DWARFLinkerDeclContext.cpp index 1c33b672c26..077fd449424 100644 --- a/tools/dsymutil/DeclContext.cpp +++ b/lib/DWARFLinker/DWARFLinkerDeclContext.cpp @@ -1,4 +1,4 @@ -//===- tools/dsymutil/DeclContext.cpp - Declaration context ---------------===// +//===- DWARFLinkerDeclContext.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/DWARFLinker/DWARFLinkerDeclContext.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 DeclContextTree::getChildDeclContext( return PointerIntPair(*ContextIter); } -} // namespace dsymutil + } // namespace llvm diff --git a/lib/DWARFLinker/LLVMBuild.txt b/lib/DWARFLinker/LLVMBuild.txt new file mode 100644 index 00000000000..b32ea3d9e74 --- /dev/null +++ b/lib/DWARFLinker/LLVMBuild.txt @@ -0,0 +1,21 @@ +;===- ./lib/DWARFLinker/LLVMBuild.txt ---------------*- Conf -*--===; +; +; 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 +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = DWARFLinker +parent = Libraries +required_libraries = DebugInfoDWARF AsmPrinter CodeGen MC Object Support diff --git a/lib/LLVMBuild.txt b/lib/LLVMBuild.txt index 3f5383d9b1f..1ae59791cd6 100644 --- a/lib/LLVMBuild.txt +++ b/lib/LLVMBuild.txt @@ -23,6 +23,7 @@ subdirectories = CodeGen DebugInfo Demangle + DWARFLinker ExecutionEngine Frontend FuzzMutate diff --git a/tools/dsymutil/CMakeLists.txt b/tools/dsymutil/CMakeLists.txt index b8466baa634..fecd8a61ad0 100644 --- a/tools/dsymutil/CMakeLists.txt +++ b/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/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinkerForBinary.cpp similarity index 93% rename from tools/dsymutil/DwarfLinker.cpp rename to tools/dsymutil/DwarfLinkerForBinary.cpp index 53f6b2899b0..b42fc1a1d50 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/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 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 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 &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 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 &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 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 -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(*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/tools/dsymutil/DwarfLinker.h b/tools/dsymutil/DwarfLinkerForBinary.h similarity index 85% rename from tools/dsymutil/DwarfLinker.h rename to tools/dsymutil/DwarfLinkerForBinary.h index b8d8e9d02e3..133e28e7fea 100644 --- a/tools/dsymutil/DwarfLinker.h +++ b/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; using UnitListTy = std::vector>; /// The core of the Dwarf linking logic. @@ -53,10 +37,10 @@ using UnitListTy = std::vector>; /// 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); - bool hasValidRelocs() const { return !ValidRelocs.empty(); } + // 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(); } - /// Reset the NextValidReloc counter. - void resetValidRelocs() { NextValidReloc = 0; } + virtual bool areRelocationsResolved() const override { return true; } + + 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 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 RelocMgr; std::unique_ptr 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> &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/tools/dsymutil/DwarfStreamer.cpp b/tools/dsymutil/DwarfStreamer.cpp index 8747aee458f..54cec3c4f68 100644 --- a/tools/dsymutil/DwarfStreamer.cpp +++ b/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/tools/dsymutil/DwarfStreamer.h b/tools/dsymutil/DwarfStreamer.h index baf215ac131..8479970a4f7 100644 --- a/tools/dsymutil/DwarfStreamer.h +++ b/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/tools/dsymutil/LLVMBuild.txt b/tools/dsymutil/LLVMBuild.txt index 61bc07b81d3..819d3c4b30d 100644 --- a/tools/dsymutil/LLVMBuild.txt +++ b/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