summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Object/COFF.h1
-rw-r--r--include/llvm/Object/ELFObjectFile.h6
-rw-r--r--include/llvm/Object/MachO.h1
-rw-r--r--include/llvm/Object/ObjectFile.h6
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp68
-rw-r--r--lib/Object/COFFObjectFile.cpp4
-rw-r--r--lib/Object/MachOObjectFile.cpp4
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-zlib.cc8
-rwxr-xr-xtest/DebugInfo/Inputs/dwarfdump-test-zlib.elf-x86-64bin9589 -> 10384 bytes
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-zlibgnu.elf-x86-64bin0 -> 10320 bytes
-rw-r--r--test/DebugInfo/dwarfdump-zlib.test6
11 files changed, 86 insertions, 18 deletions
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 7553f4bdaf7..aa12418f2d3 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -694,6 +694,7 @@ protected:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index c5f777186aa..52cde1a0f0f 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -222,6 +222,7 @@ protected:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
@@ -584,6 +585,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
}
template <class ELFT>
+bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const {
+ return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED;
+}
+
+template <class ELFT>
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
}
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 611acf3124d..6a079a964bf 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -222,6 +222,7 @@ public:
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+ bool isSectionCompressed(DataRefImpl Sec) const override;
bool isSectionText(DataRefImpl Sec) const override;
bool isSectionData(DataRefImpl Sec) const override;
bool isSectionBSS(DataRefImpl Sec) const override;
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 0a902a4590a..0f0f10b8c19 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -89,6 +89,7 @@ public:
/// @brief Get the alignment of this section as the actual value (not log 2).
uint64_t getAlignment() const;
+ bool isCompressed() const;
bool isText() const;
bool isData() const;
bool isBSS() const;
@@ -214,6 +215,7 @@ protected:
virtual std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const = 0;
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
+ virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
virtual bool isSectionText(DataRefImpl Sec) const = 0;
virtual bool isSectionData(DataRefImpl Sec) const = 0;
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
@@ -380,6 +382,10 @@ inline uint64_t SectionRef::getAlignment() const {
return OwningObject->getSectionAlignment(SectionPimpl);
}
+inline bool SectionRef::isCompressed() const {
+ return OwningObject->isSectionCompressed(SectionPimpl);
+}
+
inline bool SectionRef::isText() const {
return OwningObject->isSectionText(SectionPimpl);
}
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index d3b5e736c48..27b8c564d91 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -15,6 +15,7 @@
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -590,8 +591,8 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
-static bool consumeCompressedDebugSectionHeader(StringRef &data,
- uint64_t &OriginalSize) {
+static bool consumeCompressedGnuHeader(StringRef &data,
+ uint64_t &OriginalSize) {
// Consume "ZLIB" prefix.
if (!data.startswith("ZLIB"))
return false;
@@ -606,6 +607,50 @@ static bool consumeCompressedDebugSectionHeader(StringRef &data,
return true;
}
+static bool consumeCompressedZLibHeader(StringRef &Data, uint64_t &OriginalSize,
+ bool IsLE, bool Is64Bit) {
+ using namespace ELF;
+ uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
+ if (Data.size() < HdrSize)
+ return false;
+
+ DataExtractor Extractor(Data, IsLE, 0);
+ uint32_t Offset = 0;
+ if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
+ : sizeof(Elf32_Word)) !=
+ ELFCOMPRESS_ZLIB)
+ return false;
+
+ // Skip Elf64_Chdr::ch_reserved field.
+ if (Is64Bit)
+ Offset += sizeof(Elf64_Word);
+
+ OriginalSize = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Xword)
+ : sizeof(Elf32_Word));
+ Data = Data.substr(HdrSize);
+ return true;
+}
+
+static bool tryDecompress(StringRef &Name, StringRef &Data,
+ SmallString<32> &Out, bool ZLibStyle, bool IsLE,
+ bool Is64Bit) {
+ if (!zlib::isAvailable())
+ return false;
+
+ uint64_t OriginalSize;
+ bool Result =
+ ZLibStyle ? consumeCompressedZLibHeader(Data, OriginalSize, IsLE, Is64Bit)
+ : consumeCompressedGnuHeader(Data, OriginalSize);
+
+ if (!Result || zlib::uncompress(Data, Out, OriginalSize) != zlib::StatusOK)
+ return false;
+
+ // gnu-style names are started from "z", consume that.
+ if (!ZLibStyle)
+ Name = Name.substr(1);
+ return true;
+}
+
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L)
: IsLittleEndian(Obj.isLittleEndian()),
@@ -631,20 +676,13 @@ DWARFContextInMemory::DWARFContextInMemory(const 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))
+ bool ZLibStyleCompressed = Section.isCompressed();
+ if (ZLibStyleCompressed || name.startswith("zdebug_")) {
+ SmallString<32> Out;
+ if (!tryDecompress(name, data, Out, ZLibStyleCompressed, IsLittleEndian,
+ AddressSize == 8))
continue;
- UncompressedSections.resize(UncompressedSections.size() + 1);
- if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
- zlib::StatusOK) {
- UncompressedSections.pop_back();
- continue;
- }
- // Make data point to uncompressed section contents and save its contents.
- name = name.substr(1);
+ UncompressedSections.emplace_back(std::move(Out));
data = UncompressedSections.back();
}
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 4b6ab23f5ff..489c69cc4bc 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -292,6 +292,10 @@ uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
return Sec->getAlignment();
}
+bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
+ return false;
+}
+
bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
const coff_section *Sec = toSec(Ref);
return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 760249f56a8..d7ec3e57a58 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -653,6 +653,10 @@ uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
return uint64_t(1) << Align;
}
+bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
+ return false;
+}
+
bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
uint32_t Flags = getSectionFlags(this, Sec);
return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
index 260c3c435c1..fc60ea3449a 100644
--- a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
+++ b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
@@ -16,9 +16,11 @@ int main() {
return f(2, 3);
}
-// Built with Clang 3.2 and ld.gold linker:
+// Built with Clang 3.9 and GNU gold (GNU Binutils for Ubuntu 2.26) 1.11:
// $ mkdir -p /tmp/dbginfo
// $ cp dwarfdump-test-zlib.cc /tmp/dbginfo
// $ cd /tmp/dbginfo
-// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib \
-// -o <output>
+// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib -o dwarfdump-test-zlib.elf-x86-64
+// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib-gnu -o dwarfdump-test-zlibgnu.elf-x86-64
+// llvm-readobj -sections can be used to see that outputs really contain the compressed sections, also output in both
+// cases is slightly smaller, that is because of compression. \ No newline at end of file
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-test-zlib.elf-x86-64
index 16b3153939f..34cdb8a89ed 100755
--- a/test/DebugInfo/Inputs/dwarfdump-test-zlib.elf-x86-64
+++ b/test/DebugInfo/Inputs/dwarfdump-test-zlib.elf-x86-64
Binary files differ
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-test-zlibgnu.elf-x86-64
new file mode 100644
index 00000000000..82a45baa37d
--- /dev/null
+++ b/test/DebugInfo/Inputs/dwarfdump-test-zlibgnu.elf-x86-64
Binary files differ
diff --git a/test/DebugInfo/dwarfdump-zlib.test b/test/DebugInfo/dwarfdump-zlib.test
index cbd85ca093c..d3ef806f3f8 100644
--- a/test/DebugInfo/dwarfdump-zlib.test
+++ b/test/DebugInfo/dwarfdump-zlib.test
@@ -1,6 +1,12 @@
REQUIRES: zlib
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.elf-x86-64 | FileCheck %s
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 | FileCheck %s
CHECK: .debug_abbrev contents
+
+// Dump content of a little section to check that both zlib and zlib gnu styles do
+// the decompression correctly and result is the same. This and above also checks
+// that sections names are properly shown in zlib-gnu style (without additional 'z' prefix).
CHECK: .debug_info contents
+CHECK: 0x00000000: Compile Unit: length = 0x00000144 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000148)