diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1144,7 +1144,14 @@ if (Value == "none") { CmdArgs.push_back("--compress-debug-sections=none"); } else if (Value == "zlib") { - if (llvm::compression::elf::isAvailable()) { + if (llvm::compression::zlib::isAvailable()) { + CmdArgs.push_back( + Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); + } else { + D.Diag(diag::warn_debug_compression_unavailable); + } + } else if (Value == "zstd") { + if (llvm::compression::zstd::isAvailable()) { CmdArgs.push_back( Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); } else { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -284,7 +284,7 @@ // argument. if (const Arg *A = Args.getLastArg(options::OPT_gz_EQ)) { StringRef V = A->getValue(); - if (V == "none" || V == "zlib") + if (V == "none" || V == "zlib" || V == "zstd") CmdArgs.push_back(Args.MakeArgString("--compress-debug-sections=" + V)); else TC.getDriver().Diag(diag::err_drv_unsupported_option_argument) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -716,7 +716,7 @@ CmdArgs.push_back("--compress-debug-sections"); } else { StringRef Value = A->getValue(); - if (Value == "none" || Value == "zlib") { + if (Value == "none" || Value == "zlib" || Value == "zstd") { CmdArgs.push_back( Args.MakeArgString("--compress-debug-sections=" + Twine(Value))); } else { diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -951,11 +951,25 @@ StringRef s = args.getLastArgValue(OPT_compress_debug_sections, "none"); if (s == "none") return false; - if (s != "zlib") - error("unknown --compress-debug-sections value: " + s); - if (!compression::elf::isAvailable()) + + if (s == "zlib"){ + if (compression::zlib::isAvailable()) { + return true; + } error("--compress-debug-sections: zlib is not available"); - return true; + return false; + } + + if (s == "zstd"){ + if (compression::zstd::isAvailable()) { + return true; + } + error("--compress-debug-sections: zstd is not available"); + return false; + } + + error("unknown --compress-debug-sections value: " + s); + return false; } static StringRef getAliasSpelling(opt::Arg *arg) { diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -14,6 +14,7 @@ #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Object/ELF.h" namespace lld { @@ -232,6 +233,8 @@ // compressed in the first place, or because we ended up uncompressing it). // Since the feature is not used often, this is usually -1. mutable int64_t uncompressedSize = -1; + + llvm::DebugCompressionType CompressionType; }; // SectionPiece represents a piece of splittable section contents. @@ -383,7 +386,7 @@ template void copyShtGroup(uint8_t *buf); }; -static_assert(sizeof(InputSection) <= 160, "InputSection is too big"); +static_assert(sizeof(InputSection) <= 168, "InputSection is too big"); inline bool isDebugSection(const InputSectionBase &sec) { return (sec.flags & llvm::ELF::SHF_ALLOC) == 0 && diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -16,6 +16,8 @@ #include "SyntheticSections.h" #include "Target.h" #include "lld/Common/CommonLinkerContext.h" +#include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" @@ -73,10 +75,25 @@ // If SHF_COMPRESSED is set, parse the header. The legacy .zdebug format is no // longer supported. if (flags & SHF_COMPRESSED) { - if (!compression::elf::isAvailable()) + if (!compression::zlib::isAvailable() || !compression::zstd::isAvailable()) error(toString(file) + ": contains a compressed section, " + - "but zlib is not available"); + "but zlib or zstd is not available"); invokeELFT(parseCompressedHeader); + // uint64_t compressionFlags = (flags & SHF_COMPRESSED) / SHF_COMPRESSED_LOWEST; + // if(compressionFlags==1) { + // if (!compression::zlib::isAvailable()) + // error(toString(file) + ": contains a zlib compressed section, " + + // "but zlib is not available"); + // invokeELFT(parseCompressedHeader); + // } else if(compressionFlags==2) { + // if (!compression::zlib::isAvailable()) + // error(toString(file) + ": contains a zstd compressed section, " + + // "but zstd is not available"); + // invokeELFT(parseCompressedHeader); + // } else if(compressionFlags==3) { + // error(toString(file) + ": contains a compressed section, " + + // "but of unknown type"); + // } } } @@ -121,10 +138,23 @@ std::lock_guard lock(mu); uncompressedBuf = bAlloc().Allocate(size); } - - if (Error e = compression::elf::uncompress(toStringRef(rawData), uncompressedBuf, size)) +// TODO: COLE: this assumes that the CType has been extracted from header pre this func +// // TODO: COLE: always cast elf32 chdr cause we only want type anyway which should be first :(? +// auto *hdr = reinterpret_cast(rawData.data()); +// if (hdr->ch_type != ELFCOMPRESS_ZLIB && hdr->ch_type != ELFCOMPRESS_ZSTD) { +// error(toString(this) + ": unsupported compression type"); +// return; +// } +// DebugCompressionType CompressionType=hdr->ch_type == ELFCOMPRESS_ZSTD?DebugCompressionType::Zstd:DebugCompressionType::Z; +if(CompressionType==DebugCompressionType::Zstd){ + if (Error e = compression::zstd::uncompress(toStringRef(rawData), uncompressedBuf, size)) + fatal(toString(this) + + ": uncompress failed: " + llvm::toString(std::move(e))); +}else{ + if (Error e = compression::zlib::uncompress(toStringRef(rawData), uncompressedBuf, size)) fatal(toString(this) + ": uncompress failed: " + llvm::toString(std::move(e))); +} rawData = makeArrayRef((uint8_t *)uncompressedBuf, size); uncompressedSize = -1; } @@ -202,6 +232,7 @@ // by zlib-compressed data. This function parses a header to initialize // `uncompressedSize` member and remove the header from `rawData`. template void InputSectionBase::parseCompressedHeader() { + // uint64_t compressionFlags = (flags & SHF_COMPRESSED) / SHF_COMPRESSED_LOWEST; flags &= ~(uint64_t)SHF_COMPRESSED; // New-style header @@ -211,11 +242,11 @@ } auto *hdr = reinterpret_cast(rawData.data()); - if (hdr->ch_type != ELFCOMPRESS_ZLIB) { + if (hdr->ch_type != ELFCOMPRESS_ZLIB && (hdr->ch_type != ELFCOMPRESS_ZSTD)) { error(toString(this) + ": unsupported compression type"); return; } - + // CompressionType=hdr->ch_type == ELFCOMPRESS_ZSTD?DebugCompressionType::Zstd:DebugCompressionType::Z; uncompressedSize = hdr->ch_size; alignment = std::max(hdr->ch_addralign, 1); rawData = rawData.slice(sizeof(*hdr)); @@ -1213,9 +1244,15 @@ // to the buffer. if (uncompressedSize >= 0) { size_t size = uncompressedSize; - if (Error e = compression::elf::uncompress(toStringRef(rawData), (char *)buf, size)) + if(CompressionType==DebugCompressionType::Zstd){ + if (Error e = compression::zstd::uncompress(toStringRef(rawData), (char *)buf, size)) + fatal(toString(this) + + ": uncompress failed: " + llvm::toString(std::move(e))); + }else{ + if (Error e = compression::zlib::uncompress(toStringRef(rawData), (char *)buf, size)) fatal(toString(this) + ": uncompress failed: " + llvm::toString(std::move(e))); + } uint8_t *bufEnd = buf + size; relocate(buf, bufEnd); return; diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -12,6 +12,7 @@ #include "InputSection.h" #include "LinkerScript.h" #include "lld/Common/LLVM.h" +#include "llvm/MC/MCTargetOptions.h" #include @@ -25,6 +26,7 @@ uint32_t numShards = 0; uint32_t checksum = 0; uint64_t uncompressedSize; + llvm::DebugCompressionType CompressionType; }; // This represents a section in an output file. @@ -32,6 +34,7 @@ // The writer creates multiple OutputSections and assign them unique, // non-overlapping file offsets and VAs. class OutputSection final : public SectionBase { + llvm::DebugCompressionType CompressionType; public: OutputSection(StringRef name, uint32_t type, uint64_t flags); diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1061,6 +1061,9 @@ // Identifies a section containing compressed data. SHF_COMPRESSED = 0x800U, + // SHF_COMPRESSED = 0x1800U, + + // SHF_COMPRESSED_LOWEST = 0x800U, // This section should not be garbage collected by the linker. SHF_GNU_RETAIN = 0x200000, @@ -1769,6 +1772,7 @@ // Legal values for ch_type field of compressed section header. enum { ELFCOMPRESS_ZLIB = 1, // ZLIB/DEFLATE algorithm. + ELFCOMPRESS_ZSTD = 2, // ZLIB/DEFLATE algorithm. ELFCOMPRESS_LOOS = 0x60000000, // Start of OS-specific. ELFCOMPRESS_HIOS = 0x6fffffff, // End of OS-specific. ELFCOMPRESS_LOPROC = 0x70000000, // Start of processor-specific. diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -29,6 +29,7 @@ None, ///< No compression GNU, ///< zlib-gnu style compression Z, ///< zlib style complession + Zstd, ///< Zstandard }; enum class EmitDwarfUnwindType { diff --git a/llvm/include/llvm/Object/Decompressor.h b/llvm/include/llvm/Object/Decompressor.h --- a/llvm/include/llvm/Object/Decompressor.h +++ b/llvm/include/llvm/Object/Decompressor.h @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/Error.h" namespace llvm { @@ -53,12 +54,14 @@ static bool isGnuStyle(StringRef Name); private: - Decompressor(StringRef Data); + Decompressor(StringRef Data, DebugCompressionType CType); Error consumeCompressedGnuHeader(); Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); + Error consumeCompressedZStdHeader(bool Is64Bit, bool IsLittleEndian); StringRef SectionData; + DebugCompressionType CType; uint64_t DecompressedSize; }; diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -146,7 +146,7 @@ bool maybeWriteCompression(uint64_t Size, SmallVectorImpl &CompressedContents, - bool ZLibStyle, unsigned Alignment); + bool ZLibStyle, bool ZstdStyle, unsigned Alignment); public: ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS, @@ -819,8 +819,9 @@ // Include the debug info compression header. bool ELFWriter::maybeWriteCompression( - uint64_t Size, SmallVectorImpl &CompressedContents, bool ZLibStyle, + uint64_t Size, SmallVectorImpl &CompressedContents, bool ZLibStyle,bool ZstdStyle, unsigned Alignment) { + if(!ZstdStyle){ if (ZLibStyle) { uint64_t HdrSize = is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); @@ -850,6 +851,27 @@ W.OS << Magic; support::endian::write(W.OS, Size, support::big); return true; + }else{ + uint64_t HdrSize = + is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr); + if (Size <= HdrSize + CompressedContents.size()) + return false; + // Platform specific header is followed by compressed data. + if (is64Bit()) { + // Write Elf64_Chdr header. + write(static_cast(ELF::ELFCOMPRESS_ZSTD)); + write(static_cast(0)); // ch_reserved field. + write(static_cast(Size)); + write(static_cast(Alignment)); + } else { + // Write Elf32_Chdr header otherwise. + write(static_cast(ELF::ELFCOMPRESS_ZSTD)); + write(static_cast(Size)); + write(static_cast(Alignment)); + } + return true; + + } } void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, @@ -868,26 +890,34 @@ } assert((MAI->compressDebugSections() == DebugCompressionType::Z || - MAI->compressDebugSections() == DebugCompressionType::GNU) && - "expected zlib or zlib-gnu style compression"); + MAI->compressDebugSections() == DebugCompressionType::GNU || + MAI->compressDebugSections() == DebugCompressionType::Zstd) && + "expected zlib or zlib-gnu or zstd style compression"); SmallVector UncompressedData; raw_svector_ostream VecOS(UncompressedData); Asm.writeSectionData(VecOS, &Section, Layout); SmallVector CompressedContents; - compression::elf::compress(StringRef(UncompressedData.data(), UncompressedData.size()), - CompressedContents); + bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z; + bool ZstdStyle = MAI->compressDebugSections() == DebugCompressionType::Zstd; + if(ZstdStyle){ + compression::zstd::compress(StringRef(UncompressedData.data(), UncompressedData.size()), + CompressedContents); + }else{ + compression::zlib::compress(StringRef(UncompressedData.data(), UncompressedData.size()), + CompressedContents); + } if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, - ZlibStyle, Sec.getAlignment())) { + ZlibStyle, ZstdStyle, Sec.getAlignment())) { W.OS << UncompressedData; return; } - if (ZlibStyle) { - // Set the compressed flag. That is zlib style. + if (ZlibStyle || ZstdStyle) { + // Set the compressed flag. That is zlib or zstd style. Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); // Alignment field should reflect the requirements of // the compressed section header. diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h --- a/llvm/lib/ObjCopy/ELF/ELFObject.h +++ b/llvm/lib/ObjCopy/ELF/ELFObject.h @@ -536,12 +536,12 @@ class CompressedSection : public SectionBase { MAKE_SEC_WRITER_FRIEND - DebugCompressionType CompressionType; uint64_t DecompressedSize; uint64_t DecompressedAlign; SmallVector CompressedData; public: + DebugCompressionType CompressionType; CompressedSection(const SectionBase &Sec, DebugCompressionType CompressionType); CompressedSection(ArrayRef CompressedData, uint64_t DecompressedSize, @@ -563,8 +563,10 @@ MAKE_SEC_WRITER_FRIEND public: + DebugCompressionType OriginalCompressionType; explicit DecompressedSection(const CompressedSection &Sec) : SectionBase(Sec) { + OriginalCompressionType = Sec.CompressionType; Size = Sec.getDecompressedSize(); Align = Sec.getDecompressedAlign(); Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED); diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp --- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp +++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp @@ -468,10 +468,18 @@ Sec.OriginalData.size() - DataOffset); SmallVector DecompressedContent; - if (Error Err = compression::elf::uncompress(CompressedContent, DecompressedContent, + if(Sec.OriginalCompressionType==DebugCompressionType::Zstd){ +if (Error Err = compression::zstd::uncompress(CompressedContent, DecompressedContent, static_cast(Sec.Size))) return createStringError(errc::invalid_argument, "'" + Sec.Name + "': " + toString(std::move(Err))); + } + else{ + if (Error Err = compression::zlib::uncompress(CompressedContent, DecompressedContent, + static_cast(Sec.Size))) + return createStringError(errc::invalid_argument, + "'" + Sec.Name + "': " + toString(std::move(Err))); + } uint8_t *Buf = reinterpret_cast(Out.getBufferStart()) + Sec.Offset; std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf); @@ -534,7 +542,7 @@ Buf += sizeof(DecompressedSize); } else { Elf_Chdr_Impl Chdr; - Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB; + Chdr.ch_type = Sec.CompressionType == DebugCompressionType::Zstd ? ELF::ELFCOMPRESS_ZSTD : ELF::ELFCOMPRESS_ZLIB; Chdr.ch_size = Sec.DecompressedSize; Chdr.ch_addralign = Sec.DecompressedAlign; memcpy(Buf, &Chdr, sizeof(Chdr)); @@ -547,11 +555,19 @@ CompressedSection::CompressedSection(const SectionBase &Sec, DebugCompressionType CompressionType) - : SectionBase(Sec), CompressionType(CompressionType), - DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) { - compression::elf::compress(StringRef(reinterpret_cast(OriginalData.data()), - OriginalData.size()), - CompressedData); + : SectionBase(Sec), DecompressedSize(Sec.OriginalData.size()), + DecompressedAlign(Sec.Align), CompressionType(CompressionType) { + if (CompressionType == DebugCompressionType::Zstd) { + compression::zstd::compress( + StringRef(reinterpret_cast(OriginalData.data()), + OriginalData.size()), + CompressedData); + }else{ + compression::zlib::compress( + StringRef(reinterpret_cast(OriginalData.data()), + OriginalData.size()), + CompressedData); + } size_t ChdrSize; if (CompressionType == DebugCompressionType::GNU) { @@ -572,8 +588,8 @@ CompressedSection::CompressedSection(ArrayRef CompressedData, uint64_t DecompressedSize, uint64_t DecompressedAlign) - : CompressionType(DebugCompressionType::None), - DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) { + : DecompressedSize(DecompressedSize), + DecompressedAlign(DecompressedAlign), CompressionType(DebugCompressionType::None) { OriginalData = CompressedData; } diff --git a/llvm/lib/Object/Decompressor.cpp b/llvm/lib/Object/Decompressor.cpp --- a/llvm/lib/Object/Decompressor.cpp +++ b/llvm/lib/Object/Decompressor.cpp @@ -8,6 +8,7 @@ #include "llvm/Object/Decompressor.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Compression.h" #include "llvm/Support/DataExtractor.h" @@ -19,19 +20,43 @@ Expected Decompressor::create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit) { - if (!compression::elf::isAvailable()) + DebugCompressionType CType = DebugCompressionType::Z; + if(isGnuStyle(Name)){ + CType = DebugCompressionType::GNU; + }else{ + if(Is64Bit){ + auto *chdr = reinterpret_cast(Data.bytes_begin()); + if(chdr->ch_type == ELF::ELFCOMPRESS_ZLIB){ + CType=DebugCompressionType::Z; + } else if(chdr->ch_type == ELF::ELFCOMPRESS_ZSTD){ + CType = DebugCompressionType::Zstd; + } else { + return createError("unknown elf compress type in compressed section header"); + } + } else { + auto *chdr = reinterpret_cast(Data.bytes_begin()); + if(chdr->ch_type == ELF::ELFCOMPRESS_ZLIB){ + CType = DebugCompressionType::Z; + } else if(chdr->ch_type == ELF::ELFCOMPRESS_ZSTD){ + CType = DebugCompressionType::Zstd; + } else { + return createError("unknown elf compress type in compressed section header"); + } + } + } + + if ((CType == DebugCompressionType::Z || CType==DebugCompressionType::GNU) && !compression::zlib::isAvailable()) return createError("zlib is not available"); - - Decompressor D(Data); - Error Err = isGnuStyle(Name) ? D.consumeCompressedGnuHeader() - : D.consumeCompressedZLibHeader(Is64Bit, IsLE); + Decompressor D(Data, CType); + Error Err = CType == DebugCompressionType::GNU ? D.consumeCompressedGnuHeader() + : CType == DebugCompressionType::Z ? D.consumeCompressedZLibHeader(Is64Bit, IsLE) : D.consumeCompressedZStdHeader(Is64Bit, IsLE); if (Err) return std::move(Err); return D; } -Decompressor::Decompressor(StringRef Data) - : SectionData(Data), DecompressedSize(0) {} +Decompressor::Decompressor(StringRef Data, DebugCompressionType CType) + : SectionData(Data), CType(CType), DecompressedSize(0) {} Error Decompressor::consumeCompressedGnuHeader() { if (!SectionData.startswith("ZLIB")) @@ -72,6 +97,31 @@ return Error::success(); } + +Error Decompressor::consumeCompressedZStdHeader(bool Is64Bit, + bool IsLittleEndian) { + using namespace ELF; + uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); + if (SectionData.size() < HdrSize) + return createError("corrupted compressed section header"); + + DataExtractor Extractor(SectionData, IsLittleEndian, 0); + uint64_t Offset = 0; + if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) + : sizeof(Elf32_Word)) != + ELFCOMPRESS_ZSTD) + return createError("unsupported compression type"); + + // Skip Elf64_Chdr::ch_reserved field. + if (Is64Bit) + Offset += sizeof(Elf64_Word); + + DecompressedSize = Extractor.getUnsigned( + &Offset, Is64Bit ? sizeof(Elf64_Xword) : sizeof(Elf32_Word)); + SectionData = SectionData.substr(HdrSize); + return Error::success(); +} + bool Decompressor::isGnuStyle(StringRef Name) { return Name.startswith(".zdebug"); } @@ -94,5 +144,5 @@ Error Decompressor::decompress(MutableArrayRef Buffer) { size_t Size = Buffer.size(); - return compression::elf::uncompress(SectionData, Buffer.data(), Size); + return CType == DebugCompressionType::Zstd ? compression::zstd::uncompress(SectionData, Buffer.data(), Size) : compression::zlib::uncompress(SectionData, Buffer.data(), Size); } diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp --- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -731,6 +731,7 @@ InputArgs.getLastArgValue(OBJCOPY_compress_debug_sections_eq)) .Case("zlib-gnu", DebugCompressionType::GNU) .Case("zlib", DebugCompressionType::Z) + .Case("zstd", DebugCompressionType::Zstd) .Default(DebugCompressionType::None); if (Config.CompressionType == DebugCompressionType::None) return createStringError( @@ -740,10 +741,17 @@ .str() .c_str()); } - if (!compression::elf::isAvailable()) - return createStringError( - errc::invalid_argument, - "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress"); + if(Config.CompressionType == DebugCompressionType::Zstd) { + if (!compression::zstd::isAvailable()) + return createStringError( + errc::invalid_argument, + "LLVM was not compiled with LLVM_ENABLE_ZSTD: can not compress"); + } else { + if (!compression::zlib::isAvailable()) + return createStringError( + errc::invalid_argument, + "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress"); + } } Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink); @@ -998,11 +1006,17 @@ "cannot specify both --compress-debug-sections and " "--decompress-debug-sections"); } - - if (Config.DecompressDebugSections && !compression::elf::isAvailable()) +if(Config.CompressionType != DebugCompressionType::Zstd) { + if (Config.DecompressDebugSections && !compression::zlib::isAvailable()) return createStringError( errc::invalid_argument, "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress"); +}else{ + if (Config.DecompressDebugSections && !compression::zstd::isAvailable()) + return createStringError( + errc::invalid_argument, + "LLVM was not compiled with LLVM_ENABLE_ZSTD: cannot decompress"); +} if (Config.ExtractPartition && Config.ExtractMainPartition) return createStringError(errc::invalid_argument,