diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 7ddcc0d81d5..3c32a3e5b79 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -84,6 +84,9 @@ public: const DWARFUnit *u) const; static bool skipValue(uint16_t form, DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFUnit *u); + static bool skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, uint16_t Version, + uint8_t AddrSize); static ArrayRef getFixedFormSizes(uint8_t AddrSize, uint16_t Version); diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index a11b00a926d..3dc58423df6 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -261,6 +261,12 @@ DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFUnit *cu) { + return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(), + cu->getAddressByteSize()); +} +bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, + uint32_t *offset_ptr, uint16_t Version, + uint8_t AddrSize) { bool indirect = false; do { switch (form) { @@ -295,10 +301,10 @@ DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, // Compile unit address sized values case DW_FORM_addr: - *offset_ptr += cu->getAddressByteSize(); + *offset_ptr += AddrSize; return true; case DW_FORM_ref_addr: - *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); + *offset_ptr += getRefAddrSize(AddrSize, Version); return true; // 0 byte values - implied from the form. diff --git a/test/tools/llvm-dwp/X86/simple.test b/test/tools/llvm-dwp/X86/simple.test index 6ee19697442..1c7b1040bd3 100644 --- a/test/tools/llvm-dwp/X86/simple.test +++ b/test/tools/llvm-dwp/X86/simple.test @@ -28,6 +28,7 @@ CHECK: .debug_info.dwo contents: CHECK: 0x00000000: Compile Unit: length = 0x00000025 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000029) CHECK: DW_TAG_compile_unit CHECK: DW_AT_name {{.*}} "a.cpp" +CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOA:.*]]) CHECK: DW_TAG_variable CHECK: DW_AT_name {{.*}} "a" CHECK: DW_TAG_structure_type @@ -35,6 +36,7 @@ CHECK: DW_AT_name {{.*}} "foo" CHECK: 0x00000029: Compile Unit: length = 0x00000031 version = 0x0004 abbr_offset = 0x0031 addr_size = 0x08 (next unit at 0x0000005e) CHECK: DW_AT_name {{.*}} "b.cpp" +CHECK: DW_AT_GNU_dwo_id {{.*}} ([[DWOB:.*]]) CHECK: DW_TAG_structure_type CHECK: DW_AT_name {{.*}} "bar" CHECK: DW_TAG_subprogram @@ -45,8 +47,8 @@ CHECK: .debug_cu_index contents: Ensure only the relevant/contained sections are included in the table: CHECK: Index Signature INFO ABBREV STR_OFFSETS Don't bother checking the Signatures, they aren't correct yet. -CHECK: [0x00000000, 0x00000029) [0x00000000, 0x00000031) [0x00000000, 0x00000010) -CHECK: [0x00000029, 0x0000005e) [0x00000031, 0x00000075) [0x00000010, 0x00000024) +CHECK: 1 [[DWOA]] [0x00000000, 0x00000029) [0x00000000, 0x00000031) [0x00000000, 0x00000010) +CHECK: 2 [[DWOB]] [0x00000029, 0x0000005e) [0x00000031, 0x00000075) [0x00000010, 0x00000024) CHECK: .debug_str.dwo contents: CHECK: "clang version diff --git a/tools/llvm-dwp/llvm-dwp.cpp b/tools/llvm-dwp/llvm-dwp.cpp index e6a90cf8a3c..b68ba437f83 100644 --- a/tools/llvm-dwp/llvm-dwp.cpp +++ b/tools/llvm-dwp/llvm-dwp.cpp @@ -1,5 +1,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSet.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -82,6 +83,52 @@ writeStringsAndOffsets(MCStreamer &Out, StringMap &Strings, return std::error_code(); } +static uint32_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) { + uint64_t CurCode; + uint32_t Offset = 0; + DataExtractor AbbrevData(Abbrev, true, 0); + while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) { + // Tag + AbbrevData.getULEB128(&Offset); + // DW_CHILDREN + AbbrevData.getU8(&Offset); + // Attributes + while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset)) + ; + } + return Offset; +} + +static uint64_t getCUSignature(StringRef Abbrev, StringRef Info) { + uint32_t Offset = 0; + DataExtractor InfoData(Info, true, 0); + InfoData.getU32(&Offset); // Length + uint16_t Version = InfoData.getU16(&Offset); + InfoData.getU32(&Offset); // Abbrev offset (should be zero) + uint8_t AddrSize = InfoData.getU8(&Offset); + + uint32_t AbbrCode = InfoData.getULEB128(&Offset); + + DataExtractor AbbrevData(Abbrev, true, 0); + uint32_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode); + uint64_t Tag = AbbrevData.getULEB128(&AbbrevOffset); + (void)Tag; + // FIXME: Real error handling + assert(Tag == dwarf::DW_TAG_compile_unit); + // DW_CHILDREN + AbbrevData.getU8(&AbbrevOffset); + uint32_t Name; + uint32_t Form; + while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) | + (Form = AbbrevData.getULEB128(&AbbrevOffset)) && + Name != dwarf::DW_AT_GNU_dwo_id) { + DWARFFormValue::skipValue(Form, InfoData, &Offset, Version, AddrSize); + } + // FIXME: Real error handling + assert(Name == dwarf::DW_AT_GNU_dwo_id); + return InfoData.getU64(&Offset); +} + static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { const auto &MCOFI = *Out.getContext().getObjectFileInfo(); MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); @@ -104,7 +151,6 @@ static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { StringMap Strings; uint32_t StringOffset = 0; - uint64_t UnitIndex = 0; uint32_t ContributionOffsets[8] = {}; for (const auto &Input : Inputs) { @@ -114,10 +160,11 @@ static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { IndexEntries.emplace_back(); UnitIndexEntry &CurEntry = IndexEntries.back(); - CurEntry.Signature = UnitIndex++; StringRef CurStrSection; StringRef CurStrOffsetSection; + StringRef InfoSection; + StringRef AbbrevSection; for (const auto &Section : ErrOrObj->getBinary()->sections()) { StringRef Name; @@ -138,6 +185,14 @@ static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; ContributionOffsets[Index] += (CurEntry.Contributions[Index].Length = Contents.size()); + + if (Kind == DW_SECT_INFO) { + assert(InfoSection.empty()); + InfoSection = Contents; + } else if (Kind == DW_SECT_ABBREV) { + assert(AbbrevSection.empty()); + AbbrevSection = Contents; + } } MCSection *OutSection = SectionPair->second.first; @@ -151,6 +206,10 @@ static std::error_code write(MCStreamer &Out, ArrayRef Inputs) { } } + assert(!AbbrevSection.empty()); + assert(!InfoSection.empty()); + CurEntry.Signature = getCUSignature(AbbrevSection, InfoSection); + if (auto Err = writeStringsAndOffsets(Out, Strings, StringOffset, StrSection, StrOffsetSection, CurStrSection, CurStrOffsetSection))