diff options
-rw-r--r-- | llvm/test/tools/llvm-dwp/Inputs/compress/a.dwo | bin | 0 -> 1297 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-dwp/X86/compress.test | 17 | ||||
-rw-r--r-- | llvm/tools/llvm-dwp/llvm-dwp.cpp | 50 |
3 files changed, 62 insertions, 5 deletions
diff --git a/llvm/test/tools/llvm-dwp/Inputs/compress/a.dwo b/llvm/test/tools/llvm-dwp/Inputs/compress/a.dwo Binary files differnew file mode 100644 index 00000000000..4bef4059856 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/Inputs/compress/a.dwo diff --git a/llvm/test/tools/llvm-dwp/X86/compress.test b/llvm/test/tools/llvm-dwp/X86/compress.test new file mode 100644 index 00000000000..47ebaccf282 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/X86/compress.test @@ -0,0 +1,17 @@ +RUN: llvm-dwp %p/../Inputs/compress/a.dwo -o %t +RUN: llvm-dwarfdump %t | FileCheck %s + +Simple test built from this input which produces DWARF long enough to be compressed in the .[z]debug_info section: + + void f(int a, int b, int c, int d) { + } + +Since the compression is pretty orthogonal, we're not trying to test that the +compression library functioned correctly, just that dwp used it to decompress +the section - so test a few simple features and be done with it. + +CHECK: .debug_info.dwo contents: +CHECK: Compile Unit: +CHECK: DW_TAG_compile_unit +CHECK: DW_TAG_subprogram +CHECK: DW_TAG_formal_parameter diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index 9bc32760591..52dee3add48 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -12,6 +12,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MathExtras.h" @@ -237,7 +238,7 @@ static void writeIndex(MCStreamer &Out, MCSection *Section, auto H = S & Mask; while (Buckets[H]) { assert(S != IndexEntries[Buckets[H] - 1].Signature && - "Duplicate type unit"); + "Duplicate unit"); H = (H + (((S >> 32) & Mask) | 1)) % Buckets.size(); } Buckets[H] = i + 1; @@ -270,6 +271,22 @@ static void writeIndex(MCStreamer &Out, MCSection *Section, writeIndexTable(Out, ContributionOffsets, IndexEntries, &DWARFUnitIndex::Entry::SectionContribution::Length); } +static bool consumeCompressedDebugSectionHeader(StringRef &data, + uint64_t &OriginalSize) { + // Consume "ZLIB" prefix. + if (!data.startswith("ZLIB")) + return false; + data = data.substr(4); + // Consume uncompressed section size (big-endian 8 bytes). + DataExtractor extractor(data, false, 8); + uint32_t Offset = 0; + OriginalSize = extractor.getU64(&Offset); + if (Offset == 0) + return false; + data = data.substr(Offset); + return true; +} + static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) { const auto &MCOFI = *Out.getContext().getObjectFileInfo(); MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); @@ -311,20 +328,43 @@ static std::error_code write(MCStreamer &Out, ArrayRef<std::string> Inputs) { StringRef CurCUIndexSection; StringRef CurTUIndexSection; + SmallVector<SmallString<32>, 4> UncompressedSections; + for (const auto &Section : ErrOrObj->getBinary()->sections()) { + if (Section.isBSS()) + continue; + if (Section.isVirtual()) + continue; + StringRef Name; if (std::error_code Err = Section.getName(Name)) return Err; - auto SectionPair = - KnownSections.find(Name.substr(Name.find_first_not_of("._"))); - if (SectionPair == KnownSections.end()) - continue; + Name = Name.substr(Name.find_first_not_of("._")); StringRef Contents; if (auto Err = Section.getContents(Contents)) return Err; + if (Name.startswith("zdebug_")) { + uint64_t OriginalSize; + if (!zlib::isAvailable() || + !consumeCompressedDebugSectionHeader(Contents, OriginalSize)) + continue; + UncompressedSections.resize(UncompressedSections.size() + 1); + if (zlib::uncompress(Contents, UncompressedSections.back(), OriginalSize) != + zlib::StatusOK) { + UncompressedSections.pop_back(); + continue; + } + Name = Name.substr(1); + Contents = UncompressedSections.back(); + } + + auto SectionPair = KnownSections.find(Name); + if (SectionPair == KnownSections.end()) + continue; + if (DWARFSectionKind Kind = SectionPair->second.second) { auto Index = Kind - DW_SECT_INFO; if (Kind != DW_SECT_TYPES) { |