diff options
Diffstat (limited to 'lib/DebugInfo')
-rw-r--r-- | lib/DebugInfo/DWARFContext.cpp | 38 | ||||
-rw-r--r-- | lib/DebugInfo/DWARFContext.h | 3 |
2 files changed, 41 insertions, 0 deletions
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 74a8c36..1e13731 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -10,6 +10,8 @@ #include "DWARFContext.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/Path.h" @@ -483,6 +485,22 @@ DIInliningInfo DWARFContext::getInliningInfoForAddress(uint64_t Address, return InliningInfo; } +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; +} + DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : IsLittleEndian(Obj->isLittleEndian()), AddressSize(Obj->getBytesInAddress()) { @@ -497,6 +515,22 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes. + // Check if debug info section is compressed with zlib. + if (name.startswith("zdebug_")) { + uint64_t OriginalSize; + if (!zlib::isAvailable() || + !consumeCompressedDebugSectionHeader(data, OriginalSize)) + continue; + OwningPtr<MemoryBuffer> UncompressedSection; + if (zlib::uncompress(data, UncompressedSection, OriginalSize) != + zlib::StatusOK) + continue; + // Make data point to uncompressed section contents and save its contents. + name = name.substr(1); + data = UncompressedSection->getBuffer(); + UncompressedSections.push_back(UncompressedSection.take()); + } + StringRef *Section = StringSwitch<StringRef*>(name) .Case("debug_info", &InfoSection) .Case("debug_abbrev", &AbbrevSection) @@ -584,4 +618,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : } } +DWARFContextInMemory::~DWARFContextInMemory() { + DeleteContainerPointers(UncompressedSections); +} + void DWARFContextInMemory::anchor() { } diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h index 37b2729..78c18e6 100644 --- a/lib/DebugInfo/DWARFContext.h +++ b/lib/DebugInfo/DWARFContext.h @@ -161,8 +161,11 @@ class DWARFContextInMemory : public DWARFContext { StringRef RangeDWOSection; StringRef AddrSection; + SmallVector<MemoryBuffer*, 4> UncompressedSections; + public: DWARFContextInMemory(object::ObjectFile *); + ~DWARFContextInMemory(); virtual bool isLittleEndian() const { return IsLittleEndian; } virtual uint8_t getAddressSize() const { return AddressSize; } virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; } |