diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h --- a/bolt/include/bolt/Core/DIEBuilder.h +++ b/bolt/include/bolt/Core/DIEBuilder.h @@ -16,208 +16,210 @@ #define BOLT_CORE_DIE_BUILDER_H #include "llvm/CodeGen/DIE.h" -#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" -#include "llvm/IR/Type.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" -#include -#include #include #include -#include #include -#include -#include -#include #include -#include #include namespace llvm { namespace bolt { +class DIEStreamer; class DIEBuilder { + friend DIEStreamer; + +public: + /// Wrapper around DIE so we can access DIEs easily. struct DIEInfo { DIE *Die; uint32_t DieId; uint32_t UnitId; - uint32_t CanonicalDIEOffset; }; - struct UnitInfo { - std::list DieInfoList; - uint32_t UnitId; - uint32_t UnitOffset; - bool Isconstructed = false; - uint32_t NewDieId = 0; + /// Contains information for the CU level of DWARF. + struct DWARFUnitInfo { + // Contains all the DIEs for the current unit. + // Accessed by DIE ID. + std::vector> DieInfoVector; + DIE *UnitDie = nullptr; + uint32_t UnitId = 0; + uint32_t UnitOffset = 0; + uint32_t UnitLength = 0; + bool IsConstructed = false; + // A map of DIE offsets in original DWARF section to DIE ID. + // Whih is used to access DieInfoVector. std::unordered_map DIEIDMap; - std::unordered_map DIEId2InfoMap; }; - struct ForwardReferenceInfo { - ForwardReferenceInfo(DIEInfo *Die, - DWARFAbbreviationDeclaration::AttributeSpec spec) - : Dst(Die), AttrSpec(spec) {} +private: + /// Contains information so that we we can update references in locexpr after + /// we calculated all the final DIE offsets. + struct LocWithReference { + LocWithReference(std::vector &&BlockData, DWARFUnit &U, DIE &Die, + dwarf::Form Form, dwarf::Attribute Attr) + : BlockData(BlockData), U(U), Die(Die), Form(Form), Attr(Attr) {} + std::vector BlockData; + DWARFUnit &U; + DIE &Die; + dwarf::Form Form; + dwarf::Attribute Attr; + }; + /// Contains information so that we can update cross CU references, after we + /// calculated all the final DIE offsets. + struct AddrReferenceInfo { + AddrReferenceInfo(DIEInfo *Die, + DWARFAbbreviationDeclaration::AttributeSpec Spec) + : Dst(Die), AttrSpec(Spec) {} DIEInfo *Dst; DWARFAbbreviationDeclaration::AttributeSpec AttrSpec; }; - bool IsBuilt = false; - std::unordered_map> UnitDIEs; - std::unordered_map UnitIDMap; + /// A map of Units to Unit Index. + std::unordered_map UnitIDMap; + /// A map of Type Units to Type DIEs. std::unordered_map TypeDIEMap; std::vector DUList; - std::vector CloneUnitCtxMap; - std::vector> ForwardReferences; + std::vector CloneUnitCtxMap; + std::vector> AddrReferences; FoldingSet AbbreviationsSet; std::vector> Abbreviations; std::vector DWARF4TUVector; - std::vector DWARF4CUVector; + std::vector LocWithReferencesToProcess; BumpPtrAllocator DIEAlloc; /// Resolve the reference in DIE, if target is not loaded into IR, /// pre-allocate it. \p RefCU will be updated to the Unit specific by \p /// RefValue. - DWARFDie - resolveDIEReference(const DWARFFormValue &RefValue, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - DWARFUnit *&RefCU, - DWARFDebugInfoEntry &DwarfDebugInfoEntry, - const std::vector &DUOffsetList); - - /// Clone one attribute according the format. \return the size of this + DWARFDie resolveDIEReference(const DWARFFormValue &RefValue, + DWARFUnit *&RefCU, + DWARFDebugInfoEntry &DwarfDebugInfoEntry, + const std::vector &DUOffsetList); + + /// Resolve the reference in DIE, if target is not loaded into IR, + /// pre-allocate it. \p RefCU will be updated to the Unit specific by \p + /// RefValue. + DWARFDie resolveDIEReference(const uint64_t ReffOffset, DWARFUnit *&RefCU, + DWARFDebugInfoEntry &DwarfDebugInfoEntry, + const std::vector &DUOffsetList); + + /// Clone one attribute according to the format. \return the size of this /// attribute. - uint32_t + void cloneAttribute(DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U, const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, bool IsLittleEndian, - std::vector &DUOffsetList); + const std::vector &DUOffsetList); /// Clone an attribute in string format. - uint32_t cloneStringAttribute( - DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U); + void cloneStringAttribute( + DIE &Die, const DWARFUnit &U, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); /// Clone an attribute in reference format. - uint32_t cloneDieReferenceAttribute( - DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize, - const DWARFFormValue &Val, DWARFUnit &U, - std::vector &DUOffsetList); + void cloneDieReferenceAttribute( + DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val, const std::vector &DUOffsetList); /// Clone an attribute in block format. - uint32_t - cloneBlockAttribute(DIE &Die, DWARFUnit &U, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize, - bool IsLittleEndian); + void cloneBlockAttribute( + DIE &Die, DWARFUnit &U, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); + enum class CloneExpressionStage { INIT, PATCH }; /// Clone an attribute in expression format. \p OutputBuffer will hold the /// output content. - void cloneExpression(DataExtractor &Data, DWARFExpression &Expression, - DWARFUnit &U, SmallVectorImpl &OutputBuffer); + /// Returns true if Expression contains a reference. + bool cloneExpression(const DataExtractor &Data, + const DWARFExpression &Expression, DWARFUnit &U, + SmallVectorImpl &OutputBuffer, + const CloneExpressionStage &Stage); /// Clone an attribute in address format. - uint32_t - cloneAddressAttribute(DIE &Die, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, const DWARFUnit &U); + void cloneAddressAttribute( + DIE &Die, const DWARFUnit &U, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); - /// Clone an attribute in Refsig format. - uint32_t - cloneRefsigAttribute(DIE &Die, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, const DWARFFormValue &Val); + /// Clone an attribute in refsig format. + void cloneRefsigAttribute( + DIE &Die, const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); /// Clone an attribute in scalar format. - uint32_t - cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize); + void cloneScalarAttribute( + DIE &Die, const DWARFDie &InputDIE, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); /// Clone an attribute in loclist format. - uint32_t - cloneLoclistAttrubute(DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize); + void cloneLoclistAttrubute( + DIE &Die, const DWARFDie &InputDIE, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val); - /// Update the Cross-CU reference offset. - void computeReference(); + /// Update references once the layout is finalized. + void updateReferences(); /// Update the Offset and Size of DIE. - uint32_t computeDIEOffset(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset); + uint32_t computeDIEOffset(const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset); - void registerUnit(DWARFUnit &Unit) { - UnitIDMap[&Unit] = DUList.size(); - DUList.push_back(&Unit); - } + void registerUnit(DWARFUnit &DU); /// \return the unique ID of \p U if it exists. - std::optional getUnitId(DWARFUnit &DU) { - if (UnitIDMap.count(&DU)) - return UnitIDMap[&DU]; - return std::nullopt; - } + std::optional getUnitId(const DWARFUnit &DU); - UnitInfo &getUnitInfo(uint32_t UnitId) { return CloneUnitCtxMap[UnitId]; } + DWARFUnitInfo &getUnitInfo(uint32_t UnitId) { + return CloneUnitCtxMap[UnitId]; + } DIEInfo &getDIEInfo(uint32_t UnitId, uint32_t DIEId) { - if (CloneUnitCtxMap[UnitId].DIEId2InfoMap.count(DIEId)) - return *CloneUnitCtxMap[UnitId].DIEId2InfoMap[DIEId]; + if (CloneUnitCtxMap[UnitId].DieInfoVector.size() > DIEId) + return *CloneUnitCtxMap[UnitId].DieInfoVector[DIEId].get(); - errs() << "BOLT-ERROR: The DIE is not allocated before looking up, some" + errs() << "BOLT-WARNING: [internal-dwarf-error]: The DIE is not allocated " + "before looking up, some" << "unexpected corner cases happened.\n"; - return CloneUnitCtxMap[UnitId].DieInfoList.front(); + return *CloneUnitCtxMap[UnitId].DieInfoVector.front().get(); } - UnitInfo &getUnitInfoByDwarfUnit(DWARFUnit &DwarfUnit) { - std::optional UnitId = getUnitId(DwarfUnit); - return getUnitInfo(*UnitId); - } - - std::optional getAllocDIEId(DWARFUnit &DU, DWARFDie &DDie) { - UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU); - uint64_t Offset = DDie.getOffset(); - - if (!UnitInfo.DIEIDMap.count(Offset)) - return std::nullopt; - return UnitInfo.DIEIDMap[Offset]; + std::optional getAllocDIEId(const DWARFUnit &DU, + const uint64_t Offset) { + const DWARFUnitInfo &DWARFUnitInfo = getUnitInfoByDwarfUnit(DU); + auto Iter = DWARFUnitInfo.DIEIDMap.find(Offset); + return (Iter == DWARFUnitInfo.DIEIDMap.end()) + ? std::nullopt + : std::optional(Iter->second); } - - std::optional getAllocDIEId(DWARFUnit &DU, uint64_t Offset) { - UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU); - - if (!UnitInfo.DIEIDMap.count(Offset)) - return std::nullopt; - return UnitInfo.DIEIDMap[Offset]; + std::optional getAllocDIEId(const DWARFUnit &DU, + const DWARFDie &DDie) { + return getAllocDIEId(DU, DDie.getOffset()); } - // To avoid overhead, do not use this unless we do get the UnitInfo first. - // We can use getDIEInfo with UnitId and DieId - DIEInfo &getDIEInfoByDwarfDie(DWARFDie *DwarfDie) { - DWARFUnit *DwarfUnit = DwarfDie->getDwarfUnit(); - std::optional UnitId = getUnitId(*DwarfUnit); - std::optional hasDIEId = getAllocDIEId(*DwarfUnit, *DwarfDie); - assert(hasDIEId.has_value()); + // To avoid overhead, do not use this unless we do get the DWARFUnitInfo + // first. We can use getDIEInfo with UnitId and DieId + DIEInfo &getDIEInfoByDwarfDie(DWARFDie &DwarfDie) { + DWARFUnit &DwarfUnit = *DwarfDie.getDwarfUnit(); + std::optional UnitId = getUnitId(DwarfUnit); + std::optional HasDieId = getAllocDIEId(DwarfUnit, DwarfDie); + assert(HasDieId); - return getDIEInfo(*UnitId, *hasDIEId); + return getDIEInfo(*UnitId, *HasDieId); } - std::optional allocDIE(DWARFUnit &DU, DWARFDie &DDie, - BumpPtrAllocator &Alloc, uint32_t UId, - uint32_t offset = 0); - - uint32_t AllocDIEId(DWARFUnit &DU) { - UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU); - return UnitInfo.NewDieId++; - } + uint32_t allocDIE(const DWARFUnit &DU, const DWARFDie &DDie, + BumpPtrAllocator &Alloc, const uint32_t UId); /// Construct IR for \p DU. \p DUOffsetList specific the Unit in current /// Section. @@ -225,14 +227,22 @@ /// Construct a DIE for \p DDie in \p U. \p DUOffsetList specific the Unit in /// current Section. - DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, bool IsLittleEndian, - uint32_t UnitId, + DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId, std::vector &DUOffsetList); public: DIEBuilder(DWARFContext *DwarfContext, bool IsDWO = false); - std::vector getDIEsByUnit(DWARFUnit &DU) { return UnitDIEs[&DU]; } + /// Returns DWARFUnitInfo for DWARFUnit + DWARFUnitInfo &getUnitInfoByDwarfUnit(const DWARFUnit &DwarfUnit) { + std::optional UnitId = getUnitId(DwarfUnit); + return getUnitInfo(*UnitId); + } + + const std::vector> &getDIEsByUnit(DWARFUnit &DU) { + DWARFUnitInfo &U = getUnitInfoByDwarfUnit(DU); + return U.DieInfoVector; + } std::vector> &getAbbrevs() { return Abbreviations; } @@ -246,17 +256,16 @@ } std::vector getDWARF4TUVector() { return DWARF4TUVector; } - bool isEmpty() { return !IsBuilt; } + bool isEmpty() { return CloneUnitCtxMap.empty(); } - DIE *getUnitDIEbyUnit(DWARFUnit &DU) { - assert(UnitDIEs.count(&DU) && UnitDIEs[&DU].size() && - "DU is not constructed in IR"); - return UnitDIEs[&DU].front(); + DIE *getUnitDIEbyUnit(const DWARFUnit &DU) { + const DWARFUnitInfo &U = getUnitInfoByDwarfUnit(DU); + return U.UnitDie; } /// Generate and populate all Abbrevs. void generateAbbrevs(); - void generateUnitAbbrevs(DIE *die); + void generateUnitAbbrevs(DIE *Die); void assignAbbrev(DIEAbbrev &Abbrev); /// Finish current DIE construction. diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -481,8 +481,6 @@ BinaryContext &BC; }; -class DebugInfoBinaryPatcher; -class DebugAbbrevWriter; enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter }; /// Serializes part of a .debug_loc DWARF section with LocationLists. @@ -607,7 +605,6 @@ static uint32_t LoclistBaseOffset; }; -enum class PatcherKind { SimpleBinaryPatcher, DebugInfoBinaryPatcher }; /// Abstract interface for classes that apply modifications to a binary string. class BinaryPatcher { public: @@ -639,14 +636,6 @@ public: virtual ~SimpleBinaryPatcher() {} - virtual PatcherKind getKind() const { - return PatcherKind::SimpleBinaryPatcher; - } - - static bool classof(const SimpleBinaryPatcher *Patcher) { - return Patcher->getKind() == PatcherKind::SimpleBinaryPatcher; - } - /// Adds a patch to replace the contents of the binary string starting at the /// specified \p Offset with the string \p NewValue. /// The \p OldValueSize is the size of the old value that will be replaced. @@ -693,387 +682,6 @@ std::string patchBinary(StringRef BinaryContents) override; }; -class DebugInfoBinaryPatcher : public SimpleBinaryPatcher { -public: - enum class DebugPatchKind { - PatchBaseClass, - PatchValue32, - PatchValue64to32, - PatchValue32GenericSize, - PatchValue64, - PatchValueVariable, - ReferencePatchValue, - DWARFUnitOffsetBaseLabel, - DestinationReferenceLabel, - NewDebugEntry - }; - - struct Patch { - Patch(uint32_t O, DebugPatchKind K) : Offset(O), Kind(K) {} - DebugPatchKind getKind() const { return Kind; } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchBaseClass; - } - - uint32_t Offset; - DebugPatchKind Kind; - }; - - struct DebugPatch64to32 : public Patch { - DebugPatch64to32(uint32_t O, uint32_t V) - : Patch(O, DebugPatchKind::PatchValue64to32) { - Value = V; - } - DebugPatchKind getKind() const { return Kind; } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchValue64to32; - } - uint32_t Value; - }; - - struct DebugPatch32 : public Patch { - DebugPatch32(uint32_t O, uint32_t V) - : Patch(O, DebugPatchKind::PatchValue32) { - Value = V; - } - DebugPatchKind getKind() const { return Kind; } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchValue32; - } - uint32_t Value; - }; - - /// Patch for 4 byte entry, where original entry size is not 4 bytes or 8 - /// bytes. - struct DebugPatch32GenericSize : public Patch { - DebugPatch32GenericSize(uint32_t O, uint32_t V, uint32_t OVS) - : Patch(O, DebugPatchKind::PatchValue32GenericSize) { - Value = V; - OldValueSize = OVS; - } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchValue32GenericSize; - } - uint32_t Value; - uint32_t OldValueSize; - }; - - struct DebugPatch64 : public Patch { - DebugPatch64(uint32_t O, uint64_t V) - : Patch(O, DebugPatchKind::PatchValue64) { - Value = V; - } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchValue64; - } - uint64_t Value; - }; - - struct DebugPatchVariableSize : public Patch { - DebugPatchVariableSize(uint32_t O, uint32_t OVS, uint32_t V) - : Patch(O, DebugPatchKind::PatchValueVariable) { - OldValueSize = OVS; - Value = V; - } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::PatchValueVariable; - } - uint32_t OldValueSize; - uint32_t Value; - }; - - struct DebugPatchReference : public Patch { - struct Data { - uint32_t OldValueSize : 4; - uint32_t DirectRelative : 1; - uint32_t IndirectRelative : 1; - uint32_t DirectAbsolute : 1; - }; - DebugPatchReference(uint32_t O, uint32_t OVS, uint32_t DO, dwarf::Form F) - : Patch(O, DebugPatchKind::ReferencePatchValue) { - PatchInfo.OldValueSize = OVS; - DestinationOffset = DO; - PatchInfo.DirectRelative = - F == dwarf::DW_FORM_ref1 || F == dwarf::DW_FORM_ref2 || - F == dwarf::DW_FORM_ref4 || F == dwarf::DW_FORM_ref8; - PatchInfo.IndirectRelative = F == dwarf::DW_FORM_ref_udata; - PatchInfo.DirectAbsolute = F == dwarf::DW_FORM_ref_addr; - } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::ReferencePatchValue; - } - Data PatchInfo; - uint32_t DestinationOffset; - }; - - struct DWARFUnitOffsetBaseLabel : public Patch { - DWARFUnitOffsetBaseLabel(uint32_t O) - : Patch(O, DebugPatchKind::DWARFUnitOffsetBaseLabel) {} - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::DWARFUnitOffsetBaseLabel; - } - }; - - struct DestinationReferenceLabel : public Patch { - DestinationReferenceLabel() = delete; - DestinationReferenceLabel(uint32_t O) - : Patch(O, DebugPatchKind::DestinationReferenceLabel) {} - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::DestinationReferenceLabel; - } - }; - - struct NewDebugEntry : public Patch { - NewDebugEntry() = delete; - NewDebugEntry(uint32_t O, std::string &&V) - : Patch(O, DebugPatchKind::NewDebugEntry) { - CurrentOrder = NewDebugEntry::OrderCounter++; - Value = std::move(V); - } - - static bool classof(const Patch *Writer) { - return Writer->getKind() == DebugPatchKind::NewDebugEntry; - } - static uint32_t OrderCounter; - uint32_t CurrentOrder; - std::string Value; - }; - - PatcherKind getKind() const override { - return PatcherKind::DebugInfoBinaryPatcher; - } - - static bool classof(const SimpleBinaryPatcher *Patcher) { - return Patcher->getKind() == PatcherKind::DebugInfoBinaryPatcher; - } - - /// This function takes in \p BinaryContents, and re-writes it with new - /// patches inserted into it. It returns an updated string. - std::string patchBinary(StringRef BinaryContents) override; - - /// Adds a patch to put the integer \p NewValue encoded as a 64-bit - /// little-endian value at offset \p Offset. - void addLE64Patch(uint64_t Offset, uint64_t NewValue) override; - - /// Adds a patch to put the integer \p NewValue encoded as a 32-bit - /// little-endian value at offset \p Offset. - /// The \p OldValueSize is the size of the old value that will be replaced. - void addLE32Patch(uint64_t Offset, uint32_t NewValue, - uint32_t OldValueSize = 4) override; - - /// Add a patch at \p Offset with \p Value using unsigned LEB128 encoding with - /// size \p OldValueSize. - /// The \p OldValueSize is the size of the old value that will be replaced. - void addUDataPatch(uint64_t Offset, uint64_t Value, - uint32_t OldValueSize) override; - - /// Adds a label \p Offset for DWARF UNit. - /// Used to recompute relative references. - void addUnitBaseOffsetLabel(uint64_t Offset); - - /// Adds a Label for destination. Either relative or explicit reference. - void addDestinationReferenceLabel(uint64_t Offset); - - /// Adds a reference at \p Offset to patch with new fully resolved \p - /// DestinationOffset . The \p OldValueSize is the original size of entry in - /// the DIE. The \p Form is the form of the entry. - void addReferenceToPatch(uint64_t Offset, uint32_t DestinationOffset, - uint32_t OldValueSize, dwarf::Form Form); - - /// Inserts a new uint32_t \p Value at the end of \p DIE . - void insertNewEntry(const DWARFDie &DIE, uint32_t); - - /// Inserts a new encoded \p Value at the end of \p DIE . - void insertNewEntry(const DWARFDie &DIE, std::string &&Value); - - /// Clears unordered set for DestinationLabels. - void clearDestinationLabels() { DestinationLabels.clear(); } - - /// Sets DWARF Units offset, \p DWPOffset , within DWP file. - void setDWPOffset(uint64_t DWPOffset) { DWPUnitOffset = DWPOffset; } - - /// When this function is invoked all of the DebugInfo Patches must be done. - /// Returns a map of old CU offsets to new offsets and new sizes. - CUOffsetMap computeNewOffsets(DWARFContext &DWCtx, bool IsDWOContext); - -private: - struct PatchDeleter { - void operator()(Patch *P) const { - Patch *Pp = reinterpret_cast(P); - switch (Pp->Kind) { - default: - llvm_unreachable( - "Not all delete instances handled for Patch derived classes"); - case DebugPatchKind::PatchValue32: - delete reinterpret_cast(P); - break; - case DebugPatchKind::PatchValue64to32: - delete reinterpret_cast(P); - break; - case DebugPatchKind::PatchValue32GenericSize: - delete reinterpret_cast(P); - break; - case DebugPatchKind::PatchValue64: - delete reinterpret_cast(P); - break; - case DebugPatchKind::PatchValueVariable: - delete reinterpret_cast(P); - break; - case DebugPatchKind::ReferencePatchValue: - delete reinterpret_cast(P); - break; - case DebugPatchKind::DWARFUnitOffsetBaseLabel: - delete reinterpret_cast(P); - break; - case DebugPatchKind::DestinationReferenceLabel: - delete reinterpret_cast(P); - break; - case DebugPatchKind::NewDebugEntry: - delete reinterpret_cast(P); - break; - } - } - }; - using UniquePatchPtrType = std::unique_ptr; - - uint64_t DWPUnitOffset{0}; - int32_t ChangeInSize{0}; - std::vector DebugPatches; - /// Mutex used for parallel processing of debug info. - std::mutex WriterMutex; - /// Stores fully resolved addresses of DIEs that are being referenced. - std::unordered_set DestinationLabels; - /// Map of original debug info references to new ones. - std::unordered_map OldToNewOffset; -}; - -/// Class to facilitate modifying and writing abbreviation sections. -class DebugAbbrevWriter { - /// Mutex used for parallel processing of debug info. - std::mutex WriterMutex; - - /// Offsets of abbreviation sets in normal .debug_abbrev section. - std::vector AbbrevSetOffsets; - - /// Abbrev data set for a single unit. - struct AbbrevData { - uint64_t Offset{0}; ///< Offset of the data in the final section. - std::unique_ptr Buffer; - std::unique_ptr Stream; - }; - /// Map original unit to abbreviations data. - std::unordered_map UnitsAbbrevData; - - /// Map from Hash Signature to AbbrevData. - llvm::StringMap> AbbrevDataCache; - - /// Attributes substitution (patch) information. - struct PatchInfo { - dwarf::Attribute OldAttr; - dwarf::Attribute NewAttr; - uint8_t NewAttrForm; - }; - - struct AbbrevEntry { - dwarf::Attribute Attr; - dwarf::Form Form; - }; - - using PatchesTy = std::unordered_map>; - std::unordered_map Patches; - - using AbbrevEntryTy = std::unordered_map>; - std::unordered_map NewAbbrevEntries; - - /// DWARF context containing abbreviations. - DWARFContext &Context; - - /// DWO ID used to identify unit contribution in DWP. - std::optional DWOId; - - /// Add abbreviations from compile/type \p Unit to the writer. - void addUnitAbbreviations(DWARFUnit &Unit); - -public: - /// Create an abbrev section writer for abbreviations in \p Context. - /// If no \p DWOId is given, all normal (non-DWO) abbreviations in the - /// \p Context are handled. Otherwise, only abbreviations associated with - /// the compile unit matching \p DWOId in DWP or DWO will be covered by - /// an instance of this class. - /// - /// NOTE: Type unit abbreviations are not handled separately for DWOs. - /// Most of the time, using type units with DWO is not a good idea. - /// If type units are used, the caller is responsible for verifying - /// that abbreviations are shared by CU and TUs. - DebugAbbrevWriter(DWARFContext &Context, - std::optional DWOId = std::nullopt) - : Context(Context), DWOId(DWOId) {} - - DebugAbbrevWriter(const DebugAbbrevWriter &) = delete; - DebugAbbrevWriter &operator=(const DebugAbbrevWriter &) = delete; - - DebugAbbrevWriter(DebugAbbrevWriter &&) = delete; - DebugAbbrevWriter &operator=(DebugAbbrevWriter &&) = delete; - - virtual ~DebugAbbrevWriter() = default; - - /// Substitute attribute \p AttrTag in abbreviation declaration \p Abbrev - /// belonging to CU \p Unit with new attribute \p NewAttrTag having - /// \p NewAttrForm form. - void addAttributePatch(const DWARFUnit &Unit, - const DWARFAbbreviationDeclaration *Abbrev, - dwarf::Attribute AttrTag, dwarf::Attribute NewAttrTag, - uint8_t NewAttrForm) { - assert(&Unit.getContext() == &Context && - "cannot update attribute from a different DWARF context"); - std::lock_guard Lock(WriterMutex); - Patches[&Unit][Abbrev].emplace_back( - PatchInfo{AttrTag, NewAttrTag, NewAttrForm}); - } - - /// Adds attribute \p AttrTag and \p NewAttrForm in abbreviation declaration - /// \p Abbrev belonging to CU \p Unit . - void addAttribute(const DWARFUnit &Unit, - const DWARFAbbreviationDeclaration *Abbrev, - dwarf::Attribute AttrTag, dwarf::Form AttrForm) { - assert(&Unit.getContext() == &Context && - "cannot update attribute from a different DWARF context"); - std::lock_guard Lock(WriterMutex); - bool AlreadyAdded = - llvm::any_of(NewAbbrevEntries[&Unit][Abbrev], - [&](AbbrevEntry &E) { return E.Attr == AttrTag; }); - - if (AlreadyAdded) - return; - NewAbbrevEntries[&Unit][Abbrev].emplace_back( - AbbrevEntry{AttrTag, AttrForm}); - } - - /// Return a buffer with concatenated abbrev sections for all CUs and TUs - /// in the associated DWARF context. Section offsets could be queried using - /// getAbbreviationsOffsetForUnit() interface. For DWP, we are using DWOId - /// to return only that unit's contribution to abbrev section. - std::unique_ptr finalize(); - - /// Return an offset in the finalized abbrev section corresponding to CU/TU. - uint64_t getAbbreviationsOffsetForUnit(const DWARFUnit &Unit) { - assert(!DWOId && "offsets are tracked for non-DWO units only"); - assert(UnitsAbbrevData.count(&Unit) && "no abbrev data found for unit"); - return UnitsAbbrevData[&Unit]->Offset; - } -}; - /// Similar to MCDwarfLineEntry, but identifies the location by its address /// instead of MCLabel. class BinaryDwarfLineEntry : public MCDwarfLoc { diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -32,13 +32,24 @@ class DWARFRewriter { public: DWARFRewriter() = delete; - using DebugTypesSignaturesPerCUMap = - std::unordered_map>; + /// Contains information about TU so we can write out correct entries in GDB + /// index. + struct GDBIndexTUEntry { + uint64_t UnitOffset; + uint64_t TypeHash; + uint64_t TypeDIERelativeOffset; + }; + /// Contains information for CU or TU so we can output correct {cu, tu}-index. + struct UnitMeta { + uint64_t Offset; + uint64_t Length; + uint64_t TUHash; + }; private: BinaryContext &BC; - std::mutex DebugInfoPatcherMutex; + std::mutex DWARFRewriterMutex; /// Stores and serializes information that will be put into the /// .debug_ranges DWARF section. @@ -65,9 +76,6 @@ /// .debug_str_offsets DWARF section. std::unique_ptr StrOffstsWriter; - /// .debug_abbrev section writer for the main binary. - std::unique_ptr AbbrevWriter; - using LocWriters = std::map>; /// Use a separate location list writer for each compilation unit LocWriters LocListWritersByCU; @@ -78,23 +86,10 @@ /// Store Rangelists writer for each DWO CU. RangeListsDWOWriers RangeListsWritersByCU; - using DebugAbbrevDWOWriters = - std::unordered_map>; - /// Abbrev section writers for DWOs. - DebugAbbrevDWOWriters BinaryDWOAbbrevWriters; - - using DebugInfoDWOPatchers = - std::unordered_map>; - /// Binary patchers for DWO debug_info sections. - DebugInfoDWOPatchers BinaryDWODebugInfoPatchers; - - /// Stores all the Type Signatures for DWO CU. - DebugTypesSignaturesPerCUMap TypeSignaturesPerCU; - std::mutex LocListDebugInfoPatchesMutex; /// Dwo id specific its .debug_info.dwo section content. - std::unordered_map DwoDebufInfoMap; + std::unordered_map DwoDebugInfoMap; /// Dwo id specific its .debug_abbrev.dwo section content. std::unordered_map DwoDebugAbbrevMap; @@ -108,6 +103,16 @@ std::unordered_map LineTablePatchMap; std::unordered_map TypeUnitRelocMap; + /// Entries for GDB Index Types CU List + using GDBIndexTUEntryType = std::vector; + GDBIndexTUEntryType GDBIndexTUEntryVector; + + using UnitMetaVectorType = std::vector; + using TUnitMetaDwoMapType = std::unordered_map; + using CUnitMetaDwoMapType = std::unordered_map; + CUnitMetaDwoMapType CUnitMetaDwoMap; + TUnitMetaDwoMapType TUnitMetaDwoMap; + /// DWARFLegacy is all DWARF versions before DWARF 5. enum class DWARFVersion { DWARFLegacy, DWARF5 }; @@ -142,7 +147,7 @@ void updateDebugAddressRanges(); /// Rewrite .gdb_index section if present. - void updateGdbIndexSection(CUOffsetMap &CUMap); + void updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs); /// Output .dwo files. void writeDWOFiles(std::unordered_map &DWOIdToName); @@ -167,21 +172,6 @@ operator DWARFDie() { return DWARFDie(Unit, &DIE); } }; - /// DIEs with abbrevs that were not converted to DW_AT_ranges. - /// We only update those when all DIEs have been processed to guarantee that - /// the abbrev (which is shared) is intact. - using PendingRangesType = std::unordered_map< - const DWARFAbbreviationDeclaration *, - std::vector>>; - - /// Convert \p Abbrev from using a simple DW_AT_(low|high)_pc range to - /// DW_AT_ranges with optional \p RangesBase. - void - convertToRangesPatchAbbrev(const DWARFUnit &Unit, - const DWARFAbbreviationDeclaration *Abbrev, - DebugAbbrevWriter &AbbrevWriter, - std::optional RangesBase = std::nullopt); - /// Update \p DIE that was using DW_AT_(low|high)_pc with DW_AT_ranges offset. /// Updates to the DIE should be synced with abbreviation updates using the /// function above. @@ -191,22 +181,6 @@ DIEValue &HighPCAttrInfo, uint64_t LowPCToUse, std::optional RangesBase = std::nullopt); - /// Helper function for creating and returning per-DWO patchers/writers. - template - Patcher *getBinaryDWOPatcherHelper(T &BinaryPatchers, uint64_t DwoId) { - std::lock_guard Lock(DebugInfoPatcherMutex); - auto Iter = BinaryPatchers.find(DwoId); - if (Iter == BinaryPatchers.end()) { - // Using make_pair instead of {} to work around bug in older version of - // the library. https://timsong-cpp.github.io/lwg-issues/2354 - Iter = BinaryPatchers - .insert(std::make_pair(DwoId, std::make_unique())) - .first; - } - - return static_cast(Iter->second.get()); - } - /// Adds a \p Str to .debug_str section. /// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using /// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets @@ -223,30 +197,6 @@ /// Update stmt_list for CUs based on the new .debug_line \p Layout. void updateLineTableOffsets(const MCAsmLayout &Layout); - /// Returns a DWO Debug Info Patcher for DWO ID. - /// Creates a new instance if it does not already exist. - SimpleBinaryPatcher *getBinaryDWODebugInfoPatcher(uint64_t DwoId) { - return getBinaryDWOPatcherHelper( - BinaryDWODebugInfoPatchers, DwoId); - } - - /// Creates abbrev writer for DWO unit with \p DWOId. - DebugAbbrevWriter *createBinaryDWOAbbrevWriter(DWARFContext &Context, - uint64_t DWOId) { - std::lock_guard Lock(DebugInfoPatcherMutex); - auto &Entry = BinaryDWOAbbrevWriters[DWOId]; - Entry = std::make_unique(Context, DWOId); - return Entry.get(); - } - - /// Returns DWO abbrev writer for \p DWOId. The writer must exist. - DebugAbbrevWriter *getBinaryDWOAbbrevWriter(uint64_t DWOId) { - auto Iter = BinaryDWOAbbrevWriters.find(DWOId); - assert(Iter != BinaryDWOAbbrevWriters.end() && "writer does not exist"); - return Iter->second.get(); - } - /// Given a \p DWOId, return its DebugLocWriter if it exists. DebugLocWriter *getDebugLocWriter(uint64_t DWOId) { auto Iter = LocListWritersByCU.find(DWOId); @@ -255,7 +205,7 @@ } StringRef getDwoDebugInfoStr(uint64_t DWOId) { - return DwoDebufInfoMap[DWOId]; + return DwoDebugInfoMap[DWOId]; } StringRef getDwoDebugAbbrevStr(uint64_t DWOId) { @@ -269,7 +219,7 @@ uint64_t getDwoRangesBase(uint64_t DWOId) { return DwoRangesBase[DWOId]; } void setDwoDebugInfoStr(uint64_t DWOId, StringRef Str) { - DwoDebufInfoMap[DWOId] = Str.str(); + DwoDebugInfoMap[DWOId] = Str.str(); } void setDwoDebugAbbrevStr(uint64_t DWOId, StringRef Str) { @@ -283,6 +233,39 @@ void setDwoRangesBase(uint64_t DWOId, uint64_t RangesBase) { DwoRangesBase[DWOId] = RangesBase; } + + /// Adds an GDBIndexTUEntry if .gdb_index seciton exists. + void addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry); + + /// Returns all entries needed for Types CU list + const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const { + return GDBIndexTUEntryVector; + } + + /// Stores meta data for each CU per DWO ID. It's used to create cu-index for + /// DWARF5. + void addCUnitMetaEntry(const uint64_t DWOId, const UnitMeta &Entry) { + auto RetVal = CUnitMetaDwoMap.insert({DWOId, Entry}); + if (!RetVal.second) + errs() << "BOLT-WARNING: [internal-dwarf-error]: Trying to set CU meta " + "data twice for DWOID: " + << Twine::utohexstr(DWOId) << ".\n"; + } + + /// Stores meta data for each TU per DWO ID. It's used to create cu-index for + /// DWARF5. + void addTUnitMetaEntry(const uint64_t DWOId, const UnitMeta &Entry) { + TUnitMetaDwoMap[DWOId].emplace_back(Entry); + } + + /// Returns Meta data for TUs in offset increasing order. + UnitMetaVectorType &getTUnitMetaEntries(const uint64_t DWOId) { + return TUnitMetaDwoMap[DWOId]; + } + /// Returns Meta data for TUs in offset increasing order. + const UnitMeta &getCUnitMetaEntry(const uint64_t DWOId) { + return CUnitMetaDwoMap[DWOId]; + } }; } // namespace bolt diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -1,3 +1,11 @@ +//===- bolt/Core/DIEBuilder.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 "bolt/Core/DIEBuilder.h" #include "bolt/Core/BinaryContext.h" #include "bolt/Core/ParallelUtilities.h" @@ -32,51 +40,80 @@ namespace llvm { namespace bolt { -void DIEBuilder::computeReference() { - for (auto &[SrcDIEInfo, ReferenceInfo] : ForwardReferences) { +void DIEBuilder::updateReferences() { + for (auto &[SrcDIEInfo, ReferenceInfo] : AddrReferences) { DIEInfo *DstDIEInfo = ReferenceInfo.Dst; - UnitInfo &DstUnitInfo = getUnitInfo(DstDIEInfo->UnitId); + DWARFUnitInfo &DstUnitInfo = getUnitInfo(DstDIEInfo->UnitId); dwarf::Attribute Attr = ReferenceInfo.AttrSpec.Attr; dwarf::Form Form = ReferenceInfo.AttrSpec.Form; - uint64_t CUBase = 0; - - // If DWARF 4, type unit is store in .debug_types. So we need to calibrate - // the begin of .debug_info to the first Compile Unit offset. - if (!DWARF4CUVector.empty()) { - UnitInfo &FirstCUInfo = getUnitInfoByDwarfUnit(*DWARF4CUVector.front()); - CUBase = FirstCUInfo.UnitOffset; - } - uint64_t NewAddr = - DstDIEInfo->Die->getOffset() + DstUnitInfo.UnitOffset - CUBase; + const uint64_t NewAddr = + DstDIEInfo->Die->getOffset() + DstUnitInfo.UnitOffset; SrcDIEInfo->Die->replaceValue(DIEAlloc, Attr, Form, DIEInteger(NewAddr)); } + // Handling referenes in location expressions. + for (LocWithReference &LocExpr : LocWithReferencesToProcess) { + SmallVector Buffer; + DataExtractor Data(StringRef((const char *)LocExpr.BlockData.data(), + LocExpr.BlockData.size()), + LocExpr.U.isLittleEndian(), + LocExpr.U.getAddressByteSize()); + DWARFExpression Expr(Data, LocExpr.U.getAddressByteSize(), + LocExpr.U.getFormParams().Format); + cloneExpression(Data, Expr, LocExpr.U, Buffer, CloneExpressionStage::PATCH); + + DIEValueList *AttrVal; + if (LocExpr.Form == dwarf::DW_FORM_exprloc) { + DIELoc *DL = new (DIEAlloc) DIELoc; + DL->setSize(Buffer.size()); + AttrVal = static_cast(DL); + } else { + DIEBlock *DBL = new (DIEAlloc) DIEBlock; + DBL->setSize(Buffer.size()); + AttrVal = static_cast(DBL); + } + for (auto Byte : Buffer) + AttrVal->addValue(DIEAlloc, static_cast(0), + dwarf::DW_FORM_data1, DIEInteger(Byte)); + + DIEValue Value; + if (LocExpr.Form == dwarf::DW_FORM_exprloc) + Value = + DIEValue(dwarf::Attribute(LocExpr.Attr), dwarf::Form(LocExpr.Form), + static_cast(AttrVal)); + else + Value = + DIEValue(dwarf::Attribute(LocExpr.Attr), dwarf::Form(LocExpr.Form), + static_cast(AttrVal)); + + LocExpr.Die.replaceValue(DIEAlloc, LocExpr.Attr, LocExpr.Form, Value); + } + return; } -std::optional DIEBuilder::allocDIE(DWARFUnit &DU, DWARFDie &DDie, - BumpPtrAllocator &Alloc, - uint32_t UId, uint32_t offset) { - auto &UnitInfo = getUnitInfo(UId); - auto DDieOffset = DDie.getOffset(); - if (UnitInfo.DIEIDMap.count(DDieOffset)) - return UnitInfo.DIEIDMap[DDieOffset]; - uint32_t DId = AllocDIEId(DU); +uint32_t DIEBuilder::allocDIE(const DWARFUnit &DU, const DWARFDie &DDie, + BumpPtrAllocator &Alloc, const uint32_t UId) { + DWARFUnitInfo &DWARFUnitInfo = getUnitInfo(UId); + const uint64_t DDieOffset = DDie.getOffset(); + if (DWARFUnitInfo.DIEIDMap.count(DDieOffset)) + return DWARFUnitInfo.DIEIDMap[DDieOffset]; DIE *Die = DIE::get(Alloc, dwarf::Tag(DDie.getTag())); - UnitInfo.DIEIDMap[DDieOffset] = DId; - UnitInfo.DieInfoList.push_back(DIEInfo{Die, DId, UId, offset}); - UnitInfo.DIEId2InfoMap[DId] = &UnitInfo.DieInfoList.back(); - + const uint32_t DId = DWARFUnitInfo.DieInfoVector.size(); + DWARFUnitInfo.DIEIDMap[DDieOffset] = DId; + DWARFUnitInfo.DieInfoVector.emplace_back( + std::make_unique(DIEInfo{Die, DId, UId})); return DId; } void DIEBuilder::constructFromUnit(DWARFUnit &DU, std::vector &DUOffsetList) { std::optional UnitId = getUnitId(DU); - if (!UnitId.has_value()) { - errs() << "BOLT-WARNING: " << format("Skip Unit at 0x%x\n", DU.getOffset()); + if (!UnitId) { + errs() << "BOLT-WARNING: [internal-dwarf-error]: " + << "Skip Unit at " << Twine::utohexstr(DU.getOffset()) << "\n"; return; } @@ -88,20 +125,14 @@ std::vector CurParentDIEStack; std::vector Parents; uint32_t TUTypeOffset = 0; - bool IsTypeDIE = false; - bool IsCUDIE = true; - if (DWARFTypeUnit *TU = dyn_cast_or_null(&DU)) { + if (DWARFTypeUnit *TU = dyn_cast_or_null(&DU)) TUTypeOffset = TU->getTypeOffset(); - } assert(DebugInfoData.isValidOffset(NextCUOffset - 1)); Parents.push_back(UINT32_MAX); do { - if (TUTypeOffset == DIEOffset - DU.getOffset()) { - IsTypeDIE = true; - } - + const bool IsTypeDIE = (TUTypeOffset == DIEOffset - DU.getOffset()); if (!DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, Parents.back())) break; @@ -110,153 +141,117 @@ DIEEntry.getAbbreviationDeclarationPtr()) { DWARFDie DDie(&DU, &DIEEntry); - DIE *CurDIE = constructDIEFast(DDie, DU, DU.getContext().isLittleEndian(), - *UnitId, DUOffsetList); - if (IsTypeDIE) { + DIE *CurDIE = constructDIEFast(DDie, DU, *UnitId, DUOffsetList); + DWARFUnitInfo &UI = getUnitInfo(*UnitId); + // Can't rely on first element in DieVector due to cross CU forward + // references. + if (!UI.UnitDie) + UI.UnitDie = CurDIE; + if (IsTypeDIE) TypeDIEMap[&DU] = CurDIE; - IsTypeDIE = false; - } if (!CurParentDIEStack.empty()) CurParentDIEStack.back()->addChild(CurDIE); - if (AbbrDecl->hasChildren()) { + if (AbbrDecl->hasChildren()) CurParentDIEStack.push_back(CurDIE); - } else if (IsCUDIE) { - // Stop if we have single compile unit die w/o children. - break; - } } else { // NULL DIE: finishes current children scope. CurParentDIEStack.pop_back(); } - - if (IsCUDIE) - IsCUDIE = false; } while (CurParentDIEStack.size() > 0); - CloneUnitCtxMap[*UnitId].Isconstructed = true; + CloneUnitCtxMap[*UnitId].IsConstructed = true; } DIEBuilder::DIEBuilder(DWARFContext *DwarfContext, bool IsDWO) { - outs() << "BOLT-INFO: Constructing DIE...\n"; - IsBuilt = true; - const DWARFUnitIndex &TUIndex = DwarfContext->getTUIndex(); if (!TUIndex.getRows().empty()) { for (auto &Row : TUIndex.getRows()) { uint64_t Signature = Row.getSignature(); - // manually populate TypeUnit to UnitVector DwarfContext->getTypeUnitForHash(DwarfContext->getMaxVersion(), Signature, true); } } - uint32_t MaxVersion = - IsDWO ? DwarfContext->getMaxDWOVersion() : DwarfContext->getMaxVersion(); unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() : DwarfContext->getNumCompileUnits(); - DWARFContext::compile_unit_range CU4Ranges = - IsDWO ? DwarfContext->dwo_compile_units() : DwarfContext->compile_units(); - DWARFContext::unit_iterator_range CU5Ranges = - IsDWO ? DwarfContext->dwo_info_section_units() - : DwarfContext->info_section_units(); + CUNum += IsDWO ? DwarfContext->getNumDWOTypeUnits() + : DwarfContext->getNumTypeUnits(); - if (MaxVersion >= 5) { - CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() + - DwarfContext->getNumDWOTypeUnits() - : DwarfContext->getNumCompileUnits() + - DwarfContext->getNumTypeUnits(); - } + CloneUnitCtxMap.resize(CUNum); + DWARFContext::unit_iterator_range CU4TURanges = + IsDWO ? DwarfContext->dwo_types_section_units() + : DwarfContext->types_section_units(); - CloneUnitCtxMap = std::vector(CUNum); + for (std::unique_ptr &DU : CU4TURanges) { + registerUnit(*DU.get()); + DWARF4TUVector.push_back(DU.get()); + } + for (std::unique_ptr &DU : CU4TURanges) + constructFromUnit(*DU.get(), DWARF4TUVector); - if (MaxVersion >= 5) { - for (std::unique_ptr &DU : CU5Ranges) { - if (!DU.get()) - continue; - registerUnit(*DU.get()); - } - for (std::unique_ptr &DU : CU5Ranges) { - if (!DU.get()) - continue; - constructFromUnit(*DU.get(), DUList); - } - } else { - DWARFContext::unit_iterator_range CU4TURanges = - IsDWO ? DwarfContext->dwo_types_section_units() - : DwarfContext->types_section_units(); - for (std::unique_ptr &DU : CU4TURanges) { - CloneUnitCtxMap.resize(CloneUnitCtxMap.size() + 1); - registerUnit(*DU.get()); - DWARF4TUVector.push_back(DU.get()); - } - for (std::unique_ptr &DU : CU4TURanges) { - constructFromUnit(*DU.get(), DWARF4TUVector); - } + DWARFContext::unit_iterator_range CURanges = + IsDWO ? DwarfContext->dwo_info_section_units() + : DwarfContext->info_section_units(); - for (std::unique_ptr &DU : CU4Ranges) { - registerUnit(*DU.get()); - DWARF4CUVector.push_back(DU.get()); - } - for (std::unique_ptr &DU : CU4Ranges) { - constructFromUnit(*DU.get(), DWARF4CUVector); - } + // This handles DWARF4 CUs and DWARF5 CU/TUs. + // Creating a vector so that for reference handling only DWARF5 CU/TUs are + // used, and not DWARF4 TUs. + std::vector DWARF5CUTUVector; + for (std::unique_ptr &DU : CURanges) { + registerUnit(*DU.get()); + DWARF5CUTUVector.push_back(DU.get()); } - outs() << "BOLT-INFO: Finish constructing DIE\n"; + + for (std::unique_ptr &DU : CURanges) + constructFromUnit(*DU.get(), DWARF5CUTUVector); } -DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U, - bool IsLittleEndian, uint32_t UnitId, +DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U, uint32_t UnitId, std::vector &DUOffsetList) { std::optional Idx = getAllocDIEId(U, DDie); - if (Idx.has_value()) { - UnitInfo &UnitInfo = getUnitInfo(UnitId); + if (Idx) { + DWARFUnitInfo &DWARFUnitInfo = getUnitInfo(UnitId); DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); - if (UnitInfo.Isconstructed && DieInfo.Die) + if (DWARFUnitInfo.IsConstructed && DieInfo.Die) return DieInfo.Die; } else { Idx = allocDIE(U, DDie, DIEAlloc, UnitId); } DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); - DIE *Die = DieInfo.Die; - UnitDIEs[&U].push_back(Die); uint64_t Offset = DDie.getOffset(); uint64_t NextOffset = Offset; DWARFDataExtractor Data = U.getDebugInfoExtractor(); DWARFDebugInfoEntry DDIEntry; - if (DDIEntry.extractFast(U, &NextOffset, Data, U.getNextUnitOffset(), 0)) { + if (DDIEntry.extractFast(U, &NextOffset, Data, U.getNextUnitOffset(), 0)) assert(NextOffset - U.getOffset() <= Data.getData().size() && "NextOffset OOB"); - } SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset)); Data = DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize()); - Offset = 0; const DWARFAbbreviationDeclaration *Abbrev = DDie.getAbbreviationDeclarationPtr(); - Offset += getULEB128Size(Abbrev->getCode()); + uint64_t AttrOffset = getULEB128Size(Abbrev->getCode()); - for (const auto &AttrSpec : Abbrev->attributes()) { + using AttrSpec = DWARFAbbreviationDeclaration::AttributeSpec; + for (const AttrSpec &AttrSpec : Abbrev->attributes()) { DWARFFormValue Val(AttrSpec.Form); - uint64_t AttrSize = Offset; - Val.extractValue(Data, &Offset, U.getFormParams(), &U); - AttrSize = Offset - AttrSize; - cloneAttribute(*Die, DDie, U, Val, AttrSpec, AttrSize, IsLittleEndian, - DUOffsetList); + Val.extractValue(Data, &AttrOffset, U.getFormParams(), &U); + cloneAttribute(*DieInfo.Die, DDie, U, Val, AttrSpec, DUOffsetList); } - return Die; + return DieInfo.Die; } static DWARFUnit *getUnitForOffset(const std::vector &Units, - uint64_t Offset) { + const uint64_t Offset) { auto CU = llvm::upper_bound(Units, Offset, [](uint64_t LHS, const DWARFUnit *RHS) { return LHS < RHS->getNextUnitOffset(); @@ -264,14 +259,12 @@ return CU != Units.end() ? *CU : nullptr; } -uint32_t DIEBuilder::computeDIEOffset(DWARFUnit &CU, DIE &Die, +uint32_t DIEBuilder::computeDIEOffset(const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset) { uint32_t CurSize = 0; - Die.setOffset(CurOffset); - for (DIEValue &Val : Die.values()) { + for (DIEValue &Val : Die.values()) CurSize += Val.sizeOf(CU.getFormParams()); - } CurSize += getULEB128Size(Die.getAbbrevNumber()); CurOffset += CurSize; @@ -292,32 +285,54 @@ void DIEBuilder::finish() { uint64_t UnitStartOffset = 0; - - for (DWARFUnit *CU : DUList) { - DIE *UnitDIE = getUnitDIEbyUnit(*CU); - uint32_t HeaderSize = CU->getHeaderSize(); + auto computeOffset = [&](const DWARFUnit &CU) -> void { + DIE *UnitDIE = getUnitDIEbyUnit(CU); + uint32_t HeaderSize = CU.getHeaderSize(); uint32_t CurOffset = HeaderSize; - computeDIEOffset(*CU, *UnitDIE, CurOffset); + computeDIEOffset(CU, *UnitDIE, CurOffset); - UnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(*CU); + DWARFUnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(CU); CurUnitInfo.UnitOffset = UnitStartOffset; - UnitStartOffset += HeaderSize + UnitDIE->getSize(); + CurUnitInfo.UnitLength = HeaderSize + UnitDIE->getSize(); + UnitStartOffset += CurUnitInfo.UnitLength; + }; + unsigned Index = 0; + unsigned Size = DUList.size(); + // Computing offsets for .debug_types section. + // It's processed first when CU is registered so will be at the begginnig of + // the vector. + for (; Index < Size; ++Index) { + const DWARFUnit &CU = *DUList[Index]; + if (!(CU.getVersion() < 5 && CU.isTypeUnit())) + break; + computeOffset(CU); } + UnitStartOffset = 0; + for (; Index < Size; ++Index) + computeOffset(*DUList[Index]); - computeReference(); + updateReferences(); } -DWARFDie DIEBuilder::resolveDIEReference( - const DWARFFormValue &RefValue, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, DWARFUnit *&RefCU, - DWARFDebugInfoEntry &DwarfDebugInfoEntry, - const std::vector &DUOffsetList) { +DWARFDie +DIEBuilder::resolveDIEReference(const DWARFFormValue &RefValue, + DWARFUnit *&RefCU, + DWARFDebugInfoEntry &DwarfDebugInfoEntry, + const std::vector &DUOffsetList) { assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); uint64_t RefOffset = *RefValue.getAsReference(); + return resolveDIEReference(RefOffset, RefCU, DwarfDebugInfoEntry, + DUOffsetList); +} - if ((RefCU = getUnitForOffset(DUOffsetList, RefOffset))) { +DWARFDie +DIEBuilder::resolveDIEReference(const uint64_t RefOffset, DWARFUnit *&RefCU, + DWARFDebugInfoEntry &DwarfDebugInfoEntry, + const std::vector &DUOffsetList) { + uint64_t TmpRefOffset = RefOffset; + if ((RefCU = getUnitForOffset(DUOffsetList, TmpRefOffset))) { DWARFDataExtractor DebugInfoData = RefCU->getDebugInfoExtractor(); - if (DwarfDebugInfoEntry.extractFast(*RefCU, &RefOffset, DebugInfoData, + if (DwarfDebugInfoEntry.extractFast(*RefCU, &TmpRefOffset, DebugInfoData, RefCU->getNextUnitOffset(), 0)) { // In a file with broken references, an attribute might point to a NULL // DIE. @@ -326,55 +341,45 @@ std::optional UnitId = getUnitId(*RefCU); // forward reference - if (UnitId.has_value() && !CloneUnitCtxMap[*UnitId].Isconstructed) { - std::optional IsAllocId = getAllocDIEId(*RefCU, RefDie); - if (!IsAllocId.has_value()) { - // forward reference but need allocate a empty one - IsAllocId = allocDIE(*RefCU, RefDie, DIEAlloc, *UnitId); - } - - uint32_t DIEId = *IsAllocId; - DIEInfo &DieInfo = getDIEInfo(*UnitId, DIEId); - DieInfo.CanonicalDIEOffset = 0xDEADBEEF; - } + if (UnitId && !CloneUnitCtxMap[*UnitId].IsConstructed && + !getAllocDIEId(*RefCU, RefDie)) + allocDIE(*RefCU, RefDie, DIEAlloc, *UnitId); return RefDie; } } } - llvm_unreachable("could not find referenced CU\n"); + errs() << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " + "CU.\n"; return DWARFDie(); } -uint32_t DIEBuilder::cloneDieReferenceAttribute( - DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize, - const DWARFFormValue &Val, DWARFUnit &U, - std::vector &DUOffsetList) { - uint64_t Ref = *Val.getAsReference(); +void DIEBuilder::cloneDieReferenceAttribute( + DIE &Die, const DWARFUnit &U, const DWARFDie &InputDIE, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val, const std::vector &DUOffsetList) { + const uint64_t Ref = *Val.getAsReference(); DIE *NewRefDie = nullptr; DWARFUnit *RefUnit = nullptr; DWARFDebugInfoEntry DDIEntry; - DWARFDie RefDie = - resolveDIEReference(Val, AttrSpec, RefUnit, DDIEntry, DUOffsetList); - - if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling) - return 0; - - std::optional UnitId = getUnitId(*RefUnit); - std::optional IsAllocId = getAllocDIEId(*RefUnit, RefDie); - if (!IsAllocId.has_value()) - llvm_unreachable( - "[error] encounter unexpected unallocated DIE. Should be alloc!"); - uint32_t DIEId = *IsAllocId; + const DWARFDie RefDie = + resolveDIEReference(Val, RefUnit, DDIEntry, DUOffsetList); + + if (!RefDie) + return; + + const std::optional UnitId = getUnitId(*RefUnit); + const std::optional IsAllocId = getAllocDIEId(*RefUnit, RefDie); + assert(IsAllocId.has_value() && "Encountered unexpected unallocated DIE."); + const uint32_t DIEId = *IsAllocId; DIEInfo &DieInfo = getDIEInfo(*UnitId, DIEId); if (!DieInfo.Die) { assert(Ref > InputDIE.getOffset()); - llvm_unreachable( - "[error] encounter unexpected unallocated DIE. Should be alloc!"); + errs() << "BOLT-WARNING: [internal-dwarf-error]: encounter unexpected " + "unallocated DIE. Should be alloc!\n"; // We haven't cloned this DIE yet. Just create an empty one and // store it. It'll get really cloned when we process it. DieInfo.Die = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); @@ -386,49 +391,48 @@ // to calculate them in `finish` due to the possible modification of // the DIE. DWARFDie CurDie = const_cast(InputDIE); - DIEInfo *CurDieInfo = &getDIEInfoByDwarfDie(&CurDie); - ForwardReferences.push_back( - std::make_pair(CurDieInfo, ForwardReferenceInfo(&DieInfo, AttrSpec))); + DIEInfo *CurDieInfo = &getDIEInfoByDwarfDie(CurDie); + AddrReferences.push_back( + std::make_pair(CurDieInfo, AddrReferenceInfo(&DieInfo, AttrSpec))); Die.addValue(DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr, DIEInteger(0xDEADBEEF)); - return U.getRefAddrByteSize(); + return; } - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie)); - - return AttrSize; + Die.addValue(DIEAlloc, AttrSpec.Attr, AttrSpec.Form, DIEEntry(*NewRefDie)); } -uint32_t DIEBuilder::cloneStringAttribute( - DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U) { +void DIEBuilder::cloneStringAttribute( + DIE &Die, const DWARFUnit &U, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val) { if (AttrSpec.Form == dwarf::DW_FORM_string) { - auto StrAddr = Val.getAsCString(); + Expected StrAddr = Val.getAsCString(); if (!StrAddr) { consumeError(StrAddr.takeError()); - return AttrSize; + return; } - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::DW_FORM_string, + Die.addValue(DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_string, new (DIEAlloc) DIEInlineString(StrAddr.get(), DIEAlloc)); } else { std::optional OffsetIndex = Val.getRawUValue(); - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form, + Die.addValue(DIEAlloc, AttrSpec.Attr, AttrSpec.Form, DIEInteger(*OffsetIndex)); } - return AttrSize; } -void DIEBuilder::cloneExpression(DataExtractor &Data, - DWARFExpression &Expression, DWARFUnit &U, - SmallVectorImpl &OutputBuffer) { +bool DIEBuilder::cloneExpression(const DataExtractor &Data, + const DWARFExpression &Expression, + DWARFUnit &U, + SmallVectorImpl &OutputBuffer, + const CloneExpressionStage &Stage) { using Encoding = DWARFExpression::Operation::Encoding; - + using Descr = DWARFExpression::Operation::Description; uint64_t OpOffset = 0; - for (auto &Op : Expression) { - auto Description = Op.getDescription(); + bool DoesContainReference = false; + for (const DWARFExpression::Operation &Op : Expression) { + const Descr &Description = Op.getDescription(); // DW_OP_const_type is variable-length and has 3 // operands. Thus far we only support 2. if ((Description.Op.size() == 2 && @@ -436,7 +440,8 @@ (Description.Op.size() == 2 && Description.Op[1] == Encoding::BaseTypeRef && Description.Op[0] != Encoding::Size1)) - outs() << "BOLT-INFO: Unsupported DW_OP encoding.\n"; + outs() << "BOLT-WARNING: [internal-dwarf-error]: unsupported DW_OP " + "encoding.\n"; if ((Description.Op.size() == 1 && Description.Op[0] == Encoding::BaseTypeRef) || @@ -446,7 +451,8 @@ // This code assumes that the other non-typeref operand fits into 1 // byte. assert(OpOffset < Op.getEndOffset()); - uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; + const uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1; + (void)ULEBsize; assert(ULEBsize <= 16); // Copy over the operation. @@ -460,41 +466,41 @@ } uint32_t Offset = 0; if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) { - DWARFDie RefDie = U.getDIEForOffset(RefOffset); - std::optional RefDieID = getAllocDIEId(U, RefOffset); + DoesContainReference = true; + std::optional RefDieID = + getAllocDIEId(U, U.getOffset() + RefOffset); std::optional RefUnitID = getUnitId(U); if (RefDieID.has_value() && RefUnitID.has_value()) { DIEInfo &RefDieInfo = getDIEInfo(*RefUnitID, *RefDieID); if (DIE *Clone = RefDieInfo.Die) - Offset = RefDie.getOffset(); + Offset = Stage == CloneExpressionStage::INIT ? RefOffset + : Clone->getOffset(); else - errs() << "BOLT-WARNING: base type ref doesn't point to " + errs() << "BOLT-WARNING: [internal-dwarf-error]: base type ref " + "doesn't point to " "DW_TAG_base_type.\n"; } } uint8_t ULEB[16]; - unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize); - if (RealSize > ULEBsize) { - // Emit the generic type as a fallback. - RealSize = encodeULEB128(0, ULEB, ULEBsize); - errs() << "BOLT-WARNING: base type ref doesn't fit.\n"; - } - assert(RealSize == ULEBsize && "padding failed"); - ArrayRef ULEBbytes(ULEB, ULEBsize); + // Hard coding to max size so size doesn't change when we update the + // offset. + encodeULEB128(Offset, ULEB, 4); + ArrayRef ULEBbytes(ULEB, 4); OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end()); } else { // Copy over everything else unmodified. - StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); + const StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset()); OutputBuffer.append(Bytes.begin(), Bytes.end()); } OpOffset = Op.getEndOffset(); } + return DoesContainReference; } -uint32_t DIEBuilder::cloneBlockAttribute( +void DIEBuilder::cloneBlockAttribute( DIE &Die, DWARFUnit &U, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian) { + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val) { DIEValueList *Attr; DIEValue Value; DIELoc *Loc = nullptr; @@ -506,30 +512,25 @@ U.getVersion())) { Block = new (DIEAlloc) DIEBlock; } else { - errs() << "BOLT-WARNING: Unexpected Form value in " + errs() << "BOLT-WARNING: [internal-dwarf-error]: Unexpected Form value in " "cloneBlockAttribute\n"; - return 0; + return; } Attr = Loc ? static_cast(Loc) : static_cast(Block); - if (Loc) - Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), Loc); - else - Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), Block); - SmallVector Buffer; ArrayRef Bytes = *Val.getAsBlock(); if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) && (Val.isFormClass(DWARFFormValue::FC_Block) || Val.isFormClass(DWARFFormValue::FC_Exprloc))) { DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()), - IsLittleEndian, U.getAddressByteSize()); + U.isLittleEndian(), U.getAddressByteSize()); DWARFExpression Expr(Data, U.getAddressByteSize(), U.getFormParams().Format); - cloneExpression(Data, Expr, U, Buffer); + if (cloneExpression(Data, Expr, U, Buffer, CloneExpressionStage::INIT)) + LocWithReferencesToProcess.emplace_back(Bytes.vec(), U, Die, + AttrSpec.Form, AttrSpec.Attr); Bytes = Buffer; } for (auto Byte : Bytes) @@ -541,31 +542,35 @@ else Block->setSize(Bytes.size()); + if (Loc) + Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), Loc); + else + Value = DIEValue(dwarf::Attribute(AttrSpec.Attr), + dwarf::Form(AttrSpec.Form), Block); Die.addValue(DIEAlloc, Value); - return AttrSize; } -uint32_t DIEBuilder::cloneAddressAttribute( - DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, const DWARFUnit &U) { - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue())); - return U.getAddressByteSize(); +void DIEBuilder::cloneAddressAttribute( + DIE &Die, const DWARFUnit &U, + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val) { + Die.addValue(DIEAlloc, AttrSpec.Attr, AttrSpec.Form, + DIEInteger(Val.getRawUValue())); } -uint32_t DIEBuilder::cloneRefsigAttribute( +void DIEBuilder::cloneRefsigAttribute( DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, const DWARFFormValue &Val) { - std::optional SigVal = Val.getRawUValue(); - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::DW_FORM_ref_sig8, DIEInteger(*SigVal)); - return AttrSize; + const DWARFFormValue &Val) { + const std::optional SigVal = Val.getRawUValue(); + Die.addValue(DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_sig8, + DIEInteger(*SigVal)); } -uint32_t DIEBuilder::cloneScalarAttribute( +void DIEBuilder::cloneScalarAttribute( DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize) { + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val) { uint64_t Value; if (auto OptionalValue = Val.getAsUnsignedConstant()) @@ -575,44 +580,42 @@ else if (auto OptionalValue = Val.getAsSectionOffset()) Value = *OptionalValue; else { - errs() << "BOLT-WARNING: Unsupported scalar attribute form. Dropping " + errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " + "attribute form. Dropping " "attribute.\n"; - return 0; + return; } - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), DIEInteger(Value)); - return AttrSize; + Die.addValue(DIEAlloc, AttrSpec.Attr, AttrSpec.Form, DIEInteger(Value)); } -uint32_t DIEBuilder::cloneLoclistAttrubute( +void DIEBuilder::cloneLoclistAttrubute( DIE &Die, const DWARFDie &InputDIE, - DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - const DWARFFormValue &Val, unsigned AttrSize) { - uint64_t Value; + const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, + const DWARFFormValue &Val) { + std::optional Value = std::nullopt; if (auto OptionalValue = Val.getAsUnsignedConstant()) - Value = *OptionalValue; + Value = OptionalValue; else if (auto OptionalValue = Val.getAsSignedConstant()) - Value = *OptionalValue; + Value = OptionalValue; else if (auto OptionalValue = Val.getAsSectionOffset()) - Value = *OptionalValue; - else { - errs() << "BOLT-WARNING: Unsupported scalar attribute form. Dropping " + Value = OptionalValue; + else + errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported scalar " + "attribute form. Dropping " "attribute.\n"; - return 0; - } - Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), - dwarf::Form(AttrSpec.Form), DIELocList(Value)); - return AttrSize; + if (!Value.has_value()) + return; + + Die.addValue(DIEAlloc, AttrSpec.Attr, AttrSpec.Form, DIELocList(*Value)); } -uint32_t DIEBuilder::cloneAttribute( +void DIEBuilder::cloneAttribute( DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U, const DWARFFormValue &Val, const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, - unsigned AttrSize, bool IsLittleEndian, - std::vector &DUOffsetList) { + const std::vector &DUOffsetList) { switch (AttrSpec.Form) { case dwarf::DW_FORM_strp: case dwarf::DW_FORM_string: @@ -623,24 +626,27 @@ case dwarf::DW_FORM_strx4: case dwarf::DW_FORM_GNU_str_index: case dwarf::DW_FORM_line_strp: - return cloneStringAttribute(Die, AttrSpec, AttrSize, Val, U); + cloneStringAttribute(Die, U, AttrSpec, Val); + break; case dwarf::DW_FORM_ref_addr: case dwarf::DW_FORM_ref1: case dwarf::DW_FORM_ref2: case dwarf::DW_FORM_ref4: case dwarf::DW_FORM_ref8: - return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, U, - DUOffsetList); + cloneDieReferenceAttribute(Die, U, InputDIE, AttrSpec, Val, DUOffsetList); + break; case dwarf::DW_FORM_block: case dwarf::DW_FORM_block1: case dwarf::DW_FORM_block2: case dwarf::DW_FORM_block4: case dwarf::DW_FORM_exprloc: - return cloneBlockAttribute(Die, U, AttrSpec, Val, AttrSize, IsLittleEndian); + cloneBlockAttribute(Die, U, AttrSpec, Val); + break; case dwarf::DW_FORM_addr: case dwarf::DW_FORM_addrx: case dwarf::DW_FORM_GNU_addr_index: - return cloneAddressAttribute(Die, AttrSpec, Val, U); + cloneAddressAttribute(Die, U, AttrSpec, Val); + break; case dwarf::DW_FORM_data1: case dwarf::DW_FORM_data2: case dwarf::DW_FORM_data4: @@ -652,19 +658,20 @@ case dwarf::DW_FORM_flag: case dwarf::DW_FORM_flag_present: case dwarf::DW_FORM_implicit_const: - return cloneScalarAttribute(Die, InputDIE, AttrSpec, Val, AttrSize); + cloneScalarAttribute(Die, InputDIE, AttrSpec, Val); + break; case dwarf::DW_FORM_loclistx: - return cloneLoclistAttrubute(Die, InputDIE, AttrSpec, Val, AttrSize); + cloneLoclistAttrubute(Die, InputDIE, AttrSpec, Val); + break; case dwarf::DW_FORM_ref_sig8: - return cloneRefsigAttribute(Die, AttrSpec, AttrSize, Val); + cloneRefsigAttribute(Die, AttrSpec, Val); + break; default: - std::string Msg = "Unsupported attribute form " + - dwarf::FormEncodingString(AttrSpec.Form).str() + - " in cloneAttribute. Dropping."; - llvm_unreachable(Msg.c_str()); + errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported attribute " + "form " + + dwarf::FormEncodingString(AttrSpec.Form).str() + + " in cloneAttribute. Dropping."; } - - return 0; } void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) { // Check the set for priors. @@ -691,7 +698,7 @@ } void DIEBuilder::generateAbbrevs() { - if (!IsBuilt) + if (isEmpty()) return; for (DWARFUnit *DU : DUList) { @@ -713,5 +720,31 @@ } } +static uint64_t getHash(const DWARFUnit &DU) { + // Before DWARF5 TU units are in their own section, so at least one offset, + // first one, will be the same as CUs in .debug_info.dwo section + if (DU.getVersion() < 5 && DU.isTypeUnit()) { + MD5 Hash; + uint64_t TypeUnitHash = cast_or_null(&DU)->getTypeHash(); + uint64_t Offset = DU.getOffset(); + Hash.update(llvm::ArrayRef((uint8_t *)&TypeUnitHash, sizeof(TypeUnitHash))); + Hash.update(llvm::ArrayRef((uint8_t *)&Offset, sizeof(Offset))); + return Hash.final().high(); + } + return DU.getOffset(); +} + +void DIEBuilder::registerUnit(DWARFUnit &DU) { + UnitIDMap[getHash(DU)] = DUList.size(); + DUList.push_back(&DU); +} + +std::optional DIEBuilder::getUnitId(const DWARFUnit &DU) { + auto Iter = UnitIDMap.find(getHash(DU)); + if (Iter != UnitIDMap.end()) + return Iter->second; + return std::nullopt; +} + } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -801,22 +801,6 @@ DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; -void DebugInfoBinaryPatcher::addUnitBaseOffsetLabel(uint64_t Offset) { - Offset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - DebugPatches.emplace_back(new DWARFUnitOffsetBaseLabel(Offset)); -} - -void DebugInfoBinaryPatcher::addDestinationReferenceLabel(uint64_t Offset) { - Offset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - auto RetVal = DestinationLabels.insert(Offset); - if (!RetVal.second) - return; - - DebugPatches.emplace_back(new DestinationReferenceLabel(Offset)); -} - static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { std::string LE64(ByteSize, 0); for (size_t I = 0; I < ByteSize; ++I) { @@ -826,69 +810,6 @@ return LE64; } -void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, - uint32_t Value) { - std::string StrValue = encodeLE(4, Value); - insertNewEntry(DIE, std::move(StrValue)); -} - -void DebugInfoBinaryPatcher::insertNewEntry(const DWARFDie &DIE, - std::string &&Value) { - const DWARFAbbreviationDeclaration *AbbrevDecl = - DIE.getAbbreviationDeclarationPtr(); - - // In case this DIE has no attributes. - uint32_t Offset = DIE.getOffset() + 1; - size_t NumOfAttributes = AbbrevDecl->getNumAttributes(); - if (NumOfAttributes) { - std::optional Val = - findAttributeInfo(DIE, AbbrevDecl, NumOfAttributes - 1); - assert(Val && "Invalid Value."); - - Offset = Val->Offset + Val->Size - DWPUnitOffset; - } - std::lock_guard Lock(WriterMutex); - DebugPatches.emplace_back(new NewDebugEntry(Offset, std::move(Value))); -} - -void DebugInfoBinaryPatcher::addReferenceToPatch(uint64_t Offset, - uint32_t DestinationOffset, - uint32_t OldValueSize, - dwarf::Form Form) { - Offset -= DWPUnitOffset; - DestinationOffset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - DebugPatches.emplace_back( - new DebugPatchReference(Offset, OldValueSize, DestinationOffset, Form)); -} - -void DebugInfoBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t NewValue, - uint32_t OldValueSize) { - Offset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - DebugPatches.emplace_back( - new DebugPatchVariableSize(Offset, OldValueSize, NewValue)); -} - -void DebugInfoBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) { - Offset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - DebugPatches.emplace_back(new DebugPatch64(Offset, NewValue)); -} - -void DebugInfoBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue, - uint32_t OldValueSize) { - Offset -= DWPUnitOffset; - std::lock_guard Lock(WriterMutex); - if (OldValueSize == 4) - DebugPatches.emplace_back(new DebugPatch32(Offset, NewValue)); - else if (OldValueSize == 8) - DebugPatches.emplace_back(new DebugPatch64to32(Offset, NewValue)); - else - DebugPatches.emplace_back( - new DebugPatch32GenericSize(Offset, NewValue, OldValueSize)); -} - void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset, std::string &&NewValue, uint32_t OldValueSize) { @@ -937,242 +858,6 @@ return BinaryContentsStr; } -CUOffsetMap DebugInfoBinaryPatcher::computeNewOffsets(DWARFContext &DWCtx, - bool IsDWOContext) { - CUOffsetMap CUMap; - llvm::sort(DebugPatches, [](const UniquePatchPtrType &V1, - const UniquePatchPtrType &V2) { - if (V1.get()->Offset == V2.get()->Offset) { - if (V1->Kind == DebugPatchKind::NewDebugEntry && - V2->Kind == DebugPatchKind::NewDebugEntry) - return reinterpret_cast(V1.get())->CurrentOrder < - reinterpret_cast(V2.get())->CurrentOrder; - - // This is a case where we are modifying first entry of next - // DIE, and adding a new one. - return V1->Kind == DebugPatchKind::NewDebugEntry; - } - return V1.get()->Offset < V2.get()->Offset; - }); - - DWARFUnitVector::compile_unit_range CompileUnits = - IsDWOContext ? DWCtx.dwo_compile_units() : DWCtx.compile_units(); - - for (const std::unique_ptr &CU : CompileUnits) - CUMap[CU->getOffset()] = {static_cast(CU->getOffset()), - static_cast(CU->getLength())}; - - // Calculating changes in .debug_info size from Patches to build a map of old - // to updated reference destination offsets. - uint32_t PreviousOffset = 0; - int32_t PreviousChangeInSize = 0; - for (UniquePatchPtrType &PatchBase : DebugPatches) { - Patch *P = PatchBase.get(); - switch (P->Kind) { - default: - continue; - case DebugPatchKind::PatchValue64to32: { - PreviousChangeInSize -= 4; - break; - } - case DebugPatchKind::PatchValue32GenericSize: { - DebugPatch32GenericSize *DPVS = - reinterpret_cast(P); - PreviousChangeInSize += 4 - DPVS->OldValueSize; - break; - } - case DebugPatchKind::PatchValueVariable: { - DebugPatchVariableSize *DPV = - reinterpret_cast(P); - std::string Temp; - raw_string_ostream OS(Temp); - encodeULEB128(DPV->Value, OS); - PreviousChangeInSize += Temp.size() - DPV->OldValueSize; - break; - } - case DebugPatchKind::DestinationReferenceLabel: { - DestinationReferenceLabel *DRL = - reinterpret_cast(P); - OldToNewOffset[DRL->Offset] = - DRL->Offset + ChangeInSize + PreviousChangeInSize; - break; - } - case DebugPatchKind::ReferencePatchValue: { - // This doesn't look to be a common case, so will always encode as 4 bytes - // to reduce algorithmic complexity. - DebugPatchReference *RDP = reinterpret_cast(P); - if (RDP->PatchInfo.IndirectRelative) { - PreviousChangeInSize += 4 - RDP->PatchInfo.OldValueSize; - assert(RDP->PatchInfo.OldValueSize <= 4 && - "Variable encoding reference greater than 4 bytes."); - } - break; - } - case DebugPatchKind::DWARFUnitOffsetBaseLabel: { - DWARFUnitOffsetBaseLabel *BaseLabel = - reinterpret_cast(P); - uint32_t CUOffset = BaseLabel->Offset; - ChangeInSize += PreviousChangeInSize; - uint32_t CUOffsetUpdate = CUOffset + ChangeInSize; - CUMap[CUOffset].Offset = CUOffsetUpdate; - CUMap[PreviousOffset].Length += PreviousChangeInSize; - PreviousChangeInSize = 0; - PreviousOffset = CUOffset; - break; - } - case DebugPatchKind::NewDebugEntry: { - NewDebugEntry *NDE = reinterpret_cast(P); - PreviousChangeInSize += NDE->Value.size(); - break; - } - } - } - CUMap[PreviousOffset].Length += PreviousChangeInSize; - return CUMap; -} -uint32_t DebugInfoBinaryPatcher::NewDebugEntry::OrderCounter = 0; - -std::string DebugInfoBinaryPatcher::patchBinary(StringRef BinaryContents) { - std::string NewBinaryContents; - NewBinaryContents.reserve(BinaryContents.size() + ChangeInSize); - uint32_t StartOffset = 0; - uint32_t DwarfUnitBaseOffset = 0; - uint32_t OldValueSize = 0; - uint32_t Offset = 0; - std::string ByteSequence; - std::vector> LengthPatches; - // Wasting one entry to avoid checks for first. - LengthPatches.push_back({0, 0}); - - // Applying all the patches replacing current entry. - // This might change the size of .debug_info section. - for (const UniquePatchPtrType &PatchBase : DebugPatches) { - Patch *P = PatchBase.get(); - switch (P->Kind) { - default: - continue; - case DebugPatchKind::ReferencePatchValue: { - DebugPatchReference *RDP = reinterpret_cast(P); - uint32_t DestinationOffset = RDP->DestinationOffset; - assert(OldToNewOffset.count(DestinationOffset) && - "Destination Offset for reference not updated."); - uint32_t UpdatedOffset = OldToNewOffset[DestinationOffset]; - Offset = RDP->Offset; - OldValueSize = RDP->PatchInfo.OldValueSize; - if (RDP->PatchInfo.DirectRelative) { - UpdatedOffset -= DwarfUnitBaseOffset; - ByteSequence = encodeLE(OldValueSize, UpdatedOffset); - // In theory reference for DW_FORM_ref{1,2,4,8} can be right on the edge - // and overflow if later debug information grows. - if (ByteSequence.size() > OldValueSize) - errs() << "BOLT-ERROR: Relative reference of size " - << Twine::utohexstr(OldValueSize) - << " overflows with the new encoding.\n"; - } else if (RDP->PatchInfo.DirectAbsolute) { - ByteSequence = encodeLE(OldValueSize, UpdatedOffset); - } else if (RDP->PatchInfo.IndirectRelative) { - UpdatedOffset -= DwarfUnitBaseOffset; - ByteSequence.clear(); - raw_string_ostream OS(ByteSequence); - encodeULEB128(UpdatedOffset, OS, 4); - } else { - llvm_unreachable("Invalid Reference form."); - } - break; - } - case DebugPatchKind::PatchValue32: { - DebugPatch32 *P32 = reinterpret_cast(P); - Offset = P32->Offset; - OldValueSize = 4; - ByteSequence = encodeLE(4, P32->Value); - break; - } - case DebugPatchKind::PatchValue64to32: { - DebugPatch64to32 *P64to32 = reinterpret_cast(P); - Offset = P64to32->Offset; - OldValueSize = 8; - ByteSequence = encodeLE(4, P64to32->Value); - break; - } - case DebugPatchKind::PatchValue32GenericSize: { - DebugPatch32GenericSize *DPVS = - reinterpret_cast(P); - Offset = DPVS->Offset; - OldValueSize = DPVS->OldValueSize; - ByteSequence = encodeLE(4, DPVS->Value); - break; - } - case DebugPatchKind::PatchValueVariable: { - DebugPatchVariableSize *PV = - reinterpret_cast(P); - Offset = PV->Offset; - OldValueSize = PV->OldValueSize; - ByteSequence.clear(); - raw_string_ostream OS(ByteSequence); - encodeULEB128(PV->Value, OS); - break; - } - case DebugPatchKind::PatchValue64: { - DebugPatch64 *P64 = reinterpret_cast(P); - Offset = P64->Offset; - OldValueSize = 8; - ByteSequence = encodeLE(8, P64->Value); - break; - } - case DebugPatchKind::DWARFUnitOffsetBaseLabel: { - DWARFUnitOffsetBaseLabel *BaseLabel = - reinterpret_cast(P); - Offset = BaseLabel->Offset; - OldValueSize = 0; - ByteSequence.clear(); - auto &Patch = LengthPatches.back(); - // Length to copy between last patch entry and next compile unit. - uint32_t RemainingLength = Offset - StartOffset; - uint32_t NewCUOffset = NewBinaryContents.size() + RemainingLength; - DwarfUnitBaseOffset = NewCUOffset; - // Length of previous CU = This CU Offset - sizeof(length) - last CU - // Offset. - Patch.second = NewCUOffset - 4 - Patch.first; - LengthPatches.push_back({NewCUOffset, 0}); - break; - } - case DebugPatchKind::NewDebugEntry: { - NewDebugEntry *NDE = reinterpret_cast(P); - Offset = NDE->Offset; - OldValueSize = 0; - ByteSequence = NDE->Value; - break; - } - } - - assert((P->Kind == DebugPatchKind::NewDebugEntry || - Offset + ByteSequence.size() <= BinaryContents.size()) && - "Applied patch runs over binary size."); - uint32_t Length = Offset - StartOffset; - NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), - Length); - NewBinaryContents.append(ByteSequence.data(), ByteSequence.size()); - StartOffset = Offset + OldValueSize; - } - uint32_t Length = BinaryContents.size() - StartOffset; - NewBinaryContents.append(BinaryContents.substr(StartOffset, Length).data(), - Length); - DebugPatches.clear(); - - // Patching lengths of CUs - auto &Patch = LengthPatches.back(); - Patch.second = NewBinaryContents.size() - 4 - Patch.first; - for (uint32_t J = 1, Size = LengthPatches.size(); J < Size; ++J) { - const auto &Patch = LengthPatches[J]; - ByteSequence = encodeLE(4, Patch.second); - Offset = Patch.first; - for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) - NewBinaryContents[Offset + I] = ByteSequence[I]; - } - - return NewBinaryContents; -} - void DebugStrOffsetsWriter::initialize( const DWARFSection &StrOffsetsSection, const std::optional Contr) { @@ -1245,196 +930,6 @@ return Offset; } -void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { - const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations(); - if (!Abbrevs) - return; - - const PatchesTy &UnitPatches = Patches[&Unit]; - const AbbrevEntryTy &AbbrevEntries = NewAbbrevEntries[&Unit]; - - // We are duplicating abbrev sections, to handle the case where for one CU we - // modify it, but for another we don't. - auto UnitDataPtr = std::make_unique(); - AbbrevData &UnitData = *UnitDataPtr.get(); - UnitData.Buffer = std::make_unique(); - UnitData.Stream = std::make_unique(*UnitData.Buffer); - - raw_svector_ostream &OS = *UnitData.Stream.get(); - - // Returns true if AbbrevData is re-used, false otherwise. - auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { - llvm::SHA1 Hasher; - Hasher.update(AbbrevData); - std::array Hash = Hasher.final(); - StringRef Key((const char *)Hash.data(), Hash.size()); - auto Iter = AbbrevDataCache.find(Key); - if (Iter != AbbrevDataCache.end()) { - UnitsAbbrevData[&Unit] = Iter->second.get(); - return true; - } - AbbrevDataCache[Key] = std::move(UnitDataPtr); - UnitsAbbrevData[&Unit] = &UnitData; - return false; - }; - // Take a fast path if there are no patches to apply. Simply copy the original - // contents. - if (UnitPatches.empty() && AbbrevEntries.empty()) { - StringRef AbbrevSectionContents = - Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection() - : Unit.getContext().getDWARFObj().getAbbrevSection(); - StringRef AbbrevContents; - - const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex(); - if (!CUIndex.getRows().empty()) { - // Handle DWP section contribution. - const DWARFUnitIndex::Entry *DWOEntry = - CUIndex.getFromHash(*Unit.getDWOId()); - if (!DWOEntry) - return; - - const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution = - DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV); - AbbrevContents = AbbrevSectionContents.substr( - DWOContrubution->getOffset(), DWOContrubution->getLength()); - } else if (!Unit.isDWOUnit()) { - const uint64_t StartOffset = Unit.getAbbreviationsOffset(); - - // We know where the unit's abbreviation set starts, but not where it ends - // as such data is not readily available. Hence, we have to build a sorted - // list of start addresses and find the next starting address to determine - // the set boundaries. - // - // FIXME: if we had a full access to DWARFDebugAbbrev::AbbrDeclSets - // we wouldn't have to build our own sorted list for the quick lookup. - if (AbbrevSetOffsets.empty()) { - for (const std::pair - &P : *Unit.getContext().getDebugAbbrev()) - AbbrevSetOffsets.push_back(P.first); - sort(AbbrevSetOffsets); - } - auto It = upper_bound(AbbrevSetOffsets, StartOffset); - const uint64_t EndOffset = - It == AbbrevSetOffsets.end() ? AbbrevSectionContents.size() : *It; - AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset); - } else { - // For DWO unit outside of DWP, we expect the entire section to hold - // abbreviations for this unit only. - AbbrevContents = AbbrevSectionContents; - } - - if (!hashAndAddAbbrev(AbbrevContents)) { - OS.reserveExtraSpace(AbbrevContents.size()); - OS << AbbrevContents; - } - return; - } - - for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) { - const DWARFAbbreviationDeclaration &Abbrev = *I; - auto Patch = UnitPatches.find(&Abbrev); - - encodeULEB128(Abbrev.getCode(), OS); - encodeULEB128(Abbrev.getTag(), OS); - encodeULEB128(Abbrev.hasChildren(), OS); - for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec : - Abbrev.attributes()) { - if (Patch != UnitPatches.end()) { - bool Patched = false; - // Patches added later take a precedence over earlier ones. - for (const PatchInfo &PI : llvm::reverse(Patch->second)) { - if (PI.OldAttr != AttrSpec.Attr) - continue; - - encodeULEB128(PI.NewAttr, OS); - encodeULEB128(PI.NewAttrForm, OS); - Patched = true; - break; - } - if (Patched) - continue; - } - - encodeULEB128(AttrSpec.Attr, OS); - encodeULEB128(AttrSpec.Form, OS); - if (AttrSpec.isImplicitConst()) - encodeSLEB128(AttrSpec.getImplicitConstValue(), OS); - } - const auto Entries = AbbrevEntries.find(&Abbrev); - // Adding new Abbrevs for inserted entries. - if (Entries != AbbrevEntries.end()) { - for (const AbbrevEntry &Entry : Entries->second) { - encodeULEB128(Entry.Attr, OS); - encodeULEB128(Entry.Form, OS); - } - } - encodeULEB128(0, OS); - encodeULEB128(0, OS); - } - encodeULEB128(0, OS); - - hashAndAddAbbrev(OS.str()); -} - -std::unique_ptr DebugAbbrevWriter::finalize() { - // Used to create determinism for writing out abbrevs. - std::vector Abbrevs; - if (DWOId) { - // We expect abbrev_offset to always be zero for DWO units as there - // should be one CU per DWO, and TUs should share the same abbreviation - // set with the CU. - // For DWP AbbreviationsOffset is an Abbrev contribution in the DWP file, so - // can be none zero. Thus we are skipping the check for DWP. - bool IsDWP = !Context.getCUIndex().getRows().empty(); - if (!IsDWP) { - for (const std::unique_ptr &Unit : Context.dwo_units()) { - if (Unit->getAbbreviationsOffset() != 0) { - errs() << "BOLT-ERROR: detected DWO unit with non-zero abbr_offset. " - "Unable to update debug info.\n"; - exit(1); - } - } - } - - DWARFUnit *Unit = Context.getDWOCompileUnitForHash(*DWOId); - // Issue abbreviations for the DWO CU only. - addUnitAbbreviations(*Unit); - AbbrevData *Abbrev = UnitsAbbrevData[Unit]; - Abbrevs.push_back(Abbrev); - } else { - Abbrevs.reserve(Context.getNumCompileUnits() + Context.getNumTypeUnits()); - std::unordered_set ProcessedAbbrevs; - // Add abbreviations from compile and type non-DWO units. - for (const std::unique_ptr &Unit : Context.normal_units()) { - addUnitAbbreviations(*Unit); - AbbrevData *Abbrev = UnitsAbbrevData[Unit.get()]; - if (!ProcessedAbbrevs.insert(Abbrev).second) - continue; - Abbrevs.push_back(Abbrev); - } - } - - DebugBufferVector ReturnBuffer; - // Pre-calculate the total size of abbrev section. - uint64_t Size = 0; - for (const AbbrevData *UnitData : Abbrevs) - Size += UnitData->Buffer->size(); - - ReturnBuffer.reserve(Size); - - uint64_t Pos = 0; - for (AbbrevData *UnitData : Abbrevs) { - ReturnBuffer.append(*UnitData->Buffer); - UnitData->Offset = Pos; - Pos += UnitData->Buffer->size(); - - UnitData->Buffer.reset(); - UnitData->Stream.reset(); - } - - return std::make_unique(ReturnBuffer); -} - static void emitDwarfSetLineAddrAbs(MCStreamer &OS, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t Address, diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -70,13 +71,12 @@ namespace llvm { namespace bolt { - +/// Emits debug information into .debug_info or .debug_types section. class DIEStreamer : public DwarfStreamer { DIEBuilder *DIEBldr; + DWARFRewriter &Rewriter; private: - DIE *findTypeDIE(DWARFUnit &TU) { return DIEBldr->getTypeDIE(TU); } - /// Emit the compilation unit header for \p Unit in the debug_info /// section. /// @@ -133,9 +133,12 @@ void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE, unsigned DwarfVersion) { - AsmPrinter &Asm = getAsmPrinter(); - + const uint64_t TypeSignature = cast(Unit).getTypeHash(); + DIE *TypeDIE = DIEBldr->getTypeDIE(Unit); + const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit); + Rewriter.addGDBTypeUnitEntry( + {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()}); if (Unit.getVersion() < 5) { // Switch the section to .debug_types section. std::unique_ptr &MS = Asm.OutStreamer; @@ -147,13 +150,6 @@ } else switchToDebugInfoSection(DwarfVersion); - DWARFTypeUnit *DTU = dyn_cast_or_null(&Unit); - assert(DTU && Unit.isTypeUnit() && - "Emit TypeUnit header but not a type unit"); - - const uint64_t TypeSignature = DTU->getTypeHash(); - DIE *TypeDIE = findTypeDIE(Unit); - emitCommonHeader(Unit, UnitDIE, DwarfVersion); Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature)); Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0); @@ -172,12 +168,13 @@ } public: - DIEStreamer(DIEBuilder *DIEBldr, DWARFLinker::OutputFileType OutFileType, + DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter, + DWARFLinker::OutputFileType OutFileType, raw_pwrite_stream &OutFile, std::function Translator, DWARFLinker::messageHandler Warning) : DwarfStreamer(OutFileType, OutFile, Translator, Warning), - DIEBldr(DIEBldr){}; + DIEBldr(DIEBldr), Rewriter(Rewriter){}; using DwarfStreamer::emitCompileUnitHeader; @@ -297,16 +294,11 @@ return DWARFAddressRangesVector(); } -static std::optional -getAsSectionedAddress(const DWARFUnit &DU, const DIEValue &AttrVal) { - DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue()); - return DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU); -} - static std::optional getAsAddress(const DWARFUnit &DU, const DIEValue &AttrVal) { + DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue()); if (std::optional SA = - getAsSectionedAddress(DU, AttrVal)) + DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU)) return SA->Address; return std::nullopt; } @@ -341,18 +333,13 @@ return DWOName; } -static void emitUnit(DIEBuilder &DIEBldr, - std::unique_ptr &Streamer, DWARFUnit &Unit) { - DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit); - Streamer->emitUnit(Unit, *UnitDIE); -} - static std::unique_ptr createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile, - StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr) { + StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr, + DWARFRewriter &Rewriter) { std::unique_ptr Streamer = std::make_unique( - &DIEBldr, llvm::DWARFLinker::OutputFileType::Object, OutFile, + &DIEBldr, Rewriter, llvm::DWARFLinker::OutputFileType::Object, OutFile, [](StringRef Input) -> StringRef { return Input; }, [&](const Twine &Warning, StringRef Context, const DWARFDie *) {}); Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName); @@ -363,6 +350,76 @@ return Streamer; } +static DWARFRewriter::UnitMeta emitUnit(DIEBuilder &DIEBldr, + std::unique_ptr &Streamer, + DWARFUnit &Unit) { + DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit); + const DIEBuilder::DWARFUnitInfo &U = DIEBldr.getUnitInfoByDwarfUnit(Unit); + Streamer->emitUnit(Unit, *UnitDIE); + uint64_t TypeHash = 0; + if (DWARFTypeUnit *DTU = dyn_cast_or_null(&Unit)) + TypeHash = DTU->getTypeHash(); + return {U.UnitOffset, U.UnitLength, TypeHash}; +} + +static void emitDWOBuilder(DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter, + const DWARFUnit &SplitCU, const uint64_t DWOId) { + // populate debug_info and debug_abbrev for current dwo into StringRef. + DWODIEBuilder.generateAbbrevs(); + DWODIEBuilder.finish(); + + SmallVector OutBuffer; + std::shared_ptr ObjOS = + std::make_shared(OutBuffer); + const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile(); + auto TheTriple = std::make_unique(File->makeTriple()); + std::unique_ptr Streamer = createDIEStreamer( + *TheTriple, *ObjOS, "DwoStreamerInitAug2", DWODIEBuilder, Rewriter); + if (SplitCU.getContext().getMaxDWOVersion() >= 5) { + // TODO: Handle DWP as input. Right now it will iterate over all of CUs and + // TUs + for (std::unique_ptr &CU : + SplitCU.getContext().dwo_info_section_units()) { + DWARFRewriter::UnitMeta MI = emitUnit(DWODIEBuilder, Streamer, *CU.get()); + if (CU->isTypeUnit()) + Rewriter.addTUnitMetaEntry(DWOId, MI); + else + Rewriter.addCUnitMetaEntry(DWOId, MI); + } + } else { + for (std::unique_ptr &CU : + SplitCU.getContext().dwo_compile_units()) + emitUnit(DWODIEBuilder, Streamer, *CU.get()); + + // emit debug_types sections for dwarf4 + for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector()) { + DWARFRewriter::UnitMeta MI = emitUnit(DWODIEBuilder, Streamer, *CU); + Rewriter.addTUnitMetaEntry(DWOId, MI); + } + } + + Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(), + SplitCU.getContext().getMaxVersion()); + Streamer->finish(); + + std::unique_ptr ObjectMemBuffer = + MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false); + std::unique_ptr Obj = cantFail( + object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()), + "error creating in-memory object"); + + for (const SectionRef &Secs : Obj->sections()) { + StringRef Contents = cantFail(Secs.getContents()); + StringRef Name = cantFail(Secs.getName()); + if (Name.equals(".debug_abbrev")) + Rewriter.setDwoDebugAbbrevStr(DWOId, Contents); + else if (Name.equals(".debug_info")) + Rewriter.setDwoDebugInfoStr(DWOId, Contents); + else if (Name.equals(".debug_types")) + Rewriter.setDwoDebugTypeStr(DWOId, Contents); + } +} + void DWARFRewriter::addStringHelper(DIEBuilder &DIEBldr, DIE &Die, const DWARFUnit &Unit, DIEValue &DIEAttrInfo, StringRef Str) { @@ -483,7 +540,7 @@ : LegacyRangesSectionWriter.get(); // Skipping CUs that failed to load. if (SplitCU) { - DIEBuilder DwoDIEBlder(&(*SplitCU)->getContext(), true); + DIEBuilder DWODIEBuilder(&(*SplitCU)->getContext(), true); updateDWONameCompDir(*Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit)); @@ -504,62 +561,14 @@ } } - updateUnitDebugInfo(*(*SplitCU), DwoDIEBlder, *DebugLocWriter, + updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, *DebugLocWriter, *TempRangesSectionWriter); - DebugLocWriter->finalize(DwoDIEBlder, - *DwoDIEBlder.getUnitDIEbyUnit(**SplitCU)); + DebugLocWriter->finalize(DWODIEBuilder, + *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU)); if (Unit->getVersion() >= 5) TempRangesSectionWriter->finalizeSection(); - // populate debug_info and debug_abbrev for current dwo into stringRef. - DwoDIEBlder.generateAbbrevs(); - DwoDIEBlder.finish(); - - SmallVector OutBuffer; - std::shared_ptr ObjOS = - std::make_shared(OutBuffer); - const object::ObjectFile *File = - (*SplitCU)->getContext().getDWARFObj().getFile(); - auto TheTriple = std::make_unique(File->makeTriple()); - std::unique_ptr Streamer = createDIEStreamer( - *TheTriple, *ObjOS, "DwoStreamerInitAug2", DwoDIEBlder); - - if ((*SplitCU)->getContext().getMaxDWOVersion() >= 5) { - for (std::unique_ptr &CU : - (*SplitCU)->getContext().dwo_info_section_units()) - emitUnit(DwoDIEBlder, Streamer, *CU.get()); - } else { - for (std::unique_ptr &CU : - (*SplitCU)->getContext().dwo_compile_units()) - emitUnit(DwoDIEBlder, Streamer, *CU.get()); - - // emit debug_types sections for dwarf4 - for (DWARFUnit *CU : DwoDIEBlder.getDWARF4TUVector()) - emitUnit(DwoDIEBlder, Streamer, *CU); - } - - Streamer->emitAbbrevs(DwoDIEBlder.getAbbrevs(), - (*SplitCU)->getContext().getMaxVersion()); - Streamer->finish(); - - std::unique_ptr ObjectMemBuffer = - MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", - false); - std::unique_ptr Obj = - cantFail(object::ObjectFile::createObjectFile( - ObjectMemBuffer->getMemBufferRef()), - "error creating in-memory object"); - - for (const SectionRef &Secs : Obj->sections()) { - StringRef Contents = cantFail(Secs.getContents()); - StringRef Name = cantFail(Secs.getName()); - if (Name.equals(".debug_abbrev")) - setDwoDebugAbbrevStr(*DWOId, Contents); - else if (Name.equals(".debug_info")) - setDwoDebugInfoStr(*DWOId, Contents); - else if (Name.equals(".debug_types")) - setDwoDebugTypeStr(*DWOId, Contents); - } + emitDWOBuilder(DWODIEBuilder, *this, **SplitCU, *DWOId); } { @@ -605,7 +614,7 @@ else writeDWOFiles(DWOIdToName); - updateGdbIndexSection(OffsetMap); + updateGdbIndexSection(OffsetMap, CUIndex); } void DWARFRewriter::updateUnitDebugInfo( @@ -617,13 +626,11 @@ uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize(); uint64_t NextCUOffset = Unit.getNextUnitOffset(); - std::vector DIEs = DIEBldr.getDIEsByUnit(Unit); - - bool IsDWP = false; - if (DWARFContext *DWOCtx = BC.getDWOContext()) - IsDWP = !DWOCtx->getCUIndex().getRows().empty(); + const std::vector> &DIs = + DIEBldr.getDIEsByUnit(Unit); - for (DIE *Die : DIEs) { + for (const std::unique_ptr &DI : DIs) { + DIE *Die = DI->Die; switch (Die->getTag()) { case dwarf::DW_TAG_compile_unit: case dwarf::DW_TAG_skeleton_unit: { @@ -657,14 +664,10 @@ updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset, 0, RangesBase); DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list); - if (StmtListAttrVal) { - if (LineTablePatchMap.count(&Unit)) { - DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list, - StmtListAttrVal.getForm(), - DIEInteger(LineTablePatchMap[&Unit])); - } - } - + if (LineTablePatchMap.count(&Unit)) + DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list, + StmtListAttrVal.getForm(), + DIEInteger(LineTablePatchMap[&Unit])); break; } @@ -1043,7 +1046,7 @@ dwarf::Form Form = LowPCAttrInfo.getForm(); assert(Form != dwarf::DW_FORM_LLVM_addrx_offset && "DW_FORM_LLVM_addrx_offset is not supported"); - std::lock_guard Lock(DebugInfoPatcherMutex); + std::lock_guard Lock(DWARFRewriterMutex); if (Form == dwarf::DW_FORM_GNU_addr_index) { // If there is no new address, storing old address. // Re-using Index to make implementation easier. @@ -1069,19 +1072,6 @@ errs() << "BOLT-WARNING: unexpected form value for attribute " "LowPCAttrInfo\n"; } - } else if (IsDWP && Unit.isDWOUnit()) { - // Not a common path so don't want to search all DIEs all the time. - DIEValue SignatureAttrInfo = Die->findAttribute(dwarf::DW_AT_signature); - if (!SignatureAttrInfo) - continue; - // If input is DWP file we need to keep track of which TU came from each - // CU, so we can write it out correctly. - if (uint64_t Val = SignatureAttrInfo.getDIEInteger().getValue()) - TypeSignaturesPerCU[*Unit.getDWOId()].insert(Val); - else { - errs() << "BOT-ERROR: DW_AT_signature form is not supported.\n"; - exit(1); - } } } } @@ -1207,6 +1197,11 @@ if (!Label) continue; + std::optional AttrVal = + findAttributeInfo(CU.get()->getUnitDIE(), dwarf::DW_AT_stmt_list); + if (!AttrVal) + continue; + const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label); DebugLineOffsetMap[GetStatementListValue(CU.get())] = LineTableOffset; assert(DbgInfoSection && ".debug_info section must exist"); @@ -1353,13 +1348,13 @@ std::make_shared(OutBuffer); const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile(); auto TheTriple = std::make_unique(File->makeTriple()); - std::unique_ptr Streamer = - createDIEStreamer(*TheTriple, *ObjOS, "AbbrevStreamerInitAug2", DIEBlder); + std::unique_ptr Streamer = createDIEStreamer( + *TheTriple, *ObjOS, "AbbrevStreamerInitAug2", DIEBlder, *this); // generate debug_info and CUMap CUOffsetMap CUMap; uint32_t CUOffset = 0; - for (std::unique_ptr &CU : BC.DwCtx->compile_units()) { + for (std::unique_ptr &CU : BC.DwCtx->info_section_units()) { emitUnit(DIEBlder, Streamer, *CU.get()); uint32_t StartOffset = CUOffset; @@ -1369,11 +1364,9 @@ CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4}; } - if (BC.DwCtx->getMaxVersion() < 5) { - // Emit Type Unit of DWARF 4 to .debug_type section - for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) - emitUnit(DIEBlder, Streamer, *TU); - } + // Emit Type Unit of DWARF 4 to .debug_type section + for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) + emitUnit(DIEBlder, Streamer, *TU); Streamer->emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion()); Streamer->finish(); @@ -1461,14 +1454,12 @@ // Exctracts an appropriate slice if input is DWP. // Applies patches or overwrites the section. -std::optional -updateDebugData(DWARFContext &DWCtx, std::string &Storage, - StringRef SectionName, StringRef SectionContents, - const StringMap &KnownSections, - MCStreamer &Streamer, DWARFRewriter &Writer, - const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId, - std::unique_ptr &OutputBuffer, - DebugRangeListsSectionWriter *RangeListsWriter) { +std::optional updateDebugData( + DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents, + const StringMap &KnownSections, MCStreamer &Streamer, + DWARFRewriter &Writer, const DWARFUnitIndex::Entry *CUDWOEntry, + uint64_t DWOId, std::unique_ptr &OutputBuffer, + DebugRangeListsSectionWriter *RangeListsWriter) { using DWOSectionContribution = const DWARFUnitIndex::Entry::SectionContribution; @@ -1486,9 +1477,7 @@ auto SectionIter = KnownSections.find(SectionName); if (SectionIter == KnownSections.end()) return std::nullopt; - Streamer.switchSection(SectionIter->second.first); - StringRef OutData = SectionContents; uint64_t DWPOffset = 0; switch (SectionIter->second.second) { @@ -1496,18 +1485,16 @@ if (!SectionName.equals("debug_str.dwo")) errs() << "BOLT-WARNING: unsupported debug section: " << SectionName << "\n"; - return OutData; + return SectionContents; } case DWARFSectionKind::DW_SECT_INFO: { - StringRef DebugInfoStr = Writer.getDwoDebugInfoStr(DWOId); - return getSliceData(CUDWOEntry, DebugInfoStr, - DWARFSectionKind::DW_SECT_INFO, DWPOffset); + return Writer.getDwoDebugInfoStr(DWOId); } case DWARFSectionKind::DW_SECT_EXT_TYPES: { return Writer.getDwoDebugTypeStr(DWOId); } case DWARFSectionKind::DW_SECT_STR_OFFSETS: { - return getSliceData(CUDWOEntry, OutData, + return getSliceData(CUDWOEntry, SectionContents, DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset); } case DWARFSectionKind::DW_SECT_ABBREV: { @@ -1524,8 +1511,8 @@ OutputBuffer->size()); } case DWARFSectionKind::DW_SECT_LINE: { - return getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE, - DWPOffset); + return getSliceData(CUDWOEntry, SectionContents, + DWARFSectionKind::DW_SECT_LINE, DWPOffset); } case DWARFSectionKind::DW_SECT_RNGLISTS: { OutputBuffer = RangeListsWriter->releaseBuffer(); @@ -1537,90 +1524,6 @@ } // namespace -struct TUContribution { - uint64_t Signature{0}; - uint32_t Length{0}; -}; -using TUContributionVector = std::vector; -/// Iterates over all the signatures used in this CU, and -/// uses TU Index to extract their contributions from the DWP file. -/// It stores them in DWOTUSection. -static std::string extractDWOTUFromDWP( - const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU, - const DWARFUnitIndex &TUIndex, StringRef Contents, - TUContributionVector &TUContributionsToCU, uint64_t DWOId) { - std::string DWOTUSection; - using TUEntry = - std::pair; - std::vector TUContributions; - for (const uint64_t TUSignature : TypeSignaturesPerCU.at(DWOId)) { - const DWARFUnitIndex::Entry *TUDWOEntry = TUIndex.getFromHash(TUSignature); - const DWARFUnitIndex::Entry::SectionContribution *C = - TUDWOEntry->getContribution(DW_SECT_EXT_TYPES); - TUContributions.emplace_back(TUSignature, C); - } - - // Sorting so it's easy to compare output. - // They should be sharing the same Abbrev. - llvm::sort(TUContributions, [](const TUEntry &V1, const TUEntry &V2) -> bool { - return V1.second->getOffset() < V2.second->getOffset(); - }); - - for (auto &PairEntry : TUContributions) { - const DWARFUnitIndex::Entry::SectionContribution *C = PairEntry.second; - const uint64_t TUSignature = PairEntry.first; - DWOTUSection.append( - Contents.slice(C->getOffset(), C->getOffset() + C->getLength()).str()); - TUContributionsToCU.push_back({TUSignature, C->getLength32()}); - } - return DWOTUSection; -} - -static void extractDWOTUFromDWO(StringRef Contents, - TUContributionVector &TUContributionsToCU) { - uint64_t Offset = 0; - DataExtractor Data(Contents, true, 0); - while (Data.isValidOffset(Offset)) { - uint64_t PrevOffset = Offset; - // Length of the unit, including the 4 byte length field. - const uint32_t Length = Data.getU32(&Offset) + 4; - - Data.getU16(&Offset); // Version - Data.getU32(&Offset); // Abbrev offset - Data.getU8(&Offset); // Address size - const uint64_t TUSignature = Data.getU64(&Offset); - Offset = PrevOffset + Length; - TUContributionsToCU.push_back({TUSignature, Length}); - } -} - -static void extractTypesFromDWPDWARF5( - const MCObjectFileInfo &MCOFI, const DWARFUnitIndex &TUIndex, - const DWARFRewriter::DebugTypesSignaturesPerCUMap &TypeSignaturesPerCU, - MCStreamer &Streamer, StringRef Contents, uint64_t DWOId) { - std::vector - TUContributions; - if (!TypeSignaturesPerCU.count(DWOId)) - return; - for (const uint64_t Val : TypeSignaturesPerCU.at(DWOId)) { - const DWARFUnitIndex::Entry *TUE = TUIndex.getFromHash(Val); - const DWARFUnitIndex::Entry::SectionContribution *C = - TUE->getContribution(DWARFSectionKind::DW_SECT_INFO); - TUContributions.push_back(C); - } - // Sorting so it's easy to compare output. - // They should be sharing the same Abbrev. - llvm::sort(TUContributions, - [](const DWARFUnitIndex::Entry::SectionContribution *V1, - const DWARFUnitIndex::Entry::SectionContribution *V2) -> bool { - return V1->getOffset() < V2->getOffset(); - }); - Streamer.switchSection(MCOFI.getDwarfInfoDWOSection()); - for (const auto *C : TUContributions) - Streamer.emitBytes( - Contents.slice(C->getOffset(), C->getOffset() + C->getLength())); -} - void DWARFRewriter::writeDWP( std::unordered_map &DWOIdToName) { SmallString<0> OutputNameStr; @@ -1665,14 +1568,12 @@ // Setup DWP code once. DWARFContext *DWOCtx = BC.getDWOContext(); const DWARFUnitIndex *CUIndex = nullptr; - const DWARFUnitIndex *TUIndex = nullptr; bool IsDWP = false; if (DWOCtx) { CUIndex = &DWOCtx->getCUIndex(); - TUIndex = &DWOCtx->getTUIndex(); IsDWP = !CUIndex->getRows().empty(); } - + uint64_t DebugInfoSize = 0; for (const std::unique_ptr &CU : BC.DwCtx->compile_units()) { std::optional DWOId = CU->getDWOId(); if (!DWOId) @@ -1721,36 +1622,30 @@ "No RangeListsWriter for DWO ID."); RangeListssWriter = RangeListsWritersByCU[*DWOId].get(); } - std::string DWOTUSection; - TUContributionVector TUContributionsToCU; + auto AddType = [&](unsigned int Index, uint32_t IndexVersion, + uint64_t Offset, uint64_t Length, + uint64_t Hash) -> void { + UnitIndexEntry TUEntry = CurEntry; + if (IndexVersion < 5) + TUEntry.Contributions[0] = {}; + TUEntry.Contributions[Index].setOffset(Offset); + TUEntry.Contributions[Index].setLength(Length); + ContributionOffsets[Index] += TUEntry.Contributions[Index].getLength32(); + TypeIndexEntries.insert(std::make_pair(Hash, TUEntry)); + }; for (const SectionRef &Section : DWOFile->sections()) { - std::string DWOTUSection; - std::string Storage; std::unique_ptr OutputData; StringRef SectionName = getSectionName(Section); Expected ContentsExp = Section.getContents(); assert(ContentsExp && "Invalid contents."); - StringRef Contents = *ContentsExp; - const bool IsTypesDWO = SectionName == "debug_types.dwo"; - if (IsDWP && IsTypesDWO) { - assert(TUIndex && - "DWP Input with .debug_types.dwo section with TU Index."); - DWOTUSection = - extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents, - TUContributionsToCU, *DWOId); - Contents = DWOTUSection; - } else if (IsTypesDWO) { - extractDWOTUFromDWO(Contents, TUContributionsToCU); - } - std::optional TOutData = updateDebugData( - (*DWOCU)->getContext(), Storage, SectionName, Contents, KnownSections, + (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData, RangeListssWriter); if (!TOutData) continue; StringRef OutData = *TOutData; - if (IsTypesDWO) { + if (SectionName == "debug_types.dwo") { Streamer->emitBytes(OutData); continue; } @@ -1767,8 +1662,20 @@ Streamer->emitBytes(OutData); unsigned int Index = getContributionIndex(SectionIter->second.second, IndexVersion); - CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]); - CurEntry.Contributions[Index].setLength(OutData.size()); + uint64_t Offset = ContributionOffsets[Index]; + uint64_t Length = OutData.size(); + if (CU->getVersion() >= 5 && + SectionIter->second.second == DWARFSectionKind::DW_SECT_INFO) { + for (UnitMeta &MI : getTUnitMetaEntries(*DWOId)) + MI.Offset += DebugInfoSize; + + const UnitMeta &MI = getCUnitMetaEntry(*DWOId); + Offset = DebugInfoSize + MI.Offset; + Length = MI.Length; + DebugInfoSize += OutData.size(); + } + CurEntry.Contributions[Index].setOffset(Offset); + CurEntry.Contributions[Index].setLength(Length); ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32(); } @@ -1793,19 +1700,10 @@ } // Handling TU - if (!TUContributionsToCU.empty()) { - const unsigned Index = - getContributionIndex(DW_SECT_EXT_TYPES, IndexVersion); - for (const TUContribution &TUC : TUContributionsToCU) { - UnitIndexEntry TUEntry = CurEntry; - TUEntry.Contributions[0] = {}; - TUEntry.Contributions[Index].setOffset(ContributionOffsets[Index]); - TUEntry.Contributions[Index].setLength(TUC.Length); - ContributionOffsets[Index] += - TUEntry.Contributions[Index].getLength32(); - TypeIndexEntries.insert(std::make_pair(TUC.Signature, TUEntry)); - } - } + const unsigned Index = getContributionIndex( + IndexVersion < 5 ? DW_SECT_EXT_TYPES : DW_SECT_INFO, IndexVersion); + for (UnitMeta &MI : getTUnitMetaEntries(*DWOId)) + AddType(Index, IndexVersion, MI.Offset, MI.Length, MI.TUHash); } if (Version < 5) { @@ -1836,11 +1734,9 @@ // Setup DWP code once. DWARFContext *DWOCtx = BC.getDWOContext(); const DWARFUnitIndex *CUIndex = nullptr; - const DWARFUnitIndex *TUIndex = nullptr; bool IsDWP = false; if (DWOCtx) { CUIndex = &DWOCtx->getCUIndex(); - TUIndex = &DWOCtx->getTUIndex(); IsDWP = !CUIndex->getRows().empty(); } @@ -1884,46 +1780,26 @@ // Handling .debug_rnglists.dwo seperatly. The original .o/.dwo might not // have .debug_rnglists so won't be part of the loop below. if (!RangeListssWriter->empty()) { - std::string Storage; std::unique_ptr OutputData; - if (std::optional OutData = updateDebugData( - (*DWOCU)->getContext(), Storage, "debug_rnglists.dwo", "", - KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData, - RangeListssWriter)) + if (std::optional OutData = + updateDebugData((*DWOCU)->getContext(), "debug_rnglists.dwo", + "", KnownSections, *Streamer, *this, CUDWOEntry, + *DWOId, OutputData, RangeListssWriter)) Streamer->emitBytes(*OutData); } } - TUContributionVector TUContributionsToCU; for (const SectionRef &Section : File->sections()) { - std::string Storage; - std::string DWOTUSection; std::unique_ptr OutputData; StringRef SectionName = getSectionName(Section); if (SectionName == "debug_rnglists.dwo") continue; Expected ContentsExp = Section.getContents(); assert(ContentsExp && "Invalid contents."); - StringRef Contents = *ContentsExp; - if (IsDWP && SectionName == "debug_types.dwo") { - assert(TUIndex && - "DWP Input with .debug_types.dwo section with TU Index."); - DWOTUSection = - extractDWOTUFromDWP(TypeSignaturesPerCU, *TUIndex, Contents, - TUContributionsToCU, *DWOId); - Contents = DWOTUSection; - } else if (IsDWP && CU->getVersion() >= 5 && - SectionName == "debug_info.dwo") { - assert(TUIndex && - "DWP Input with .debug_types.dwo section with TU Index."); - extractTypesFromDWPDWARF5(MCOFI, *TUIndex, TypeSignaturesPerCU, - *Streamer, Contents, *DWOId); - } - - if (std::optional OutData = updateDebugData( - (*DWOCU)->getContext(), Storage, SectionName, Contents, - KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData, - RangeListssWriter)) + if (std::optional OutData = + updateDebugData((*DWOCU)->getContext(), SectionName, *ContentsExp, + KnownSections, *Streamer, *this, CUDWOEntry, + *DWOId, OutputData, RangeListssWriter)) Streamer->emitBytes(*OutData); } Streamer->finish(); @@ -1931,7 +1807,14 @@ } } -void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap) { +void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) { + std::lock_guard Lock(DWARFRewriterMutex); + if (!BC.getGdbIndexSection()) + return; + GDBIndexTUEntryVector.emplace_back(Entry); +} + +void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) { if (!BC.getGdbIndexSection()) return; @@ -1962,19 +1845,46 @@ // Map CUs offsets to indices and verify existing index table. std::map OffsetToIndexMap; const uint32_t CUListSize = CUTypesOffset - CUListOffset; - const unsigned NumCUs = BC.DwCtx->getNumCompileUnits(); - if (CUListSize != NumCUs * 16) { + const uint32_t TUListSize = AddressTableOffset - CUTypesOffset; + const unsigned NUmCUsEncoded = CUListSize / 16; + unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion(); + unsigned NumDWARF5TUs = + getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits(); + bool SkipTypeUnits = false; + // For DWARF5 Types are in .debug_info. + // LLD doesn't generate Types CU List, and in CU list offset + // only includes CUs. + // GDB 11+ includes only CUs in CU list and generates Types + // list. + // GDB 9 includes CUs and TUs in CU list and generates TYpes + // list. The NumCUs is CUs + TUs, so need to modify the check. + // For split-dwarf + // GDB-11, DWARF5: TU units from dwo are not included. + // GDB-11, DWARF4: TU units from dwo are included. + if (MaxDWARFVersion >= 5) + SkipTypeUnits = !TUListSize ? true + : ((NUmCUsEncoded + NumDWARF5TUs) == + BC.DwCtx->getNumCompileUnits()); + + if (!((CUListSize == NumCUs * 16) || + (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) { errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n"; exit(1); } - for (unsigned Index = 0; Index < NumCUs; ++Index, Data += 16) { + DenseSet OriginalOffsets; + for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits(); + Index < Units; ++Index) { const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index); + if (SkipTypeUnits && CU->isTypeUnit()) + continue; const uint64_t Offset = read64le(Data); + Data += 16; if (CU->getOffset() != Offset) { errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n"; exit(1); } + OriginalOffsets.insert(Offset); OffsetToIndexMap[Offset] = Index; } @@ -2010,21 +1920,30 @@ // Writing out CU List for (auto &CUInfo : CUMap) { + // Skipping TU for DWARF5 when they are not included in CU list. + if (!OriginalOffsets.count(CUInfo.first)) + continue; write64le(Buffer, CUInfo.second.Offset); // Length encoded in CU doesn't contain first 4 bytes that encode length. write64le(Buffer + 8, CUInfo.second.Length + 4); Buffer += 16; } - // Copy over types CU list - // Spec says " triplet, the first value is the CU offset, the second value is - // the type offset in the CU, and the third value is the type signature" - // Looking at what is being generated by gdb-add-index. The first entry is TU - // offset, second entry is offset from it, and third entry is the type - // signature. - memcpy(Buffer, GdbIndexContents.data() + CUTypesOffset, - AddressTableOffset - CUTypesOffset); - Buffer += AddressTableOffset - CUTypesOffset; + // Rewrite TU CU List, since abbrevs can be different. + // Entry example: + // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature = + // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset, + // the second value is the type offset in the CU, and the third value is the + // type signature" Looking at what is being generated by gdb-add-index. The + // first entry is TU offset, second entry is offset from it, and third entry + // is the type signature. + if (TUListSize) + for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) { + write64le(Buffer, Entry.UnitOffset); + write64le(Buffer + 8, Entry.TypeDIERelativeOffset); + write64le(Buffer + 16, Entry.TypeHash); + Buffer += sizeof(GDBIndexTUEntry); + } // Generate new address table. for (const std::pair &CURangesPair : diff --git a/bolt/test/X86/Inputs/dwarf4-duplicate-types-helper.s b/bolt/test/X86/Inputs/dwarf4-duplicate-types-helper.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-duplicate-types-helper.s @@ -0,0 +1,280 @@ +# struct Foo2a { +# char *c1; +# char *c2; +# char *c3; +# }; +# int foo() { +# Foo2a f; +# return 0; +# } + .text + .file "helper.cpp" + .globl _Z3foov # -- Begin function _Z3foov + .p2align 4, 0x90 + .type _Z3foov,@function +_Z3foov: # @_Z3foov +.Lfunc_begin0: + .file 1 "dwarf4-duplicate-types-test" "helper.cpp" + .loc 1 6 0 # helper.cpp:6:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 1 8 3 prologue_end # helper.cpp:8:3 + xorl %eax, %eax + .loc 1 8 3 epilogue_begin is_stmt 0 # helper.cpp:8:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size _Z3foov, .Lfunc_end0-_Z3foov + .cfi_endproc + # -- End function + .section .debug_types,"G",@progbits,1175092228111723119,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 7448148824980338162 # Type Signature <--- Manually modified to have same signature as TU in main + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x42 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x2e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string11 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string7 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string9 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3f:0xc DW_TAG_member + .long .Linfo_string10 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x4c:0x5 DW_TAG_pointer_type + .long 81 # DW_AT_type + .byte 5 # Abbrev [5] 0x51:0x7 DW_TAG_base_type + .long .Linfo_string8 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x5c DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 7 # Abbrev [7] 0x2a:0x2c DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_linkage_name + .long .Linfo_string4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 86 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x47:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 93 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x56:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 9 # Abbrev [9] 0x5d:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 1175092228111723119 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Facebook clang version 15.0.0 (ssh://git-ro.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project e11a3497eb7c3f5a9d56030f25e27e0522994d62)" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=146 +.Linfo_string2: + .asciz "dwarf4-duplicate-types-test" # string offset=157 +.Linfo_string3: + .asciz "_Z3foov" # string offset=223 +.Linfo_string4: + .asciz "foo" # string offset=231 +.Linfo_string5: + .asciz "int" # string offset=235 +.Linfo_string6: + .asciz "f" # string offset=239 +.Linfo_string7: + .asciz "c1" # string offset=241 +.Linfo_string8: + .asciz "char" # string offset=244 +.Linfo_string9: + .asciz "c2" # string offset=249 +.Linfo_string10: + .asciz "c3" # string offset=252 +.Linfo_string11: + .asciz "Foo2a" # string offset=255 + .ident "Facebook clang version 15.0.0 (ssh://git-ro.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project e11a3497eb7c3f5a9d56030f25e27e0522994d62)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-duplicate-types-main.s b/bolt/test/X86/Inputs/dwarf4-duplicate-types-main.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-duplicate-types-main.s @@ -0,0 +1,321 @@ +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# int main(int argc, char *argv[]) { +# Foo f; +# return 0; +# } + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "dwarf4-duplicate-types-test" "main.cpp" + .loc 1 6 0 # main.cpp:6:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 8 2 prologue_end # main.cpp:8:2 + xorl %eax, %eax + .loc 1 8 2 epilogue_begin is_stmt 0 # main.cpp:8:2 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_types,"G",@progbits,7448148824980338162,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 7448148824980338162 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x42 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x2e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string12 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string9 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string10 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3f:0xc DW_TAG_member + .long .Linfo_string11 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x4c:0x5 DW_TAG_pointer_type + .long 81 # DW_AT_type + .byte 5 # Abbrev [5] 0x51:0x7 DW_TAG_base_type + .long .Linfo_string7 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x85 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 7 # Abbrev [7] 0x2a:0x44 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 110 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x43:0xe DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 110 # DW_AT_type + .byte 8 # Abbrev [8] 0x51:0xe DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 117 # DW_AT_type + .byte 9 # Abbrev [9] 0x5f:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .long .Linfo_string8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 134 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x6e:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x75:0x5 DW_TAG_pointer_type + .long 122 # DW_AT_type + .byte 4 # Abbrev [4] 0x7a:0x5 DW_TAG_pointer_type + .long 127 # DW_AT_type + .byte 5 # Abbrev [5] 0x7f:0x7 DW_TAG_base_type + .long .Linfo_string7 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x86:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "Facebook clang version 15.0.0 (ssh://git-ro.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project e11a3497eb7c3f5a9d56030f25e27e0522994d62)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=146 +.Linfo_string2: + .asciz "dwarf4-duplicate-types-test" # string offset=155 +.Linfo_string3: + .asciz "main" # string offset=221 +.Linfo_string4: + .asciz "int" # string offset=226 +.Linfo_string5: + .asciz "argc" # string offset=230 +.Linfo_string6: + .asciz "argv" # string offset=235 +.Linfo_string7: + .asciz "char" # string offset=240 +.Linfo_string8: + .asciz "f" # string offset=245 +.Linfo_string9: + .asciz "c1" # string offset=247 +.Linfo_string10: + .asciz "c2" # string offset=250 +.Linfo_string11: + .asciz "c3" # string offset=253 +.Linfo_string12: + .asciz "Foo" # string offset=256 + .ident "Facebook clang version 15.0.0 (ssh://git-ro.vip.facebook.com/data/gitrepos/osmeta/external/llvm-project e11a3497eb7c3f5a9d56030f25e27e0522994d62)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-gdb-index-types-helper.s b/bolt/test/X86/Inputs/dwarf4-gdb-index-types-helper.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-gdb-index-types-helper.s @@ -0,0 +1,309 @@ +# clang++ helper.cpp -ggnu-pubnames -g2 -gdwarf-4 -fdebug-types-section -S -o +# typedef struct +# { +# unsigned a; +# unsigned b; +# } S2; +# +# int foo() { +# S2 s; +# s.a = 0x64A40101; +# } + .text + .file "helper.cpp" + .globl _Z3foov # -- Begin function _Z3foov + .p2align 4, 0x90 + .type _Z3foov,@function +_Z3foov: # @_Z3foov +.Lfunc_begin0: + .file 1 "/dwarf4-lenght-test" "helper.cpp" + .loc 1 7 0 # helper.cpp:7:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 1 9 7 prologue_end # helper.cpp:9:7 + movl $1688469761, -8(%rbp) # imm = 0x64A40101 + .loc 1 9 3 is_stmt 0 # helper.cpp:9:3 + ud2 +.Ltmp1: +.Lfunc_end0: + .size _Z3foov, .Lfunc_end0-_Z3foov + .cfi_endproc + # -- End function + .section .debug_types,"G",@progbits,69467852836524312,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 69467852836524312 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x2d DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x1e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x23:0xc DW_TAG_member + .long .Linfo_string7 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2f:0xc DW_TAG_member + .long .Linfo_string9 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x7 DW_TAG_base_type + .long .Linfo_string8 # DW_AT_name + .byte 7 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 22 # DW_TAG_typedef + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 5 # Abbrev [5] 0xb:0x67 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 6 # Abbrev [6] 0x2a:0x2c DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_linkage_name + .long .Linfo_string4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 86 # DW_AT_type + # DW_AT_external + .byte 7 # Abbrev [7] 0x47:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 93 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x56:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 8 # Abbrev [8] 0x5d:0xb DW_TAG_typedef + .long 104 # DW_AT_type + .long .Linfo_string10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 9 # Abbrev [9] 0x68:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 69467852836524312 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=146 +.Linfo_string2: + .asciz "/home/ayermolo/local/tasks/T117448832/dwarf4-lenght-test" # string offset=157 +.Linfo_string3: + .asciz "_Z3foov" # string offset=214 +.Linfo_string4: + .asciz "foo" # string offset=222 +.Linfo_string5: + .asciz "int" # string offset=226 +.Linfo_string6: + .asciz "s" # string offset=230 +.Linfo_string7: + .asciz "a" # string offset=232 +.Linfo_string8: + .asciz "unsigned int" # string offset=234 +.Linfo_string9: + .asciz "b" # string offset=247 +.Linfo_string10: + .asciz "S2" # string offset=249 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 114 # Compilation Unit Length + .long 42 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "foo" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 114 # Compilation Unit Length + .long 93 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "S2" # External Name + .long 86 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 11 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "unsigned int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-gdb-index-types-main.s b/bolt/test/X86/Inputs/dwarf4-gdb-index-types-main.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-gdb-index-types-main.s @@ -0,0 +1,308 @@ +# clang++ main.cpp -ggnu-pubnames -g2 -gdwarf-4 -fdebug-types-section -S -o +# typedef struct +# { +# unsigned a; +# unsigned b; +# } S; +# +# int main() { +# S s; +# s.a = 0x64A40101; +# } + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/dwarf4-lenght-test" "main.cpp" + .loc 1 7 0 # main.cpp:7:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 1 9 7 prologue_end # main.cpp:9:7 + movl $1688469761, -8(%rbp) # imm = 0x64A40101 + .loc 1 10 1 # main.cpp:10:1 + xorl %eax, %eax + .loc 1 10 1 epilogue_begin is_stmt 0 # main.cpp:10:1 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_types,"G",@progbits,4721183873463917179,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 4721183873463917179 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x2d DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x1e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x23:0xc DW_TAG_member + .long .Linfo_string6 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2f:0xc DW_TAG_member + .long .Linfo_string8 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x7 DW_TAG_base_type + .long .Linfo_string7 # DW_AT_name + .byte 7 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 22 # DW_TAG_typedef + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 5 # Abbrev [5] 0xb:0x63 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 6 # Abbrev [6] 0x2a:0x28 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 82 # DW_AT_type + # DW_AT_external + .byte 7 # Abbrev [7] 0x43:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 89 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x52:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 8 # Abbrev [8] 0x59:0xb DW_TAG_typedef + .long 100 # DW_AT_type + .long .Linfo_string9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 9 # Abbrev [9] 0x64:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 4721183873463917179 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=146 +.Linfo_string2: + .asciz "/dwarf4-lenght-test" # string offset=155 +.Linfo_string3: + .asciz "main" # string offset=212 +.Linfo_string4: + .asciz "int" # string offset=217 +.Linfo_string5: + .asciz "s" # string offset=221 +.Linfo_string6: + .asciz "a" # string offset=223 +.Linfo_string7: + .asciz "unsigned int" # string offset=225 +.Linfo_string8: + .asciz "b" # string offset=238 +.Linfo_string9: + .asciz "S" # string offset=240 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 110 # Compilation Unit Length + .long 42 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 110 # Compilation Unit Length + .long 82 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 89 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "S" # External Name + .long 11 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "unsigned int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-gdb-index-types-v8.gdb-index b/bolt/test/X86/Inputs/dwarf4-gdb-index-types-v8.gdb-index new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@" # DW_FORM_GNU_str_index + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 4 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 0 + .ascii "helper.cpp" + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad .Lfunc_begin0 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 25 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "foo" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 68 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo2a" # External Name + .long 64 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 11 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "char" # External Name + .long 77 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo3" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-split-gdb-index-types-main.s b/bolt/test/X86/Inputs/dwarf4-split-gdb-index-types-main.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-split-gdb-index-types-main.s @@ -0,0 +1,538 @@ +# struct Foo2a { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo3 { +# char *c1; +# char *c2; +# }; +# +# int foo() { +# Foo2a f; +# Foo3 f2; +# } + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "." "main.cpp" + .loc 1 10 0 # main.cpp:10:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 12 9 prologue_end # main.cpp:12:9 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 1 12 7 is_stmt 0 # main.cpp:12:7 + movq %rax, -40(%rbp) + .loc 1 13 9 is_stmt 1 # main.cpp:13:9 + movq -16(%rbp), %rax + .loc 1 13 14 is_stmt 0 # main.cpp:13:14 + movl -8(%rbp), %ecx + .loc 1 13 19 # main.cpp:13:19 + addl $1, %ecx + .loc 1 13 9 # main.cpp:13:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 13 7 # main.cpp:13:7 + movq %rax, -32(%rbp) + .loc 1 14 9 is_stmt 1 # main.cpp:14:9 + movq -16(%rbp), %rax + .loc 1 14 14 is_stmt 0 # main.cpp:14:14 + movl -8(%rbp), %ecx + .loc 1 14 19 # main.cpp:14:19 + addl $2, %ecx + .loc 1 14 9 # main.cpp:14:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 14 7 # main.cpp:14:7 + movq %rax, -24(%rbp) + .loc 1 16 9 is_stmt 1 # main.cpp:16:9 + movq -16(%rbp), %rax + .loc 1 16 14 is_stmt 0 # main.cpp:16:14 + movl -8(%rbp), %ecx + .loc 1 16 19 # main.cpp:16:19 + addl $3, %ecx + .loc 1 16 9 # main.cpp:16:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 16 7 # main.cpp:16:7 + movq %rax, -40(%rbp) + .loc 1 17 9 is_stmt 1 # main.cpp:17:9 + movq -16(%rbp), %rax + .loc 1 17 14 is_stmt 0 # main.cpp:17:14 + movl -8(%rbp), %ecx + .loc 1 17 19 # main.cpp:17:19 + addl $4, %ecx + .loc 1 17 9 # main.cpp:17:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 17 7 # main.cpp:17:7 + movq %rax, -32(%rbp) + .loc 1 18 2 is_stmt 1 # main.cpp:18:2 + xorl %eax, %eax + .loc 1 18 2 epilogue_begin is_stmt 0 # main.cpp:18:2 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_types.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 7448148824980338162 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x33 DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 9 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x24:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2d:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x36:0x9 DW_TAG_member + .byte 8 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type + .long 69 # DW_AT_type + .byte 5 # Abbrev [5] 0x45:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .long .Ldebug_info_dwo_end1-.Ldebug_info_dwo_start1 # Length of Unit +.Ldebug_info_dwo_start1: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5322170643381124694 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x2a DW_TAG_type_unit + .short 33 # DW_AT_language + .long 0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 11 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x24:0x9 DW_TAG_member + .byte 6 # DW_AT_name + .long 55 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x2d:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 55 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x37:0x5 DW_TAG_pointer_type + .long 60 # DW_AT_type + .byte 5 # Abbrev [5] 0x3c:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end1: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lskel_string0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .long .Lskel_string1 # DW_AT_GNU_dwo_name + .quad 4780348136649610820 # DW_AT_GNU_dwo_id + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_GNU_addr_base +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=68 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "main" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=5 +.Linfo_string2: + .asciz "argc" # string offset=9 +.Linfo_string3: + .asciz "argv" # string offset=14 +.Linfo_string4: + .asciz "char" # string offset=19 +.Linfo_string5: + .asciz "f" # string offset=24 +.Linfo_string6: + .asciz "c1" # string offset=26 +.Linfo_string7: + .asciz "c2" # string offset=29 +.Linfo_string8: + .asciz "c3" # string offset=32 +.Linfo_string9: + .asciz "Foo" # string offset=35 +.Linfo_string10: + .asciz "f2" # string offset=39 +.Linfo_string11: + .asciz "Foo2" # string offset=42 +.Linfo_string12: + .asciz "clang version 15.0.0" # string offset=47 +.Linfo_string13: + .asciz "main.cpp" # string offset=193 +.Linfo_string14: + .asciz "main.dwo" # string offset=202 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 5 + .long 9 + .long 14 + .long 19 + .long 24 + .long 26 + .long 29 + .long 32 + .long 35 + .long 39 + .long 42 + .long 47 + .long 193 + .long 202 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit +.Ldebug_info_dwo_start2: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x6f DW_TAG_compile_unit + .byte 12 # DW_AT_producer + .short 33 # DW_AT_language + .byte 13 # DW_AT_name + .byte 14 # DW_AT_GNU_dwo_name + .quad 4780348136649610820 # DW_AT_GNU_dwo_id + .byte 7 # Abbrev [7] 0x19:0x3c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 0 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 85 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x28:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 2 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 85 # DW_AT_type + .byte 8 # Abbrev [8] 0x33:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .byte 3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 89 # DW_AT_type + .byte 9 # Abbrev [9] 0x3e:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 103 # DW_AT_type + .byte 9 # Abbrev [9] 0x49:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .byte 10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 15 # DW_AT_decl_line + .long 112 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x55:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x59:0x5 DW_TAG_pointer_type + .long 94 # DW_AT_type + .byte 4 # Abbrev [4] 0x5e:0x5 DW_TAG_pointer_type + .long 99 # DW_AT_type + .byte 5 # Abbrev [5] 0x63:0x4 DW_TAG_base_type + .byte 4 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x67:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x70:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end2: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_line.dwo,"e",@progbits +.Ltmp2: + .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length +.Ldebug_line_start0: + .short 4 + .long .Lprologue_end0-.Lprologue_start0 +.Lprologue_start0: + .byte 1 + .byte 1 + .byte 1 + .byte -5 + .byte 14 + .byte 1 + .byte 0 + .ascii "main.cpp" + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.Lprologue_end0: +.Ldebug_line_end0: + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad .Lfunc_begin0 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 25 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 85 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 99 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 103 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo" # External Name + .long 112 # DIE offset + .byte 16 # Attributes: TYPE, EXTERNAL + .asciz "Foo2" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-split-gdb-index-types-v8.gdb-index b/bolt/test/X86/Inputs/dwarf4-split-gdb-index-types-v8.gdb-index new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ {0x00000062}) +# POSTCHECK-EMPTY: +# POSTCHECK-NEXT: DW_TAG_typedef [6] +# POSTCHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0059 => {0x00000059} "structure ") + +# typedef struct +# { +# unsigned a; +# unsigned b; +# } S; +# +# int main() { +# S s; +# s.a = 0x64A40101; +# } + + .text + .file "main.cpp" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/dwarf4-sibling-test" "main.cpp" + .loc 1 7 0 # main.cpp:7:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp0: + .loc 1 9 7 prologue_end # main.cpp:9:7 + movl $1688469761, -8(%rbp) # imm = 0x64A40101 + .loc 1 10 1 # main.cpp:10:1 + xorl %eax, %eax + .loc 1 10 1 epilogue_begin is_stmt 0 # main.cpp:10:1 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 22 # DW_TAG_typedef + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 1 # DW_AT_sibling <-- manually added + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x7f DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x28 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .long 82 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x43:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .long 89 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x52:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size +.Linfo_structured_type: + .byte 6 # Abbrev [6] 0x64:0x1e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long .Linfo_sibling # DW_AT_sibling <-- Manually added +.Linfo_sibling: + .byte 5 # Abbrev [5] 0x59:0xb DW_TAG_typedef + .long .Linfo_structured_type # DW_AT_type <-- Manually modified + .long .Linfo_string9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 5 # DW_AT_decl_line + .byte 7 # Abbrev [7] 0x69:0xc DW_TAG_member + .long .Linfo_string6 # DW_AT_name + .long .Linfo_base_type # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 7 # Abbrev [7] 0x75:0xc DW_TAG_member + .long .Linfo_string8 # DW_AT_name + .long .Linfo_base_type # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark +.Linfo_base_type: + .byte 4 # Abbrev [4] 0x82:0x7 DW_TAG_base_type + .long .Linfo_string7 # DW_AT_name + .byte 7 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=146 +.Linfo_string2: + .asciz "/dwarf4-sibling-test" # string offset=155 +.Linfo_string3: + .asciz "main" # string offset=213 +.Linfo_string4: + .asciz "int" # string offset=218 +.Linfo_string5: + .asciz "s" # string offset=222 +.Linfo_string6: + .asciz "a" # string offset=224 +.Linfo_string7: + .asciz "unsigned int" # string offset=226 +.Linfo_string8: + .asciz "b" # string offset=239 +.Linfo_string9: + .asciz "S" # string offset=241 + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf4-split-gdb-index-types-gdb-generated.test b/bolt/test/X86/dwarf4-split-gdb-index-types-gdb-generated.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-split-gdb-index-types-gdb-generated.test @@ -0,0 +1,51 @@ +# REQUIRES: system-linux + +# RUN: rm -rf %t +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: llvm-mc --split-dwarf-file=main.dwo -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-split-gdb-index-types-main.s -o maingdb.o +# RUN: llvm-mc --split-dwarf-file=helper.dwo -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-split-gdb-index-types-helper.s -o helpergdb.o +# RUN: %clang %cflags maingdb.o helpergdb.o -o maingdb.exe -Wl,-q +# RUN: llvm-objcopy maingdb.exe --add-section=.gdb_index=%p/Inputs/dwarf4-split-gdb-index-types-v8.gdb-index +# RUN: llvm-bolt maingdb.exe -o maingdb.exe.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index maingdb.exe.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB with split-dwarf DWARF4. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x0, Length = 0x34 +# POSTCHECK-NEXT: 1: Offset = 0x34, Length = 0x34 +# POSTCHECK: Types CU list offset = 0x38, has 4 entries +# POSTCHECK-NEXT: 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature = 0x675d23e4f33235f2 +# POSTCHECK-NEXT: 1: offset = 0x0000004a, type_offset = 0x0000001e, type_signature = 0x49dc260088be7e56 +# POSTCHECK-NEXT: 2: offset = 0x00000000, type_offset = 0x0000001e, type_signature = 0x104ec427d2ebea6f +# POSTCHECK-NEXT: 3: offset = 0x0000004a, type_offset = 0x0000001e, type_signature = 0xb4580bc1535df1e4 +# POSTCHECK: Address area offset = 0x98, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0x7a]]) (Size: 0x7a), CU id = 0 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0x8]]) (Size: 0x8), CU id = 1 +# POSTCHECK: Symbol table offset = 0xc0, size = 1024, filled slots +# POSTCHECK-NEXT: 192: Name offset = 0x38, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: Foo2, CU vector index: 0 +# POSTCHECK-NEXT: 193: Name offset = 0x3d, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: Foo3, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x42, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: main, CU vector index: 2 +# POSTCHECK-NEXT: 518: Name offset = 0x47, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: char, CU vector index: 3 +# POSTCHECK-NEXT: 560: Name offset = 0x4c, CU vector offset = 0x20 +# POSTCHECK-NEXT: String name: Foo2a, CU vector index: 4 +# POSTCHECK-NEXT: 634: Name offset = 0x52, CU vector offset = 0x28 +# POSTCHECK-NEXT: String name: Foo, CU vector index: 5 +# POSTCHECK-NEXT: 661: Name offset = 0x56, CU vector offset = 0x30 +# POSTCHECK-NEXT: String name: foo, CU vector index: 6 +# POSTCHECK-NEXT: 754: Name offset = 0x5a, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: int, CU vector index: 3 +# POSTCHECK: Constant pool offset = 0x20c0, has 7 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x10000003 +# POSTCHECK-NEXT: 1(0x8): 0x10000005 +# POSTCHECK-NEXT: 2(0x10): 0x30000000 +# POSTCHECK-NEXT: 3(0x18): 0x90000000 +# POSTCHECK-NEXT: 4(0x20): 0x10000004 diff --git a/bolt/test/X86/dwarf4-types-dwarf5-types.test b/bolt/test/X86/dwarf4-types-dwarf5-types.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-types-dwarf5-types.test @@ -0,0 +1,79 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-dwarf5-types-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-dwarf5-types-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-types %t.bolt | FileCheck --check-prefix=POSTCHECKTU %s + +# Check BOLT handles DWARF4/5 with fdebug-types. + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit [6] +# POSTCHECK: DW_TAG_subprogram [7] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x007c => {0x0000007c} "int") +# POSTCHECK: DW_TAG_formal_parameter [8] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x007c => {0x0000007c} "int") +# POSTCHECK: DW_TAG_formal_parameter [8] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0083 => {0x00000083} "char **") +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0094 => {0x00000094} "Foo") +# POSTCHECK: DW_TAG_base_type [5] +# POSTCHECK: DW_TAG_pointer_type [4] + +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_type_unit [11] +# POSTCHECK: DW_TAG_member [13] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0045 => {0x000000ec} "char *") +# POSTCHECK: DW_TAG_pointer_type [4] +# POSTCHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x004a => {0x000000f1} "char") + +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_type_unit [11] +# POSTCHECK: DW_TAG_structure_type [12] +# POSTCHECK: DW_TAG_member [13] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000132} "char *") +# POSTCHECK: DW_TAG_member [13] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000132} "char *") +# POSTCHECK: DW_TAG_pointer_type [4] +# POSTCHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000137} "char") + +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_compile_unit [15] +# POSTCHECK: DW_TAG_subprogram [16] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0048 => {0x00000184} "int") +# POSTCHECK: DW_TAG_variable [17] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x00000188} "Foo2a") +# POSTCHECK: DW_TAG_base_type [14] +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x104ec427d2ebea6f) +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: DW_AT_signature [DW_FORM_ref_sig8] (0xb4580bc1535df1e4) + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU-SAME: type_signature = 0x675d23e4f33235f2 +# POSTCHECKTU-SAME: type_offset = 0x001e +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x0000004c} "char *") +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x0000004c} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0051 => {0x00000051} "char") +# POSTCHECKTU: DW_TAG_base_type [5] +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "char") + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU-SAME: type_signature = 0x49dc260088be7e56 +# POSTCHECKTU-SAME: type_offset = 0x001e +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_structure_type [2] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000099} "char *") +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000099} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0045 => {0x0000009e} "char") +# POSTCHECKTU: DW_TAG_base_type [5] +# POSTCHECKTU-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "char") diff --git a/bolt/test/X86/dwarf4-types-dwarf5.test b/bolt/test/X86/dwarf4-types-dwarf5.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-types-dwarf5.test @@ -0,0 +1,40 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-dwarf5-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-dwarf5-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-types %t.bolt | FileCheck --check-prefix=POSTCHECKTU %s + +# Check BOLT handles DWARF4 with fdebug-types, and DWARF5 without. + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_subprogram +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x007c => {0x0000007c} "int") +# POSTCHECK: DW_TAG_formal_parameter +# POSTCHECK: DW_TAG_structure_type +# POSTCHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x675d23e4f33235f2) +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_subprogram +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0031 => {0x000000d8} "int") +# POSTCHECK: DW_TAG_base_type + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_structure_type [2] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x0000004c} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0051 => {0x00000051} "char") +# POSTCHECKTU: DW_TAG_base_type [5] +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_structure_type [2] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000099} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0045 => {0x0000009e} "char") diff --git a/bolt/test/X86/dwarf4-types-forward-backward-cross-reference.s b/bolt/test/X86/dwarf4-types-forward-backward-cross-reference.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-types-forward-backward-cross-reference.s @@ -0,0 +1,878 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t.o +# RUN: %clang %cflags -gdwarf-4 %t.o -o %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# This test checks that BOLT handles correctly backward and forward cross CU references +# for DWARF4 with -fdebug-types-section + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_variable [10] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000112 "Foo2a") + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_variable [10] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000094 "Foo") +# POSTCHECK: DW_TAG_variable [10] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000190 "Foo3a") + +# main.cpp +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo2 { +# char *c1; +# char *c2; +# }; +# int main(int argc, char *argv[]) { +# Foo f; +# f.c1 = argv[argc]; +# f.c2 = argv[argc + 1]; +# f.c3 = argv[argc + 2]; +# Foo2 f2; +# f.c1 = argv[argc + 3]; +# f.c2 = argv[argc + 4]; +# return 0; +# } + +# helper.cpp +# struct Foo2a { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo3 { +# char *c1; +# char *c2; +# }; +# +# int foo() { +# Foo2a f; +# Foo3 f2; +# return 0; +# } + +# helper1.cpp +# struct Foo3a { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo4 { +# char *c1; +# char *c2; +# }; +# +# int foo2() { +# Foo3a f; +# Foo4 f2; +# return 0; +# } + + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/dwarf4-types-forward-cross-reference-test" "main.cpp" + .loc 1 10 0 # main.cpp:10:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 12 9 prologue_end # main.cpp:12:9 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 1 12 7 is_stmt 0 # main.cpp:12:7 + movq %rax, -40(%rbp) + .loc 1 13 9 is_stmt 1 # main.cpp:13:9 + movq -16(%rbp), %rax + .loc 1 13 14 is_stmt 0 # main.cpp:13:14 + movl -8(%rbp), %ecx + .loc 1 13 19 # main.cpp:13:19 + addl $1, %ecx + .loc 1 13 9 # main.cpp:13:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 13 7 # main.cpp:13:7 + movq %rax, -32(%rbp) + .loc 1 14 9 is_stmt 1 # main.cpp:14:9 + movq -16(%rbp), %rax + .loc 1 14 14 is_stmt 0 # main.cpp:14:14 + movl -8(%rbp), %ecx + .loc 1 14 19 # main.cpp:14:19 + addl $2, %ecx + .loc 1 14 9 # main.cpp:14:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 14 7 # main.cpp:14:7 + movq %rax, -24(%rbp) + .loc 1 16 9 is_stmt 1 # main.cpp:16:9 + movq -16(%rbp), %rax + .loc 1 16 14 is_stmt 0 # main.cpp:16:14 + movl -8(%rbp), %ecx + .loc 1 16 19 # main.cpp:16:19 + addl $3, %ecx + .loc 1 16 9 # main.cpp:16:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 16 7 # main.cpp:16:7 + movq %rax, -40(%rbp) + .loc 1 17 9 is_stmt 1 # main.cpp:17:9 + movq -16(%rbp), %rax + .loc 1 17 14 is_stmt 0 # main.cpp:17:14 + movl -8(%rbp), %ecx + .loc 1 17 19 # main.cpp:17:19 + addl $4, %ecx + .loc 1 17 9 # main.cpp:17:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 17 7 # main.cpp:17:7 + movq %rax, -32(%rbp) + .loc 1 18 2 is_stmt 1 # main.cpp:18:2 + xorl %eax, %eax + .loc 1 18 2 epilogue_begin is_stmt 0 # main.cpp:18:2 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z3foov # -- Begin function _Z3foov + .p2align 4, 0x90 + .type _Z3foov,@function +_Z3foov: # @_Z3foov +.Lfunc_begin1: + .file 2 "/dwarf4-types-forward-cross-reference-test" "helper.cpp" + .loc 2 11 0 is_stmt 1 # helper.cpp:11:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp2: + .loc 2 14 3 prologue_end # helper.cpp:14:3 + xorl %eax, %eax + .loc 2 14 3 epilogue_begin is_stmt 0 # helper.cpp:14:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end1: + .size _Z3foov, .Lfunc_end1-_Z3foov + .cfi_endproc + # -- End function + .globl _Z4foo2v # -- Begin function _Z4foo2v + .p2align 4, 0x90 + .type _Z4foo2v,@function +_Z4foo2v: # @_Z4foo2v +.Lfunc_begin2: + .file 3 "/dwarf4-types-forward-cross-reference-test" "helper1.cpp" + .loc 3 11 0 is_stmt 1 # helper1.cpp:11:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp4: + .loc 3 14 3 prologue_end # helper1.cpp:14:3 + xorl %eax, %eax + .loc 3 14 3 epilogue_begin is_stmt 0 # helper1.cpp:14:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp5: +.Lfunc_end2: + .size _Z4foo2v, .Lfunc_end2-_Z4foo2v + .cfi_endproc + # -- End function + .section .debug_types,"G",@progbits,7448148824980338162,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 7448148824980338162 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x42 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x2e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string18 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3f:0xc DW_TAG_member + .long .Linfo_string17 # DW_AT_name + .long 76 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x4c:0x5 DW_TAG_pointer_type + .long 81 # DW_AT_type + .byte 5 # Abbrev [5] 0x51:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_types,"G",@progbits,5322170643381124694,comdat + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 5322170643381124694 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x36 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string20 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 64 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type + .long 69 # DW_AT_type + .byte 5 # Abbrev [5] 0x45:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_types,"G",@progbits,1175092228111723119,comdat + .long .Ldebug_info_end2-.Ldebug_info_start2 # Length of Unit +.Ldebug_info_start2: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad 1175092228111723119 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x42 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x2e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string21 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 76 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 76 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3f:0xc DW_TAG_member + .long .Linfo_string17 # DW_AT_name + .long 76 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x4c:0x5 DW_TAG_pointer_type + .long 81 # DW_AT_type + .byte 5 # Abbrev [5] 0x51:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end2: + .section .debug_types,"G",@progbits,12995149649732825572,comdat + .long .Ldebug_info_end3-.Ldebug_info_start3 # Length of Unit +.Ldebug_info_start3: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad -5451594423976726044 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x36 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string22 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 64 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 64 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type + .long 69 # DW_AT_type + .byte 5 # Abbrev [5] 0x45:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end3: + .section .debug_types,"G",@progbits,10693860647081617285,comdat + .long .Ldebug_info_end4-.Ldebug_info_start4 # Length of Unit +.Ldebug_info_start4: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad -7752883426627934331 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x42 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x2e DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string23 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 3 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 76 # DW_AT_type + .byte 3 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 76 # DW_AT_type + .byte 3 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3f:0xc DW_TAG_member + .long .Linfo_string17 # DW_AT_name + .long 76 # DW_AT_type + .byte 3 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x4c:0x5 DW_TAG_pointer_type + .long 81 # DW_AT_type + .byte 5 # Abbrev [5] 0x51:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end4: + .section .debug_types,"G",@progbits,17604755499357858397,comdat + .long .Ldebug_info_end5-.Ldebug_info_start5 # Length of Unit +.Ldebug_info_start5: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .quad -841988574351693219 # Type Signature + .long 30 # Type DIE Offset + .byte 1 # Abbrev [1] 0x17:0x36 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # Abbrev [2] 0x1e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string24 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 3 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x27:0xc DW_TAG_member + .long .Linfo_string15 # DW_AT_name + .long 64 # DW_AT_type + .byte 3 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_member + .long .Linfo_string16 # DW_AT_name + .long 64 # DW_AT_type + .byte 3 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x40:0x5 DW_TAG_pointer_type + .long 69 # DW_AT_type + .byte 5 # Abbrev [5] 0x45:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end5: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code <-- Manually added abbrev decl + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end6-.Ldebug_info_start6 # Length of Unit +.Ldebug_info_start6: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x9c DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 7 # Abbrev [7] 0x2a:0x52 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 124 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x43:0xe DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .long .Linfo_string11 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 124 # DW_AT_type + .byte 8 # Abbrev [8] 0x51:0xe DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 131 # DW_AT_type + .byte 9 # Abbrev [9] 0x5f:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .long .Linfo_string14 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 148 # DW_AT_type + .byte 12 # Abbrev [12] 0x6d:0xe DW_TAG_variable <-- Manually modified s/9/12 + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .long .Linfo_string19 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 15 # DW_AT_decl_line + .long .Lmanual_label # DW_AT_type <-- Manually modified + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x7c:0x7 DW_TAG_base_type + .long .Linfo_string6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x83:0x5 DW_TAG_pointer_type + .long 136 # DW_AT_type + .byte 4 # Abbrev [4] 0x88:0x5 DW_TAG_pointer_type + .long 141 # DW_AT_type + .byte 5 # Abbrev [5] 0x8d:0x7 DW_TAG_base_type + .long .Linfo_string13 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size +.Lmanual_label_forward: + .byte 10 # Abbrev [10] 0x94:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x9d:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end6: +.Lcu_begin1: + .long .Ldebug_info_end7-.Ldebug_info_start7 # Length of Unit +.Ldebug_info_start7: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x73 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string3 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 11 # Abbrev [11] 0x2a:0x3a DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string7 # DW_AT_linkage_name + .long .Linfo_string8 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 100 # DW_AT_type + # DW_AT_external + .byte 12 # Abbrev [12] 0x47:0xe DW_TAG_variable2 <-- Manually modified s/9/12 + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .long .Linfo_string14 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long .Lmanual_label_forward # DW_AT_type <-- Manually modified + .byte 12 # Abbrev [12] 0x55:0xe DW_TAG_variable <-- Manually modified s/9/12 + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .long .Linfo_string19 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long .Lmanual_label2 # DW_AT_type <-- Manually modified + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x64:0x7 DW_TAG_base_type + .long .Linfo_string6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size +.Lmanual_label: + .byte 10 # Abbrev [10] 0x6b:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 1175092228111723119 # DW_AT_signature + .byte 10 # Abbrev [10] 0x74:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -5451594423976726044 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end7: +.Lcu_begin2: + .long .Ldebug_info_end8-.Ldebug_info_start8 # Length of Unit +.Ldebug_info_start8: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 6 # Abbrev [6] 0xb:0x73 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string4 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 11 # Abbrev [11] 0x2a:0x3a DW_TAG_subprogram + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .long .Linfo_string9 # DW_AT_linkage_name + .long .Linfo_string10 # DW_AT_name + .byte 3 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 100 # DW_AT_type + # DW_AT_external + .byte 9 # Abbrev [9] 0x47:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .long .Linfo_string14 # DW_AT_name + .byte 3 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 107 # DW_AT_type + .byte 9 # Abbrev [9] 0x55:0xe DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .long .Linfo_string19 # DW_AT_name + .byte 3 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long 116 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x64:0x7 DW_TAG_base_type + .long .Linfo_string6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size +.Lmanual_label2: + .byte 10 # Abbrev [10] 0x6b:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -7752883426627934331 # DW_AT_signature + .byte 10 # Abbrev [10] 0x74:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -841988574351693219 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end8: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=105 +.Linfo_string2: + .asciz "/dwarf4-types-forward-cross-reference-test" # string offset=114 +.Linfo_string3: + .asciz "helper.cpp" # string offset=194 +.Linfo_string4: + .asciz "helper1.cpp" # string offset=205 +.Linfo_string5: + .asciz "main" # string offset=217 +.Linfo_string6: + .asciz "int" # string offset=222 +.Linfo_string7: + .asciz "_Z3foov" # string offset=226 +.Linfo_string8: + .asciz "foo" # string offset=234 +.Linfo_string9: + .asciz "_Z4foo2v" # string offset=238 +.Linfo_string10: + .asciz "foo2" # string offset=247 +.Linfo_string11: + .asciz "argc" # string offset=252 +.Linfo_string12: + .asciz "argv" # string offset=257 +.Linfo_string13: + .asciz "char" # string offset=262 +.Linfo_string14: + .asciz "f" # string offset=267 +.Linfo_string15: + .asciz "c1" # string offset=269 +.Linfo_string16: + .asciz "c2" # string offset=272 +.Linfo_string17: + .asciz "c3" # string offset=275 +.Linfo_string18: + .asciz "Foo" # string offset=278 +.Linfo_string19: + .asciz "f2" # string offset=282 +.Linfo_string20: + .asciz "Foo2" # string offset=285 +.Linfo_string21: + .asciz "Foo2a" # string offset=290 +.Linfo_string22: + .asciz "Foo3" # string offset=296 +.Linfo_string23: + .asciz "Foo3a" # string offset=301 +.Linfo_string24: + .asciz "Foo4" # string offset=307 + .ident "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" + .ident "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" + .ident "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf4-types.test b/bolt/test/X86/dwarf4-types.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf4-types.test @@ -0,0 +1,64 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-types-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-types %t.bolt | FileCheck --check-prefix=POSTCHECKTU %s + +# Check BOLT handles DWARF4/5 with fdebug-types. + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit [6] +# POSTCHECK: DW_TAG_subprogram [7] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x007c => {0x0000007c} "int") +# POSTCHECK: DW_TAG_formal_parameter [8] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x007c => {0x0000007c} "int") +# POSTCHECK: DW_TAG_formal_parameter [8] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0083 => {0x00000083} "char **") +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0094 => {0x00000094} "Foo") +# POSTCHECK: DW_TAG_base_type [5] +# POSTCHECK: DW_TAG_pointer_type [4] + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit [6] +# POSTCHECK: DW_TAG_subprogram [11] +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x006b => {0x00000112} "Foo2a") +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0074 => {0x0000011b} "Foo3") +# POSTCHECK: DW_TAG_base_type [5] +# POSTCHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "int") +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: DW_AT_signature [DW_FORM_ref_sig8] (0x104ec427d2ebea6f) +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: DW_AT_signature [DW_FORM_ref_sig8] (0xb4580bc1535df1e4) + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU-SAME: type_signature = 0x675d23e4f33235f2 +# POSTCHECKTU-SAME: type_offset = 0x001e +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x0000004c} "char *") +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x004c => {0x0000004c} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0051 => {0x00000051} "char") +# POSTCHECKTU: DW_TAG_base_type [5] +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "char") + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU-SAME: type_signature = 0x49dc260088be7e56 +# POSTCHECKTU-SAME: type_offset = 0x001e +# POSTCHECKTU: DW_TAG_type_unit [1] +# POSTCHECKTU: DW_TAG_structure_type [2] +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000099} "char *") +# POSTCHECKTU: DW_TAG_member [3] +# POSTCHECKTU: DW_AT_type [DW_FORM_ref4] (cu + 0x0040 => {0x00000099} "char *") +# POSTCHECKTU: DW_TAG_pointer_type [4] +# POSTCHECKTU-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0045 => {0x0000009e} "char") +# POSTCHECKTU: DW_TAG_base_type [5] +# POSTCHECKTU-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "char") diff --git a/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb11.test b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb11.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb11.test @@ -0,0 +1,41 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmaingdb.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-gdb-index-types-helper.s -o %thelpergdb.o +# RUN: %clang %cflags %tmaingdb.o %thelpergdb.o -o %tgdb.exe -Wl,-q +# RUN: llvm-objcopy %tgdb.exe --add-section=.gdb_index=%p/Inputs/dwarf5-dwarf4-gdb-index-types-v8.generted-gdb11.gdb-index +# RUN: llvm-bolt %tgdb.exe -o %tgdb.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %tgdb.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 1: Offset = 0x92, Length = 0x72 +# POSTCHECK: Types CU list offset = 0x38, has 2 entries +# POSTCHECK-NEXT: 0: offset = 0x00000000, type_offset = 0x00000023, type_signature = 0x418503b8111e9a7b +# POSTCHECK-NEXT: 1: offset = 0x00000000, type_offset = 0x0000001e, type_signature = 0x00f6cca4e3a15118 +# POSTCHECK: Address area offset = 0x68, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 2 +# POSTCHECK: Symbol table offset = 0x90, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x20, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x22, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x25, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: main, CU vector index: 2 +# POSTCHECK-NEXT: 661: Name offset = 0x2a, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: foo, CU vector index: 3 +# POSTCHECK-NEXT: 732: Name offset = 0x2e, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 1 +# POSTCHECK-NEXT: 754: Name offset = 0x3b, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: int, CU vector index: 0 +# POSTCHECK: Constant pool offset = 0x2090, has 4 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000001 +# POSTCHECK-NEXT: 1(0x8): 0x90000002 +# POSTCHECK-NEXT: 2(0x10): 0x30000001 +# POSTCHECK-NEXT: 3(0x18): 0x30000002 diff --git a/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb9.test b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb9.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-gdb-generated-gdb9.test @@ -0,0 +1,43 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmaingdb.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-gdb-index-types-helper.s -o %thelpergdb.o +# RUN: %clang %cflags %tmaingdb.o %thelpergdb.o -o %tgdb.exe -Wl,-q +# RUN: llvm-objcopy %tgdb.exe --add-section=.gdb_index=%p/Inputs/dwarf5-dwarf4-gdb-index-types-v8.generted-gdb9.gdb-index +# RUN: llvm-bolt %tgdb.exe -o %tgdb.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %tgdb.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 3 entries +# POSTCHECK-NEXT: 0: Offset = 0x0, Length = 0x40 +# POSTCHECK-NEXT: 1: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 2: Offset = 0x92, Length = 0x72 +# POSTCHECK: Types CU list offset = 0x48, has 2 entries +# POSTCHECK-NEXT: 0: offset = 0x00000000, type_offset = 0x00000023, type_signature = 0x418503b8111e9a7b +# POSTCHECK-NEXT: 1: offset = 0x00000000, type_offset = 0x0000001e, type_signature = 0x00f6cca4e3a15118 +# POSTCHECK: Address area offset = 0x78, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 2 +# POSTCHECK: Symbol table offset = 0xa0, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x28, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x2a, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x2d, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: main, CU vector index: 2 +# POSTCHECK-NEXT: 661: Name offset = 0x32, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: foo, CU vector index: 3 +# POSTCHECK-NEXT: 732: Name offset = 0x36, CU vector offset = 0x20 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 4 +# POSTCHECK-NEXT: 754: Name offset = 0x43, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: int, CU vector index: 0 +# POSTCHECK: Constant pool offset = 0x20a0, has 5 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000001 +# POSTCHECK-NEXT: 1(0x8): 0x90000002 +# POSTCHECK-NEXT: 2(0x10): 0x30000001 +# POSTCHECK-NEXT: 3(0x18): 0x30000002 +# POSTCHECK-NEXT: 4(0x20): 0x90000000 diff --git a/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-lld-generated.test b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-lld-generated.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-dwarf4-gdb-index-types-lld-generated.test @@ -0,0 +1,40 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-gdb-index-types-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe -Wl,-q -Wl,--gdb-index +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by LLD. + +# POSTCHECK: Version = 7 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 1: Offset = 0x92, Length = 0x72 +# POSTCHECK: Types CU list offset = 0x38, has 0 entries +# POSTCHECK: Address area offset = 0x38, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 2 +# POSTCHECK: Symbol table offset = 0x60, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x38, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x3a, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x4a, CU vector offset = 0x1c +# POSTCHECK-NEXT: String name: main, CU vector index: 3 +# POSTCHECK-NEXT: 661: Name offset = 0x53, CU vector offset = 0x30 +# POSTCHECK-NEXT: String name: foo, CU vector index: 5 +# POSTCHECK-NEXT: 732: Name offset = 0x3d, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 2 +# POSTCHECK-NEXT: 754: Name offset = 0x4f, CU vector offset = 0x24 +# POSTCHECK-NEXT: String name: int, CU vector index: 4 +# POSTCHECK: Constant pool offset = 0x2060, has 6 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000000 +# POSTCHECK-NEXT: 1(0x8): 0x90000001 +# POSTCHECK-NEXT: 2(0x10): 0x10000000 0x10000001 +# POSTCHECK-NEXT: 3(0x1c): 0x30000000 +# POSTCHECK-NEXT: 4(0x24): 0x90000000 0x90000001 +# POSTCHECK-NEXT: 5(0x30): 0x30000001 diff --git a/bolt/test/X86/dwarf5-dwarf4-types-backward-forward-cross-reference.test b/bolt/test/X86/dwarf5-dwarf4-types-backward-forward-cross-reference.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-dwarf4-types-backward-forward-cross-reference.test @@ -0,0 +1,47 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-dwarf4-types-backward-forward-cross-reference-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-dwarf4-types-backward-forward-cross-reference-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-types %t.bolt | FileCheck --check-prefix=POSTCHECKTU %s + +# This test checks that BOLT handles correctly backward and forward cross CU references +# for DWARF5 and DWARF4 with -fdebug-types-section + +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_type_unit +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_variable [14] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000000001f8 "Foo2a") +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_variable [14] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000199 "Foo") +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_variable [20] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000000002f4 "Foo4a") +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_compile_unit +# POSTCHECK: DW_TAG_variable [20] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000276 "Foo3a") + +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit +# POSTCHECKTU: DW_TAG_structure_type +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "Foo3a") +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit +# POSTCHECKTU: DW_TAG_structure_type +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "Foo4") +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit +# POSTCHECKTU: DW_TAG_structure_type +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "Foo4a") +# POSTCHECKTU: version = 0x0004 +# POSTCHECKTU: DW_TAG_type_unit +# POSTCHECKTU: DW_TAG_structure_type +# POSTCHECKTU: DW_AT_name [DW_FORM_strp] ( .debug_str[0x{{[0-9a-f]+}}] = "Foo5") diff --git a/bolt/test/X86/dwarf5-ftypes-dwo-mono-input-dwp-output.test b/bolt/test/X86/dwarf5-ftypes-dwo-mono-input-dwp-output.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-ftypes-dwo-mono-input-dwp-output.test @@ -0,0 +1,55 @@ +# REQUIRES: system-linux +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc --split-dwarf-file=main.dwo -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-split-gdb-index-types-main.s -o main.o +; RUN: llvm-mc --split-dwarf-file=helper.dwo -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-split-gdb-index-types-helper.s -o helper1.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-types-helper2.s -o helper2.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o helper1.o helper2.o -o main.exe +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo | FileCheck -check-prefix=PRE-BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info helper2.o | FileCheck -check-prefix=PRE-BOLT2 %s +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections --write-dwp +; RUN: llvm-dwarfdump --show-form --verbose --debug-info -r 0 main.exe.bolt.dwp | FileCheck -check-prefix=BOLT %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-TU-INDEX %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-cu-index main.exe.bolt.dwp | FileCheck -check-prefix=BOLT-DWP-CU-INDEX %s + +; Test input into bolt a .dwo file with TU Index. +; Test split-dwarf and monolithic TUs. +; Make sure the output .dwp file has a type and cu information. + +; PRE-BOLT: Type Unit +; PRE-BOLT-SAME: 0x675d23e4f33235f2 +; PRE-BOLT: Type Unit +; PRE-BOLT-SAME: 0x49dc260088be7e56 + +; PRE-BOLT2: 0x8f55ac73549bc003 +; PRE-BOLT2: DW_TAG_type_unit +; PRE-BOLT2: 0xe7734af8fed0632e +; PRE-BOLT2: DW_TAG_type_unit + +; BOLT: 0x00000000: Type Unit: length = 0x00000047 +; BOLT-SAME: 0x675d23e4f33235f2 +; BOLT: 0x0000004b: Type Unit: length = 0x0000003e +; BOLT-SAME: 0x49dc260088be7e56 +; BOLT: 0x0000008d: Compile Unit: length = 0x00000074 +; BOLT-SAME: 0x4257354d8bb35644 +; BOLT: 0x00000105: Type Unit: length = 0x00000047 +; BOLT-SAME: 0x104ec427d2ebea6f +; BOLT: 0x00000150: Type Unit: length = 0x0000003e +; BOLT-SAME: 0xb4580bc1535df1e4 +; BOLT: 0x00000192: Compile Unit: length = 0x00000051 +; BOLT-SAME: 0x7738bfb5f3edfb73 +; BOLT-NOT: 0x8f55ac73549bc003 +; BOLT-NOT: 0xe7734af8fed0632e + +; BOLT-DWP-TU-INDEX: version = 5, units = 4, slots = 8 +; BOLT-DWP-TU-INDEX: Index Signature +; BOLT-DWP-TU-INDEX: 3 0x675d23e4f33235f2 [0x0000000000000000, 0x000000000000004b) [0x00000000, 0x00000083) [0x00000000, 0x00000056) [0x00000000, 0x00000044) +; BOLT-DWP-TU-INDEX: 5 0xb4580bc1535df1e4 [0x0000000000000150, 0x0000000000000192) [0x00000083, 0x000000f9) [0x00000056, 0x000000ae) [0x00000044, 0x00000084) +; BOLT-DWP-TU-INDEX: 7 0x49dc260088be7e56 [0x000000000000004b, 0x000000000000008d) [0x00000000, 0x00000083) [0x00000000, 0x00000056) [0x00000000, 0x00000044) +; BOLT-DWP-TU-INDEX: 8 0x104ec427d2ebea6f [0x0000000000000105, 0x0000000000000150) [0x00000083, 0x000000f9) [0x00000056, 0x000000ae) [0x00000044, 0x00000084) + +; BOLT-DWP-CU-INDEX: version = 5, units = 2, slots = 4 +; BOLT-DWP-CU-INDEX: Index Signature +; BOLT-DWP-CU-INDEX: 1 0x4257354d8bb35644 [0x000000000000008d, 0x0000000000000105) [0x00000000, 0x00000083) [0x00000000, 0x00000056) [0x00000000, 0x00000044) +; BOLT-DWP-CU-INDEX: 4 0x7738bfb5f3edfb73 [0x0000000000000192, 0x00000000000001e7) [0x00000083, 0x000000f9) [0x00000056, 0x000000ae) [0x00000044, 0x00000084) diff --git a/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb11.test b/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb11.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb11.test @@ -0,0 +1,41 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmaingdb.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-helper.s -o %thelpergdb.o +# RUN: %clang %cflags %tmaingdb.o %thelpergdb.o -o %tgdb.exe -Wl,-q +# RUN: llvm-objcopy %tgdb.exe --add-section=.gdb_index=%p/Inputs/dwarf5-gdb-index-types-v8.generted-gdb11.gdb-index +# RUN: llvm-bolt %tgdb.exe -o %tgdb.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %tgdb.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 1: Offset = 0xd2, Length = 0x53 +# POSTCHECK: Types CU list offset = 0x38, has 2 entries +# POSTCHECK-NEXT: 0: offset = 0x00000000, type_offset = 0x00000023, type_signature = 0x418503b8111e9a7b +# POSTCHECK-NEXT: 1: offset = 0x00000092, type_offset = 0x00000023, type_signature = 0x00f6cca4e3a15118 +# POSTCHECK: Address area offset = 0x68, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 3 +# POSTCHECK: Symbol table offset = 0x90, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x28, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x2a, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x2d, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: main, CU vector index: 2 +# POSTCHECK-NEXT: 661: Name offset = 0x32, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: foo, CU vector index: 3 +# POSTCHECK-NEXT: 732: Name offset = 0x36, CU vector offset = 0x20 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 4 +# POSTCHECK-NEXT: 754: Name offset = 0x43, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: int, CU vector index: 0 +# POSTCHECK: Constant pool offset = 0x2090, has 5 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000001 +# POSTCHECK-NEXT: 1(0x8): 0x90000003 +# POSTCHECK-NEXT: 2(0x10): 0x30000001 +# POSTCHECK-NEXT: 3(0x18): 0x30000003 diff --git a/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb9.test b/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb9.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-gdb-index-types-gdb-generated-gdb9.test @@ -0,0 +1,43 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmaingdb.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-helper.s -o %thelpergdb.o +# RUN: %clang %cflags %tmaingdb.o %thelpergdb.o -o %tgdb.exe -Wl,-q +# RUN: llvm-objcopy %tgdb.exe --add-section=.gdb_index=%p/Inputs/dwarf5-gdb-index-types-v8.generted-gdb9.gdb-index +# RUN: llvm-bolt %tgdb.exe -o %tgdb.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %tgdb.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 4 entries +# POSTCHECK-NEXT: 0: Offset = 0x0, Length = 0x40 +# POSTCHECK-NEXT: 1: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 2: Offset = 0x92, Length = 0x40 +# POSTCHECK-NEXT: 3: Offset = 0xd2, Length = 0x53 +# POSTCHECK: Types CU list offset = 0x58, has 2 entries +# POSTCHECK-NEXT: 0: offset = 0x00000000, type_offset = 0x00000023, type_signature = 0x418503b8111e9a7b +# POSTCHECK-NEXT: 1: offset = 0x00000092, type_offset = 0x00000023, type_signature = 0x00f6cca4e3a15118 +# POSTCHECK: Address area offset = 0x88, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 3 +# POSTCHECK: Symbol table offset = 0xb0, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x28, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x2a, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x2d, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: main, CU vector index: 2 +# POSTCHECK-NEXT: 661: Name offset = 0x32, CU vector offset = 0x18 +# POSTCHECK-NEXT: String name: foo, CU vector index: 3 +# POSTCHECK-NEXT: 732: Name offset = 0x36, CU vector offset = 0x20 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 4 +# POSTCHECK-NEXT: 754: Name offset = 0x43, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: int, CU vector index: 0 +# POSTCHECK: Constant pool offset = 0x20b0, has 5 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000001 +# POSTCHECK-NEXT: 1(0x8): 0x90000003 +# POSTCHECK-NEXT: 2(0x10): 0x30000001 +# POSTCHECK-NEXT: 3(0x18): 0x30000003 diff --git a/bolt/test/X86/dwarf5-gdb-index-types-lld-generated.test b/bolt/test/X86/dwarf5-gdb-index-types-lld-generated.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-gdb-index-types-lld-generated.test @@ -0,0 +1,40 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-gdb-index-types-helper.s -o %thelper.o +# RUN: %clang %cflags %tmain.o %thelper.o -o %t.exe -Wl,-q -Wl,--gdb-index +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by LLD. + +# POSTCHECK: Version = 7 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x40, Length = 0x52 +# POSTCHECK-NEXT: 1: Offset = 0xd2, Length = 0x53 +# POSTCHECK: Types CU list offset = 0x38, has 0 entries +# POSTCHECK: Address area offset = 0x38, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0xf]]) (Size: 0xf), CU id = 1 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0xd]]) (Size: 0xd), CU id = 3 +# POSTCHECK: Symbol table offset = 0x60, size = 1024, filled slots +# POSTCHECK-NEXT: 2: Name offset = 0x38, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: S, CU vector index: 0 +# POSTCHECK-NEXT: 71: Name offset = 0x3a, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: S2, CU vector index: 1 +# POSTCHECK-NEXT: 489: Name offset = 0x4a, CU vector offset = 0x1c +# POSTCHECK-NEXT: String name: main, CU vector index: 3 +# POSTCHECK-NEXT: 661: Name offset = 0x53, CU vector offset = 0x30 +# POSTCHECK-NEXT: String name: foo, CU vector index: 5 +# POSTCHECK-NEXT: 732: Name offset = 0x3d, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: unsigned int, CU vector index: 2 +# POSTCHECK-NEXT: 754: Name offset = 0x4f, CU vector offset = 0x24 +# POSTCHECK-NEXT: String name: int, CU vector index: 4 +# POSTCHECK: Constant pool offset = 0x2060, has 6 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x90000000 +# POSTCHECK-NEXT: 1(0x8): 0x90000001 +# POSTCHECK-NEXT: 2(0x10): 0x10000000 0x10000001 +# POSTCHECK-NEXT: 3(0x1c): 0x30000000 +# POSTCHECK-NEXT: 4(0x24): 0x90000000 0x90000001 +# POSTCHECK-NEXT: 5(0x30): 0x30000001 diff --git a/bolt/test/X86/dwarf5-locexpr-referrence.test b/bolt/test/X86/dwarf5-locexpr-referrence.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-locexpr-referrence.test @@ -0,0 +1,21 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-locexpr-referrence-main.s -o %tmain.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-locexpr-referrence-helper.s -o %thelper.o +# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=CHECK %s + +# This test checks that we update relative DIE references with DW_OP_convert that are in locexpr. + +# CHECK: version = 0x0005 +# CHECK: version = 0x0005 +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location +# CHECK-SAME: DW_OP_convert (0x00000028 -> 0x0000005d) +# CHECK-SAME: DW_OP_convert (0x0000002c -> 0x00000061) +# CHECK: version = 0x0005 +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_location +# CHECK-SAME: DW_OP_convert (0x00000028 -> 0x000000c4) +# CHECK-SAME: DW_OP_convert (0x0000002c -> 0x000000c8) diff --git a/bolt/test/X86/dwarf5-split-gdb-index-types-gdb-generated.test b/bolt/test/X86/dwarf5-split-gdb-index-types-gdb-generated.test new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-split-gdb-index-types-gdb-generated.test @@ -0,0 +1,37 @@ +# REQUIRES: system-linux + +# RUN: rm -rf %t +# RUN: mkdir -p %t +# RUN: cd %t +# RUN: llvm-mc --split-dwarf-file=main.dwo -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-split-gdb-index-types-main.s -o maingdb.o +# RUN: llvm-mc --split-dwarf-file=helper.dwo -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-split-gdb-index-types-helper.s -o helpergdb.o +# RUN: %clang %cflags maingdb.o helpergdb.o -o maingdb.exe -Wl,-q +# RUN: llvm-objcopy maingdb.exe --add-section=.gdb_index=%p/Inputs/dwarf5-split-gdb-index-types-v8.gdb-index +# RUN: llvm-bolt maingdb.exe -o maingdb.exe.bolt --update-debug-sections +# RUN: llvm-dwarfdump --gdb-index maingdb.exe.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles gdb-index generated by GDB with split-dwarf DWARF4. + +# POSTCHECK: Version = 8 +# POSTCHECK: CU list offset = 0x18, has 2 entries +# POSTCHECK-NEXT: 0: Offset = 0x0, Length = 0x29 +# POSTCHECK-NEXT: 1: Offset = 0x29, Length = 0x29 +# POSTCHECK: Types CU list offset = 0x38, has 0 entries +# POSTCHECK: Address area offset = 0x38, has 2 entries +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR:]], +# POSTCHECK-SAME: 0x[[#ADDR + 0x7a]]) (Size: 0x7a), CU id = 0 +# POSTCHECK-NEXT: Low/High address = [0x[[#%.4x,ADDR1:]], +# POSTCHECK-SAME: 0x[[#ADDR1 + 0x8]]) (Size: 0x8), CU id = 1 +# POSTCHECK: Symbol table offset = 0x60, size = 1024, filled slots +# POSTCHECK-NEXT: 489: Name offset = 0x18, CU vector offset = 0x0 +# POSTCHECK-NEXT: String name: main, CU vector index: 0 +# POSTCHECK-NEXT: 518: Name offset = 0x1d, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: char, CU vector index: 1 +# POSTCHECK-NEXT: 661: Name offset = 0x22, CU vector offset = 0x10 +# POSTCHECK-NEXT: String name: foo, CU vector index: 2 +# POSTCHECK-NEXT: 754: Name offset = 0x26, CU vector offset = 0x8 +# POSTCHECK-NEXT: String name: int, CU vector index: 1 +# POSTCHECK: Constant pool offset = 0x2060, has 3 CU vectors +# POSTCHECK-NEXT: 0(0x0): 0x30000000 +# POSTCHECK-NEXT: 1(0x8): 0x90000000 +# POSTCHECK-NEXT: 2(0x10): 0x30000001 diff --git a/bolt/test/X86/dwarf5-types-backward-cross-reference.s b/bolt/test/X86/dwarf5-types-backward-cross-reference.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-types-backward-cross-reference.s @@ -0,0 +1,752 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t.o +# RUN: %clang %cflags -gdwarf-5 %t.o -o %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# This test checks that BOLT handles backward cross CU references for dwarf5 +# when -fdebug-types-sections is specified. + +# The assembly was manually modified to do cross CU reference. + +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Compile Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: DW_TAG_structure_type [10] +# POSTCHECK: Compile Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_TAG_variable [12] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000199 "Foo") + + +# main.cpp +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo2 { +# char *c1; +# char *c2; +# }; +# int main(int argc, char *argv[]) { +# Foo f; +# f.c1 = argv[argc]; +# f.c2 = argv[argc + 1]; +# f.c3 = argv[argc + 2]; +# Foo2 f2; +# f.c1 = argv[argc + 3]; +# f.c2 = argv[argc + 4]; +# return 0; +# } + +# helper.cpp +# struct Foo2a { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo3 { +# char *c1; +# char *c2; +# }; +# +# int foo() { +# Foo2a f; +# Foo3 f2; +# return 0; +# } + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "/dwarf5-types-backward-cross-reference-test" "main.cpp" md5 0x13f000d932d7bb7e6986b96c183027b9 + .loc 1 10 0 # main.cpp:10:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 12 9 prologue_end # main.cpp:12:9 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 1 12 7 is_stmt 0 # main.cpp:12:7 + movq %rax, -40(%rbp) + .loc 1 13 9 is_stmt 1 # main.cpp:13:9 + movq -16(%rbp), %rax + .loc 1 13 14 is_stmt 0 # main.cpp:13:14 + movl -8(%rbp), %ecx + .loc 1 13 19 # main.cpp:13:19 + addl $1, %ecx + .loc 1 13 9 # main.cpp:13:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 13 7 # main.cpp:13:7 + movq %rax, -32(%rbp) + .loc 1 14 9 is_stmt 1 # main.cpp:14:9 + movq -16(%rbp), %rax + .loc 1 14 14 is_stmt 0 # main.cpp:14:14 + movl -8(%rbp), %ecx + .loc 1 14 19 # main.cpp:14:19 + addl $2, %ecx + .loc 1 14 9 # main.cpp:14:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 14 7 # main.cpp:14:7 + movq %rax, -24(%rbp) + .loc 1 16 9 is_stmt 1 # main.cpp:16:9 + movq -16(%rbp), %rax + .loc 1 16 14 is_stmt 0 # main.cpp:16:14 + movl -8(%rbp), %ecx + .loc 1 16 19 # main.cpp:16:19 + addl $3, %ecx + .loc 1 16 9 # main.cpp:16:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 16 7 # main.cpp:16:7 + movq %rax, -40(%rbp) + .loc 1 17 9 is_stmt 1 # main.cpp:17:9 + movq -16(%rbp), %rax + .loc 1 17 14 is_stmt 0 # main.cpp:17:14 + movl -8(%rbp), %ecx + .loc 1 17 19 # main.cpp:17:19 + addl $4, %ecx + .loc 1 17 9 # main.cpp:17:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 17 7 # main.cpp:17:7 + movq %rax, -32(%rbp) + .loc 1 18 2 is_stmt 1 # main.cpp:18:2 + xorl %eax, %eax + .loc 1 18 2 epilogue_begin is_stmt 0 # main.cpp:18:2 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z3foov # -- Begin function _Z3foov + .p2align 4, 0x90 + .type _Z3foov,@function +_Z3foov: # @_Z3foov +.Lfunc_begin1: + .file 2 "/dwarf5-types-backward-cross-reference-test" "helper.cpp" md5 0x650c984f17ca3a4e7785e30e6ca8f130 + .loc 2 11 0 is_stmt 1 # helper.cpp:11:0 + .cfi_startproc +# %bb.0: # %entry + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp2: + .loc 2 14 3 prologue_end # helper.cpp:14:3 + xorl %eax, %eax + .loc 2 14 3 epilogue_begin is_stmt 0 # helper.cpp:14:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end1: + .size _Z3foov, .Lfunc_end1-_Z3foov + .cfi_endproc + # -- End function + .section .debug_info,"G",@progbits,7448148824980338162,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 7448148824980338162 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 15 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member + .byte 14 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type + .long 74 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_info,"G",@progbits,5322170643381124694,comdat + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5322170643381124694 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x2e DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 17 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x5 DW_TAG_pointer_type + .long 65 # DW_AT_type + .byte 5 # Abbrev [5] 0x41:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_info,"G",@progbits,1175092228111723119,comdat + .long .Ldebug_info_end2-.Ldebug_info_start2 # Length of Unit +.Ldebug_info_start2: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 1175092228111723119 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 18 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member + .byte 14 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type + .long 74 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end2: + .section .debug_info,"G",@progbits,12995149649732825572,comdat + .long .Ldebug_info_end3-.Ldebug_info_start3 # Length of Unit +.Ldebug_info_start3: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -5451594423976726044 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x2e DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 19 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 60 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 60 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x5 DW_TAG_pointer_type + .long 65 # DW_AT_type + .byte 5 # Abbrev [5] 0x41:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end3: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code <-- Manually added abbrev decl + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end4-.Ldebug_info_start4 # Length of Unit +.Ldebug_info_start4: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 6 # Abbrev [6] 0xc:0x78 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 7 # Abbrev [7] 0x23:0x3c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 95 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x32:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 95 # DW_AT_type + .byte 8 # Abbrev [8] 0x3d:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .byte 9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 99 # DW_AT_type + .byte 9 # Abbrev [9] 0x48:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 11 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 113 # DW_AT_type + .byte 9 # Abbrev [9] 0x53:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .byte 16 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 15 # DW_AT_decl_line + .long 122 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x5f:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x63:0x5 DW_TAG_pointer_type + .long 104 # DW_AT_type + .byte 4 # Abbrev [4] 0x68:0x5 DW_TAG_pointer_type + .long 109 # DW_AT_type + .byte 5 # Abbrev [5] 0x6d:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .Lmanual_label: + .byte 10 # Abbrev [10] 0x71:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x7a:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end4: +.Lcu_begin1: + .long .Ldebug_info_end5-.Ldebug_info_start5 # Length of Unit +.Ldebug_info_start5: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 6 # Abbrev [6] 0xc:0x55 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 3 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 11 # Abbrev [11] 0x23:0x27 DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 6 # DW_AT_linkage_name + .byte 7 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 74 # DW_AT_type + # DW_AT_external + .byte 9 # Abbrev [9] 0x33:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .byte 11 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 78 # DW_AT_type + .byte 12 # Abbrev [12] 0x3e:0xb DW_TAG_variable <-- Manually modified s/9/12 + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 16 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long .Lmanual_label # DW_AT_type <-- Manually modified + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x4e:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 1175092228111723119 # DW_AT_signature + .byte 10 # Abbrev [10] 0x57:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -5451594423976726044 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end5: + .section .debug_str_offsets,"",@progbits + .long 84 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=105 +.Linfo_string2: + .asciz "/dwarf5-types-backward-reference-test" # string offset=114 +.Linfo_string3: + .asciz "helper.cpp" # string offset=189 +.Linfo_string4: + .asciz "main" # string offset=200 +.Linfo_string5: + .asciz "int" # string offset=205 +.Linfo_string6: + .asciz "_Z3foov" # string offset=209 +.Linfo_string7: + .asciz "foo" # string offset=217 +.Linfo_string8: + .asciz "argc" # string offset=221 +.Linfo_string9: + .asciz "argv" # string offset=226 +.Linfo_string10: + .asciz "char" # string offset=231 +.Linfo_string11: + .asciz "f" # string offset=236 +.Linfo_string12: + .asciz "c1" # string offset=238 +.Linfo_string13: + .asciz "c2" # string offset=241 +.Linfo_string14: + .asciz "c3" # string offset=244 +.Linfo_string15: + .asciz "Foo" # string offset=247 +.Linfo_string16: + .asciz "f2" # string offset=251 +.Linfo_string17: + .asciz "Foo2" # string offset=254 +.Linfo_string18: + .asciz "Foo2a" # string offset=259 +.Linfo_string19: + .asciz "Foo3" # string offset=265 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .long .Linfo_string12 + .long .Linfo_string13 + .long .Linfo_string14 + .long .Linfo_string15 + .long .Linfo_string16 + .long .Linfo_string17 + .long .Linfo_string18 + .long .Linfo_string19 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .ident "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" + .ident "clang version 17.0.0 (https://github.com/llvm/llvm-project.git 73027ae39b1492e5b6033358a13b86d7d1e781ae)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-types-forward-cross-reference.s b/bolt/test/X86/dwarf5-types-forward-cross-reference.s new file mode 100644 --- /dev/null +++ b/bolt/test/X86/dwarf5-types-forward-cross-reference.s @@ -0,0 +1,751 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %s -o %t.o +# RUN: %clang %cflags -gdwarf-5 %t.o -o %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# This test checks that BOLT handles forward cross CU references for dwarf5 +# when -fdebug-types-sections is specified. + +# The assembly was manually modified to do cross CU reference. + +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Type Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: Compile Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: DW_TAG_variable [9] +# POSTCHECK: DW_AT_type [DW_FORM_ref_addr] (0x00000000000001f8 "Foo2a") +# POSTCHECK: Compile Unit +# POSTCHECK-SAME: version = 0x0005 +# POSTCHECK: DW_TAG_structure_type [11] + + +# main.cpp +# struct Foo { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo2 { +# char *c1; +# char *c2; +# }; +# int main(int argc, char *argv[]) { +# Foo f; +# f.c1 = argv[argc]; +# f.c2 = argv[argc + 1]; +# f.c3 = argv[argc + 2]; +# Foo2 f2; +# f.c1 = argv[argc + 3]; +# f.c2 = argv[argc + 4]; +# return 0; +# } + +# helper.cpp +# struct Foo2a { +# char *c1; +# char *c2; +# char *c3; +# }; +# struct Foo3 { +# char *c1; +# char *c2; +# }; +# +# int foo() { +# Foo2a f; +# Foo3 f2; +# return 0; +# } + + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .file 1 "dwarf5-types-dwarf5-types-cross-reference-test" "main.cpp" md5 0x13f000d932d7bb7e6986b96c183027b9 + .loc 1 10 0 # main.cpp:10:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp + movl $0, -4(%rbp) + movl %edi, -8(%rbp) + movq %rsi, -16(%rbp) +.Ltmp0: + .loc 1 12 9 prologue_end # main.cpp:12:9 + movq -16(%rbp), %rax + movslq -8(%rbp), %rcx + movq (%rax,%rcx,8), %rax + .loc 1 12 7 is_stmt 0 # main.cpp:12:7 + movq %rax, -40(%rbp) + .loc 1 13 9 is_stmt 1 # main.cpp:13:9 + movq -16(%rbp), %rax + .loc 1 13 14 is_stmt 0 # main.cpp:13:14 + movl -8(%rbp), %ecx + .loc 1 13 19 # main.cpp:13:19 + addl $1, %ecx + .loc 1 13 9 # main.cpp:13:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 13 7 # main.cpp:13:7 + movq %rax, -32(%rbp) + .loc 1 14 9 is_stmt 1 # main.cpp:14:9 + movq -16(%rbp), %rax + .loc 1 14 14 is_stmt 0 # main.cpp:14:14 + movl -8(%rbp), %ecx + .loc 1 14 19 # main.cpp:14:19 + addl $2, %ecx + .loc 1 14 9 # main.cpp:14:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 14 7 # main.cpp:14:7 + movq %rax, -24(%rbp) + .loc 1 16 9 is_stmt 1 # main.cpp:16:9 + movq -16(%rbp), %rax + .loc 1 16 14 is_stmt 0 # main.cpp:16:14 + movl -8(%rbp), %ecx + .loc 1 16 19 # main.cpp:16:19 + addl $3, %ecx + .loc 1 16 9 # main.cpp:16:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 16 7 # main.cpp:16:7 + movq %rax, -40(%rbp) + .loc 1 17 9 is_stmt 1 # main.cpp:17:9 + movq -16(%rbp), %rax + .loc 1 17 14 is_stmt 0 # main.cpp:17:14 + movl -8(%rbp), %ecx + .loc 1 17 19 # main.cpp:17:19 + addl $4, %ecx + .loc 1 17 9 # main.cpp:17:9 + movslq %ecx, %rcx + movq (%rax,%rcx,8), %rax + .loc 1 17 7 # main.cpp:17:7 + movq %rax, -32(%rbp) + .loc 1 18 2 is_stmt 1 # main.cpp:18:2 + xorl %eax, %eax + .loc 1 18 2 epilogue_begin is_stmt 0 # main.cpp:18:2 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp1: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z3foov # -- Begin function _Z3foov + .p2align 4, 0x90 + .type _Z3foov,@function +_Z3foov: # @_Z3foov +.Lfunc_begin1: + .file 2 "/dwarf5-types-dwarf5-types-cross-reference-test" "helper.cpp" md5 0x650c984f17ca3a4e7785e30e6ca8f130 + .loc 2 11 0 is_stmt 1 # helper.cpp:11:0 + .cfi_startproc +# %bb.0: + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset %rbp, -16 + movq %rsp, %rbp + .cfi_def_cfa_register %rbp +.Ltmp2: + .loc 2 14 3 prologue_end # helper.cpp:14:3 + xorl %eax, %eax + .loc 2 14 3 epilogue_begin is_stmt 0 # helper.cpp:14:3 + popq %rbp + .cfi_def_cfa %rsp, 8 + retq +.Ltmp3: +.Lfunc_end1: + .size _Z3foov, .Lfunc_end1-_Z3foov + .cfi_endproc + # -- End function + .section .debug_info,"G",@progbits,7448148824980338162,comdat + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 7448148824980338162 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 15 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member + .byte 14 # DW_AT_name + .long 69 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type + .long 74 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_info,"G",@progbits,5322170643381124694,comdat + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 5322170643381124694 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x2e DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 17 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 60 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x5 DW_TAG_pointer_type + .long 65 # DW_AT_type + .byte 5 # Abbrev [5] 0x41:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_info,"G",@progbits,1175092228111723119,comdat + .long .Ldebug_info_end2-.Ldebug_info_start2 # Length of Unit +.Ldebug_info_start2: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 1175092228111723119 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x37 DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 18 # DW_AT_name + .byte 24 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x3b:0x9 DW_TAG_member + .byte 14 # DW_AT_name + .long 69 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .byte 16 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x45:0x5 DW_TAG_pointer_type + .long 74 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end2: + .section .debug_info,"G",@progbits,12995149649732825572,comdat + .long .Ldebug_info_end3-.Ldebug_info_start3 # Length of Unit +.Ldebug_info_start3: + .short 5 # DWARF version number + .byte 2 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -5451594423976726044 # Type Signature + .long 35 # Type DIE Offset + .byte 1 # Abbrev [1] 0x18:0x2e DW_TAG_type_unit + .short 33 # DW_AT_language + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 2 # Abbrev [2] 0x23:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 19 # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .byte 3 # Abbrev [3] 0x29:0x9 DW_TAG_member + .byte 12 # DW_AT_name + .long 60 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 3 # Abbrev [3] 0x32:0x9 DW_TAG_member + .byte 13 # DW_AT_name + .long 60 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x3c:0x5 DW_TAG_pointer_type + .long 65 # DW_AT_type + .byte 5 # Abbrev [5] 0x41:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_end3: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 65 # DW_TAG_type_unit + .byte 1 # DW_CHILDREN_yes + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 105 # DW_AT_signature + .byte 32 # DW_FORM_ref_sig8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code <-- Manually added abbrev decl + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end4-.Ldebug_info_start4 # Length of Unit +.Ldebug_info_start4: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 6 # Abbrev [6] 0xc:0x78 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 7 # Abbrev [7] 0x23:0x3c DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 95 # DW_AT_type + # DW_AT_external + .byte 8 # Abbrev [8] 0x32:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 120 + .byte 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 95 # DW_AT_type + .byte 8 # Abbrev [8] 0x3d:0xb DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 145 + .byte 112 + .byte 9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 99 # DW_AT_type + .byte 12 # Abbrev [12] 0x48:0xb DW_TAG_variable <-- Manually modified s/9/12 + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 11 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long .Lmanual_label # DW_AT_type <-- Manually modified + .byte 9 # Abbrev [9] 0x53:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 72 + .byte 16 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 15 # DW_AT_decl_line + .long 122 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x5f:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 4 # Abbrev [4] 0x63:0x5 DW_TAG_pointer_type + .long 104 # DW_AT_type + .byte 4 # Abbrev [4] 0x68:0x5 DW_TAG_pointer_type + .long 109 # DW_AT_type + .byte 5 # Abbrev [5] 0x6d:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 10 # Abbrev [10] 0x71:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 7448148824980338162 # DW_AT_signature + .byte 10 # Abbrev [10] 0x7a:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 5322170643381124694 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end4: +.Lcu_begin1: + .long .Ldebug_info_end5-.Ldebug_info_start5 # Length of Unit +.Ldebug_info_start5: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 6 # Abbrev [6] 0xc:0x55 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 3 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .byte 11 # Abbrev [11] 0x23:0x27 DW_TAG_subprogram + .byte 1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 86 + .byte 6 # DW_AT_linkage_name + .byte 7 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .long 74 # DW_AT_type + # DW_AT_external + .byte 9 # Abbrev [9] 0x33:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 104 + .byte 11 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .long 78 # DW_AT_type + .byte 9 # Abbrev [9] 0x3e:0xb DW_TAG_variable + .byte 2 # DW_AT_location + .byte 145 + .byte 88 + .byte 16 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 13 # DW_AT_decl_line + .long 87 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x4a:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size +.Lmanual_label: + .byte 10 # Abbrev [10] 0x4e:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad 1175092228111723119 # DW_AT_signature + .byte 10 # Abbrev [10] 0x57:0x9 DW_TAG_structure_type + # DW_AT_declaration + .quad -5451594423976726044 # DW_AT_signature + .byte 0 # End Of Children Mark +.Ldebug_info_end5: + .section .debug_str_offsets,"",@progbits + .long 84 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 15.0.0" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=146 +.Linfo_string2: + .asciz "/dwarf5-types-dwarf5-types-cross-reference-test" # string offset=155 +.Linfo_string3: + .asciz "helper.cpp" # string offset=240 +.Linfo_string4: + .asciz "main" # string offset=251 +.Linfo_string5: + .asciz "int" # string offset=256 +.Linfo_string6: + .asciz "_Z3foov" # string offset=260 +.Linfo_string7: + .asciz "foo" # string offset=268 +.Linfo_string8: + .asciz "argc" # string offset=272 +.Linfo_string9: + .asciz "argv" # string offset=277 +.Linfo_string10: + .asciz "char" # string offset=282 +.Linfo_string11: + .asciz "f" # string offset=287 +.Linfo_string12: + .asciz "c1" # string offset=289 +.Linfo_string13: + .asciz "c2" # string offset=292 +.Linfo_string14: + .asciz "c3" # string offset=295 +.Linfo_string15: + .asciz "Foo" # string offset=298 +.Linfo_string16: + .asciz "f2" # string offset=302 +.Linfo_string17: + .asciz "Foo2" # string offset=305 +.Linfo_string18: + .asciz "Foo2a" # string offset=310 +.Linfo_string19: + .asciz "Foo3" # string offset=316 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .long .Linfo_string12 + .long .Linfo_string13 + .long .Linfo_string14 + .long .Linfo_string15 + .long .Linfo_string16 + .long .Linfo_string17 + .long .Linfo_string18 + .long .Linfo_string19 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 +.Ldebug_addr_end0: + .ident "clang version 15.0.0" + .ident "clang version 15.0.0" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: