#include <mutex>
#include <set>
#include <unordered_map>
+#include <unordered_set>
#include <vector>
namespace llvm {
class BinaryContext;
class DWARFRewriter {
+public:
DWARFRewriter() = delete;
+ using DebugTypesSignaturesPerCUMap =
+ std::unordered_map<uint64_t, std::unordered_set<uint64_t>>;
+private:
BinaryContext &BC;
std::mutex DebugInfoPatcherMutex;
/// Binary patchers for DWO debug_info sections.
DebugInfoDWOPatchers BinaryDWODebugInfoPatchers;
+ /// Stores all the Type Signatures for DWO CU.
+ DebugTypesSignaturesPerCUMap TypeSignaturesPerCU;
+
std::mutex LocListDebugInfoPatchesMutex;
/// DWARFLegacy is all DWARF versions before DWARF 5.
#include <cstdint>
#include <string>
#include <unordered_map>
+#include <utility>
+#include <vector>
#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"
DWARFDataExtractor DebugInfoData = Unit.getDebugInfoExtractor();
uint32_t Depth = 0;
+ bool IsDWP = false;
+ if (DWARFContext *DWOCtx = BC.getDWOContext())
+ IsDWP = !DWOCtx->getCUIndex().getRows().empty();
+
while (
DIEOffset < NextCUOffset &&
Die.extractFast(Unit, &DIEOffset, DebugInfoData, NextCUOffset, Depth)) {
errs() << "BOLT-WARNING: unexpected form value for attribute at 0x"
<< Twine::utohexstr(AttrOffset);
}
+ } else if (IsDWP && Unit.isDWOUnit()) {
+ // Not a common path so don't want to search all DIEs all the time.
+ Optional<AttrInfo> SignatureAttrVal =
+ findAttributeInfo(DIE, dwarf::DW_AT_signature);
+ if (!SignatureAttrVal)
+ 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 (Optional<uint64_t> Val = SignatureAttrVal->V.getAsReferenceUVal())
+ TypeSignaturesPerCU[*DIE.getDwarfUnit()->getDWOId()].insert(*Val);
+ else {
+ errs() << "BOT-ERROR: DW_AT_signature form is not supported.\n";
+ exit(1);
+ }
}
}
}
StringRef SectionName, StringRef SectionContents,
const StringMap<KnownSectionsEntry> &KnownSections,
MCStreamer &Streamer, DWARFRewriter &Writer,
- const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
+ const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
std::unique_ptr<DebugBufferVector> &OutputBuffer,
DebugRangeListsSectionWriter *RangeListsWriter) {
auto applyPatch = [&](DebugInfoBinaryPatcher *Patcher,
auto SectionIter = KnownSections.find(SectionName);
if (SectionIter == KnownSections.end())
return None;
+
Streamer.SwitchSection(SectionIter->second.first);
StringRef OutData = SectionContents;
uint32_t DWPOffset = 0;
return OutData;
}
case DWARFSectionKind::DW_SECT_INFO: {
- OutData = getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO,
+ OutData = getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_INFO,
DWPOffset);
DebugInfoBinaryPatcher *Patcher = llvm::cast<DebugInfoBinaryPatcher>(
Writer.getBinaryDWODebugInfoPatcher(DWOId));
return applyPatch(Patcher, OutData);
}
case DWARFSectionKind::DW_SECT_EXT_TYPES: {
- return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES,
+ return getSliceData(nullptr, OutData, DWARFSectionKind::DW_SECT_EXT_TYPES,
DWPOffset);
}
case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
- return getSliceData(DWOEntry, OutData,
+ return getSliceData(CUDWOEntry, OutData,
DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
}
case DWARFSectionKind::DW_SECT_ABBREV: {
OutputBuffer->size());
}
case DWARFSectionKind::DW_SECT_LINE: {
- return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE,
+ return getSliceData(CUDWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE,
DWPOffset);
}
case DWARFSectionKind::DW_SECT_RNGLISTS: {
} // namespace
+struct TUContribution {
+ uint64_t Signature{0};
+ uint32_t Length{0};
+};
+using TUContributionVector = std::vector<TUContribution>;
+/// 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<uint64_t, const DWARFUnitIndex::Entry::SectionContribution *>;
+ std::vector<TUEntry> 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.
+ std::sort(TUContributions.begin(), TUContributions.end(),
+ [](const TUEntry &V1, const TUEntry &V2) -> bool {
+ return V1.second->Offset < V2.second->Offset;
+ });
+
+ for (auto &PairEntry : TUContributions) {
+ const DWARFUnitIndex::Entry::SectionContribution *C = PairEntry.second;
+ const uint64_t TUSignature = PairEntry.first;
+ DWOTUSection.append(Contents.slice(C->Offset, C->Offset + C->Length).str());
+ TUContributionsToCU.push_back({TUSignature, C->Length});
+ }
+ return DWOTUSection;
+}
+
+static void extractDWOTUFromDWO(StringRef Contents,
+ TUContributionVector &TUContributionsToCU) {
+ uint64_t Offset = 0;
+ DataExtractor Data(Contents, true, 0);
+ while (Data.isValidOffset(Offset)) {
+ auto 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 auto 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<const DWARFUnitIndex::Entry::SectionContribution *>
+ TUContributions;
+ 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.
+ std::sort(TUContributions.begin(), TUContributions.end(),
+ [](const DWARFUnitIndex::Entry::SectionContribution *V1,
+ const DWARFUnitIndex::Entry::SectionContribution *V2) -> bool {
+ return V1->Offset < V2->Offset;
+ });
+ Streamer.SwitchSection(MCOFI.getDwarfInfoDWOSection());
+ for (const auto *C : TUContributions)
+ Streamer.emitBytes(Contents.slice(C->Offset, C->Offset + C->Length));
+}
+
void DWARFRewriter::writeDWP(
std::unordered_map<uint64_t, std::string> &DWOIdToName) {
SmallString<0> OutputNameStr;
std::deque<SmallString<32>> UncompressedSections;
DWPStringPool Strings(*Streamer, StrSection);
MapVector<uint64_t, UnitIndexEntry> IndexEntries;
- constexpr uint32_t IndexVersion = 2;
+ MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
+ uint16_t Version = 0;
+ uint32_t IndexVersion = 2;
// 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();
}
if (!DWOCU)
continue;
- assert(CU->getVersion() <= 4 && "For DWP output only DWARF4 is supported");
+ if (Version == 0) {
+ Version = CU->getVersion();
+ IndexVersion = Version < 5 ? 2 : 5;
+ } else if (Version != CU->getVersion()) {
+ errs() << "BOLT-ERROR: Incompatible DWARF compile unit versions.\n";
+ exit(1);
+ }
+
UnitIndexEntry CurEntry = {};
CurEntry.DWOName =
dwarf::toString(CU->getUnitDIE().find(
// i.e. offset and length, of each compile/type unit to a section.
std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
- const DWARFUnitIndex::Entry *DWOEntry = nullptr;
+ const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
if (IsDWP)
- DWOEntry = CUIndex->getFromHash(*DWOId);
+ CUDWOEntry = CUIndex->getFromHash(*DWOId);
bool StrSectionWrittenOut = false;
const object::ObjectFile *DWOFile =
"No RangeListsWriter for DWO ID.");
RangeListssWriter = RangeListsWritersByCU[*DWOId].get();
}
+ std::string DWOTUSection;
+ TUContributionVector TUContributionsToCU;
for (const SectionRef &Section : DWOFile->sections()) {
+ std::string DWOTUSection;
std::string Storage = "";
std::unique_ptr<DebugBufferVector> OutputData;
StringRef SectionName = getSectionName(Section);
- Expected<StringRef> Contents = Section.getContents();
- assert(Contents && "Invalid contents.");
- Optional<StringRef> TOutData =
- updateDebugData((*DWOCU)->getContext(), Storage, SectionName,
- *Contents, KnownSections, *Streamer, *this, DWOEntry,
- *DWOId, OutputData, RangeListssWriter);
+ Expected<StringRef> 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);
+ }
+
+ Optional<StringRef> TOutData = updateDebugData(
+ (*DWOCU)->getContext(), Storage, SectionName, Contents, KnownSections,
+ *Streamer, *this, CUDWOEntry, *DWOId, OutputData, RangeListssWriter);
if (!TOutData)
continue;
StringRef OutData = *TOutData;
- StringRef Name = getSectionName(Section);
- if (Name.equals("debug_str.dwo")) {
+ if (IsTypesDWO) {
+ Streamer->emitBytes(OutData);
+ continue;
+ }
+
+ if (SectionName.equals("debug_str.dwo")) {
CurStrSection = OutData;
} else {
// Since handleDebugDataPatching returned true, we already know this is
// a known section.
- auto SectionIter = KnownSections.find(Name);
+ auto SectionIter = KnownSections.find(SectionName);
if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
CurStrOffsetSection = OutData;
else
errs() << "BOLT-ERROR: " << toString(std::move(Err)) << "\n";
return;
}
+
+ // 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].Offset = ContributionOffsets[Index];
+ TUEntry.Contributions[Index].Length = TUC.Length;
+ ContributionOffsets[Index] += TUEntry.Contributions[Index].Length;
+ TypeIndexEntries.insert(std::make_pair(TUC.Signature, TUEntry));
+ }
+ }
}
- // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
- // section does not exist, so no need to do anything about this.
- ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
+ if (Version < 5) {
+ // Lie about there being no info contributions so the TU index only includes
+ // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
+ // contribution to the info section, so we do not want to lie about it.
+ ContributionOffsets[0] = 0;
+ }
+ writeIndex(*Streamer.get(), MCOFI.getDwarfTUIndexSection(),
+ ContributionOffsets, TypeIndexEntries, IndexVersion);
+
+ if (Version < 5) {
+ // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
+ // section does not exist, so no need to do anything about this.
+ ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
+ // Unlie about the info contribution
+ ContributionOffsets[0] = 1;
+ }
writeIndex(*Streamer.get(), MCOFI.getDwarfCUIndexSection(),
ContributionOffsets, IndexEntries, IndexVersion);
// 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();
}
std::unique_ptr<ToolOutputFile> TempOut =
std::make_unique<ToolOutputFile>(FullPath, EC, sys::fs::OF_None);
- const DWARFUnitIndex::Entry *DWOEntry = nullptr;
+ const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
if (IsDWP)
- DWOEntry = CUIndex->getFromHash(*DWOId);
+ CUDWOEntry = CUIndex->getFromHash(*DWOId);
const object::ObjectFile *File =
(*DWOCU)->getContext().getDWARFObj().getFile();
std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
- StringMap<KnownSectionsEntry> KnownSections =
- createKnownSectionsMap(*Streamer->getContext().getObjectFileInfo());
+ const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
+ StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);
DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
if (CU->getVersion() == 5) {
std::unique_ptr<DebugBufferVector> OutputData;
if (Optional<StringRef> OutData = updateDebugData(
(*DWOCU)->getContext(), Storage, "debug_rnglists.dwo", "",
- KnownSections, *Streamer, *this, DWOEntry, *DWOId, OutputData,
+ 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<DebugBufferVector> OutputData;
StringRef SectionName = getSectionName(Section);
if (SectionName == "debug_rnglists.dwo")
continue;
- Expected<StringRef> Contents = Section.getContents();
- assert(Contents && "Invalid contents.");
- if (Optional<StringRef> OutData =
- updateDebugData((*DWOCU)->getContext(), Storage, SectionName,
- *Contents, KnownSections, *Streamer, *this,
- DWOEntry, *DWOId, OutputData, RangeListssWriter))
+ Expected<StringRef> 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 (Optional<StringRef> OutData = updateDebugData(
+ (*DWOCU)->getContext(), Storage, SectionName, Contents,
+ KnownSections, *Streamer, *this, CUDWOEntry, *DWOId, OutputData,
+ RangeListssWriter))
Streamer->emitBytes(*OutData);
}
Streamer->Finish();
llvm-boltdiff
llvm-bolt-heatmap
llvm-dwarfdump
+ llvm-dwp
llvm-mc
llvm-nm
llvm-objdump
--- /dev/null
+# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-4 -fdebug-types-section
+# 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;
+# }
+
+ .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 12 0 # main.cpp:12: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 14 10 prologue_end # main.cpp:14:10
+ movq -16(%rbp), %rax
+ movslq -8(%rbp), %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 1 14 8 is_stmt 0 # main.cpp:14:8
+ movq %rax, -40(%rbp)
+ .loc 1 15 10 is_stmt 1 # main.cpp:15:10
+ movq -16(%rbp), %rax
+ .loc 1 15 15 is_stmt 0 # main.cpp:15:15
+ movl -8(%rbp), %ecx
+ .loc 1 15 20 # main.cpp:15:20
+ addl $1, %ecx
+ .loc 1 15 10 # main.cpp:15:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 1 15 8 # main.cpp:15:8
+ movq %rax, -32(%rbp)
+ .loc 1 16 10 is_stmt 1 # main.cpp:16:10
+ movq -16(%rbp), %rax
+ .loc 1 16 15 is_stmt 0 # main.cpp:16:15
+ movl -8(%rbp), %ecx
+ .loc 1 16 20 # main.cpp:16:20
+ addl $2, %ecx
+ .loc 1 16 10 # main.cpp:16:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 1 16 8 # main.cpp:16:8
+ movq %rax, -24(%rbp)
+ .loc 1 18 10 is_stmt 1 # main.cpp:18:10
+ movq -16(%rbp), %rax
+ .loc 1 18 15 is_stmt 0 # main.cpp:18:15
+ movl -8(%rbp), %ecx
+ .loc 1 18 20 # main.cpp:18:20
+ addl $3, %ecx
+ .loc 1 18 10 # main.cpp:18:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 1 18 8 # main.cpp:18:8
+ movq %rax, -40(%rbp)
+ .loc 1 19 10 is_stmt 1 # main.cpp:19:10
+ movq -16(%rbp), %rax
+ .loc 1 19 15 is_stmt 0 # main.cpp:19:15
+ movl -8(%rbp), %ecx
+ .loc 1 19 20 # main.cpp:19:20
+ addl $4, %ecx
+ .loc 1 19 10 # main.cpp:19:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 1 19 8 # main.cpp:19:8
+ movq %rax, -32(%rbp)
+ .loc 1 20 3 is_stmt 1 # main.cpp:20:3
+ xorl %eax, %eax
+ 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 7 # 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 8 # 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 9 # 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=38
+ .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=68
+.Linfo_string14:
+ .asciz "main.dwo" # string offset=77
+ .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 68
+ .long 77
+ .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 12 # 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 12 # 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 12 # 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 13 # 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 17 # 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 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 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 0 # End Mark
+.LpubTypes_end0:
+ .ident "clang version 15.0.0"
+ .section ".note.GNU-stack","",@progbits
+ .addrsig
+ .section .debug_line,"",@progbits
+.Lline_table_start0:
--- /dev/null
+# clang++ main.cpp -g2 -gsplit-dwarf=split -gdwarf-5 -fdebug-types-section -S
+# 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;
+# }
+
+ .text
+ .file "main.cpp"
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main,@function
+main: # @main
+.Lfunc_begin0:
+ .file 0 "." "main.cpp" md5 0xa832f464c853be0f9c52da29cd913807
+ .loc 0 12 0 # main.cpp:12: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 0 14 10 prologue_end # main.cpp:14:10
+ movq -16(%rbp), %rax
+ movslq -8(%rbp), %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 0 14 8 is_stmt 0 # main.cpp:14:8
+ movq %rax, -40(%rbp)
+ .loc 0 15 10 is_stmt 1 # main.cpp:15:10
+ movq -16(%rbp), %rax
+ .loc 0 15 15 is_stmt 0 # main.cpp:15:15
+ movl -8(%rbp), %ecx
+ .loc 0 15 20 # main.cpp:15:20
+ addl $1, %ecx
+ .loc 0 15 10 # main.cpp:15:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 0 15 8 # main.cpp:15:8
+ movq %rax, -32(%rbp)
+ .loc 0 16 10 is_stmt 1 # main.cpp:16:10
+ movq -16(%rbp), %rax
+ .loc 0 16 15 is_stmt 0 # main.cpp:16:15
+ movl -8(%rbp), %ecx
+ .loc 0 16 20 # main.cpp:16:20
+ addl $2, %ecx
+ .loc 0 16 10 # main.cpp:16:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 0 16 8 # main.cpp:16:8
+ movq %rax, -24(%rbp)
+ .loc 0 18 10 is_stmt 1 # main.cpp:18:10
+ movq -16(%rbp), %rax
+ .loc 0 18 15 is_stmt 0 # main.cpp:18:15
+ movl -8(%rbp), %ecx
+ .loc 0 18 20 # main.cpp:18:20
+ addl $3, %ecx
+ .loc 0 18 10 # main.cpp:18:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 0 18 8 # main.cpp:18:8
+ movq %rax, -40(%rbp)
+ .loc 0 19 10 is_stmt 1 # main.cpp:19:10
+ movq -16(%rbp), %rax
+ .loc 0 19 15 is_stmt 0 # main.cpp:19:15
+ movl -8(%rbp), %ecx
+ .loc 0 19 20 # main.cpp:19:20
+ addl $4, %ecx
+ .loc 0 19 10 # main.cpp:19:10
+ movslq %ecx, %rcx
+ movq (%rax,%rcx,8), %rax
+ .loc 0 19 8 # main.cpp:19:8
+ movq %rax, -32(%rbp)
+ .loc 0 20 3 is_stmt 1 # main.cpp:20:3
+ xorl %eax, %eax
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.Ltmp1:
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ # -- End function
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit
+.Ldebug_info_dwo_start0:
+ .short 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 7448148824980338162 # Type Signature
+ .long 31 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x33 DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x1f:0x22 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 9 # DW_AT_name
+ .byte 24 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x25:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 65 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 2 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x2e:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 65 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 3 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x37:0x9 DW_TAG_member
+ .byte 8 # DW_AT_name
+ .long 65 # DW_AT_type
+ .byte 0 # 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] 0x41:0x5 DW_TAG_pointer_type
+ .long 70 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x46: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 5 # DWARF version number
+ .byte 6 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 5322170643381124694 # Type Signature
+ .long 31 # Type DIE Offset
+ .byte 1 # Abbrev [1] 0x18:0x2a DW_TAG_type_unit
+ .short 33 # DW_AT_language
+ .long 0 # DW_AT_stmt_list
+ .byte 2 # Abbrev [2] 0x1f:0x19 DW_TAG_structure_type
+ .byte 5 # DW_AT_calling_convention
+ .byte 11 # DW_AT_name
+ .byte 16 # DW_AT_byte_size
+ .byte 0 # DW_AT_decl_file
+ .byte 7 # DW_AT_decl_line
+ .byte 3 # Abbrev [3] 0x25:0x9 DW_TAG_member
+ .byte 6 # DW_AT_name
+ .long 56 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 8 # DW_AT_decl_line
+ .byte 0 # DW_AT_data_member_location
+ .byte 3 # Abbrev [3] 0x2e:0x9 DW_TAG_member
+ .byte 7 # DW_AT_name
+ .long 56 # DW_AT_type
+ .byte 0 # DW_AT_decl_file
+ .byte 9 # DW_AT_decl_line
+ .byte 8 # DW_AT_data_member_location
+ .byte 0 # End Of Children Mark
+ .byte 4 # Abbrev [4] 0x38:0x5 DW_TAG_pointer_type
+ .long 61 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x3d: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 74 # DW_TAG_skeleton_unit
+ .byte 0 # DW_CHILDREN_no
+ .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 27 # DW_AT_comp_dir
+ .byte 37 # DW_FORM_strx1
+ .ascii "\264B" # DW_AT_GNU_pubnames
+ .byte 25 # DW_FORM_flag_present
+ .byte 118 # DW_AT_dwo_name
+ .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 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 4 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .quad 4780348136649610820
+ .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit
+ .long .Lline_table_start0 # DW_AT_stmt_list
+ .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
+ .byte 0 # DW_AT_comp_dir
+ # DW_AT_GNU_pubnames
+ .byte 1 # DW_AT_dwo_name
+ .byte 0 # DW_AT_low_pc
+ .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+ .long .Laddr_table_base0 # DW_AT_addr_base
+.Ldebug_info_end0:
+ .section .debug_str_offsets,"",@progbits
+ .long 12 # Length of String Offsets Set
+ .short 5
+ .short 0
+.Lstr_offsets_base0:
+ .section .debug_str,"MS",@progbits,1
+.Lskel_string0:
+ .asciz "." # string offset=0
+.Lskel_string1:
+ .asciz "main.dwo" # string offset=38
+ .section .debug_str_offsets,"",@progbits
+ .long .Lskel_string0
+ .long .Lskel_string1
+ .section .debug_str_offsets.dwo,"e",@progbits
+ .long 64 # Length of String Offsets Set
+ .short 5
+ .short 0
+ .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=68
+.Linfo_string14:
+ .asciz "main.dwo" # string offset=77
+ .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 68
+ .long 77
+ .section .debug_info.dwo,"e",@progbits
+ .long .Ldebug_info_dwo_end2-.Ldebug_info_dwo_start2 # Length of Unit
+.Ldebug_info_dwo_start2:
+ .short 5 # DWARF version number
+ .byte 5 # DWARF Unit Type
+ .byte 8 # Address Size (in bytes)
+ .long 0 # Offset Into Abbrev. Section
+ .quad 4780348136649610820
+ .byte 6 # Abbrev [6] 0x14:0x67 DW_TAG_compile_unit
+ .byte 12 # DW_AT_producer
+ .short 33 # DW_AT_language
+ .byte 13 # DW_AT_name
+ .byte 14 # DW_AT_dwo_name
+ .byte 7 # Abbrev [7] 0x1a: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 0 # DW_AT_decl_file
+ .byte 12 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ # DW_AT_external
+ .byte 8 # Abbrev [8] 0x29:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 120
+ .byte 2 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 12 # DW_AT_decl_line
+ .long 86 # DW_AT_type
+ .byte 8 # Abbrev [8] 0x34:0xb DW_TAG_formal_parameter
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 112
+ .byte 3 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 12 # DW_AT_decl_line
+ .long 90 # DW_AT_type
+ .byte 9 # Abbrev [9] 0x3f:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 88
+ .byte 5 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 13 # DW_AT_decl_line
+ .long 104 # DW_AT_type
+ .byte 9 # Abbrev [9] 0x4a:0xb DW_TAG_variable
+ .byte 2 # DW_AT_location
+ .byte 145
+ .byte 72
+ .byte 10 # DW_AT_name
+ .byte 0 # DW_AT_decl_file
+ .byte 17 # DW_AT_decl_line
+ .long 113 # DW_AT_type
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x56: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] 0x5a:0x5 DW_TAG_pointer_type
+ .long 95 # DW_AT_type
+ .byte 4 # Abbrev [4] 0x5f:0x5 DW_TAG_pointer_type
+ .long 100 # DW_AT_type
+ .byte 5 # Abbrev [5] 0x64: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] 0x68:0x9 DW_TAG_structure_type
+ # DW_AT_declaration
+ .quad 7448148824980338162 # DW_AT_signature
+ .byte 10 # Abbrev [10] 0x71: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
+ .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 118 # DW_AT_dwo_name
+ .byte 37 # DW_FORM_strx1
+ .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 0 # EOM(3)
+ .section .debug_line.dwo,"e",@progbits
+.Ltmp2:
+ .long .Ldebug_line_end0-.Ldebug_line_start0 # unit length
+.Ldebug_line_start0:
+ .short 5
+ .byte 8
+ .byte 0
+ .long .Lprologue_end0-.Lprologue_start0
+.Lprologue_start0:
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte -5
+ .byte 14
+ .byte 1
+ .byte 1
+ .byte 1
+ .byte 8
+ .byte 1
+ .ascii "/home/ayermolo/local/tasks/T104766233"
+ .byte 0
+ .byte 3
+ .byte 1
+ .byte 8
+ .byte 2
+ .byte 15
+ .byte 5
+ .byte 30
+ .byte 1
+ .ascii "main.cpp"
+ .byte 0
+ .byte 0
+ .byte 0xa8, 0x32, 0xf4, 0x64
+ .byte 0xc8, 0x53, 0xbe, 0x0f
+ .byte 0x9c, 0x52, 0xda, 0x29
+ .byte 0xcd, 0x91, 0x38, 0x07
+.Lprologue_end0:
+.Ldebug_line_end0:
+ .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
+.Ldebug_addr_end0:
+ .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 40 # Compilation Unit Length
+ .long 26 # 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 40 # Compilation Unit Length
+ .long 104 # DIE offset
+ .byte 16 # Attributes: TYPE, EXTERNAL
+ .asciz "Foo" # External Name
+ .long 113 # DIE offset
+ .byte 16 # Attributes: TYPE, EXTERNAL
+ .asciz "Foo2" # External Name
+ .long 86 # DIE offset
+ .byte 144 # Attributes: TYPE, STATIC
+ .asciz "int" # External Name
+ .long 100 # DIE offset
+ .byte 144 # Attributes: TYPE, STATIC
+ .asciz "char" # 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:
--- /dev/null
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections -write-dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types 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
+
+; Test input into bolt a .dwo file with TU Index.
+; Make sure the output .dwp file has a type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+
+; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; BOLT-DWP-TU-INDEX: Index Signature
+; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
--- /dev/null
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.dwo.dwo | FileCheck -check-prefix=BOLT %s
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure output in the .dwo files has type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
--- /dev/null
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf4-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-4 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections -write-dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-types 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
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure the output .dwp file has a type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+
+; BOLT-DWP-TU-INDEX: version = 2, units = 2, slots = 4
+; BOLT-DWP-TU-INDEX: Index Signature
+; BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
--- /dev/null
+# REQUIRES: system-linux
+; RUN: rm -rf %t
+; RUN: mkdir %t
+; RUN: cd %t
+; RUN: llvm-mc --split-dwarf-file=main.dwo --triple=x86_64-unknown-linux-gnu \
+; RUN: --filetype=obj %p/Inputs/dwarf5-ftypes-split-dwarf.s -o=main.o
+; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe
+; RUN: llvm-dwp -e main.exe -o main.exe.dwp
+; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.exe.dwp | FileCheck -check-prefix=PRE-BOLT %s
+; RUN: llvm-dwarfdump --show-form --verbose --debug-tu-index main.exe.dwp | FileCheck -check-prefix=PRE-BOLT-DWP-TU-INDEX %s
+; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections
+; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo | FileCheck -check-prefix=BOLT %s
+
+; Test input into bolt a DWP file with TU Index.
+; Make sure output in the .dwo files has type information.
+
+; PRE-BOLT: DW_TAG_type_unit
+; PRE-BOLT: DW_TAG_type_unit
+
+; PRE-BOLT-DWP-TU-INDEX: version = 5, units = 2, slots = 4
+; PRE-BOLT-DWP-TU-INDEX: Index Signature
+; PRE-BOLT-DWP-TU-INDEX: 0x675d23e4f33235f2
+; PRE-BOLT-DWP-TU-INDEX-NEXT: 0x49dc260088be7e56
+
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_type_unit
+; BOLT: DW_TAG_compile_unit
ToolSubst('link_fdata', command=sys.executable, unresolved='fatal', extra_args=[link_fdata_cmd]),
ToolSubst('merge-fdata', unresolved='fatal'),
ToolSubst('llvm-readobj', unresolved='fatal'),
+ ToolSubst('llvm-dwp', unresolved='fatal'),
]
llvm_config.add_tool_substitutions(tools, tool_dirs)