Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -24,6 +24,7 @@ #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/DebugInfo/DWARF/DWARFCompression.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" @@ -828,7 +829,7 @@ [](InputSectionBase *S) { if (!S->Live) return; - if (S->isCompressed()) + if (DWARFCompression::isCompressedELFSection(S->Flags, S->Name)) S->uncompress(); if (auto *MS = dyn_cast>(S)) MS->splitIntoPieces(); Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -138,22 +138,12 @@ // section. uintX_t getOffset(uintX_t Offset) const; - // ELF supports ZLIB-compressed section. - // Returns true if the section is compressed. - bool isCompressed() const; void uncompress(); // Returns a source location string. Used to construct an error message. std::string getLocation(uintX_t Offset); void relocate(uint8_t *Buf, uint8_t *BufEnd); - -private: - std::pair, uint64_t> - getElfCompressedData(ArrayRef Data); - - std::pair, uint64_t> - getRawCompressedData(ArrayRef Data); }; // SectionPiece represents a piece of splittable section contents. Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -19,6 +19,7 @@ #include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" +#include "llvm/DebugInfo/DWARF/DWARFCompression.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include @@ -128,62 +129,13 @@ llvm_unreachable("invalid section kind"); } -template bool InputSectionBase::isCompressed() const { - return (Flags & SHF_COMPRESSED) || Name.startswith(".zdebug"); -} - -// Returns compressed data and its size when uncompressed. -template -std::pair, uint64_t> -InputSectionBase::getElfCompressedData(ArrayRef Data) { - // Compressed section with Elf_Chdr is the ELF standard. - if (Data.size() < sizeof(Elf_Chdr)) - fatal(toString(this) + ": corrupted compressed section"); - auto *Hdr = reinterpret_cast(Data.data()); - if (Hdr->ch_type != ELFCOMPRESS_ZLIB) - fatal(toString(this) + ": unsupported compression type"); - return {Data.slice(sizeof(*Hdr)), Hdr->ch_size}; -} - -// Returns compressed data and its size when uncompressed. -template -std::pair, uint64_t> -InputSectionBase::getRawCompressedData(ArrayRef Data) { - // Compressed sections without Elf_Chdr header contain this header - // instead. This is a GNU extension. - struct ZlibHeader { - char Magic[4]; // Should be "ZLIB" - char Size[8]; // Uncompressed size in big-endian - }; - - if (Data.size() < sizeof(ZlibHeader)) - fatal(toString(this) + ": corrupted compressed section"); - auto *Hdr = reinterpret_cast(Data.data()); - if (memcmp(Hdr->Magic, "ZLIB", 4)) - fatal(toString(this) + ": broken ZLIB-compressed section"); - return {Data.slice(sizeof(*Hdr)), read64be(Hdr->Size)}; -} - // Uncompress section contents. Note that this function is called // from parallel_for_each, so it must be thread-safe. template void InputSectionBase::uncompress() { - if (!zlib::isAvailable()) - fatal(toString(this) + - ": build lld with zlib to enable compressed sections support"); - - // This section is compressed. Here we decompress it. Ideally, all - // compressed sections have SHF_COMPRESSED bit and their contents - // start with headers of Elf_Chdr type. However, sections whose - // names start with ".zdebug_" don't have the bit and contains a raw - // ZLIB-compressed data (which is a bad thing because section names - // shouldn't be significant in ELF.) We need to be able to read both. - ArrayRef Buf; // Compressed data - size_t Size; // Uncompressed size - if (Flags & SHF_COMPRESSED) - std::tie(Buf, Size) = getElfCompressedData(Data); - else - std::tie(Buf, Size) = getRawCompressedData(Data); - + DWARFCompression Uncompressor(Name, toStringRef(Data), + ELFT::TargetEndianness == llvm::support::little, + ELFT::Is64Bits); + size_t Size = Uncompressor.UncompressedSize; // Uncompress Buf. char *OutputBuf; { @@ -191,8 +143,8 @@ std::lock_guard Lock(Mu); OutputBuf = BAlloc.Allocate(Size); } - if (zlib::uncompress(toStringRef(Buf), OutputBuf, Size) != zlib::StatusOK) - fatal(toString(this) + ": error while uncompressing section"); + if (!Uncompressor.uncompress(OutputBuf, Size)) + fatal(toString(this) + ": " + Uncompressor.getErrorMessage()); Data = ArrayRef((uint8_t *)OutputBuf, Size); }