forked from OSchip/llvm-project
[Dsymutil][Debuginfo][NFC] #4 Refactor dsymutil to separate DWARF optimizing part.
Summary: The primary goal of this refactoring is to separate DWARF optimizing part. So that it could be reused by linker or by any other client. There was a thread on llvm-dev discussing the necessity of such a refactoring: http://lists.llvm.org/pipermail/llvm-dev/2019-September/135068.html. This is a final part from series of patches for dsymutil. Previous patches : D71068, D71839, D72476. This patch: 1. Creates lib/DWARFLinker interface : void addObjectFile(DwarfLinkerObjFile &ObjFile); bool link(); void setOptions; 1. Moves all linking logic from tools/dsymutil/DwarfLinkerForBinary into lib/DWARFLinker. 2. Renames RelocationManager into AddressesManager. 3. Remarks creation logic moved from separate parallel execution into object file loading routine. Testing: it passes "check-all" lit testing. MD5 checksum for clang .dSYM bundle matches for the dsymutil with/without that patch. Reviewers: JDevlieghere, friss, dblaikie, aprantl, jdoerfert Reviewed By: JDevlieghere Subscribers: merge_guards_bot, hiraditya, jfb, llvm-commits, probinson, thegameg Tags: #llvm, #debug-info Differential Revision: https://reviews.llvm.org/D72915
This commit is contained in:
parent
784204fd7e
commit
a8c5a461a8
|
@ -910,6 +910,9 @@ public:
|
|||
///
|
||||
unsigned ComputeSize(const AsmPrinter *AP) const;
|
||||
|
||||
// TODO: move setSize() and Size to DIEValueList.
|
||||
void setSize(unsigned size) { Size = size; }
|
||||
|
||||
/// BestForm - Choose the best form for data.
|
||||
///
|
||||
dwarf::Form BestForm(unsigned DwarfVersion) const {
|
||||
|
@ -944,6 +947,9 @@ public:
|
|||
///
|
||||
unsigned ComputeSize(const AsmPrinter *AP) const;
|
||||
|
||||
// TODO: move setSize() and Size to DIEValueList.
|
||||
void setSize(unsigned size) { Size = size; }
|
||||
|
||||
/// BestForm - Choose the best form for data.
|
||||
///
|
||||
dwarf::Form BestForm() const {
|
||||
|
|
|
@ -21,6 +21,13 @@ namespace llvm {
|
|||
|
||||
enum class DwarfLinkerClient { Dsymutil, LLD, General };
|
||||
|
||||
/// The kind of accelerator tables we should emit.
|
||||
enum class AccelTableKind {
|
||||
Apple, ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
|
||||
Dwarf, ///< DWARF v5 .debug_names.
|
||||
Default, ///< Dwarf for DWARF5 or later, Apple otherwise.
|
||||
};
|
||||
|
||||
/// Partial address range. Besides an offset, only the
|
||||
/// HighPC is stored. The structure is stored in a map where the LowPC is the
|
||||
/// key.
|
||||
|
@ -193,6 +200,599 @@ public:
|
|||
virtual uint64_t getDebugInfoSectionSize() const = 0;
|
||||
};
|
||||
|
||||
using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
|
||||
|
||||
/// this class represents Object File and it`s additional info.
|
||||
class DwarfLinkerObjFile {
|
||||
public:
|
||||
DwarfLinkerObjFile(StringRef Name, const object::ObjectFile *File,
|
||||
const std::vector<std::string> &Warnings)
|
||||
: FileName(Name), ObjFile(File), Warnings(Warnings) {}
|
||||
|
||||
/// object file name.
|
||||
StringRef FileName;
|
||||
/// object file.
|
||||
const object::ObjectFile *ObjFile;
|
||||
/// helpful address information(list of valid address ranges, relocations).
|
||||
std::unique_ptr<AddressesMap> Addresses;
|
||||
/// warnings for object file.
|
||||
const std::vector<std::string> &Warnings;
|
||||
};
|
||||
|
||||
typedef std::function<void(const Twine &Warning, StringRef Context,
|
||||
const DWARFDie *DIE)>
|
||||
messageHandler;
|
||||
typedef std::function<ErrorOr<DwarfLinkerObjFile &>(StringRef ContainerName,
|
||||
StringRef Path)>
|
||||
objFileLoader;
|
||||
typedef std::map<std::string, std::string> swiftInterfacesMap;
|
||||
|
||||
/// The core of the Dwarf linking logic.
|
||||
///
|
||||
/// The generation of the dwarf information from the object files will be
|
||||
/// driven by the selection of 'root DIEs', which are DIEs that
|
||||
/// describe variables or functions that resolves to the corresponding
|
||||
/// code section(and thus have entries in the Addresses map). All the debug
|
||||
/// information that will be generated(the DIEs, but also the line
|
||||
/// tables, ranges, ...) is derived from that set of root DIEs.
|
||||
///
|
||||
/// The root DIEs are identified because they contain relocations that
|
||||
/// points to code section(the low_pc for a function, the location for
|
||||
/// a variable). These relocations are called ValidRelocs in the
|
||||
/// AddressesInfo and are gathered as a very first step when we start
|
||||
/// processing a object file.
|
||||
class DWARFLinker {
|
||||
public:
|
||||
DWARFLinker(const Triple &Triple, DwarfEmitter *Emitter,
|
||||
DwarfLinkerClient ClientID = DwarfLinkerClient::General)
|
||||
: Triple(Triple), DwarfEmitter(Emitter), DwarfLinkerClientID(ClientID) {}
|
||||
|
||||
/// Add object file to be linked.
|
||||
void addObjectFile(DwarfLinkerObjFile &ObjFile);
|
||||
|
||||
/// Link debug info for added objFiles. Object
|
||||
/// files are linked all together.
|
||||
bool link();
|
||||
|
||||
/// A number of methods setting various linking options:
|
||||
|
||||
/// Allows to generate log of linking process to the standard output.
|
||||
void setVerbosity(bool Verbose) { Options.Verbose = Verbose; }
|
||||
|
||||
/// Do not emit linked dwarf info.
|
||||
void setNoOutput(bool NoOut) { Options.NoOutput = NoOut; }
|
||||
|
||||
/// Do not unique types according to ODR.
|
||||
void setNoODR(bool NoODR) { Options.NoODR = NoODR; }
|
||||
|
||||
/// update existing DWARF info(for the linked binary).
|
||||
void setUpdate(bool Update) { Options.Update = Update; }
|
||||
|
||||
/// Use specified number of threads for parallel files linking.
|
||||
void setNumThreads(unsigned NumThreads) { Options.Threads = NumThreads; }
|
||||
|
||||
/// Set kind of accelerator tables to be generated.
|
||||
void setAccelTableKind(AccelTableKind Kind) {
|
||||
Options.TheAccelTableKind = Kind;
|
||||
}
|
||||
|
||||
/// Set prepend path for clang modules.
|
||||
void setPrependPath(const std::string &Ppath) { Options.PrependPath = Ppath; }
|
||||
|
||||
/// Set translator which would be used for strings.
|
||||
void
|
||||
setStringsTranslator(std::function<StringRef(StringRef)> StringsTranslator) {
|
||||
this->StringsTranslator = StringsTranslator;
|
||||
}
|
||||
|
||||
/// Set estimated objects files amount, for preliminary data allocation.
|
||||
void setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
|
||||
ObjectContexts.reserve(ObjFilesNum);
|
||||
}
|
||||
|
||||
/// Set warning handler which would be used to report warnings.
|
||||
void setWarningHandler(messageHandler Handler) {
|
||||
Options.WarningHandler = Handler;
|
||||
}
|
||||
|
||||
/// Set error handler which would be used to report errors.
|
||||
void setErrorHandler(messageHandler Handler) {
|
||||
Options.ErrorHandler = Handler;
|
||||
}
|
||||
|
||||
/// Set object files loader which would be used to load
|
||||
/// additional objects for splitted dwarf.
|
||||
void setObjFileLoader(objFileLoader Loader) {
|
||||
Options.ObjFileLoader = Loader;
|
||||
}
|
||||
|
||||
/// Set map for Swift interfaces.
|
||||
void setSwiftInterfacesMap(swiftInterfacesMap *Map) {
|
||||
Options.ParseableSwiftInterfaces = Map;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Flags passed to DwarfLinker::lookForDIEsToKeep
|
||||
enum TraversalFlags {
|
||||
TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
|
||||
TF_InFunctionScope = 1 << 1, ///< Current scope is a function scope.
|
||||
TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept DIE.
|
||||
TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept DIE.
|
||||
TF_ODR = 1 << 4, ///< Use the ODR while keeping dependents.
|
||||
TF_SkipPC = 1 << 5, ///< Skip all location attributes.
|
||||
};
|
||||
|
||||
/// The distinct types of work performed by the work loop.
|
||||
enum class WorklistItemType {
|
||||
/// Given a DIE, look for DIEs to be kept.
|
||||
LookForDIEsToKeep,
|
||||
/// Given a DIE, look for children of this DIE to be kept.
|
||||
LookForChildDIEsToKeep,
|
||||
/// Given a DIE, look for DIEs referencing this DIE to be kept.
|
||||
LookForRefDIEsToKeep,
|
||||
/// Given a DIE, look for parent DIEs to be kept.
|
||||
LookForParentDIEsToKeep,
|
||||
/// Given a DIE, update its incompleteness based on whether its children are
|
||||
/// incomplete.
|
||||
UpdateChildIncompleteness,
|
||||
/// Given a DIE, update its incompleteness based on whether the DIEs it
|
||||
/// references are incomplete.
|
||||
UpdateRefIncompleteness,
|
||||
};
|
||||
|
||||
/// This class represents an item in the work list. The type defines what kind
|
||||
/// of work needs to be performed when processing the current item. The flags
|
||||
/// and info fields are optional based on the type.
|
||||
struct WorklistItem {
|
||||
WorklistItemType Type;
|
||||
DWARFDie Die;
|
||||
CompileUnit &CU;
|
||||
unsigned Flags;
|
||||
unsigned AncestorIdx = 0;
|
||||
CompileUnit::DIEInfo *OtherInfo = nullptr;
|
||||
|
||||
WorklistItem(DWARFDie Die, CompileUnit &CU, unsigned Flags,
|
||||
WorklistItemType T = WorklistItemType::LookForDIEsToKeep)
|
||||
: Type(T), Die(Die), CU(CU), Flags(Flags) {}
|
||||
|
||||
WorklistItem(DWARFDie Die, CompileUnit &CU, WorklistItemType T,
|
||||
CompileUnit::DIEInfo *OtherInfo = nullptr)
|
||||
: Type(T), Die(Die), CU(CU), OtherInfo(OtherInfo) {}
|
||||
|
||||
WorklistItem(unsigned AncestorIdx, CompileUnit &CU, unsigned Flags)
|
||||
: Type(WorklistItemType::LookForParentDIEsToKeep), CU(CU), Flags(Flags),
|
||||
AncestorIdx(AncestorIdx) {}
|
||||
};
|
||||
|
||||
/// returns true if we need to translate strings.
|
||||
bool needToTranslateStrings() { return StringsTranslator != nullptr; }
|
||||
|
||||
void reportWarning(const Twine &Warning, const DwarfLinkerObjFile &OF,
|
||||
const DWARFDie *DIE = nullptr) const {
|
||||
if (Options.WarningHandler != nullptr)
|
||||
Options.WarningHandler(Warning, OF.FileName, DIE);
|
||||
}
|
||||
|
||||
void reportError(const Twine &Warning, const DwarfLinkerObjFile &OF,
|
||||
const DWARFDie *DIE = nullptr) const {
|
||||
if (Options.ErrorHandler != nullptr)
|
||||
Options.ErrorHandler(Warning, OF.FileName, DIE);
|
||||
}
|
||||
|
||||
/// Remembers the oldest and newest DWARF version we've seen in a unit.
|
||||
void updateDwarfVersion(unsigned Version) {
|
||||
MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
|
||||
MinDwarfVersion = std::min(MinDwarfVersion, Version);
|
||||
}
|
||||
|
||||
/// Remembers the kinds of accelerator tables we've seen in a unit.
|
||||
void updateAccelKind(DWARFContext &Dwarf);
|
||||
|
||||
/// Emit warnings as Dwarf compile units to leave a trail after linking.
|
||||
bool emitPaperTrailWarnings(const DwarfLinkerObjFile &OF,
|
||||
OffsetsStringPool &StringPool);
|
||||
|
||||
void copyInvariantDebugSection(const object::ObjectFile &Obj);
|
||||
|
||||
/// Keeps track of data associated with one object during linking.
|
||||
struct LinkContext {
|
||||
DwarfLinkerObjFile &ObjectFile;
|
||||
std::unique_ptr<DWARFContext> DwarfContext;
|
||||
UnitListTy CompileUnits;
|
||||
bool Skip = false;
|
||||
|
||||
LinkContext(DwarfLinkerObjFile &objFile) : ObjectFile(objFile) {
|
||||
|
||||
if (ObjectFile.ObjFile)
|
||||
DwarfContext = DWARFContext::create(*ObjectFile.ObjFile);
|
||||
}
|
||||
|
||||
/// Clear part of the context that's no longer needed when we're done with
|
||||
/// the debug object.
|
||||
void clear() {
|
||||
DwarfContext.reset(nullptr);
|
||||
CompileUnits.clear();
|
||||
ObjectFile.Addresses->clear();
|
||||
}
|
||||
};
|
||||
|
||||
/// Called before emitting object data
|
||||
void cleanupAuxiliarryData(LinkContext &Context);
|
||||
|
||||
/// Look at the parent of the given DIE and decide whether they should be
|
||||
/// kept.
|
||||
void lookForParentDIEsToKeep(unsigned AncestorIdx, CompileUnit &CU,
|
||||
unsigned Flags,
|
||||
SmallVectorImpl<WorklistItem> &Worklist);
|
||||
|
||||
/// Look at the children of the given DIE and decide whether they should be
|
||||
/// kept.
|
||||
void lookForChildDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
|
||||
unsigned Flags,
|
||||
SmallVectorImpl<WorklistItem> &Worklist);
|
||||
|
||||
/// Look at DIEs referenced by the given DIE and decide whether they should be
|
||||
/// kept. All DIEs referenced though attributes should be kept.
|
||||
void lookForRefDIEsToKeep(const DWARFDie &Die, CompileUnit &CU,
|
||||
unsigned Flags, const UnitListTy &Units,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
SmallVectorImpl<WorklistItem> &Worklist);
|
||||
|
||||
/// \defgroup FindRootDIEs Find DIEs corresponding to Address map entries.
|
||||
///
|
||||
/// @{
|
||||
/// Recursively walk the \p DIE tree and look for DIEs to
|
||||
/// keep. Store that information in \p CU's DIEInfo.
|
||||
///
|
||||
/// The return value indicates whether the DIE is incomplete.
|
||||
void lookForDIEsToKeep(AddressesMap &RelocMgr, RangesTy &Ranges,
|
||||
const UnitListTy &Units, const DWARFDie &DIE,
|
||||
const DwarfLinkerObjFile &OF, CompileUnit &CU,
|
||||
unsigned Flags);
|
||||
|
||||
/// If this compile unit is really a skeleton CU that points to a
|
||||
/// clang module, register it in ClangModules and return true.
|
||||
///
|
||||
/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
|
||||
/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
|
||||
/// hash.
|
||||
bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
OffsetsStringPool &OffsetsStringPool,
|
||||
UniquingStringPool &UniquingStringPoolStringPool,
|
||||
DeclContextTree &ODRContexts,
|
||||
uint64_t ModulesEndOffset, unsigned &UnitID,
|
||||
bool IsLittleEndian, unsigned Indent = 0,
|
||||
bool Quiet = false);
|
||||
|
||||
/// Recursively add the debug info in this clang module .pcm
|
||||
/// file (and all the modules imported by it in a bottom-up fashion)
|
||||
/// to Units.
|
||||
Error loadClangModule(DWARFDie CUDie, StringRef FilePath,
|
||||
StringRef ModuleName, uint64_t DwoId,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
OffsetsStringPool &OffsetsStringPool,
|
||||
UniquingStringPool &UniquingStringPool,
|
||||
DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
|
||||
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(AddressesMap &RelocMgr, RangesTy &Ranges,
|
||||
const UnitListTy &Units, const DWARFDie &DIE,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
const DwarfLinkerObjFile &OF, CompileUnit &CU,
|
||||
bool UseODR);
|
||||
|
||||
unsigned shouldKeepDIE(AddressesMap &RelocMgr, RangesTy &Ranges,
|
||||
const DWARFDie &DIE, const DwarfLinkerObjFile &OF,
|
||||
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
|
||||
/// Check if a variable describing DIE should be kept.
|
||||
/// \returns updated TraversalFlags.
|
||||
unsigned shouldKeepVariableDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo, unsigned Flags);
|
||||
|
||||
unsigned shouldKeepSubprogramDIE(AddressesMap &RelocMgr, RangesTy &Ranges,
|
||||
const DWARFDie &DIE,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
|
||||
/// 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.
|
||||
DWARFDie resolveDIEReference(const DwarfLinkerObjFile &OF,
|
||||
const UnitListTy &Units,
|
||||
const DWARFFormValue &RefValue,
|
||||
const DWARFDie &DIE, CompileUnit *&RefCU);
|
||||
|
||||
/// @}
|
||||
|
||||
/// \defgroup Methods used to link the debug information
|
||||
///
|
||||
/// @{
|
||||
|
||||
struct DWARFLinkerOptions;
|
||||
|
||||
class DIECloner {
|
||||
DWARFLinker &Linker;
|
||||
DwarfEmitter *Emitter;
|
||||
DwarfLinkerObjFile &ObjFile;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator &DIEAlloc;
|
||||
|
||||
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
|
||||
|
||||
bool Update;
|
||||
|
||||
public:
|
||||
DIECloner(DWARFLinker &Linker, DwarfEmitter *Emitter,
|
||||
DwarfLinkerObjFile &ObjFile, BumpPtrAllocator &DIEAlloc,
|
||||
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
|
||||
bool Update)
|
||||
: Linker(Linker), Emitter(Emitter), ObjFile(ObjFile),
|
||||
DIEAlloc(DIEAlloc), CompileUnits(CompileUnits), Update(Update) {}
|
||||
|
||||
/// Recursively clone \p InputDIE into an tree of DIE objects
|
||||
/// where useless (as decided by lookForDIEsToKeep()) bits have been
|
||||
/// stripped out and addresses have been rewritten according to the
|
||||
/// address map.
|
||||
///
|
||||
/// \param OutOffset is the offset the cloned DIE in the output
|
||||
/// compile unit.
|
||||
/// \param PCOffset (while cloning a function scope) is the offset
|
||||
/// applied to the entry point of the function to get the linked address.
|
||||
/// \param Die the output DIE to use, pass NULL to create one.
|
||||
/// \returns the root of the cloned tree or null if nothing was selected.
|
||||
DIE *cloneDIE(const DWARFDie &InputDIE, const DwarfLinkerObjFile &OF,
|
||||
CompileUnit &U, OffsetsStringPool &StringPool,
|
||||
int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
|
||||
bool IsLittleEndian, DIE *Die = nullptr);
|
||||
|
||||
/// Construct the output DIE tree by cloning the DIEs we
|
||||
/// chose to keep above. If there are no valid relocs, then there's
|
||||
/// nothing to clone/emit.
|
||||
void cloneAllCompileUnits(DWARFContext &DwarfContext,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
OffsetsStringPool &StringPool,
|
||||
bool IsLittleEndian);
|
||||
|
||||
private:
|
||||
using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
|
||||
|
||||
/// Information gathered and exchanged between the various
|
||||
/// clone*Attributes helpers about the attributes of a particular DIE.
|
||||
struct AttributesInfo {
|
||||
/// Names.
|
||||
DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
|
||||
|
||||
/// Offsets in the string pool.
|
||||
uint32_t NameOffset = 0;
|
||||
uint32_t MangledNameOffset = 0;
|
||||
|
||||
/// Value of AT_low_pc in the input DIE
|
||||
uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
/// Value of AT_high_pc in the input DIE
|
||||
uint64_t OrigHighPc = 0;
|
||||
|
||||
/// Offset to apply to PC addresses inside a function.
|
||||
int64_t PCOffset = 0;
|
||||
|
||||
/// Does the DIE have a low_pc attribute?
|
||||
bool HasLowPc = false;
|
||||
|
||||
/// Does the DIE have a ranges attribute?
|
||||
bool HasRanges = false;
|
||||
|
||||
/// Is this DIE only a declaration?
|
||||
bool IsDeclaration = false;
|
||||
|
||||
AttributesInfo() = default;
|
||||
};
|
||||
|
||||
friend DIECloner;
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
const DwarfLinkerObjFile &OF, CompileUnit &U,
|
||||
OffsetsStringPool &StringPool,
|
||||
const DWARFFormValue &Val,
|
||||
const AttributeSpec AttrSpec, unsigned AttrSize,
|
||||
AttributesInfo &AttrInfo, bool IsLittleEndian);
|
||||
|
||||
/// Clone a string attribute described by \p AttrSpec and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, const DWARFUnit &U,
|
||||
OffsetsStringPool &StringPool,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
AttributeSpec AttrSpec,
|
||||
unsigned AttrSize,
|
||||
const DWARFFormValue &Val,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
CompileUnit &Unit);
|
||||
|
||||
/// Clone a DWARF expression that may be referencing another DIE.
|
||||
void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
|
||||
const DwarfLinkerObjFile &OF, CompileUnit &Unit,
|
||||
SmallVectorImpl<uint8_t> &OutputBuffer);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneBlockAttribute(DIE &Die, const DwarfLinkerObjFile &OF,
|
||||
CompileUnit &Unit, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
bool IsLittleEndian);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val,
|
||||
const CompileUnit &Unit,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Clone a scalar attribute and add it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
const DwarfLinkerObjFile &OF, CompileUnit &U,
|
||||
AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Get the potential name and mangled name for the entity
|
||||
/// described by \p Die and store them in \Info if they are not
|
||||
/// already there.
|
||||
/// \returns is a name was found.
|
||||
bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
|
||||
OffsetsStringPool &StringPool, bool StripTemplate = false);
|
||||
|
||||
/// Create a copy of abbreviation Abbrev.
|
||||
void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
|
||||
|
||||
uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
|
||||
const DwarfLinkerObjFile &OF,
|
||||
int RecurseDepth = 0);
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
OffsetsStringPool &StringPool, bool SkipPubSection);
|
||||
};
|
||||
|
||||
/// Assign an abbreviation number to \p Abbrev
|
||||
void assignAbbrev(DIEAbbrev &Abbrev);
|
||||
|
||||
/// Compute and emit debug_ranges section for \p Unit, and
|
||||
/// patch the attributes referencing it.
|
||||
void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
|
||||
const DwarfLinkerObjFile &OF) const;
|
||||
|
||||
/// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
|
||||
/// one.
|
||||
void generateUnitRanges(CompileUnit &Unit) const;
|
||||
|
||||
/// Extract the line tables from the original dwarf, extract the relevant
|
||||
/// parts according to the linked function ranges and emit the result in the
|
||||
/// debug_line section.
|
||||
void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
|
||||
const DwarfLinkerObjFile &OF);
|
||||
|
||||
/// Emit the accelerator entries for \p Unit.
|
||||
void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
|
||||
/// Patch the frame info for an object file and emit it.
|
||||
void patchFrameInfoForObject(const DwarfLinkerObjFile &, RangesTy &Ranges,
|
||||
DWARFContext &, unsigned AddressSize);
|
||||
|
||||
/// FoldingSet that uniques the abbreviations.
|
||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||
|
||||
/// Storage for the unique Abbreviations.
|
||||
/// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
|
||||
/// changed to a vector of unique_ptrs.
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
|
||||
|
||||
/// DIELoc objects that need to be destructed (but not freed!).
|
||||
std::vector<DIELoc *> DIELocs;
|
||||
|
||||
/// DIEBlock objects that need to be destructed (but not freed!).
|
||||
std::vector<DIEBlock *> DIEBlocks;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator DIEAlloc;
|
||||
/// @}
|
||||
|
||||
Triple Triple;
|
||||
|
||||
DwarfEmitter *DwarfEmitter;
|
||||
std::vector<LinkContext> ObjectContexts;
|
||||
|
||||
unsigned MaxDwarfVersion = 0;
|
||||
unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
|
||||
|
||||
bool AtLeastOneAppleAccelTable = false;
|
||||
bool AtLeastOneDwarfAccelTable = false;
|
||||
|
||||
/// The CIEs that have been emitted in the output section. The actual CIE
|
||||
/// data serves a the key to this StringMap, this takes care of comparing the
|
||||
/// semantics of CIEs defined in different object files.
|
||||
StringMap<uint32_t> EmittedCIEs;
|
||||
|
||||
/// Offset of the last CIE that has been emitted in the output
|
||||
/// debug_frame section.
|
||||
uint32_t LastCIEOffset = 0;
|
||||
|
||||
/// Apple accelerator tables.
|
||||
AccelTable<DWARF5AccelTableStaticData> DebugNames;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
|
||||
AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
|
||||
|
||||
/// Mapping the PCM filename to the DwoId.
|
||||
StringMap<uint64_t> ClangModules;
|
||||
|
||||
DwarfLinkerClient DwarfLinkerClientID;
|
||||
|
||||
std::function<StringRef(StringRef)> StringsTranslator = nullptr;
|
||||
|
||||
/// linking options
|
||||
struct DWARFLinkerOptions {
|
||||
/// Generate processing log to the standard output.
|
||||
bool Verbose = false;
|
||||
|
||||
/// Skip emitting output
|
||||
bool NoOutput = false;
|
||||
|
||||
/// Do not unique types according to ODR
|
||||
bool NoODR = false;
|
||||
|
||||
/// Update
|
||||
bool Update = false;
|
||||
|
||||
/// Number of threads.
|
||||
unsigned Threads = 1;
|
||||
|
||||
/// The accelerator table kind
|
||||
AccelTableKind TheAccelTableKind = AccelTableKind::Default;
|
||||
|
||||
/// Prepend path for the clang modules.
|
||||
std::string PrependPath;
|
||||
|
||||
// warning handler
|
||||
messageHandler WarningHandler = nullptr;
|
||||
|
||||
// error handler
|
||||
messageHandler ErrorHandler = nullptr;
|
||||
|
||||
objFileLoader ObjFileLoader = nullptr;
|
||||
|
||||
/// A list of all .swiftinterface files referenced by the debug
|
||||
/// info, mapping Module name to path on disk. The entries need to
|
||||
/// be uniqued and sorted and there are only few entries expected
|
||||
/// per compile unit, which is why this is a std::map.
|
||||
/// this is dsymutil specific fag.
|
||||
swiftInterfacesMap *ParseableSwiftInterfaces = nullptr;
|
||||
} Options;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DWARFLINKER_DWARFLINKER_H
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -17,26 +17,20 @@
|
|||
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
|
||||
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/Remarks/RemarkFormat.h"
|
||||
#include "llvm/Remarks/RemarkLinker.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace dsymutil {
|
||||
|
||||
using UnitListTy = std::vector<std::unique_ptr<CompileUnit>>;
|
||||
|
||||
/// The core of the Dwarf linking logic.
|
||||
/// The core of the Dsymutil Dwarf linking logic.
|
||||
///
|
||||
/// The link of the dwarf information from the object files will be
|
||||
/// driven by the selection of 'root DIEs', which are DIEs that
|
||||
/// describe variables or functions that are present in the linked
|
||||
/// binary (and thus have entries in the debug map). All the debug
|
||||
/// information that will be linked (the DIEs, but also the line
|
||||
/// tables, ranges, ...) is derived from that set of root DIEs.
|
||||
///
|
||||
/// The root DIEs are identified because they contain relocations that
|
||||
/// correspond to a debug map entry at specific places (the low_pc for
|
||||
/// 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.
|
||||
/// driven by DWARFLinker. DwarfLinkerForBinary reads DebugMap objects
|
||||
/// and pass information to the DWARFLinker. DWARFLinker
|
||||
/// optimizes DWARF taking into account valid relocations.
|
||||
/// Finally, optimized DWARF is passed to DwarfLinkerForBinary through
|
||||
/// DWARFEmitter interface.
|
||||
class DwarfLinkerForBinary {
|
||||
public:
|
||||
DwarfLinkerForBinary(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
|
||||
|
@ -46,7 +40,7 @@ public:
|
|||
/// Link the contents of the DebugMap.
|
||||
bool link(const DebugMap &);
|
||||
|
||||
void reportWarning(const Twine &Warning, const DebugMapObject &DMO,
|
||||
void reportWarning(const Twine &Warning, StringRef Context,
|
||||
const DWARFDie *DIE = nullptr) const;
|
||||
|
||||
/// Flags passed to DwarfLinker::lookForDIEsToKeep
|
||||
|
@ -60,21 +54,9 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
/// Remembers the oldest and newest DWARF version we've seen in a unit.
|
||||
void updateDwarfVersion(unsigned Version) {
|
||||
MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
|
||||
MinDwarfVersion = std::min(MinDwarfVersion, Version);
|
||||
}
|
||||
|
||||
/// Remembers the kinds of accelerator tables we've seen in a unit.
|
||||
void updateAccelKind(DWARFContext &Dwarf);
|
||||
|
||||
/// Emit warnings as Dwarf compile units to leave a trail after linking.
|
||||
bool emitPaperTrailWarnings(const DebugMapObject &DMO, const DebugMap &Map,
|
||||
OffsetsStringPool &StringPool);
|
||||
|
||||
/// Keeps track of relocations.
|
||||
class RelocationManager : public AddressesMap {
|
||||
class AddressManager : public AddressesMap {
|
||||
struct ValidReloc {
|
||||
uint64_t Offset;
|
||||
uint32_t Size;
|
||||
|
@ -105,8 +87,8 @@ private:
|
|||
RangesTy AddressRanges;
|
||||
|
||||
public:
|
||||
RelocationManager(DwarfLinkerForBinary &Linker,
|
||||
const object::ObjectFile &Obj, const DebugMapObject &DMO)
|
||||
AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
|
||||
const DebugMapObject &DMO)
|
||||
: Linker(Linker) {
|
||||
findValidRelocsInDebugInfo(Obj, DMO);
|
||||
|
||||
|
@ -135,7 +117,7 @@ private:
|
|||
int64_t(Mapping.BinaryAddress) - *Mapping.ObjectAddress);
|
||||
}
|
||||
}
|
||||
virtual ~RelocationManager() override { clear(); }
|
||||
virtual ~AddressManager() override { clear(); }
|
||||
|
||||
virtual bool areRelocationsResolved() const override { return true; }
|
||||
|
||||
|
@ -176,315 +158,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
/// Keeps track of data associated with one object during linking.
|
||||
struct LinkContext {
|
||||
DwarfLinkerForBinary &Linker;
|
||||
DebugMapObject &DMO;
|
||||
const object::ObjectFile *ObjectFile = nullptr;
|
||||
std::unique_ptr<RelocationManager> RelocMgr;
|
||||
std::unique_ptr<DWARFContext> DwarfContext;
|
||||
RangesTy Ranges;
|
||||
UnitListTy CompileUnits;
|
||||
|
||||
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;
|
||||
}
|
||||
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
|
||||
/// the debug object.
|
||||
void Clear() {
|
||||
DwarfContext.reset(nullptr);
|
||||
CompileUnits.clear();
|
||||
Ranges.clear();
|
||||
RelocMgr->clear();
|
||||
}
|
||||
};
|
||||
|
||||
/// Called at the start of a debug object link.
|
||||
void startDebugObject(LinkContext &Context);
|
||||
|
||||
/// Called at the end of a debug object link.
|
||||
void endDebugObject(LinkContext &Context);
|
||||
|
||||
/// \defgroup FindRootDIEs Find DIEs corresponding to debug map entries.
|
||||
///
|
||||
/// @{
|
||||
/// Recursively walk the \p DIE tree and look for DIEs to
|
||||
/// keep. Store that information in \p CU's DIEInfo.
|
||||
///
|
||||
/// The return value indicates whether the DIE is incomplete.
|
||||
void lookForDIEsToKeep(RelocationManager &RelocMgr, RangesTy &Ranges,
|
||||
const UnitListTy &Units, const DWARFDie &DIE,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
unsigned Flags);
|
||||
|
||||
/// If this compile unit is really a skeleton CU that points to a
|
||||
/// clang module, register it in ClangModules and return true.
|
||||
///
|
||||
/// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
|
||||
/// pointing to the module, and a DW_AT_gnu_dwo_id with the module
|
||||
/// hash.
|
||||
bool registerModuleReference(DWARFDie CUDie, const DWARFUnit &Unit,
|
||||
DebugMap &ModuleMap, const DebugMapObject &DMO,
|
||||
RangesTy &Ranges,
|
||||
OffsetsStringPool &OffsetsStringPool,
|
||||
UniquingStringPool &UniquingStringPoolStringPool,
|
||||
DeclContextTree &ODRContexts,
|
||||
uint64_t ModulesEndOffset, unsigned &UnitID,
|
||||
bool IsLittleEndian, unsigned Indent = 0,
|
||||
bool Quiet = false);
|
||||
|
||||
/// Recursively add the debug info in this clang module .pcm
|
||||
/// file (and all the modules imported by it in a bottom-up fashion)
|
||||
/// to Units.
|
||||
Error loadClangModule(DWARFDie CUDie, StringRef FilePath,
|
||||
StringRef ModuleName, uint64_t DwoId,
|
||||
DebugMap &ModuleMap, const DebugMapObject &DMO,
|
||||
RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
|
||||
UniquingStringPool &UniquingStringPool,
|
||||
DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
|
||||
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,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
bool UseODR);
|
||||
|
||||
unsigned shouldKeepDIE(RelocationManager &RelocMgr, RangesTy &Ranges,
|
||||
const DWARFDie &DIE, const DebugMapObject &DMO,
|
||||
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
|
||||
/// Check if a variable describing DIE should be kept.
|
||||
/// \returns updated TraversalFlags.
|
||||
unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
|
||||
const DWARFDie &DIE, CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo, unsigned Flags);
|
||||
|
||||
unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr,
|
||||
RangesTy &Ranges, const DWARFDie &DIE,
|
||||
const DebugMapObject &DMO, CompileUnit &Unit,
|
||||
CompileUnit::DIEInfo &MyInfo,
|
||||
unsigned Flags);
|
||||
|
||||
bool hasValidRelocation(uint32_t StartOffset, uint32_t EndOffset,
|
||||
CompileUnit::DIEInfo &Info);
|
||||
/// @}
|
||||
|
||||
/// \defgroup Linking Methods used to link the debug information
|
||||
///
|
||||
/// @{
|
||||
|
||||
class DIECloner {
|
||||
DwarfLinkerForBinary &Linker;
|
||||
RelocationManager &RelocMgr;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator &DIEAlloc;
|
||||
|
||||
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits;
|
||||
LinkOptions Options;
|
||||
|
||||
public:
|
||||
DIECloner(DwarfLinkerForBinary &Linker, RelocationManager &RelocMgr,
|
||||
BumpPtrAllocator &DIEAlloc,
|
||||
std::vector<std::unique_ptr<CompileUnit>> &CompileUnits,
|
||||
LinkOptions &Options)
|
||||
: Linker(Linker), RelocMgr(RelocMgr), DIEAlloc(DIEAlloc),
|
||||
CompileUnits(CompileUnits), Options(Options) {}
|
||||
|
||||
/// Recursively clone \p InputDIE into an tree of DIE objects
|
||||
/// where useless (as decided by lookForDIEsToKeep()) bits have been
|
||||
/// stripped out and addresses have been rewritten according to the
|
||||
/// debug map.
|
||||
///
|
||||
/// \param OutOffset is the offset the cloned DIE in the output
|
||||
/// compile unit.
|
||||
/// \param PCOffset (while cloning a function scope) is the offset
|
||||
/// applied to the entry point of the function to get the linked address.
|
||||
/// \param Die the output DIE to use, pass NULL to create one.
|
||||
/// \returns the root of the cloned tree or null if nothing was selected.
|
||||
DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
|
||||
CompileUnit &U, OffsetsStringPool &StringPool,
|
||||
int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
|
||||
bool IsLittleEndian, DIE *Die = nullptr);
|
||||
|
||||
/// Construct the output DIE tree by cloning the DIEs we
|
||||
/// chose to keep above. If there are no valid relocs, then there's
|
||||
/// nothing to clone/emit.
|
||||
void cloneAllCompileUnits(DWARFContext &DwarfContext,
|
||||
const DebugMapObject &DMO, RangesTy &Ranges,
|
||||
OffsetsStringPool &StringPool,
|
||||
bool IsLittleEndian);
|
||||
|
||||
private:
|
||||
using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
|
||||
|
||||
/// Information gathered and exchanged between the various
|
||||
/// clone*Attributes helpers about the attributes of a particular DIE.
|
||||
struct AttributesInfo {
|
||||
/// Names.
|
||||
DwarfStringPoolEntryRef Name, MangledName, NameWithoutTemplate;
|
||||
|
||||
/// Offsets in the string pool.
|
||||
uint32_t NameOffset = 0;
|
||||
uint32_t MangledNameOffset = 0;
|
||||
|
||||
/// Value of AT_low_pc in the input DIE
|
||||
uint64_t OrigLowPc = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
/// Value of AT_high_pc in the input DIE
|
||||
uint64_t OrigHighPc = 0;
|
||||
|
||||
/// Offset to apply to PC addresses inside a function.
|
||||
int64_t PCOffset = 0;
|
||||
|
||||
/// Does the DIE have a low_pc attribute?
|
||||
bool HasLowPc = false;
|
||||
|
||||
/// Does the DIE have a ranges attribute?
|
||||
bool HasRanges = false;
|
||||
|
||||
/// Is this DIE only a declaration?
|
||||
bool IsDeclaration = false;
|
||||
|
||||
AttributesInfo() = default;
|
||||
};
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
unsigned cloneAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
const DebugMapObject &DMO, CompileUnit &U,
|
||||
OffsetsStringPool &StringPool,
|
||||
const DWARFFormValue &Val,
|
||||
const AttributeSpec AttrSpec, unsigned AttrSize,
|
||||
AttributesInfo &AttrInfo, bool IsLittleEndian);
|
||||
|
||||
/// Clone a string attribute described by \p AttrSpec and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, const DWARFUnit &U,
|
||||
OffsetsStringPool &StringPool,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneDieReferenceAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
AttributeSpec AttrSpec,
|
||||
unsigned AttrSize,
|
||||
const DWARFFormValue &Val,
|
||||
const DebugMapObject &DMO,
|
||||
CompileUnit &Unit);
|
||||
|
||||
/// Clone a DWARF expression that may be referencing another DIE.
|
||||
void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
|
||||
const DebugMapObject &DMO, CompileUnit &Unit,
|
||||
SmallVectorImpl<uint8_t> &OutputBuffer);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneBlockAttribute(DIE &Die, const DebugMapObject &DMO,
|
||||
CompileUnit &Unit, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
bool IsLittleEndian);
|
||||
|
||||
/// Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneAddressAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val,
|
||||
const CompileUnit &Unit,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Clone a scalar attribute and add it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
const DebugMapObject &DMO, CompileUnit &U,
|
||||
AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
AttributesInfo &Info);
|
||||
|
||||
/// Get the potential name and mangled name for the entity
|
||||
/// described by \p Die and store them in \Info if they are not
|
||||
/// already there.
|
||||
/// \returns is a name was found.
|
||||
bool getDIENames(const DWARFDie &Die, AttributesInfo &Info,
|
||||
OffsetsStringPool &StringPool, bool StripTemplate = false);
|
||||
|
||||
/// Create a copy of abbreviation Abbrev.
|
||||
void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR);
|
||||
|
||||
uint32_t hashFullyQualifiedName(DWARFDie DIE, CompileUnit &U,
|
||||
const DebugMapObject &DMO,
|
||||
int RecurseDepth = 0);
|
||||
|
||||
/// Helper for cloneDIE.
|
||||
void addObjCAccelerator(CompileUnit &Unit, const DIE *Die,
|
||||
DwarfStringPoolEntryRef Name,
|
||||
OffsetsStringPool &StringPool, bool SkipPubSection);
|
||||
};
|
||||
|
||||
/// Assign an abbreviation number to \p Abbrev
|
||||
void assignAbbrev(DIEAbbrev &Abbrev);
|
||||
|
||||
/// Compute and emit debug_ranges section for \p Unit, and
|
||||
/// patch the attributes referencing it.
|
||||
void patchRangesForUnit(const CompileUnit &Unit, DWARFContext &Dwarf,
|
||||
const DebugMapObject &DMO) const;
|
||||
|
||||
/// Generate and emit the DW_AT_ranges attribute for a compile_unit if it had
|
||||
/// one.
|
||||
void generateUnitRanges(CompileUnit &Unit) const;
|
||||
|
||||
/// Extract the line tables from the original dwarf, extract the relevant
|
||||
/// parts according to the linked function ranges and emit the result in the
|
||||
/// debug_line section.
|
||||
void patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf,
|
||||
RangesTy &Ranges, const DebugMapObject &DMO);
|
||||
|
||||
/// Emit the accelerator entries for \p Unit.
|
||||
void emitAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
void emitDwarfAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
void emitAppleAcceleratorEntriesForUnit(CompileUnit &Unit);
|
||||
|
||||
/// Patch the frame info for an object file and emit it.
|
||||
void patchFrameInfoForObject(const DebugMapObject &, RangesTy &Ranges,
|
||||
DWARFContext &, unsigned AddressSize);
|
||||
|
||||
/// FoldingSet that uniques the abbreviations.
|
||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||
|
||||
/// Storage for the unique Abbreviations.
|
||||
/// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot be
|
||||
/// changed to a vector of unique_ptrs.
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
|
||||
|
||||
/// DIELoc objects that need to be destructed (but not freed!).
|
||||
std::vector<DIELoc *> DIELocs;
|
||||
|
||||
/// DIEBlock objects that need to be destructed (but not freed!).
|
||||
std::vector<DIEBlock *> DIEBlocks;
|
||||
|
||||
/// Allocator used for all the DIEValue objects.
|
||||
BumpPtrAllocator DIEAlloc;
|
||||
/// @}
|
||||
|
||||
private:
|
||||
/// \defgroup Helpers Various helper methods.
|
||||
///
|
||||
/// @{
|
||||
|
@ -492,38 +166,16 @@ private:
|
|||
|
||||
/// Attempt to load a debug object from disk.
|
||||
ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
|
||||
const DebugMap &Map);
|
||||
/// @}
|
||||
const Triple &triple);
|
||||
ErrorOr<DwarfLinkerObjFile &> loadObject(const DebugMapObject &Obj,
|
||||
const DebugMap &DebugMap,
|
||||
remarks::RemarkLinker &RL);
|
||||
|
||||
raw_fd_ostream &OutFile;
|
||||
BinaryHolder &BinHolder;
|
||||
LinkOptions Options;
|
||||
std::unique_ptr<DwarfStreamer> Streamer;
|
||||
|
||||
unsigned MaxDwarfVersion = 0;
|
||||
unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
|
||||
|
||||
bool AtLeastOneAppleAccelTable = false;
|
||||
bool AtLeastOneDwarfAccelTable = false;
|
||||
|
||||
/// The CIEs that have been emitted in the output section. The actual CIE
|
||||
/// data serves a the key to this StringMap, this takes care of comparing the
|
||||
/// semantics of CIEs defined in different object files.
|
||||
StringMap<uint32_t> EmittedCIEs;
|
||||
|
||||
/// Offset of the last CIE that has been emitted in the output
|
||||
/// debug_frame section.
|
||||
uint32_t LastCIEOffset = 0;
|
||||
|
||||
/// Apple accelerator tables.
|
||||
AccelTable<DWARF5AccelTableStaticData> DebugNames;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
|
||||
AccelTable<AppleAccelTableStaticOffsetData> AppleObjc;
|
||||
AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
|
||||
|
||||
/// Mapping the PCM filename to the DwoId.
|
||||
StringMap<uint64_t> ClangModules;
|
||||
std::vector<std::unique_ptr<DwarfLinkerObjFile>> ObjectsForLinking;
|
||||
|
||||
/// A list of all .swiftinterface files referenced by the debug
|
||||
/// info, mapping Module name to path on disk. The entries need to
|
||||
|
|
|
@ -784,12 +784,16 @@ void DwarfStreamer::emitPubSectionForUnit(
|
|||
|
||||
/// Emit .debug_pubnames for \p Unit.
|
||||
void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
|
||||
if (Options.Minimize)
|
||||
return;
|
||||
emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
|
||||
"names", Unit, Unit.getPubnames());
|
||||
}
|
||||
|
||||
/// Emit .debug_pubtypes for \p Unit.
|
||||
void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
|
||||
if (Options.Minimize)
|
||||
return;
|
||||
emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
|
||||
"types", Unit, Unit.getPubtypes());
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "llvm/Remarks/RemarkFormat.h"
|
||||
#include "llvm/Support/WithColor.h"
|
||||
|
||||
#include "llvm/DWARFLinker/DWARFLinker.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -25,13 +26,6 @@ enum class OutputFileType {
|
|||
Assembly,
|
||||
};
|
||||
|
||||
/// The kind of accelerator tables we should emit.
|
||||
enum class AccelTableKind {
|
||||
Apple, ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
|
||||
Dwarf, ///< DWARF v5 .debug_names.
|
||||
Default, ///< Dwarf for DWARF5 or later, Apple otherwise.
|
||||
};
|
||||
|
||||
struct LinkOptions {
|
||||
/// Verbosity
|
||||
bool Verbose = false;
|
||||
|
|
Loading…
Reference in New Issue