Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -24,6 +24,7 @@ #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" #include "llvm/Support/TarWriter.h" @@ -815,7 +816,7 @@ [](InputSectionBase *S) { if (!S->Live) return; - if (S->isCompressed()) + if (Decompressor::isCompressedELFSection(S->Flags, S->Name)) S->uncompress(); if (auto *MS = dyn_cast>(S)) MS->splitIntoPieces(); Index: lld/trunk/ELF/Error.h =================================================================== --- lld/trunk/ELF/Error.h +++ lld/trunk/ELF/Error.h @@ -44,6 +44,7 @@ LLVM_ATTRIBUTE_NORETURN void exitLld(int Val); LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); +LLVM_ATTRIBUTE_NORETURN void fatal(Error &E, const Twine &Prefix); // check() functions are convenient functions to strip errors // from error-or-value objects. Index: lld/trunk/ELF/Error.cpp =================================================================== --- lld/trunk/ELF/Error.cpp +++ lld/trunk/ELF/Error.cpp @@ -103,4 +103,10 @@ fatal(Prefix + ": " + EC.message()); } +void elf::fatal(Error &E, const Twine &Prefix) { + handleAllErrors(std::move(E), [&](llvm::ErrorInfoBase &EI) { + fatal(Prefix + ": " + EI.message()); + }); +} + } // namespace lld Index: lld/trunk/ELF/InputSection.h =================================================================== --- lld/trunk/ELF/InputSection.h +++ lld/trunk/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: lld/trunk/ELF/InputSection.cpp =================================================================== --- lld/trunk/ELF/InputSection.cpp +++ lld/trunk/ELF/InputSection.cpp @@ -19,6 +19,7 @@ #include "SyntheticSections.h" #include "Target.h" #include "Thunks.h" +#include "llvm/Object/Decompressor.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include @@ -128,71 +129,23 @@ 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); + Decompressor Decompressor = check(Decompressor::create( + Name, toStringRef(Data), ELFT::TargetEndianness == llvm::support::little, + ELFT::Is64Bits)); - // Uncompress Buf. + size_t Size = Decompressor.getDecompressedSize(); char *OutputBuf; { static std::mutex Mu; 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 (Error E = Decompressor.decompress({OutputBuf, Size})) + fatal(E, toString(this)); Data = ArrayRef((uint8_t *)OutputBuf, Size); }