1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[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
This commit is contained in:
Alexey Lapshin 2019-12-20 19:23:31 +03:00
parent dbbd596280
commit 076ea9fc78
18 changed files with 342 additions and 215 deletions

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.

View File

@ -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 <map>
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<uint64_t, ObjFileAddressRange>;
/// AddressesMap represents information about valid addresses used
/// by debug information. Valid addresses are those which points to
/// live code sections. i.e. relocations for these addresses point
/// into sections which would be/are placed into resulting binary.
class AddressesMap {
public:
virtual ~AddressesMap();
/// Returns true if represented addresses are from linked file.
/// Returns false if represented addresses are from not-linked
/// object file.
virtual bool areRelocationsResolved() const = 0;
/// Checks that there are valid relocations against a .debug_info
/// section. Reset current relocation pointer if neccessary.
virtual bool hasValidRelocs(bool ResetRelocsPtr = true) = 0;
/// Checks that there is a relocation against .debug_info
/// table between \p StartOffset and \p NextOffset.
///
/// This function must be called with offsets in strictly ascending
/// order because it never looks back at relocations it already 'went past'.
/// \returns true and sets Info.InDebugMap if it is the case.
virtual bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
CompileUnit::DIEInfo &Info) = 0;
/// Apply the valid relocations to the buffer \p Data, taking into
/// account that Data is at \p BaseOffset in the debug_info section.
///
/// This function must be called with monotonic \p BaseOffset values.
///
/// \returns true whether any reloc has been applied.
virtual bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
bool IsLittleEndian) = 0;
/// Returns all valid functions address ranges(i.e., those ranges
/// which points to sections with code).
virtual RangesTy &getValidAddressRanges() = 0;
/// Erases all data.
virtual void clear() = 0;
};
} // end namespace llvm
#endif // LLVM_DWARFLINKER_DWARFLINKER_H

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -6,15 +6,15 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H #ifndef LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
#define LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H #define LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H
#include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/IntervalMap.h"
#include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/DIE.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm { namespace llvm {
namespace dsymutil {
class DeclContext; class DeclContext;
@ -46,7 +46,7 @@ struct PatchLocation {
}; };
/// Stores all information relating to a compile unit, be it in its original /// 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 { class CompileUnit {
public: public:
/// Information gathered about a DIE in the object file. /// Information gathered about a DIE in the object file.
@ -325,7 +325,6 @@ private:
std::string ClangModuleName; std::string ClangModuleName;
}; };
} // end namespace dsymutil
} // end namespace llvm } // end namespace llvm
#endif // LLVM_TOOLS_DSYMUTIL_COMPILEUNIT_H #endif // LLVM_DWARFLINKER_DWARFLINKERCOMPILEUNIT_H

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -6,20 +6,19 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H #ifndef LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
#define LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H #define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
#include "CompileUnit.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
namespace llvm { namespace llvm {
namespace dsymutil {
struct DeclMapInfo; struct DeclMapInfo;
@ -165,7 +164,6 @@ struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
} }
}; };
} // end namespace dsymutil
} // end namespace llvm } // end namespace llvm
#endif // LLVM_TOOLS_DSYMUTIL_DECLCONTEXT_H #endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H

View File

@ -8,6 +8,7 @@ add_subdirectory(CodeGen)
add_subdirectory(BinaryFormat) add_subdirectory(BinaryFormat)
add_subdirectory(Bitcode) add_subdirectory(Bitcode)
add_subdirectory(Bitstream) add_subdirectory(Bitstream)
add_subdirectory(DWARFLinker)
add_subdirectory(Frontend) add_subdirectory(Frontend)
add_subdirectory(Transforms) add_subdirectory(Transforms)
add_subdirectory(Linker) add_subdirectory(Linker)

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.

View File

@ -0,0 +1,6 @@
add_llvm_component_library(LLVMDWARFLinker
DWARFLinkerCompileUnit.cpp
DWARFLinkerDeclContext.cpp
DWARFLinker.cpp
)

View File

@ -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

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -6,11 +6,10 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "CompileUnit.h" #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "DeclContext.h" #include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
namespace llvm { namespace llvm {
namespace dsymutil {
/// Check if the DIE at \p Idx is in the scope of a function. /// Check if the DIE at \p Idx is in the scope of a function.
static bool inFunctionScope(CompileUnit &U, unsigned Idx) { static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
@ -142,5 +141,4 @@ void CompileUnit::addTypeAccelerator(const DIE *Die,
Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation); Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
} }
} // namespace dsymutil
} // namespace llvm } // namespace llvm

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // 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/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
namespace llvm { namespace llvm {
namespace dsymutil {
/// Set the last DIE/CU a context was seen in and, possibly invalidate the /// Set the last DIE/CU a context was seen in and, possibly invalidate the
/// context if it is ambiguous. /// context if it is ambiguous.
@ -206,5 +205,5 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
return PointerIntPair<DeclContext *, 1>(*ContextIter); return PointerIntPair<DeclContext *, 1>(*ContextIter);
} }
} // namespace dsymutil
} // namespace llvm } // namespace llvm

View File

@ -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

View File

@ -23,6 +23,7 @@ subdirectories =
CodeGen CodeGen
DebugInfo DebugInfo
Demangle Demangle
DWARFLinker
ExecutionEngine ExecutionEngine
Frontend Frontend
FuzzMutate FuzzMutate

View File

@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
AllTargetsInfos AllTargetsInfos
AsmPrinter AsmPrinter
DebugInfoDWARF DebugInfoDWARF
DWARFLinker
MC MC
Object Object
CodeGen CodeGen
@ -22,10 +23,8 @@ add_llvm_tool(dsymutil
dsymutil.cpp dsymutil.cpp
BinaryHolder.cpp BinaryHolder.cpp
CFBundle.cpp CFBundle.cpp
CompileUnit.cpp
DebugMap.cpp DebugMap.cpp
DeclContext.cpp DwarfLinkerForBinary.cpp
DwarfLinker.cpp
DwarfStreamer.cpp DwarfStreamer.cpp
MachODebugMapParser.cpp MachODebugMapParser.cpp
MachOUtils.cpp MachOUtils.cpp

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -6,10 +6,9 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "DwarfLinker.h" #include "DwarfLinkerForBinary.h"
#include "BinaryHolder.h" #include "BinaryHolder.h"
#include "DebugMap.h" #include "DebugMap.h"
#include "DeclContext.h"
#include "DwarfStreamer.h" #include "DwarfStreamer.h"
#include "MachOUtils.h" #include "MachOUtils.h"
#include "dsymutil.h" #include "dsymutil.h"
@ -37,6 +36,7 @@
#include "llvm/CodeGen/DIE.h" #include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/Config/config.h" #include "llvm/Config/config.h"
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.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. /// 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 /// The resulting DIE might be in another CompileUnit which is stored into \p
/// ReferencedCU. \returns null if resolving fails for any reason. /// 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 DebugMapObject &DMO,
const UnitListTy &Units, const UnitListTy &Units,
const DWARFFormValue &RefValue, const DWARFFormValue &RefValue,
@ -188,7 +188,8 @@ static bool isTypeTag(uint16_t Tag) {
return false; return false;
} }
static Error remarksErrorHandler(const DebugMapObject &DMO, DwarfLinker &Linker, static Error remarksErrorHandler(const DebugMapObject &DMO,
DwarfLinkerForBinary &Linker,
std::unique_ptr<FileError> FE) { std::unique_ptr<FileError> FE) {
bool IsArchive = DMO.getObjectFilename().endswith(")"); bool IsArchive = DMO.getObjectFilename().endswith(")");
// Don't report errors for missing remark files from static // 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)); return createFileError(FE->getFileName(), std::move(NewE));
} }
bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die, bool DwarfLinkerForBinary::DIECloner::getDIENames(const DWARFDie &Die,
AttributesInfo &Info, AttributesInfo &Info,
OffsetsStringPool &StringPool, OffsetsStringPool &StringPool,
bool StripTemplate) { bool StripTemplate) {
// This function will be called on DIEs having low_pcs and // This function will be called on DIEs having low_pcs and
// ranges. As getting the name might be more expansive, filter out // ranges. As getting the name might be more expansive, filter out
// blocks directly. // blocks directly.
@ -244,8 +245,9 @@ bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
/// Report a warning to the user, optionally including information about a /// Report a warning to the user, optionally including information about a
/// specific \p DIE related to the warning. /// specific \p DIE related to the warning.
void DwarfLinker::reportWarning(const Twine &Warning, const DebugMapObject &DMO, void DwarfLinkerForBinary::reportWarning(const Twine &Warning,
const DWARFDie *DIE) const { const DebugMapObject &DMO,
const DWARFDie *DIE) const {
StringRef Context = DMO.getObjectFilename(); StringRef Context = DMO.getObjectFilename();
warn(Warning, Context); warn(Warning, Context);
@ -260,8 +262,8 @@ void DwarfLinker::reportWarning(const Twine &Warning, const DebugMapObject &DMO,
DIE->dump(errs(), 6 /* Indent */, DumpOpts); DIE->dump(errs(), 6 /* Indent */, DumpOpts);
} }
bool DwarfLinker::createStreamer(const Triple &TheTriple, bool DwarfLinkerForBinary::createStreamer(const Triple &TheTriple,
raw_fd_ostream &OutFile) { raw_fd_ostream &OutFile) {
if (Options.NoOutput) if (Options.NoOutput)
return true; return true;
@ -397,34 +399,9 @@ static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) {
llvm_unreachable("Invalid Tag"); llvm_unreachable("Invalid Tag");
} }
void DwarfLinker::startDebugObject(LinkContext &Context) { void DwarfLinkerForBinary::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 DwarfLinker::endDebugObject(LinkContext &Context) { void DwarfLinkerForBinary::endDebugObject(LinkContext &Context) {
Context.Clear(); Context.Clear();
for (auto I = DIEBlocks.begin(), E = DIEBlocks.end(); I != E; ++I) 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 /// Iterate over the relocations of the given \p Section and
/// store the ones that correspond to debug map entries into the /// store the ones that correspond to debug map entries into the
/// ValidRelocs array. /// ValidRelocs array.
void DwarfLinker::RelocationManager::findValidRelocsMachO( void DwarfLinkerForBinary::RelocationManager::findValidRelocsMachO(
const object::SectionRef &Section, const object::MachOObjectFile &Obj, const object::SectionRef &Section, const object::MachOObjectFile &Obj,
const DebugMapObject &DMO) { const DebugMapObject &DMO) {
Expected<StringRef> ContentsOrErr = Section.getContents(); Expected<StringRef> ContentsOrErr = Section.getContents();
@ -534,7 +511,7 @@ void DwarfLinker::RelocationManager::findValidRelocsMachO(
/// Dispatch the valid relocation finding logic to the /// Dispatch the valid relocation finding logic to the
/// appropriate handler depending on the object file format. /// 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 object::SectionRef &Section, const object::ObjectFile &Obj,
const DebugMapObject &DMO) { const DebugMapObject &DMO) {
// Dispatch to the right handler depending on the file type. // 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 /// link by indicating which DIEs refer to symbols present in the
/// linked binary. /// linked binary.
/// \returns whether there are any valid relocations in the debug info. /// \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) { const object::ObjectFile &Obj, const DebugMapObject &DMO) {
// Find the debug_info section. // Find the debug_info section.
for (const object::SectionRef &Section : Obj.sections()) { 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 /// This function must be called with offsets in strictly ascending
/// order because it never looks back at relocations it already 'went past'. /// order because it never looks back at relocations it already 'went past'.
/// \returns true and sets Info.InDebugMap if it is the case. /// \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) { uint64_t StartOffset, uint64_t EndOffset, CompileUnit::DIEInfo &Info) {
assert(NextValidReloc == 0 || assert(NextValidReloc == 0 ||
StartOffset > ValidRelocs[NextValidReloc - 1].Offset); StartOffset > ValidRelocs[NextValidReloc - 1].Offset);
@ -645,11 +622,9 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
/// Check if a variable describing DIE should be kept. /// Check if a variable describing DIE should be kept.
/// \returns updated TraversalFlags. /// \returns updated TraversalFlags.
unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr, unsigned DwarfLinkerForBinary::shouldKeepVariableDIE(
const DWARFDie &DIE, RelocationManager &RelocMgr, const DWARFDie &DIE, CompileUnit &Unit,
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) {
CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
// Global variables with constant value can always be kept. // 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 // 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 // DIEInfo is filled. However, we don't want a static variable in a
// function to force us to keep the enclosing function. // function to force us to keep the enclosing function.
if (!RelocMgr.hasValidRelocation(LocationOffset, LocationEndOffset, MyInfo) || if (!RelocMgr.hasValidRelocationAt(LocationOffset, LocationEndOffset,
MyInfo) ||
(Flags & TF_InFunctionScope)) (Flags & TF_InFunctionScope))
return Flags; return Flags;
@ -692,7 +668,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
/// Check if a function describing DIE should be kept. /// Check if a function describing DIE should be kept.
/// \returns updated TraversalFlags. /// \returns updated TraversalFlags.
unsigned DwarfLinker::shouldKeepSubprogramDIE( unsigned DwarfLinkerForBinary::shouldKeepSubprogramDIE(
RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE, RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE,
const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags) { unsigned Flags) {
@ -713,7 +689,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc)); auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
assert(LowPc.hasValue() && "low_pc attribute is not an address."); assert(LowPc.hasValue() && "low_pc attribute is not an address.");
if (!LowPc || if (!LowPc ||
!RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) !RelocMgr.hasValidRelocationAt(LowPcOffset, LowPcEndOffset, MyInfo))
return Flags; return Flags;
if (Options.Verbose) { if (Options.Verbose) {
@ -748,19 +724,17 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
} }
// Replace the debug map range with a more accurate one. // 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); Unit.addFunctionRange(*LowPc, *HighPc, MyInfo.AddrAdjust);
return Flags; return Flags;
} }
/// Check if a DIE should be kept. /// Check if a DIE should be kept.
/// \returns updated TraversalFlags. /// \returns updated TraversalFlags.
unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr, unsigned DwarfLinkerForBinary::shouldKeepDIE(
RangesTy &Ranges, const DWARFDie &DIE, RelocationManager &RelocMgr, RangesTy &Ranges, const DWARFDie &DIE,
const DebugMapObject &DMO, const DebugMapObject &DMO, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
CompileUnit &Unit, unsigned Flags) {
CompileUnit::DIEInfo &MyInfo,
unsigned Flags) {
switch (DIE.getTag()) { switch (DIE.getTag()) {
case dwarf::DW_TAG_constant: case dwarf::DW_TAG_constant:
case dwarf::DW_TAG_variable: 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 // the parent chain). There are however a set of DIE types for which we want
// to ignore that directive and still walk their children. // to ignore that directive and still walk their children.
if (dieNeedsChildrenToBeMeaningful(Die.getTag())) 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 // We're finished if this DIE has no children or we're walking the parent
// chain. // chain.
if (!Die.hasChildren() || (Flags & DwarfLinker::TF_ParentWalk)) if (!Die.hasChildren() || (Flags & DwarfLinkerForBinary::TF_ParentWalk))
return; return;
// Add children in reverse order to the worklist to effectively process them // 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 /// Look at DIEs referenced by the given DIE and decide whether they should be
/// kept. All DIEs referenced though attributes should be kept. /// kept. All DIEs referenced though attributes should be kept.
static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU, static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
unsigned Flags, DwarfLinker &Linker, unsigned Flags, DwarfLinkerForBinary &Linker,
const UnitListTy &Units, const UnitListTy &Units,
const DebugMapObject &DMO, const DebugMapObject &DMO,
SmallVectorImpl<WorklistItem> &Worklist) { SmallVectorImpl<WorklistItem> &Worklist) {
bool UseOdr = (Flags & DwarfLinker::TF_DependencyWalk) bool UseOdr = (Flags & DwarfLinkerForBinary::TF_DependencyWalk)
? (Flags & DwarfLinker::TF_ODR) ? (Flags & DwarfLinkerForBinary::TF_ODR)
: CU.hasODR(); : CU.hasODR();
DWARFUnit &Unit = CU.getOrigUnit(); DWARFUnit &Unit = CU.getOrigUnit();
DWARFDataExtractor Data = Unit.getDebugInfoExtractor(); 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 // Add referenced DIEs in reverse order to the worklist to effectively
// process them in order. // process them in order.
@ -974,8 +948,9 @@ static void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness, Worklist.emplace_back(Die, CU, WorklistItemType::UpdateRefIncompleteness,
&Info); &Info);
Worklist.emplace_back(P.first, P.second, Worklist.emplace_back(P.first, P.second,
DwarfLinker::TF_Keep | DwarfLinkerForBinary::TF_Keep |
DwarfLinker::TF_DependencyWalk | ODRFlag); DwarfLinkerForBinary::TF_DependencyWalk |
ODRFlag);
} }
} }
@ -1018,11 +993,12 @@ static void lookForParentDIEsToKeep(unsigned AncestorIdx, CompileUnit &CU,
/// UpdateRefIncompleteness). /// UpdateRefIncompleteness).
/// ///
/// The return value indicates whether the DIE is incomplete. /// The return value indicates whether the DIE is incomplete.
void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr, void DwarfLinkerForBinary::lookForDIEsToKeep(RelocationManager &RelocMgr,
RangesTy &Ranges, const UnitListTy &Units, RangesTy &Ranges,
const DWARFDie &Die, const UnitListTy &Units,
const DebugMapObject &DMO, CompileUnit &Cu, const DWARFDie &Die,
unsigned Flags) { const DebugMapObject &DMO,
CompileUnit &Cu, unsigned Flags) {
// LIFO work list. // LIFO work list.
SmallVector<WorklistItem, 4> Worklist; SmallVector<WorklistItem, 4> Worklist;
Worklist.emplace_back(Die, Cu, Flags); 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 /// thus the FoldingSet we use to unique DIEAbbrevs cannot refer to
/// the instances hold by the DIEs. When we encounter an abbreviation /// the instances hold by the DIEs. When we encounter an abbreviation
/// that we don't know, we create a permanent copy of it. /// 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. // Check the set for priors.
FoldingSetNodeID ID; FoldingSetNodeID ID;
Abbrev.Profile(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, DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
const DWARFUnit &U, OffsetsStringPool &StringPool, AttributesInfo &Info) { const DWARFUnit &U, OffsetsStringPool &StringPool, AttributesInfo &Info) {
// Switch everything to out of line strings. // Switch everything to out of line strings.
@ -1157,7 +1133,7 @@ unsigned DwarfLinker::DIECloner::cloneStringAttribute(
return 4; return 4;
} }
unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute( unsigned DwarfLinkerForBinary::DIECloner::cloneDieReferenceAttribute(
DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
unsigned AttrSize, const DWARFFormValue &Val, const DebugMapObject &DMO, unsigned AttrSize, const DWARFFormValue &Val, const DebugMapObject &DMO,
CompileUnit &Unit) { CompileUnit &Unit) {
@ -1228,7 +1204,7 @@ unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute(
return AttrSize; return AttrSize;
} }
void DwarfLinker::DIECloner::cloneExpression( void DwarfLinkerForBinary::DIECloner::cloneExpression(
DataExtractor &Data, DWARFExpression Expression, const DebugMapObject &DMO, DataExtractor &Data, DWARFExpression Expression, const DebugMapObject &DMO,
CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) { CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) {
using Encoding = DWARFExpression::Operation::Encoding; 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, DIE &Die, const DebugMapObject &DMO, CompileUnit &Unit,
AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize,
bool IsLittleEndian) { bool IsLittleEndian) {
@ -1346,7 +1322,7 @@ unsigned DwarfLinker::DIECloner::cloneBlockAttribute(
return AttrSize; return AttrSize;
} }
unsigned DwarfLinker::DIECloner::cloneAddressAttribute( unsigned DwarfLinkerForBinary::DIECloner::cloneAddressAttribute(
DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val, DIE &Die, AttributeSpec AttrSpec, const DWARFFormValue &Val,
const CompileUnit &Unit, AttributesInfo &Info) { const CompileUnit &Unit, AttributesInfo &Info) {
uint64_t Addr = *Val.getAsAddress(); uint64_t Addr = *Val.getAsAddress();
@ -1394,7 +1370,7 @@ unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
return Unit.getOrigUnit().getAddressByteSize(); return Unit.getOrigUnit().getAddressByteSize();
} }
unsigned DwarfLinker::DIECloner::cloneScalarAttribute( unsigned DwarfLinkerForBinary::DIECloner::cloneScalarAttribute(
DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO,
CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
unsigned AttrSize, AttributesInfo &Info) { unsigned AttrSize, AttributesInfo &Info) {
@ -1451,7 +1427,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
// location list. // location list.
// FIXME: use DWARFAttribute::mayHaveLocationDescription(). // FIXME: use DWARFAttribute::mayHaveLocationDescription().
else if (AttrSpec.Attr == dwarf::DW_AT_location || 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); Unit.noteLocationAttribute(Patch, Info.PCOffset);
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value) else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
Info.IsDeclaration = true; Info.IsDeclaration = true;
@ -1462,7 +1438,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
/// Clone \p InputDIE's attribute described by \p AttrSpec with /// Clone \p InputDIE's attribute described by \p AttrSpec with
/// value \p Val, and add it to \p Die. /// value \p Val, and add it to \p Die.
/// \returns the size of the cloned attribute. /// \returns the size of the cloned attribute.
unsigned DwarfLinker::DIECloner::cloneAttribute( unsigned DwarfLinkerForBinary::DIECloner::cloneAttribute(
DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO, DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO,
CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val, CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val,
const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info, const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info,
@ -1517,7 +1493,7 @@ unsigned DwarfLinker::DIECloner::cloneAttribute(
/// monotonic \p BaseOffset values. /// monotonic \p BaseOffset values.
/// ///
/// \returns whether any reloc has been applied. /// \returns whether any reloc has been applied.
bool DwarfLinker::RelocationManager::applyValidRelocs( bool DwarfLinkerForBinary::RelocationManager::applyValidRelocs(
MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) { MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
assert((NextValidReloc == 0 || assert((NextValidReloc == 0 ||
BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) && BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) &&
@ -1558,11 +1534,9 @@ static bool isObjCSelector(StringRef Name) {
(Name[1] == '['); (Name[1] == '[');
} }
void DwarfLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit, void DwarfLinkerForBinary::DIECloner::addObjCAccelerator(
const DIE *Die, CompileUnit &Unit, const DIE *Die, DwarfStringPoolEntryRef Name,
DwarfStringPoolEntryRef Name, OffsetsStringPool &StringPool, bool SkipPubSection) {
OffsetsStringPool &StringPool,
bool SkipPubSection) {
assert(isObjCSelector(Name.getString()) && "not an objc selector"); assert(isObjCSelector(Name.getString()) && "not an objc selector");
// Objective C method or class function. // Objective C method or class function.
// "- [Class(Category) selector :withArg ...]" // "- [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, const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &Unit,
OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset, OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset,
unsigned Flags, bool IsLittleEndian, DIE *Die) { unsigned Flags, bool IsLittleEndian, DIE *Die) {
@ -1675,7 +1649,8 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
Data = Data =
DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
// Modify the copy with relocated addresses. // 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 // 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 // potentially stored in the input DIE. If high_pc is an address
// (Dwarf version == 2), then it might have been relocated to a // (Dwarf version == 2), then it might have been relocated to a
@ -1793,7 +1768,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
if (HasChildren) if (HasChildren)
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
// Assign a permanent abbrev number // Assign a permanent abbrev number
Linker.AssignAbbrev(NewAbbrev); Linker.assignAbbrev(NewAbbrev);
Die->setAbbrevNumber(NewAbbrev.getNumber()); Die->setAbbrevNumber(NewAbbrev.getNumber());
// Add the size of the abbreviation number to the output offset. // 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 /// Patch the input object file relevant debug_ranges entries
/// and emit them in the output file. Update the relevant attributes /// and emit them in the output file. Update the relevant attributes
/// to point at the new entries. /// to point at the new entries.
void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit, void DwarfLinkerForBinary::patchRangesForUnit(const CompileUnit &Unit,
DWARFContext &OrigDwarf, DWARFContext &OrigDwarf,
const DebugMapObject &DMO) const { const DebugMapObject &DMO) const {
DWARFDebugRangeList RangeList; DWARFDebugRangeList RangeList;
const auto &FunctionRanges = Unit.getFunctionRanges(); const auto &FunctionRanges = Unit.getFunctionRanges();
unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
@ -1879,7 +1854,7 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
/// FIXME: this could actually be done right in patchRangesForUnit, /// FIXME: this could actually be done right in patchRangesForUnit,
/// but for the sake of initial bit-for-bit compatibility with legacy /// but for the sake of initial bit-for-bit compatibility with legacy
/// dsymutil, we have to do it in a delayed pass. /// 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(); auto Attr = Unit.getUnitRangesAttribute();
if (Attr) if (Attr)
Attr->set(Streamer->getRangesSectionSize()); 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 /// Extract the line table for \p Unit from \p OrigDwarf, and
/// recreate a relocated version of these for the address ranges that /// recreate a relocated version of these for the address ranges that
/// are present in the binary. /// are present in the binary.
void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, void DwarfLinkerForBinary::patchLineTableForUnit(CompileUnit &Unit,
DWARFContext &OrigDwarf, DWARFContext &OrigDwarf,
RangesTy &Ranges, RangesTy &Ranges,
const DebugMapObject &DMO) { const DebugMapObject &DMO) {
DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list)); auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
if (!StmtList) if (!StmtList)
@ -2071,7 +2046,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
} }
} }
void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { void DwarfLinkerForBinary::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
switch (Options.TheAccelTableKind) { switch (Options.TheAccelTableKind) {
case AccelTableKind::Apple: case AccelTableKind::Apple:
emitAppleAcceleratorEntriesForUnit(Unit); emitAppleAcceleratorEntriesForUnit(Unit);
@ -2085,7 +2060,8 @@ void DwarfLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
} }
} }
void DwarfLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) { void DwarfLinkerForBinary::emitAppleAcceleratorEntriesForUnit(
CompileUnit &Unit) {
// Add namespaces. // Add namespaces.
for (const auto &Namespace : Unit.getNamespaces()) for (const auto &Namespace : Unit.getNamespaces())
AppleNamespaces.addName(Namespace.Name, AppleNamespaces.addName(Namespace.Name,
@ -2114,7 +2090,8 @@ void DwarfLinker::emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit) {
AppleObjc.addName(ObjC.Name, ObjC.Die->getOffset() + Unit.getStartOffset()); 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()) for (const auto &Namespace : Unit.getNamespaces())
DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(), DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
Namespace.Die->getTag(), Unit.getUniqueID()); 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 /// 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 /// be considered as black boxes and moved as is. The only thing to do
/// is to patch the addresses in the headers. /// is to patch the addresses in the headers.
void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO, void DwarfLinkerForBinary::patchFrameInfoForObject(const DebugMapObject &DMO,
RangesTy &Ranges, RangesTy &Ranges,
DWARFContext &OrigDwarf, DWARFContext &OrigDwarf,
unsigned AddrSize) { unsigned AddrSize) {
StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data; StringRef FrameData = OrigDwarf.getDWARFObj().getFrameSection().Data;
if (FrameData.empty()) if (FrameData.empty())
return; return;
@ -2212,25 +2189,24 @@ void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
} }
} }
void DwarfLinker::DIECloner::copyAbbrev( void DwarfLinkerForBinary::DIECloner::copyAbbrev(
const DWARFAbbreviationDeclaration &Abbrev, bool hasODR) { const DWARFAbbreviationDeclaration &Abbrev, bool HasODR) {
DIEAbbrev Copy(dwarf::Tag(Abbrev.getTag()), DIEAbbrev Copy(dwarf::Tag(Abbrev.getTag()),
dwarf::Form(Abbrev.hasChildren())); dwarf::Form(Abbrev.hasChildren()));
for (const auto &Attr : Abbrev.attributes()) { for (const auto &Attr : Abbrev.attributes()) {
uint16_t Form = Attr.Form; uint16_t Form = Attr.Form;
if (hasODR && isODRAttribute(Attr.Attr)) if (HasODR && isODRAttribute(Attr.Attr))
Form = dwarf::DW_FORM_ref_addr; Form = dwarf::DW_FORM_ref_addr;
Copy.AddAttribute(dwarf::Attribute(Attr.Attr), dwarf::Form(Form)); Copy.AddAttribute(dwarf::Attribute(Attr.Attr), dwarf::Form(Form));
} }
Linker.AssignAbbrev(Copy); Linker.assignAbbrev(Copy);
} }
uint32_t uint32_t DwarfLinkerForBinary::DIECloner::hashFullyQualifiedName(
DwarfLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U, DWARFDie DIE, CompileUnit &U, const DebugMapObject &DMO,
const DebugMapObject &DMO, int ChildRecurseDepth) {
int ChildRecurseDepth) {
const char *Name = nullptr; const char *Name = nullptr;
DWARFUnit *OrigUnit = &U.getOrigUnit(); DWARFUnit *OrigUnit = &U.getOrigUnit();
CompileUnit *CU = &U; CompileUnit *CU = &U;
@ -2281,7 +2257,7 @@ static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) {
return 0; return 0;
} }
bool DwarfLinker::registerModuleReference( bool DwarfLinkerForBinary::registerModuleReference(
DWARFDie CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, DWARFDie CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap,
const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool, const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool,
UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts, UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
@ -2339,7 +2315,8 @@ bool DwarfLinker::registerModuleReference(
} }
ErrorOr<const object::ObjectFile &> ErrorOr<const object::ObjectFile &>
DwarfLinker::loadObject(const DebugMapObject &Obj, const DebugMap &Map) { DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
const DebugMap &Map) {
auto ObjectEntry = auto ObjectEntry =
BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp()); BinHolder.getObjectEntry(Obj.getObjectFilename(), Obj.getTimestamp());
if (!ObjectEntry) { if (!ObjectEntry) {
@ -2360,7 +2337,7 @@ DwarfLinker::loadObject(const DebugMapObject &Obj, const DebugMap &Map) {
return *Object; return *Object;
} }
Error DwarfLinker::loadClangModule( Error DwarfLinkerForBinary::loadClangModule(
DWARFDie CUDie, StringRef Filename, StringRef ModuleName, uint64_t DwoId, DWARFDie CUDie, StringRef Filename, StringRef ModuleName, uint64_t DwoId,
DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges, DebugMap &ModuleMap, const DebugMapObject &DMO, RangesTy &Ranges,
OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool, OffsetsStringPool &StringPool, UniquingStringPool &UniquingStringPool,
@ -2417,7 +2394,7 @@ Error DwarfLinker::loadClangModule(
// Setup access to the debug info. // Setup access to the debug info.
auto DwarfContext = DWARFContext::create(*ErrOrObj); auto DwarfContext = DWARFContext::create(*ErrOrObj);
RelocationManager RelocMgr(*this); RelocationManager RelocMgr(*this, *ErrOrObj, DMO);
for (const auto &CU : DwarfContext->compile_units()) { for (const auto &CU : DwarfContext->compile_units()) {
updateDwarfVersion(CU->getVersion()); updateDwarfVersion(CU->getVersion());
@ -2454,7 +2431,7 @@ Error DwarfLinker::loadClangModule(
// Add this module. // Add this module.
Unit = std::make_unique<CompileUnit>(*CU, UnitID++, !Options.NoODR, Unit = std::make_unique<CompileUnit>(*CU, UnitID++, !Options.NoODR,
ModuleName); ModuleName);
Unit->setHasInterestingContent(); Unit->setHasInterestingContent();
analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(), analyzeContextInfo(CUDie, 0, *Unit, &ODRContexts.getRoot(),
UniquingStringPool, ODRContexts, ModulesEndOffset, UniquingStringPool, ODRContexts, ModulesEndOffset,
@ -2481,7 +2458,7 @@ Error DwarfLinker::loadClangModule(
return Error::success(); return Error::success();
} }
void DwarfLinker::DIECloner::cloneAllCompileUnits( void DwarfLinkerForBinary::DIECloner::cloneAllCompileUnits(
DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges, DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges,
OffsetsStringPool &StringPool, bool IsLittleEndian) { OffsetsStringPool &StringPool, bool IsLittleEndian) {
if (!Linker.Streamer) 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) if (Options.TheAccelTableKind != AccelTableKind::Default)
return; return;
@ -2564,15 +2541,14 @@ void DwarfLinker::updateAccelKind(DWARFContext &Dwarf) {
AtLeastOneAppleAccelTable = true; AtLeastOneAppleAccelTable = true;
} }
if (!AtLeastOneDwarfAccelTable && if (!AtLeastOneDwarfAccelTable && !DwarfObj.getNamesSection().Data.empty()) {
!DwarfObj.getNamesSection().Data.empty()) {
AtLeastOneDwarfAccelTable = true; AtLeastOneDwarfAccelTable = true;
} }
} }
bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO, bool DwarfLinkerForBinary::emitPaperTrailWarnings(
const DebugMap &Map, const DebugMapObject &DMO, const DebugMap &Map,
OffsetsStringPool &StringPool) { OffsetsStringPool &StringPool) {
if (DMO.getWarnings().empty() || !DMO.empty()) if (DMO.getWarnings().empty() || !DMO.empty())
return false; return false;
@ -2606,13 +2582,13 @@ bool DwarfLinker::emitPaperTrailWarnings(const DebugMapObject &DMO,
DMO.getWarnings().size() * (4 + 1 + 4) + DMO.getWarnings().size() * (4 + 1 + 4) +
1 /* End of children */; 1 /* End of children */;
DIEAbbrev Abbrev = CUDie->generateAbbrev(); DIEAbbrev Abbrev = CUDie->generateAbbrev();
AssignAbbrev(Abbrev); assignAbbrev(Abbrev);
CUDie->setAbbrevNumber(Abbrev.getNumber()); CUDie->setAbbrevNumber(Abbrev.getNumber());
Size += getULEB128Size(Abbrev.getNumber()); Size += getULEB128Size(Abbrev.getNumber());
// Abbreviation ordering needed for classic compatibility. // Abbreviation ordering needed for classic compatibility.
for (auto &Child : CUDie->children()) { for (auto &Child : CUDie->children()) {
Abbrev = Child.generateAbbrev(); Abbrev = Child.generateAbbrev();
AssignAbbrev(Abbrev); assignAbbrev(Abbrev);
Child.setAbbrevNumber(Abbrev.getNumber()); Child.setAbbrevNumber(Abbrev.getNumber());
Size += getULEB128Size(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. // copy_file attempts an APFS clone first, so this should be cheap.
if ((EC = sys::fs::copy_file(InterfaceFile, Path.str()))) if ((EC = sys::fs::copy_file(InterfaceFile, Path.str())))
warn(Twine("cannot copy parseable Swift interface ") + warn(Twine("cannot copy parseable Swift interface ") + InterfaceFile +
InterfaceFile + ": " + ": " + toString(errorCodeToError(EC)));
toString(errorCodeToError(EC)));
Path.resize(BaseLength); Path.resize(BaseLength);
} }
return Error::success(); return Error::success();
} }
static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath, static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
StringRef ArchName, StringRef ArchName, const remarks::RemarkLinker &RL) {
const remarks::RemarkLinker &RL) {
// Make sure we don't create the directories and the file if there is nothing // Make sure we don't create the directories and the file if there is nothing
// to serialize. // to serialize.
if (RL.empty()) if (RL.empty())
@ -2701,7 +2675,7 @@ static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
return Error::success(); return Error::success();
} }
bool DwarfLinker::link(const DebugMap &Map) { bool DwarfLinkerForBinary::link(const DebugMap &Map) {
if (!createStreamer(Map.getTriple(), OutFile)) if (!createStreamer(Map.getTriple(), OutFile))
return false; return false;
@ -2798,8 +2772,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
// Look for relocations that correspond to debug map entries. // Look for relocations that correspond to debug map entries.
if (LLVM_LIKELY(!Options.Update) && if (LLVM_LIKELY(!Options.Update) &&
!LinkContext.RelocMgr.findValidRelocsInDebugInfo( !LinkContext.RelocMgr->hasValidRelocs()) {
*LinkContext.ObjectFile, LinkContext.DMO)) {
if (Options.Verbose) if (Options.Verbose)
outs() << "No valid relocations found. Skipping.\n"; outs() << "No valid relocations found. Skipping.\n";
@ -2916,7 +2889,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
Streamer->copyInvariantDebugSection(*LinkContext.ObjectFile); Streamer->copyInvariantDebugSection(*LinkContext.ObjectFile);
} else { } else {
for (auto &CurrentUnit : LinkContext.CompileUnits) for (auto &CurrentUnit : LinkContext.CompileUnits)
lookForDIEsToKeep(LinkContext.RelocMgr, LinkContext.Ranges, lookForDIEsToKeep(*LinkContext.RelocMgr, LinkContext.Ranges,
LinkContext.CompileUnits, LinkContext.CompileUnits,
CurrentUnit->getOrigUnit().getUnitDIE(), CurrentUnit->getOrigUnit().getUnitDIE(),
LinkContext.DMO, *CurrentUnit, 0); LinkContext.DMO, *CurrentUnit, 0);
@ -2925,10 +2898,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
// The calls to applyValidRelocs inside cloneDIE will walk the reloc // The calls to applyValidRelocs inside cloneDIE will walk the reloc
// array again (in the same way findValidRelocsInDebugInfo() did). We // array again (in the same way findValidRelocsInDebugInfo() did). We
// need to reset the NextValidReloc index to the beginning. // need to reset the NextValidReloc index to the beginning.
LinkContext.RelocMgr.resetValidRelocs(); if (LinkContext.RelocMgr->hasValidRelocs() || LLVM_UNLIKELY(Options.Update))
if (LinkContext.RelocMgr.hasValidRelocs() || LLVM_UNLIKELY(Options.Update)) DIECloner(*this, *LinkContext.RelocMgr, DIEAlloc,
DIECloner(*this, LinkContext.RelocMgr, DIEAlloc, LinkContext.CompileUnits, LinkContext.CompileUnits, Options)
Options)
.cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO, .cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO,
LinkContext.Ranges, OffsetsStringPool, LinkContext.Ranges, OffsetsStringPool,
LinkContext.DwarfContext->isLittleEndian()); LinkContext.DwarfContext->isLittleEndian());
@ -3074,7 +3046,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder, bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
const DebugMap &DM, LinkOptions Options) { const DebugMap &DM, LinkOptions Options) {
DwarfLinker Linker(OutFile, BinHolder, std::move(Options)); DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
return Linker.link(DM); return Linker.link(DM);
} }

View File

@ -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. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information. // See https://llvm.org/LICENSE.txt for license information.
@ -10,33 +10,17 @@
#define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H #define LLVM_TOOLS_DSYMUTIL_DWARFLINKER_H
#include "BinaryHolder.h" #include "BinaryHolder.h"
#include "CompileUnit.h"
#include "DebugMap.h" #include "DebugMap.h"
#include "DeclContext.h"
#include "DwarfStreamer.h" #include "DwarfStreamer.h"
#include "LinkUtils.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" #include "llvm/DebugInfo/DWARF/DWARFContext.h"
namespace llvm { namespace llvm {
namespace dsymutil { 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>>; using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
/// The core of the Dwarf linking logic. /// 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 /// a function, the location for a variable). These relocations are
/// called ValidRelocs in the DwarfLinker and are gathered as a very /// called ValidRelocs in the DwarfLinker and are gathered as a very
/// first step when we start processing a DebugMapObject. /// first step when we start processing a DebugMapObject.
class DwarfLinker { class DwarfLinkerForBinary {
public: public:
DwarfLinker(raw_fd_ostream &OutFile, BinaryHolder &BinHolder, DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
LinkOptions Options) LinkOptions Options)
: OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {} : OutFile(OutFile), BinHolder(BinHolder), Options(std::move(Options)) {}
/// Link the contents of the DebugMap. /// Link the contents of the DebugMap.
@ -74,6 +58,7 @@ public:
TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents. TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
TF_SkipPC = 1 << 5, ///< Skip all location attributes. TF_SkipPC = 1 << 5, ///< Skip all location attributes.
}; };
private: private:
/// Remembers the oldest and newest DWARF version we've seen in a unit. /// Remembers the oldest and newest DWARF version we've seen in a unit.
void updateDwarfVersion(unsigned Version) { void updateDwarfVersion(unsigned Version) {
@ -89,7 +74,7 @@ private:
OffsetsStringPool &StringPool); OffsetsStringPool &StringPool);
/// Keeps track of relocations. /// Keeps track of relocations.
class RelocationManager { class RelocationManager : public AddressesMap {
struct ValidReloc { struct ValidReloc {
uint64_t Offset; uint64_t Offset;
uint32_t Size; uint32_t Size;
@ -105,7 +90,7 @@ private:
} }
}; };
const DwarfLinker &Linker; const DwarfLinkerForBinary &Linker;
/// The valid relocations for the current DebugMapObject. /// The valid relocations for the current DebugMapObject.
/// This vector is sorted by relocation offset. /// This vector is sorted by relocation offset.
@ -117,13 +102,48 @@ private:
/// cheap lookup during the root DIE selection and during DIE cloning. /// cheap lookup during the root DIE selection and during DIE cloning.
unsigned NextValidReloc = 0; unsigned NextValidReloc = 0;
RangesTy AddressRanges;
public: 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. virtual bool areRelocationsResolved() const override { return true; }
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 /// \defgroup FindValidRelocations Translate debug map into a list
/// of relevant relocations /// of relevant relocations
@ -141,32 +161,44 @@ private:
const DebugMapObject &DMO); const DebugMapObject &DMO);
/// @} /// @}
bool hasValidRelocation(uint64_t StartOffset, uint64_t EndOffset, bool hasValidRelocationAt(uint64_t StartOffset, uint64_t EndOffset,
CompileUnit::DIEInfo &Info); CompileUnit::DIEInfo &Info) override;
bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset, 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. /// Keeps track of data associated with one object during linking.
struct LinkContext { struct LinkContext {
DwarfLinkerForBinary &Linker;
DebugMapObject &DMO; DebugMapObject &DMO;
const object::ObjectFile *ObjectFile; const object::ObjectFile *ObjectFile = nullptr;
RelocationManager RelocMgr; std::unique_ptr<RelocationManager> RelocMgr;
std::unique_ptr<DWARFContext> DwarfContext; std::unique_ptr<DWARFContext> DwarfContext;
RangesTy Ranges; RangesTy Ranges;
UnitListTy CompileUnits; UnitListTy CompileUnits;
LinkContext(const DebugMap &Map, DwarfLinker &Linker, DebugMapObject &DMO) LinkContext(const DebugMap &Map, DwarfLinkerForBinary &Linker,
: DMO(DMO), RelocMgr(Linker) { DebugMapObject &DMO)
: Linker(Linker), DMO(DMO) {
// Swift ASTs are not object files. // Swift ASTs are not object files.
if (DMO.getType() == MachO::N_AST) { if (DMO.getType() == MachO::N_AST) {
ObjectFile = nullptr; ObjectFile = nullptr;
return; return;
} }
auto ErrOrObj = Linker.loadObject(DMO, Map); if (auto ErrOrObj = Linker.loadObject(DMO, Map)) {
ObjectFile = ErrOrObj ? &*ErrOrObj : nullptr; ObjectFile = &*ErrOrObj;
DwarfContext = ObjectFile ? DWARFContext::create(*ObjectFile) : nullptr; 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 /// Clear part of the context that's no longer needed when we're done with
@ -175,6 +207,7 @@ private:
DwarfContext.reset(nullptr); DwarfContext.reset(nullptr);
CompileUnits.clear(); CompileUnits.clear();
Ranges.clear(); Ranges.clear();
RelocMgr->clear();
} }
}; };
@ -224,7 +257,6 @@ private:
unsigned &UnitID, bool IsLittleEndian, unsigned &UnitID, bool IsLittleEndian,
unsigned Indent = 0, bool Quiet = false); unsigned Indent = 0, bool Quiet = false);
/// Mark the passed DIE as well as all the ones it depends on as kept. /// Mark the passed DIE as well as all the ones it depends on as kept.
void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges, void keepDIEAndDependencies(RelocationManager &RelocMgr, RangesTy &Ranges,
const UnitListTy &Units, const DWARFDie &DIE, const UnitListTy &Units, const DWARFDie &DIE,
@ -258,7 +290,7 @@ private:
/// @{ /// @{
class DIECloner { class DIECloner {
DwarfLinker &Linker; DwarfLinkerForBinary &Linker;
RelocationManager &RelocMgr; RelocationManager &RelocMgr;
/// Allocator used for all the DIEValue objects. /// Allocator used for all the DIEValue objects.
@ -268,7 +300,7 @@ private:
LinkOptions Options; LinkOptions Options;
public: public:
DIECloner(DwarfLinker &Linker, RelocationManager &RelocMgr, DIECloner(DwarfLinkerForBinary &Linker, RelocationManager &RelocMgr,
BumpPtrAllocator &DIEAlloc, BumpPtrAllocator &DIEAlloc,
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits, std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
LinkOptions &Options) LinkOptions &Options)
@ -409,7 +441,7 @@ private:
}; };
/// Assign an abbreviation number to \p Abbrev /// 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 /// Compute and emit debug_ranges section for \p Unit, and
/// patch the attributes referencing it. /// patch the attributes referencing it.

View File

@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "DwarfStreamer.h" #include "DwarfStreamer.h"
#include "CompileUnit.h"
#include "LinkUtils.h" #include "LinkUtils.h"
#include "MachOUtils.h" #include "MachOUtils.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.inc" #include "llvm/MC/MCTargetOptionsCommandFlags.inc"

View File

@ -9,12 +9,12 @@
#ifndef LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H #ifndef LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
#define LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H #define LLVM_TOOLS_DSYMUTIL_DWARFSTREAMER_H
#include "CompileUnit.h"
#include "DebugMap.h" #include "DebugMap.h"
#include "LinkUtils.h" #include "LinkUtils.h"
#include "llvm/CodeGen/AccelTable.h" #include "llvm/CodeGen/AccelTable.h"
#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h" #include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmBackend.h"

View File

@ -18,4 +18,4 @@
type = Tool type = Tool
name = dsymutil name = dsymutil
parent = Tools parent = Tools
required_libraries = AsmPrinter DebugInfoDWARF MC Object CodeGen Support all-targets required_libraries = AsmPrinter DebugInfoDWARF DWARFLinker MC Object CodeGen Support all-targets