Re: [PATCH v3] binutils, gdb: support zstd compressed debug sections

Enze Li via Gdb-patches
2022-09-24T06:54:01Z

Hi Fangrui,

One nit, maybe not an important one.

A proper committed message should include a link to the relevant bug on
Bugzilla. Like this,

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29563

For more detail, see here[1].

[1] https://sourceware.org/gdb/wiki/ContributionChecklist#Properly_formatted_commit_messages

Thanks,
Enze

On Thu, Sep 22 2022 at 09:08:37 PM -0700, Fangrui Song via Gdb-patches wrote:

> PR29397 PR29563: The new configure option --with-zstd defaults to auto.
> If pkgconfig/libzstd.pc is found, define HAVE_ZSTD and support zstd
> compressed debug sections for most tools.
>
> * bfd: for addr2line, objdump --dwarf, gdb, etc
> * gas: support --compress-debug-sections=zstd
> * ld: support ELFCOMPRESS_ZSTD input and --compress-debug-sections=zstd
> * objcopy: support ELFCOMPRESS_ZSTD input for
> --decompress-debug-sections and --compress-debug-sections=zstd
> * gdb: support ELFCOMPRESS_ZSTD input. The bfd change references zstd
> symbols, so gdb has to link against -lzstd in this patch.
>
> If zstd is not supported, ELFCOMPRESS_ZSTD input triggers an error. We
> can avoid HAVE_ZSTD if binutils-gdb imports zstd/ like zlib/, but this
> is too heavyweight, so don't do it for now.
>
> ```
> % ld/ld-new a.o
> ld/ld-new: a.o: section .debug_abbrev is compressed with zstd, but BFD is not built with zstd support
> ...
>
> % ld/ld-new a.o --compress-debug-sections=zstd
> ld/ld-new: --compress-debug-sections=zstd: ld is not built with zstd support
>
> % binutils/objcopy --compress-debug-sections=zstd a.o b.o
> binutils/objcopy: --compress-debug-sections=zstd: binutils is not built with zstd support
>
> % binutils/objcopy b.o --decompress-debug-sections
> binutils/objcopy: zstd.o: section .debug_abbrev is compressed with zstd, but BFD is not built with zstd support
> ...
> ```
> ---
> Changes from v1:
> * use PKG_CHECK_MODULES to check libzstd.pc
>
> Changes from v2:
> * Improve PKG_CHECK_MODULES, autoreconf -vf
> * objcopy: check --compress-debug-sections=zstd in a !HAVE_ZSTD build
> ---
> bfd/Makefile.am | 4 +-
> bfd/Makefile.in | 13 +-
> bfd/aclocal.m4 | 2 +
> bfd/bfd-in.h | 3 +-
> bfd/bfd-in2.h | 11 +-
> bfd/bfd.c | 26 +-
> bfd/compress.c | 72 +++-
> bfd/config.in | 3 +
> bfd/configure | 268 ++++++++++++-
> bfd/configure.ac | 3 +-
> bfd/elf.c | 12 +
> bfd/elfxx-target.h | 6 +-
> bfd/section.c | 3 +-
> binutils/Makefile.in | 5 +-
> binutils/aclocal.m4 | 1 +
> binutils/config.in | 3 +
> binutils/configure | 135 ++++++-
> binutils/configure.ac | 3 +-
> binutils/doc/binutils.texi | 16 +-
> binutils/objcopy.c | 19 +-
> binutils/testsuite/binutils-all/compress.exp | 44 +++
> config/zstd.m4 | 24 ++
> configure | 10 +
> configure.ac | 3 +
> gas/Makefile.am | 4 +-
> gas/Makefile.in | 13 +-
> gas/aclocal.m4 | 2 +
> gas/as.c | 13 +-
> gas/compress-debug.c | 60 ++-
> gas/compress-debug.h | 10 +-
> gas/config.in | 3 +
> gas/configure | 268 ++++++++++++-
> gas/configure.ac | 3 +-
> gas/doc/as.texi | 11 +-
> gas/write.c | 36 +-
> gdb/Makefile.in | 8 +-
> gdb/acinclude.m4 | 3 +-
> gdb/config.in | 3 +
> gdb/configure | 136 ++++++-
> gdb/configure.ac | 4 +-
> ld/Makefile.am | 5 +-
> ld/Makefile.in | 11 +-
> ld/aclocal.m4 | 1 +
> ld/config.in | 3 +
> ld/configure | 389 ++++++++++++-------
> ld/configure.ac | 7 +-
> ld/emultempl/elf.em | 9 +
> ld/ld.texi | 5 +
> ld/ldmain.c | 8 +-
> ld/lexsup.c | 4 +-
> ld/testsuite/ld-elf/compress.exp | 17 +
> 51 files changed, 1470 insertions(+), 255 deletions(-)
> create mode 100644 config/zstd.m4
>
> diff --git a/bfd/Makefile.am b/bfd/Makefile.am
> index c23dff6cac3..cfe903c63f0 100644
> --- a/bfd/Makefile.am
> +++ b/bfd/Makefile.am
> @@ -57,7 +57,7 @@ ZLIBINC = @zlibinc@
>
> WARN_CFLAGS = @WARN_CFLAGS@
> NO_WERROR = @NO_WERROR@
> -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
> AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"' @LARGEFILE_CPPFLAGS@
> if PLUGINS
> bfdinclude_HEADERS += $(INCDIR)/plugin-api.h
> @@ -776,7 +776,7 @@ ofiles: stamp-ofiles ; @true
> libbfd_la_SOURCES = $(BFD32_LIBS_CFILES)
> EXTRA_libbfd_la_SOURCES = $(CFILES)
> libbfd_la_DEPENDENCIES = $(OFILES) ofiles
> -libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB)
> +libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_LIBS)
> libbfd_la_LDFLAGS += -release `cat libtool-soversion` @SHARED_LDFLAGS@
>
> # libtool will build .libs/libbfd.a. We create libbfd.a in the build
> diff --git a/bfd/Makefile.in b/bfd/Makefile.in
> index 82843d2d61d..6be41a72a59 100644
> --- a/bfd/Makefile.in
> +++ b/bfd/Makefile.in
> @@ -122,10 +122,12 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
> $(top_srcdir)/../config/lead-dot.m4 \
> $(top_srcdir)/../config/nls.m4 \
> $(top_srcdir)/../config/override.m4 \
> + $(top_srcdir)/../config/pkg.m4 \
> $(top_srcdir)/../config/plugins.m4 \
> $(top_srcdir)/../config/po.m4 \
> $(top_srcdir)/../config/progtest.m4 \
> - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
> + $(top_srcdir)/../config/zlib.m4 \
> + $(top_srcdir)/../config/zstd.m4 $(top_srcdir)/../libtool.m4 \
> $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
> $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
> $(top_srcdir)/bfd.m4 $(top_srcdir)/warning.m4 \
> @@ -399,6 +401,9 @@ PACKAGE_URL = @PACKAGE_URL@
> PACKAGE_VERSION = @PACKAGE_VERSION@
> PATH_SEPARATOR = @PATH_SEPARATOR@
> PKGVERSION = @PKGVERSION@
> +PKG_CONFIG = @PKG_CONFIG@
> +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
> +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
> POSUB = @POSUB@
> RANLIB = @RANLIB@
> REPORT_BUGS_TEXI = @REPORT_BUGS_TEXI@
> @@ -416,6 +421,8 @@ WARN_CFLAGS = @WARN_CFLAGS@
> WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@
> WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@
> XGETTEXT = @XGETTEXT@
> +ZSTD_CFLAGS = @ZSTD_CFLAGS@
> +ZSTD_LIBS = @ZSTD_LIBS@
> abs_builddir = @abs_builddir@
> abs_srcdir = @abs_srcdir@
> abs_top_builddir = @abs_top_builddir@
> @@ -520,7 +527,7 @@ libbfd_la_LDFLAGS = $(am__append_1) -release `cat libtool-soversion` \
> # case both are empty.
> ZLIB = @zlibdir@ -lz
> ZLIBINC = @zlibinc@
> -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
> AM_CPPFLAGS = -DBINDIR='"$(bindir)"' -DLIBDIR='"$(libdir)"' \
> @LARGEFILE_CPPFLAGS@ @HDEFINES@ @COREFLAG@ @TDEFINES@ \
> $(CSEARCH) $(CSWITCHES) $(HAVEVECS) @INCINTL@
> @@ -1199,7 +1206,7 @@ OFILES = $(BFD_BACKENDS) $(BFD_MACHINES) @COREFILE@ @bfd64_libs@
> libbfd_la_SOURCES = $(BFD32_LIBS_CFILES)
> EXTRA_libbfd_la_SOURCES = $(CFILES)
> libbfd_la_DEPENDENCIES = $(OFILES) ofiles
> -libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB)
> +libbfd_la_LIBADD = `cat ofiles` @SHARED_LIBADD@ $(LIBDL) $(ZLIB) $(ZSTD_LIBS)
>
> # libtool will build .libs/libbfd.a. We create libbfd.a in the build
> # directory so that we don't have to convert all the programs that use
> diff --git a/bfd/aclocal.m4 b/bfd/aclocal.m4
> index 0f8aa1d4518..09b849dfc87 100644
> --- a/bfd/aclocal.m4
> +++ b/bfd/aclocal.m4
> @@ -1176,10 +1176,12 @@ m4_include([../config/largefile.m4])
> m4_include([../config/lead-dot.m4])
> m4_include([../config/nls.m4])
> m4_include([../config/override.m4])
> +m4_include([../config/pkg.m4])
> m4_include([../config/plugins.m4])
> m4_include([../config/po.m4])
> m4_include([../config/progtest.m4])
> m4_include([../config/zlib.m4])
> +m4_include([../config/zstd.m4])
> m4_include([../libtool.m4])
> m4_include([../ltoptions.m4])
> m4_include([../ltsugar.m4])
> diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
> index 8605056aefe..4765ea80536 100644
> --- a/bfd/bfd-in.h
> +++ b/bfd/bfd-in.h
> @@ -342,7 +342,8 @@ enum compressed_debug_section_type
> COMPRESS_DEBUG_NONE = 0,
> COMPRESS_DEBUG = 1 << 0,
> COMPRESS_DEBUG_GNU_ZLIB = COMPRESS_DEBUG | 1 << 1,
> - COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 2
> + COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 2,
> + COMPRESS_DEBUG_ZSTD = COMPRESS_DEBUG | 1 << 3
> };
>
> /* This structure is used to keep track of stabs in sections
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index 79fcc4eb912..5c80956c79c 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -349,7 +349,8 @@ enum compressed_debug_section_type
> COMPRESS_DEBUG_NONE = 0,
> COMPRESS_DEBUG = 1 << 0,
> COMPRESS_DEBUG_GNU_ZLIB = COMPRESS_DEBUG | 1 << 1,
> - COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 2
> + COMPRESS_DEBUG_GABI_ZLIB = COMPRESS_DEBUG | 1 << 2,
> + COMPRESS_DEBUG_ZSTD = COMPRESS_DEBUG | 1 << 3
> };
>
> /* This structure is used to keep track of stabs in sections
> @@ -962,7 +963,8 @@ typedef struct bfd_section
> unsigned int compress_status : 2;
> #define COMPRESS_SECTION_NONE 0
> #define COMPRESS_SECTION_DONE 1
> -#define DECOMPRESS_SECTION_SIZED 2
> +#define DECOMPRESS_SECTION_ZLIB 2
> +#define DECOMPRESS_SECTION_ZSTD 3
>
> /* The following flags are used by the ELF linker. */
>
> @@ -6637,12 +6639,14 @@ struct bfd
> #define BFD_ARCHIVE_FULL_PATH 0x100000
>
> #define BFD_CLOSED_BY_CACHE 0x200000
> + /* Compress sections in this BFD with SHF_COMPRESSED zstd. */
> +#define BFD_COMPRESS_ZSTD 0x400000
>
> /* Flags bits to be saved in bfd_preserve_save. */
> #define BFD_FLAGS_SAVED \
> (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
> | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
> - | BFD_USE_ELF_STT_COMMON)
> + | BFD_USE_ELF_STT_COMMON | BFD_COMPRESS_ZSTD)
>
> /* Flags bits which are for BFD use only. */
> #define BFD_FLAGS_FOR_BFD_USE_MASK \
> @@ -7271,6 +7275,7 @@ void bfd_update_compression_header
>
> bool bfd_check_compression_header
> (bfd *abfd, bfd_byte *contents, asection *sec,
> + unsigned int *ch_type,
> bfd_size_type *uncompressed_size,
> unsigned int *uncompressed_alignment_power);
>
> diff --git a/bfd/bfd.c b/bfd/bfd.c
> index 0a21db11fd6..5f2033bee7a 100644
> --- a/bfd/bfd.c
> +++ b/bfd/bfd.c
> @@ -177,12 +177,15 @@ CODE_FRAGMENT
> .#define BFD_ARCHIVE_FULL_PATH 0x100000
> .
> .#define BFD_CLOSED_BY_CACHE 0x200000
> +
> +. {* Compress sections in this BFD with SHF_COMPRESSED zstd. *}
> +.#define BFD_COMPRESS_ZSTD 0x400000
> .
> . {* Flags bits to be saved in bfd_preserve_save. *}
> .#define BFD_FLAGS_SAVED \
> . (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
> . | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
> -. | BFD_USE_ELF_STT_COMMON)
> +. | BFD_USE_ELF_STT_COMMON | BFD_COMPRESS_ZSTD)
> .
> . {* Flags bits which are for BFD use only. *}
> .#define BFD_FLAGS_FOR_BFD_USE_MASK \
> @@ -2500,6 +2503,9 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
> {
> const struct elf_backend_data *bed = get_elf_backend_data (abfd);
> struct bfd_elf_section_data * esd = elf_section_data (sec);
> + const unsigned int ch_type = abfd->flags & BFD_COMPRESS_ZSTD
> + ? ELFCOMPRESS_ZSTD
> + : ELFCOMPRESS_ZLIB;
>
> /* Set the SHF_COMPRESSED bit. */
> elf_section_flags (sec) |= SHF_COMPRESSED;
> @@ -2507,7 +2513,7 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
> if (bed->s->elfclass == ELFCLASS32)
> {
> Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
> - bfd_put_32 (abfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
> + bfd_put_32 (abfd, ch_type, &echdr->ch_type);
> bfd_put_32 (abfd, sec->size, &echdr->ch_size);
> bfd_put_32 (abfd, 1u << sec->alignment_power,
> &echdr->ch_addralign);
> @@ -2518,7 +2524,7 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
> else
> {
> Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
> - bfd_put_32 (abfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
> + bfd_put_32 (abfd, ch_type, &echdr->ch_type);
> bfd_put_32 (abfd, 0, &echdr->ch_reserved);
> bfd_put_64 (abfd, sec->size, &echdr->ch_size);
> bfd_put_64 (abfd, UINT64_C (1) << sec->alignment_power,
> @@ -2553,14 +2559,15 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents,
> SYNOPSIS
> bool bfd_check_compression_header
> (bfd *abfd, bfd_byte *contents, asection *sec,
> + unsigned int *ch_type,
> bfd_size_type *uncompressed_size,
> unsigned int *uncompressed_alignment_power);
>
> DESCRIPTION
> - Check the compression header at CONTENTS of SEC in ABFD and
> - store the uncompressed size in UNCOMPRESSED_SIZE and the
> - uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER
> - if the compression header is valid.
> + Check the compression header at CONTENTS of SEC in ABFD and store the
> + ch_type in CH_TYPE, uncompressed size in UNCOMPRESSED_SIZE, and the
> + uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER if the
> + compression header is valid.
>
> RETURNS
> Return TRUE if the compression header is valid.
> @@ -2569,6 +2576,7 @@ RETURNS
> bool
> bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
> asection *sec,
> + unsigned int *ch_type,
> bfd_size_type *uncompressed_size,
> unsigned int *uncompressed_alignment_power)
> {
> @@ -2591,7 +2599,9 @@ bfd_check_compression_header (bfd *abfd, bfd_byte *contents,
> chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size);
> chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign);
> }
> - if (chdr.ch_type == ELFCOMPRESS_ZLIB
> + *ch_type = chdr.ch_type;
> + if ((chdr.ch_type == ELFCOMPRESS_ZLIB
> + || chdr.ch_type == ELFCOMPRESS_ZSTD)
> && chdr.ch_addralign == (chdr.ch_addralign & -chdr.ch_addralign))
> {
> *uncompressed_size = chdr.ch_size;
> diff --git a/bfd/compress.c b/bfd/compress.c
> index b2e39826e38..95c1f4c42d1 100644
> --- a/bfd/compress.c
> +++ b/bfd/compress.c
> @@ -20,18 +20,31 @@
>
> #include "sysdep.h"
> #include <zlib.h>
> +#ifdef HAVE_ZSTD
> +#include <zstd.h>
> +#endif
> #include "bfd.h"
> +#include "elf-bfd.h"
> #include "libbfd.h"
> #include "safe-ctype.h"
>
> #define MAX_COMPRESSION_HEADER_SIZE 24
>
> static bool
> -decompress_contents (bfd_byte *compressed_buffer,
> +decompress_contents (bool is_zstd, bfd_byte *compressed_buffer,
> bfd_size_type compressed_size,
> bfd_byte *uncompressed_buffer,
> bfd_size_type uncompressed_size)
> {
> + if (is_zstd)
> + {
> +#ifdef HAVE_ZSTD
> + size_t ret = ZSTD_decompress (uncompressed_buffer, uncompressed_size,
> + compressed_buffer, compressed_size);
> + return !ZSTD_isError (ret);
> +#endif
> + }
> +
> z_stream strm;
> int rc;
>
> @@ -69,7 +82,7 @@ decompress_contents (bfd_byte *compressed_buffer,
> }
>
> /* Compress data of the size specified in @var{uncompressed_size}
> - and pointed to by @var{uncompressed_buffer} using zlib and store
> + and pointed to by @var{uncompressed_buffer} using zlib/zstd and store
> as the contents field. This function assumes the contents
> field was allocated using bfd_malloc() or equivalent.
>
> @@ -150,9 +163,10 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
> sec->size = orig_uncompressed_size;
> if (decompress)
> {
> - if (!decompress_contents (uncompressed_buffer
> - + orig_compression_header_size,
> - zlib_size, buffer, buffer_size))
> + if (!decompress_contents (
> + sec->compress_status == DECOMPRESS_SECTION_ZSTD,
> + uncompressed_buffer + orig_compression_header_size,
> + zlib_size, buffer, buffer_size))
> {
> bfd_set_error (bfd_error_bad_value);
> bfd_release (abfd, buffer);
> @@ -175,10 +189,23 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec,
> }
> else
> {
> - if (compress ((Bytef*) buffer + header_size,
> - &compressed_size,
> - (const Bytef*) uncompressed_buffer,
> - uncompressed_size) != Z_OK)
> + if (abfd->flags & BFD_COMPRESS_ZSTD)
> + {
> +#if HAVE_ZSTD
> + compressed_size = ZSTD_compress (
> + buffer + header_size, compressed_size, uncompressed_buffer,
> + uncompressed_size, ZSTD_CLEVEL_DEFAULT);
> + if (ZSTD_isError (compressed_size))
> + {
> + bfd_release (abfd, buffer);
> + bfd_set_error (bfd_error_bad_value);
> + return 0;
> + }
> +#endif
> + }
> + else if (compress ((Bytef *)buffer + header_size, &compressed_size,
> + (const Bytef *)uncompressed_buffer, uncompressed_size)
> + != Z_OK)
> {
> bfd_release (abfd, buffer);
> bfd_set_error (bfd_error_bad_value);
> @@ -237,6 +264,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
> bfd_size_type save_rawsize;
> bfd_byte *compressed_buffer;
> unsigned int compression_header_size;
> + const unsigned int compress_status = sec->compress_status;
>
> if (abfd->direction != write_direction && sec->rawsize != 0)
> sz = sec->rawsize;
> @@ -248,7 +276,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
> return true;
> }
>
> - switch (sec->compress_status)
> + switch (compress_status)
> {
> case COMPRESS_SECTION_NONE:
> if (p == NULL)
> @@ -298,7 +326,8 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
> *ptr = p;
> return true;
>
> - case DECOMPRESS_SECTION_SIZED:
> + case DECOMPRESS_SECTION_ZLIB:
> + case DECOMPRESS_SECTION_ZSTD:
> /* Read in the full compressed section contents. */
> compressed_buffer = (bfd_byte *) bfd_malloc (sec->compressed_size);
> if (compressed_buffer == NULL)
> @@ -316,7 +345,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
> /* Restore rawsize and size. */
> sec->rawsize = save_rawsize;
> sec->size = save_size;
> - sec->compress_status = DECOMPRESS_SECTION_SIZED;
> + sec->compress_status = compress_status;
> if (!ret)
> goto fail_compressed;
>
> @@ -330,8 +359,10 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr)
> /* Set header size to the zlib header size if it is a
> SHF_COMPRESSED section. */
> compression_header_size = 12;
> - if (!decompress_contents (compressed_buffer + compression_header_size,
> - sec->compressed_size - compression_header_size, p, sz))
> + if (!decompress_contents (compress_status == DECOMPRESS_SECTION_ZSTD,
> + compressed_buffer + compression_header_size,
> + sec->compressed_size - compression_header_size,
> + p, sz))
> {
> bfd_set_error (bfd_error_bad_value);
> if (p != *ptr)
> @@ -381,7 +412,8 @@ DESCRIPTION
> void
> bfd_cache_section_contents (asection *sec, void *contents)
> {
> - if (sec->compress_status == DECOMPRESS_SECTION_SIZED)
> + if (sec->compress_status == DECOMPRESS_SECTION_ZLIB
> + || sec->compress_status == DECOMPRESS_SECTION_ZSTD)
> sec->compress_status = COMPRESS_SECTION_DONE;
> sec->contents = contents;
> sec->flags |= SEC_IN_MEMORY;
> @@ -418,6 +450,7 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec,
> int compression_header_size;
> int header_size;
> unsigned int saved = sec->compress_status;
> + unsigned int ch_type;
> bool compressed;
>
> *uncompressed_align_pow_p = 0;
> @@ -448,7 +481,7 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec,
> {
> if (compression_header_size != 0)
> {
> - if (!bfd_check_compression_header (abfd, header, sec,
> + if (!bfd_check_compression_header (abfd, header, sec, &ch_type,
> uncompressed_size_p,
> uncompressed_align_pow_p))
> compression_header_size = -1;
> @@ -507,7 +540,7 @@ SYNOPSIS
> DESCRIPTION
> Record compressed section size, update section size with
> decompressed size and set compress_status to
> - DECOMPRESS_SECTION_SIZED.
> + DECOMPRESS_SECTION_{ZLIB,ZSTD}.
>
> Return @code{FALSE} if the section is not a valid compressed
> section. Otherwise, return @code{TRUE}.
> @@ -521,6 +554,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
> int header_size;
> bfd_size_type uncompressed_size;
> unsigned int uncompressed_alignment_power = 0;
> + unsigned int ch_type;
> z_stream strm;
>
> compression_header_size = bfd_get_compression_header_size (abfd, sec);
> @@ -550,6 +584,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
> uncompressed_size = bfd_getb64 (header + 4);
> }
> else if (!bfd_check_compression_header (abfd, header, sec,
> + &ch_type,
> &uncompressed_size,
> &uncompressed_alignment_power))
> {
> @@ -569,7 +604,8 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec)
> sec->compressed_size = sec->size;
> sec->size = uncompressed_size;
> bfd_set_section_alignment (sec, uncompressed_alignment_power);
> - sec->compress_status = DECOMPRESS_SECTION_SIZED;
> + sec->compress_status = ch_type == ELFCOMPRESS_ZSTD ? DECOMPRESS_SECTION_ZSTD
> + : DECOMPRESS_SECTION_ZLIB;
>
> return true;
> }
> diff --git a/bfd/config.in b/bfd/config.in
> index f54a3cacbea..a59304e0a66 100644
> --- a/bfd/config.in
> +++ b/bfd/config.in
> @@ -232,6 +232,9 @@
> /* Define to 1 if you have the <windows.h> header file. */
> #undef HAVE_WINDOWS_H
>
> +/* Define to 1 if zstd is enabled. */
> +#undef HAVE_ZSTD
> +
> /* Define to the sub-directory in which libtool stores uninstalled libraries.
> */
> #undef LT_OBJDIR
> diff --git a/bfd/configure b/bfd/configure
> index 075d2ee0a1b..d905a7bf7a8 100755
> --- a/bfd/configure
> +++ b/bfd/configure
> @@ -652,6 +652,11 @@ TDEFINES
> SHARED_LIBADD
> SHARED_LDFLAGS
> LIBM
> +ZSTD_LIBS
> +ZSTD_CFLAGS
> +PKG_CONFIG_LIBDIR
> +PKG_CONFIG_PATH
> +PKG_CONFIG
> zlibinc
> zlibdir
> EXEEXT_FOR_BUILD
> @@ -839,6 +844,7 @@ enable_maintainer_mode
> enable_install_libbfd
> enable_nls
> with_system_zlib
> +with_zstd
> '
> ac_precious_vars='build_alias
> host_alias
> @@ -848,7 +854,12 @@ CFLAGS
> LDFLAGS
> LIBS
> CPPFLAGS
> -CPP'
> +CPP
> +PKG_CONFIG
> +PKG_CONFIG_PATH
> +PKG_CONFIG_LIBDIR
> +ZSTD_CFLAGS
> +ZSTD_LIBS'
>
>
> # Initialize some variables set by options.
> @@ -1511,6 +1522,8 @@ Optional Packages:
> Binutils"
> --with-bugurl=URL Direct users to URL to report a bug
> --with-system-zlib use installed libz
> + --with-zstd support zstd compressed debug sections
> + (default=auto)
>
> Some influential environment variables:
> CC C compiler command
> @@ -1521,6 +1534,13 @@ Some influential environment variables:
> CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
> you have headers in a nonstandard directory <include dir>
> CPP C preprocessor
> + PKG_CONFIG path to pkg-config utility
> + PKG_CONFIG_PATH
> + directories to add to pkg-config's search path
> + PKG_CONFIG_LIBDIR
> + path overriding pkg-config's built-in search path
> + ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
> + ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
>
> Use these variables to override the choices made by `configure' or to help
> it to find libraries and programs with nonstandard names/locations.
> @@ -11086,7 +11106,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 11089 "configure"
> +#line 11109 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -11192,7 +11212,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 11195 "configure"
> +#line 11215 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -12995,7 +13015,7 @@ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
> ;;
> esac
>
> -# Link in zlib if we can. This allows us to read compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to read compressed debug sections.
> # This is used only by compress.c.
>
> # Use the system's zlib library.
> @@ -13015,6 +13035,246 @@ fi
>
>
>
> +
> +
> +
> +
> +
> +
> +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
> + if test -n "$ac_tool_prefix"; then
> + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
> +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +PKG_CONFIG=$ac_cv_path_PKG_CONFIG
> +if test -n "$PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
> +$as_echo "$PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> +
> +fi
> +if test -z "$ac_cv_path_PKG_CONFIG"; then
> + ac_pt_PKG_CONFIG=$PKG_CONFIG
> + # Extract the first word of "pkg-config", so it can be a program name with args.
> +set dummy pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $ac_pt_PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
> +if test -n "$ac_pt_PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
> +$as_echo "$ac_pt_PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> + if test "x$ac_pt_PKG_CONFIG" = x; then
> + PKG_CONFIG=""
> + else
> + case $cross_compiling:$ac_tool_warned in
> +yes:)
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
> +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
> +ac_tool_warned=yes ;;
> +esac
> + PKG_CONFIG=$ac_pt_PKG_CONFIG
> + fi
> +else
> + PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
> +fi
> +
> +fi
> +if test -n "$PKG_CONFIG"; then
> + _pkg_min_version=0.9.0
> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
> +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
> + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> + else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> + PKG_CONFIG=""
> + fi
> +fi
> +
> +
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +else
> + with_zstd=auto
> +fi
> +
> +
> +if test "$with_zstd" != no; then
> +
> +pkg_failed=no
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzstd" >&5
> +$as_echo_n "checking for libzstd... " >&6; }
> +
> +if test -n "$ZSTD_CFLAGS"; then
> + pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +if test -n "$ZSTD_LIBS"; then
> + pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +
> +if test $pkg_failed = no; then
> + pkg_save_LDFLAGS="$LDFLAGS"
> + LDFLAGS="$LDFLAGS $pkg_cv_ZSTD_LIBS"
> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h. */
> +
> +int
> +main ()
> +{
> +
> + ;
> + return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +
> +else
> + pkg_failed=yes
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> + conftest$ac_exeext conftest.$ac_ext
> + LDFLAGS=$pkg_save_LDFLAGS
> +fi
> +
> +
> +
> +if test $pkg_failed = yes; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
> + _pkg_short_errors_supported=yes
> +else
> + _pkg_short_errors_supported=no
> +fi
> + if test $_pkg_short_errors_supported = yes; then
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzstd" 2>&1`
> + else
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzstd" 2>&1`
> + fi
> + # Put the nasty error message in config.log where it belongs
> + echo "$ZSTD_PKG_ERRORS" >&5
> +
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +elif test $pkg_failed = untried; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +else
> + ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
> + ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +
> +$as_echo "#define HAVE_ZSTD 1" >>confdefs.h
> +
> +
> +fi
> +fi
> +
> +
> save_CFLAGS="$CFLAGS"
> CFLAGS="$CFLAGS -Werror"
> { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler support for hidden visibility" >&5
> diff --git a/bfd/configure.ac b/bfd/configure.ac
> index 28f3d1afce6..d1b2f76b31a 100644
> --- a/bfd/configure.ac
> +++ b/bfd/configure.ac
> @@ -230,9 +230,10 @@ AC_CHECK_DECLS([basename, ffs, stpcpy, asprintf, vasprintf, strnlen])
>
> BFD_BINARY_FOPEN
>
> -# Link in zlib if we can. This allows us to read compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to read compressed debug sections.
> # This is used only by compress.c.
> AM_ZLIB
> +AM_ZSTD
>
> save_CFLAGS="$CFLAGS"
> CFLAGS="$CFLAGS -Werror"
> diff --git a/bfd/elf.c b/bfd/elf.c
> index 16cea4f8aeb..e52fa458a5a 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -1260,6 +1260,18 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
> abfd, name);
> return false;
> }
> +#ifndef HAVE_ZSTD
> + if (newsect->compress_status == DECOMPRESS_SECTION_ZSTD)
> + {
> + _bfd_error_handler
> + /* xgettext:c-format */
> + (_ ("%pB: section %s is compressed with zstd, but BFD "
> + "is not built with zstd support"),
> + abfd, name);
> + newsect->compress_status = COMPRESS_SECTION_NONE;
> + return false;
> + }
> +#endif
> }
>
> if (abfd->is_linker_input)
> diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
> index feaba84bf2e..ca600bb5ddf 100644
> --- a/bfd/elfxx-target.h
> +++ b/bfd/elfxx-target.h
> @@ -989,7 +989,8 @@ const bfd_target TARGET_BIG_SYM =
> /* object_flags: mask of all file flags */
> (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
> | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS
> - | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON),
> + | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD | BFD_CONVERT_ELF_COMMON
> + | BFD_USE_ELF_STT_COMMON),
>
> /* section_flags: mask of all section flags */
> (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
> @@ -1093,7 +1094,8 @@ const bfd_target TARGET_LITTLE_SYM =
> /* object_flags: mask of all file flags */
> (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
> | DYNAMIC | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS
> - | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON),
> + | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD | BFD_CONVERT_ELF_COMMON
> + | BFD_USE_ELF_STT_COMMON),
>
> /* section_flags: mask of all section flags */
> (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY
> diff --git a/bfd/section.c b/bfd/section.c
> index c7a02d729f2..614570e976e 100644
> --- a/bfd/section.c
> +++ b/bfd/section.c
> @@ -392,7 +392,8 @@ CODE_FRAGMENT
> . unsigned int compress_status : 2;
> .#define COMPRESS_SECTION_NONE 0
> .#define COMPRESS_SECTION_DONE 1
> -.#define DECOMPRESS_SECTION_SIZED 2
> +.#define DECOMPRESS_SECTION_ZLIB 2
> +.#define DECOMPRESS_SECTION_ZSTD 3
> .
> . {* The following flags are used by the ELF linker. *}
> .
> diff --git a/binutils/Makefile.in b/binutils/Makefile.in
> index 78d32b350e3..6de4e239408 100644
> --- a/binutils/Makefile.in
> +++ b/binutils/Makefile.in
> @@ -156,7 +156,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
> $(top_srcdir)/../config/plugins.m4 \
> $(top_srcdir)/../config/po.m4 \
> $(top_srcdir)/../config/progtest.m4 \
> - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
> + $(top_srcdir)/../config/zlib.m4 \
> + $(top_srcdir)/../config/zstd.m4 $(top_srcdir)/../libtool.m4 \
> $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
> $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
> $(top_srcdir)/../bfd/version.m4 \
> @@ -575,6 +576,8 @@ WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@
> XGETTEXT = @XGETTEXT@
> YACC = `if [ -f ../bison/bison ]; then echo ../bison/bison -y -L$(srcdir)/../bison/; else echo @YACC@; fi`
> YFLAGS = -d
> +ZSTD_CFLAGS = @ZSTD_CFLAGS@
> +ZSTD_LIBS = @ZSTD_LIBS@
> abs_builddir = @abs_builddir@
> abs_srcdir = @abs_srcdir@
> abs_top_builddir = @abs_top_builddir@
> diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4
> index a877fa7f873..28271f56279 100644
> --- a/binutils/aclocal.m4
> +++ b/binutils/aclocal.m4
> @@ -1205,6 +1205,7 @@ m4_include([../config/plugins.m4])
> m4_include([../config/po.m4])
> m4_include([../config/progtest.m4])
> m4_include([../config/zlib.m4])
> +m4_include([../config/zstd.m4])
> m4_include([../libtool.m4])
> m4_include([../ltoptions.m4])
> m4_include([../ltsugar.m4])
> diff --git a/binutils/config.in b/binutils/config.in
> index c5fb919aa95..bee8c07e2f7 100644
> --- a/binutils/config.in
> +++ b/binutils/config.in
> @@ -157,6 +157,9 @@
> /* Define to 1 if you have the <windows.h> header file. */
> #undef HAVE_WINDOWS_H
>
> +/* Define to 1 if zstd is enabled. */
> +#undef HAVE_ZSTD
> +
> /* Define as const if the declaration of iconv() needs const. */
> #undef ICONV_CONST
>
> diff --git a/binutils/configure b/binutils/configure
> index 1c518227f57..54d0f184da1 100755
> --- a/binutils/configure
> +++ b/binutils/configure
> @@ -650,6 +650,8 @@ LTLIBICONV
> LIBICONV
> MSGPACK_LIBS
> MSGPACK_CFLAGS
> +ZSTD_LIBS
> +ZSTD_CFLAGS
> zlibinc
> zlibdir
> DEMANGLER_NAME
> @@ -832,6 +834,7 @@ enable_build_warnings
> enable_nls
> enable_maintainer_mode
> with_system_zlib
> +with_zstd
> with_msgpack
> enable_rpath
> with_libiconv_prefix
> @@ -853,6 +856,8 @@ DEBUGINFOD_CFLAGS
> DEBUGINFOD_LIBS
> YACC
> YFLAGS
> +ZSTD_CFLAGS
> +ZSTD_LIBS
> MSGPACK_CFLAGS
> MSGPACK_LIBS'
>
> @@ -1517,6 +1522,8 @@ Optional Packages:
> --with-debuginfod Enable debuginfo lookups with debuginfod
> (auto/yes/no)
> --with-system-zlib use installed libz
> + --with-zstd support zstd compressed debug sections
> + (default=auto)
> --with-msgpack Enable msgpack support (auto/yes/no)
> --with-gnu-ld assume the C compiler uses GNU ld default=no
> --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
> @@ -1547,6 +1554,8 @@ Some influential environment variables:
> YFLAGS The list of arguments that will be passed by default to $YACC.
> This script will default YFLAGS to the empty string to avoid a
> default value of `-d' given by some make applications.
> + ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
> + ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
> MSGPACK_CFLAGS
> C compiler flags for MSGPACK, overriding pkg-config
> MSGPACK_LIBS
> @@ -10804,7 +10813,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 10807 "configure"
> +#line 10816 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -10910,7 +10919,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 10913 "configure"
> +#line 10922 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -13468,7 +13477,7 @@ cat >>confdefs.h <<_ACEOF
> _ACEOF
>
>
> -# Link in zlib if we can. This allows us to read compressed debug
> +# Link in zlib/zstd if we can. This allows us to read compressed debug
> # sections. This is used only by readelf.c (objdump uses bfd for
> # reading compressed sections).
>
> @@ -13490,6 +13499,126 @@ fi
>
>
>
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +else
> + with_zstd=auto
> +fi
> +
> +
> +if test "$with_zstd" != no; then
> +
> +pkg_failed=no
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzstd" >&5
> +$as_echo_n "checking for libzstd... " >&6; }
> +
> +if test -n "$ZSTD_CFLAGS"; then
> + pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +if test -n "$ZSTD_LIBS"; then
> + pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +
> +if test $pkg_failed = no; then
> + pkg_save_LDFLAGS="$LDFLAGS"
> + LDFLAGS="$LDFLAGS $pkg_cv_ZSTD_LIBS"
> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h. */
> +
> +int
> +main ()
> +{
> +
> + ;
> + return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +
> +else
> + pkg_failed=yes
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> + conftest$ac_exeext conftest.$ac_ext
> + LDFLAGS=$pkg_save_LDFLAGS
> +fi
> +
> +
> +
> +if test $pkg_failed = yes; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
> + _pkg_short_errors_supported=yes
> +else
> + _pkg_short_errors_supported=no
> +fi
> + if test $_pkg_short_errors_supported = yes; then
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzstd" 2>&1`
> + else
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzstd" 2>&1`
> + fi
> + # Put the nasty error message in config.log where it belongs
> + echo "$ZSTD_PKG_ERRORS" >&5
> +
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +elif test $pkg_failed = untried; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +else
> + ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
> + ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +
> +$as_echo "#define HAVE_ZSTD 1" >>confdefs.h
> +
> +
> +fi
> +fi
> +
> +
> +
> case "${host}" in
> *-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*)
>
> diff --git a/binutils/configure.ac b/binutils/configure.ac
> index ec002d3f88f..c152b7f6733 100644
> --- a/binutils/configure.ac
> +++ b/binutils/configure.ac
> @@ -265,10 +265,11 @@ fi
>
> AC_CHECK_DECLS([asprintf, environ, getc_unlocked, stpcpy, strnlen])
>
> -# Link in zlib if we can. This allows us to read compressed debug
> +# Link in zlib/zstd if we can. This allows us to read compressed debug
> # sections. This is used only by readelf.c (objdump uses bfd for
> # reading compressed sections).
> AM_ZLIB
> +AM_ZSTD
>
> BFD_BINARY_FOPEN
>
> diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
> index 1499db5728c..34a4164eb94 100644
> --- a/binutils/doc/binutils.texi
> +++ b/binutils/doc/binutils.texi
> @@ -2159,21 +2159,23 @@ ELF ABI. Note - if compression would actually make a section
> @itemx --compress-debug-sections=zlib
> @itemx --compress-debug-sections=zlib-gnu
> @itemx --compress-debug-sections=zlib-gabi
> +@itemx --compress-debug-sections=zstd
> For ELF files, these options control how DWARF debug sections are
> compressed. @option{--compress-debug-sections=none} is equivalent
> to @option{--decompress-debug-sections}.
> @option{--compress-debug-sections=zlib} and
> @option{--compress-debug-sections=zlib-gabi} are equivalent to
> @option{--compress-debug-sections}.
> -@option{--compress-debug-sections=zlib-gnu} compresses DWARF debug
> -sections using zlib. The debug sections are renamed to begin with
> -@samp{.zdebug} instead of @samp{.debug}. Note - if compression would
> -actually make a section @emph{larger}, then it is not compressed nor
> -renamed.
> +@option{--compress-debug-sections=zlib-gnu} compresses DWARF debug sections
> +using the obsoleted zlib-gnu format. The debug sections are renamed to begin
> +with @samp{.zdebug}.
> +@option{--compress-debug-sections=zstd} compresses DWARF debug
> +sections using zstd. Note - if compression would actually make a section
> +@emph{larger}, then it is not compressed nor renamed.
>
> @item --decompress-debug-sections
> -Decompress DWARF debug sections using zlib. The original section
> -names of the compressed sections are restored.
> +Decompress DWARF debug sections. For a @samp{.zdebug} section, the original
> +name is restored.
>
> @item --elf-stt-common=yes
> @itemx --elf-stt-common=no
> diff --git a/binutils/objcopy.c b/binutils/objcopy.c
> index 43261756a42..fc668f00bbc 100644
> --- a/binutils/objcopy.c
> +++ b/binutils/objcopy.c
> @@ -232,7 +232,8 @@ static enum
> compress_zlib = compress | 1 << 1,
> compress_gnu_zlib = compress | 1 << 2,
> compress_gabi_zlib = compress | 1 << 3,
> - decompress = 1 << 4
> + compress_zstd = compress | 1 << 4,
> + decompress = 1 << 5
> } do_debug_sections = nothing;
>
> /* Whether to generate ELF common symbols with the STT_COMMON type. */
> @@ -678,8 +679,8 @@ copy_usage (FILE *stream, int exit_status)
> <commit>\n\
> --subsystem <name>[:<version>]\n\
> Set PE subsystem to <name> [& <version>]\n\
> - --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
> - Compress DWARF debug sections using zlib\n\
> + --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi|zstd}]\n\
> + Compress DWARF debug sections\n\
> --decompress-debug-sections Decompress DWARF debug sections using zlib\n\
> --elf-stt-common=[yes|no] Generate ELF common symbols with STT_COMMON\n\
> type\n\
> @@ -2659,7 +2660,8 @@ copy_object (bfd *ibfd, bfd *obfd, const bfd_arch_info_type *input_arch)
> if ((do_debug_sections & compress) != 0
> && do_debug_sections != compress)
> {
> - non_fatal (_("--compress-debug-sections=[zlib|zlib-gnu|zlib-gabi] is unsupported on `%s'"),
> + non_fatal (_ ("--compress-debug-sections=[zlib|zlib-gnu|zlib-gabi|"
> + "zstd] is unsupported on `%s'"),
> bfd_get_archive_filename (ibfd));
> return false;
> }
> @@ -3807,6 +3809,13 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
> if (do_debug_sections != compress_gnu_zlib)
> ibfd->flags |= BFD_COMPRESS_GABI;
> break;
> + case compress_zstd:
> + ibfd->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD;
> +#ifndef HAVE_ZSTD
> + fatal (_ ("--compress-debug-sections=zstd: binutils is not built with "
> + "zstd support"));
> +#endif
> + break;
> case decompress:
> ibfd->flags |= BFD_DECOMPRESS;
> break;
> @@ -5469,6 +5478,8 @@ copy_main (int argc, char *argv[])
> do_debug_sections = compress_gnu_zlib;
> else if (strcasecmp (optarg, "zlib-gabi") == 0)
> do_debug_sections = compress_gabi_zlib;
> + else if (strcasecmp (optarg, "zstd") == 0)
> + do_debug_sections = compress_zstd;
> else
> fatal (_("unrecognized --compress-debug-sections type `%s'"),
> optarg);
> diff --git a/binutils/testsuite/binutils-all/compress.exp b/binutils/testsuite/binutils-all/compress.exp
> index c88da74a987..4e74c824664 100644
> --- a/binutils/testsuite/binutils-all/compress.exp
> +++ b/binutils/testsuite/binutils-all/compress.exp
> @@ -576,6 +576,50 @@ if { [regexp_diff objdump.out $srcdir/$subdir/dw2-3gabi.W] } then {
> pass "$testname"
> }
>
> +if { [binutils_assemble_flags $srcdir/$subdir/dw2-1.S ${compressedfile}zstd.o --compress-debug-sections=zstd] } then {
> + set testname "objcopy compress debug sections with zstd"
> + set got [binutils_run $OBJCOPY "--compress-debug-sections=zstd ${testfile}.o ${copyfile}zstd.o"]
> + if ![string match "" $got] then {
> + fail "objcopy ($testname)"
> + return
> + }
> + send_log "cmp ${compressedfile}zstd.o ${copyfile}zstd.o\n"
> + verbose "cmp ${compressedfile}zstd.o ${copyfile}zstd.o"
> + set src1 ${compressedfile}zstd.o
> + set src2 ${copyfile}zstd.o
> + set status [remote_exec build cmp "${src1} ${src2}"]
> + set exec_output [lindex $status 1]
> + set exec_output [prune_warnings $exec_output]
> + if ![string match "" $exec_output] then {
> + send_log "$exec_output\n"
> + verbose "$exec_output" 1
> + fail "objcopy ($testname)"
> + } else {
> + pass "objcopy ($testname)"
> + }
> +
> + set testname "objcopy decompress compressed debug sections with zstd"
> + set got [binutils_run $OBJCOPY "--decompress-debug-sections ${compressedfile}zstd.o ${copyfile}zstd.o"]
> + if ![string match "" $got] then {
> + fail "objcopy ($testname)"
> + return
> + }
> + send_log "cmp ${testfile}.o ${copyfile}zstd.o\n"
> + verbose "cmp ${testfile}.o ${copyfile}zstd.o"
> + set src1 ${testfile}.o
> + set src2 ${copyfile}zstd.o
> + set status [remote_exec build cmp "${src1} ${src2}"]
> + set exec_output [lindex $status 1]
> + set exec_output [prune_warnings $exec_output]
> + if ![string match "" $exec_output] then {
> + send_log "$exec_output\n"
> + verbose "$exec_output" 1
> + fail "objcopy ($testname)"
> + } else {
> + pass "objcopy ($testname)"
> + }
> +}
> +
> proc convert_test { testname as_flags objcop_flags } {
> global srcdir
> global subdir
> diff --git a/config/zstd.m4 b/config/zstd.m4
> new file mode 100644
> index 00000000000..93ae17b89d3
> --- /dev/null
> +++ b/config/zstd.m4
> @@ -0,0 +1,24 @@
> +dnl Copyright (C) 2022 Free Software Foundation, Inc.
> +dnl This file is free software, distributed under the terms of the GNU
> +dnl General Public License. As a special exception to the GNU General
> +dnl Public License, this file may be distributed as part of a program
> +dnl that contains a configuration script generated by Autoconf, under
> +dnl the same distribution terms as the rest of that program.
> +
> +dnl Enable features using the zstd library.
> +AC_DEFUN([AM_ZSTD],
> +[
> +AC_ARG_WITH(zstd,
> + [AS_HELP_STRING([--with-zstd], [support zstd compressed debug sections (default=auto)])],
> + [], [with_zstd=auto])
> +
> +if test "$with_zstd" != no; then
> + PKG_CHECK_MODULES(ZSTD, [libzstd], [
> + AC_DEFINE(HAVE_ZSTD, 1, [Define to 1 if zstd is enabled.])
> + ], [
> + if test "$with_zstd" = yes; then
> + AC_MSG_ERROR([--with-zstd was given, but pkgconfig/libzstd.pc is not found])
> + fi
> + ])
> +fi
> +])
> diff --git a/configure b/configure
> index d75f47a1e95..f14e0efd675 100755
> --- a/configure
> +++ b/configure
> @@ -785,6 +785,7 @@ ac_user_opts='
> enable_option_checking
> with_build_libsubdir
> with_system_zlib
> +with_zstd
> enable_as_accelerator_for
> enable_offload_targets
> enable_gold
> @@ -1567,6 +1568,8 @@ Optional Packages:
> --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
> --with-build-libsubdir=DIR Directory where to find libraries for build system
> --with-system-zlib use installed libz
> + --with-zstd Support zstd compressed debug sections
> + (default=auto)
> --with-mpc=PATH specify prefix directory for installed MPC package.
> Equivalent to --with-mpc-include=PATH/include plus
> --with-mpc-lib=PATH/lib
> @@ -2925,6 +2928,13 @@ if test x$with_system_zlib = xyes ; then
> noconfigdirs="$noconfigdirs zlib"
> fi
>
> +
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +fi
> +
> +
> # Don't compile the bundled readline/libreadline.a if --with-system-readline
> # is provided.
> if test x$with_system_readline = xyes ; then
> diff --git a/configure.ac b/configure.ac
> index ae18d436aca..0152c69292e 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -246,6 +246,9 @@ if test x$with_system_zlib = xyes ; then
> noconfigdirs="$noconfigdirs zlib"
> fi
>
> +AC_ARG_WITH(zstd,
> +[AS_HELP_STRING([--with-zstd], [Support zstd compressed debug sections (default=auto)])])
> +
> # Don't compile the bundled readline/libreadline.a if --with-system-readline
> # is provided.
> if test x$with_system_readline = xyes ; then
> diff --git a/gas/Makefile.am b/gas/Makefile.am
> index bd597398671..5f0f24abf8d 100644
> --- a/gas/Makefile.am
> +++ b/gas/Makefile.am
> @@ -42,7 +42,7 @@ am__skipyacc =
>
> WARN_CFLAGS = @WARN_CFLAGS@ @WARN_WRITE_STRINGS@
> NO_WERROR = @NO_WERROR@
> -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
>
> TARG_CPU = @target_cpu_type@
> TARG_CPU_C = $(srcdir)/config/tc-@target_cpu_type@.c
> @@ -407,7 +407,7 @@ STAGESTUFF = *.@OBJEXT@ $(noinst_PROGRAMS)
>
> as_new_SOURCES = $(GAS_CFILES)
> as_new_LDADD = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
> - $(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM) $(ZLIB)
> + $(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM) $(ZLIB) $(ZSTD_LIBS)
> as_new_DEPENDENCIES = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
> $(extra_objects) $(GASLIBS) $(LIBINTL_DEP)
> EXTRA_as_new_SOURCES = $(CFILES) $(HFILES) $(TARGET_CPU_CFILES) \
> diff --git a/gas/Makefile.in b/gas/Makefile.in
> index c57d78f82c4..5a4dd702252 100644
> --- a/gas/Makefile.in
> +++ b/gas/Makefile.in
> @@ -140,10 +140,12 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
> $(top_srcdir)/../config/lead-dot.m4 \
> $(top_srcdir)/../config/nls.m4 \
> $(top_srcdir)/../config/override.m4 \
> + $(top_srcdir)/../config/pkg.m4 \
> $(top_srcdir)/../config/plugins.m4 \
> $(top_srcdir)/../config/po.m4 \
> $(top_srcdir)/../config/progtest.m4 \
> - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
> + $(top_srcdir)/../config/zlib.m4 \
> + $(top_srcdir)/../config/zstd.m4 $(top_srcdir)/../libtool.m4 \
> $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
> $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
> $(top_srcdir)/acinclude.m4 $(top_srcdir)/../bfd/version.m4 \
> @@ -429,6 +431,9 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
> PACKAGE_URL = @PACKAGE_URL@
> PACKAGE_VERSION = @PACKAGE_VERSION@
> PATH_SEPARATOR = @PATH_SEPARATOR@
> +PKG_CONFIG = @PKG_CONFIG@
> +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
> +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
> POSUB = @POSUB@
> RANLIB = @RANLIB@
> SED = @SED@
> @@ -443,6 +448,8 @@ WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@
> XGETTEXT = @XGETTEXT@
> YACC = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo @YACC@ ; fi`
> YFLAGS = @YFLAGS@
> +ZSTD_CFLAGS = @ZSTD_CFLAGS@
> +ZSTD_LIBS = @ZSTD_LIBS@
> abs_builddir = @abs_builddir@
> abs_srcdir = @abs_srcdir@
> abs_top_builddir = @abs_top_builddir@
> @@ -524,7 +531,7 @@ ZLIBINC = @zlibinc@
> # maintainer mode is disabled. Avoid this.
> am__skiplex =
> am__skipyacc =
> -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
> TARG_CPU = @target_cpu_type@
> TARG_CPU_C = $(srcdir)/config/tc-@target_cpu_type@.c
> TARG_CPU_O = config/tc-@target_cpu_type@.@OBJEXT@
> @@ -874,7 +881,7 @@ GASLIBS = @OPCODES_LIB@ ../bfd/libbfd.la ../libiberty/libiberty.a
> STAGESTUFF = *.@OBJEXT@ $(noinst_PROGRAMS)
> as_new_SOURCES = $(GAS_CFILES)
> as_new_LDADD = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
> - $(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM) $(ZLIB)
> + $(extra_objects) $(GASLIBS) $(LIBINTL) $(LIBM) $(ZLIB) $(ZSTD_LIBS)
>
> as_new_DEPENDENCIES = $(TARG_CPU_O) $(OBJ_FORMAT_O) $(ATOF_TARG_O) \
> $(extra_objects) $(GASLIBS) $(LIBINTL_DEP)
> diff --git a/gas/aclocal.m4 b/gas/aclocal.m4
> index 70183124da7..722030c776f 100644
> --- a/gas/aclocal.m4
> +++ b/gas/aclocal.m4
> @@ -1196,10 +1196,12 @@ m4_include([../config/lcmessage.m4])
> m4_include([../config/lead-dot.m4])
> m4_include([../config/nls.m4])
> m4_include([../config/override.m4])
> +m4_include([../config/pkg.m4])
> m4_include([../config/plugins.m4])
> m4_include([../config/po.m4])
> m4_include([../config/progtest.m4])
> m4_include([../config/zlib.m4])
> +m4_include([../config/zstd.m4])
> m4_include([../libtool.m4])
> m4_include([../ltoptions.m4])
> m4_include([../ltsugar.m4])
> diff --git a/gas/as.c b/gas/as.c
> index 6268779cf90..35ad6b3ab3b 100644
> --- a/gas/as.c
> +++ b/gas/as.c
> @@ -252,14 +252,14 @@ Options:\n\
> --alternate initially turn on alternate macro syntax\n"));
> #ifdef DEFAULT_FLAG_COMPRESS_DEBUG
> fprintf (stream, _("\
> - --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
> + --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi|zstd}]\n\
> compress DWARF debug sections using zlib [default]\n"));
> fprintf (stream, _("\
> --nocompress-debug-sections\n\
> don't compress DWARF debug sections\n"));
> #else
> fprintf (stream, _("\
> - --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi}]\n\
> + --compress-debug-sections[={none|zlib|zlib-gnu|zlib-gabi|zstd}]\n\
> compress DWARF debug sections using zlib\n"));
> fprintf (stream, _("\
> --nocompress-debug-sections\n\
> @@ -736,6 +736,15 @@ This program has absolutely no warranty.\n"));
> flag_compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
> else if (strcasecmp (optarg, "zlib-gabi") == 0)
> flag_compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
> + else if (strcasecmp (optarg, "zstd") == 0)
> + {
> +#ifdef HAVE_ZSTD
> + flag_compress_debug = COMPRESS_DEBUG_ZSTD;
> +#else
> + as_fatal (_ ("--compress-debug-sections=zstd: gas is not "
> + "built with zstd support"));
> +#endif
> + }
> else
> as_fatal (_("Invalid --compress-debug-sections option: `%s'"),
> optarg);
> diff --git a/gas/compress-debug.c b/gas/compress-debug.c
> index c80dbeec4e7..3cd175f6e57 100644
> --- a/gas/compress-debug.c
> +++ b/gas/compress-debug.c
> @@ -21,14 +21,23 @@
> #include "config.h"
> #include <stdio.h>
> #include <zlib.h>
> +#if HAVE_ZSTD
> +#include <zstd.h>
> +#endif
> #include "ansidecl.h"
> #include "compress-debug.h"
>
> /* Initialize the compression engine. */
>
> -struct z_stream_s *
> -compress_init (void)
> +void *
> +compress_init (bool use_zstd)
> {
> + if (use_zstd) {
> +#if HAVE_ZSTD
> + return ZSTD_createCCtx ();
> +#endif
> + }
> +
> static struct z_stream_s strm;
>
> strm.zalloc = NULL;
> @@ -42,22 +51,37 @@ compress_init (void)
> from the engine goes into the current frag on the obstack. */
>
> int
> -compress_data (struct z_stream_s *strm, const char **next_in,
> - int *avail_in, char **next_out, int *avail_out)
> +compress_data (bool use_zstd, void *ctx, const char **next_in, int *avail_in,
> + char **next_out, int *avail_out)
> {
> - int out_size = 0;
> - int x;
> + if (use_zstd)
> + {
> +#if HAVE_ZSTD
> + ZSTD_outBuffer ob = { *next_out, *avail_out, 0 };
> + ZSTD_inBuffer ib = { *next_in, *avail_in, 0 };
> + size_t ret = ZSTD_compressStream2 (ctx, &ob, &ib, ZSTD_e_continue);
> + *next_in += ib.pos;
> + *avail_in -= ib.pos;
> + *next_out += ob.pos;
> + *avail_out -= ob.pos;
> + if (ZSTD_isError (ret))
> + return -1;
> + return (int)ob.pos;
> +#endif
> + }
> +
> + struct z_stream_s *strm = ctx;
>
> strm->next_in = (Bytef *) (*next_in);
> strm->avail_in = *avail_in;
> strm->next_out = (Bytef *) (*next_out);
> strm->avail_out = *avail_out;
>
> - x = deflate (strm, Z_NO_FLUSH);
> + int x = deflate (strm, Z_NO_FLUSH);
> if (x != Z_OK)
> return -1;
>
> - out_size = *avail_out - strm->avail_out;
> + int out_size = *avail_out - strm->avail_out;
> *next_in = (char *) (strm->next_in);
> *avail_in = strm->avail_in;
> *next_out = (char *) (strm->next_out);
> @@ -71,10 +95,28 @@ compress_data (struct z_stream_s *strm, const char **next_in,
> needed. */
>
> int
> -compress_finish (struct z_stream_s *strm, char **next_out,
> +compress_finish (bool use_zstd, void *ctx, char **next_out,
> int *avail_out, int *out_size)
> {
> + if (use_zstd)
> + {
> +#if HAVE_ZSTD
> + ZSTD_outBuffer ob = { *next_out, *avail_out, 0 };
> + ZSTD_inBuffer ib = { 0 };
> + size_t ret = ZSTD_compressStream2 (ctx, &ob, &ib, ZSTD_e_end);
> + *out_size = ob.pos;
> + *next_out += ob.pos;
> + *avail_out -= ob.pos;
> + if (ZSTD_isError (ret))
> + return -1;
> + if (ret == 0)
> + ZSTD_freeCCtx (ctx);
> + return ret ? 1 : 0;
> +#endif
> + }
> +
> int x;
> + struct z_stream_s *strm = ctx;
>
> strm->avail_in = 0;
> strm->next_out = (Bytef *) (*next_out);
> diff --git a/gas/compress-debug.h b/gas/compress-debug.h
> index 0183e269fef..87de0f8444e 100644
> --- a/gas/compress-debug.h
> +++ b/gas/compress-debug.h
> @@ -21,19 +21,19 @@
> #ifndef COMPRESS_DEBUG_H
> #define COMPRESS_DEBUG_H
>
> +#include <stdbool.h>
> +
> struct z_stream_s;
>
> /* Initialize the compression engine. */
> -extern struct z_stream_s *
> -compress_init (void);
> +extern void *compress_init (bool);
>
> /* Stream the contents of a frag to the compression engine. Output
> from the engine goes into the current frag on the obstack. */
> -extern int
> -compress_data (struct z_stream_s *, const char **, int *, char **, int *);
> +extern int compress_data (bool, void *, const char **, int *, char **, int *);
>
> /* Finish the compression and consume the remaining compressed output. */
> extern int
> -compress_finish (struct z_stream_s *, char **, int *, int *);
> +compress_finish (bool, void *, char **, int *, int *);
>
> #endif /* COMPRESS_DEBUG_H */
> diff --git a/gas/config.in b/gas/config.in
> index e243fd277ee..0d1668a3eac 100644
> --- a/gas/config.in
> +++ b/gas/config.in
> @@ -134,6 +134,9 @@
> /* Define to 1 if you have the <windows.h> header file. */
> #undef HAVE_WINDOWS_H
>
> +/* Define to 1 if zstd is enabled. */
> +#undef HAVE_ZSTD
> +
> /* Using i386 COFF? */
> #undef I386COFF
>
> diff --git a/gas/configure b/gas/configure
> index d0449a1d7ab..1833adffaa8 100755
> --- a/gas/configure
> +++ b/gas/configure
> @@ -633,6 +633,11 @@ ac_subst_vars='am__EXEEXT_FALSE
> am__EXEEXT_TRUE
> LTLIBOBJS
> LIBOBJS
> +ZSTD_LIBS
> +ZSTD_CFLAGS
> +PKG_CONFIG_LIBDIR
> +PKG_CONFIG_PATH
> +PKG_CONFIG
> zlibinc
> zlibdir
> LIBM
> @@ -817,6 +822,7 @@ with_cpu
> enable_nls
> enable_maintainer_mode
> with_system_zlib
> +with_zstd
> '
> ac_precious_vars='build_alias
> host_alias
> @@ -828,7 +834,12 @@ LIBS
> CPPFLAGS
> CPP
> YACC
> -YFLAGS'
> +YFLAGS
> +PKG_CONFIG
> +PKG_CONFIG_PATH
> +PKG_CONFIG_LIBDIR
> +ZSTD_CFLAGS
> +ZSTD_LIBS'
>
>
> # Initialize some variables set by options.
> @@ -1493,6 +1504,8 @@ Optional Packages:
> --with-cpu=CPU default cpu variant is CPU (currently only supported
> on ARC)
> --with-system-zlib use installed libz
> + --with-zstd support zstd compressed debug sections
> + (default=auto)
>
> Some influential environment variables:
> CC C compiler command
> @@ -1509,6 +1522,13 @@ Some influential environment variables:
> YFLAGS The list of arguments that will be passed by default to $YACC.
> This script will default YFLAGS to the empty string to avoid a
> default value of `-d' given by some make applications.
> + PKG_CONFIG path to pkg-config utility
> + PKG_CONFIG_PATH
> + directories to add to pkg-config's search path
> + PKG_CONFIG_LIBDIR
> + path overriding pkg-config's built-in search path
> + ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
> + ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
>
> Use these variables to override the choices made by `configure' or to help
> it to find libraries and programs with nonstandard names/locations.
> @@ -10702,7 +10722,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 10705 "configure"
> +#line 10725 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -10808,7 +10828,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 10811 "configure"
> +#line 10831 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -13945,7 +13965,7 @@ $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h
> ;;
> esac
>
> -# Link in zlib if we can. This allows us to write compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to write compressed debug sections.
>
> # Use the system's zlib library.
> zlibdir="-L\$(top_builddir)/../zlib"
> @@ -13964,6 +13984,246 @@ fi
>
>
>
> +
> +
> +
> +
> +
> +
> +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
> + if test -n "$ac_tool_prefix"; then
> + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
> +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +PKG_CONFIG=$ac_cv_path_PKG_CONFIG
> +if test -n "$PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
> +$as_echo "$PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> +
> +fi
> +if test -z "$ac_cv_path_PKG_CONFIG"; then
> + ac_pt_PKG_CONFIG=$PKG_CONFIG
> + # Extract the first word of "pkg-config", so it can be a program name with args.
> +set dummy pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $ac_pt_PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
> +if test -n "$ac_pt_PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
> +$as_echo "$ac_pt_PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> + if test "x$ac_pt_PKG_CONFIG" = x; then
> + PKG_CONFIG=""
> + else
> + case $cross_compiling:$ac_tool_warned in
> +yes:)
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
> +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
> +ac_tool_warned=yes ;;
> +esac
> + PKG_CONFIG=$ac_pt_PKG_CONFIG
> + fi
> +else
> + PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
> +fi
> +
> +fi
> +if test -n "$PKG_CONFIG"; then
> + _pkg_min_version=0.9.0
> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
> +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
> + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> + else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> + PKG_CONFIG=""
> + fi
> +fi
> +
> +
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +else
> + with_zstd=auto
> +fi
> +
> +
> +if test "$with_zstd" != no; then
> +
> +pkg_failed=no
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzstd" >&5
> +$as_echo_n "checking for libzstd... " >&6; }
> +
> +if test -n "$ZSTD_CFLAGS"; then
> + pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +if test -n "$ZSTD_LIBS"; then
> + pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +
> +if test $pkg_failed = no; then
> + pkg_save_LDFLAGS="$LDFLAGS"
> + LDFLAGS="$LDFLAGS $pkg_cv_ZSTD_LIBS"
> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h. */
> +
> +int
> +main ()
> +{
> +
> + ;
> + return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +
> +else
> + pkg_failed=yes
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> + conftest$ac_exeext conftest.$ac_ext
> + LDFLAGS=$pkg_save_LDFLAGS
> +fi
> +
> +
> +
> +if test $pkg_failed = yes; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
> + _pkg_short_errors_supported=yes
> +else
> + _pkg_short_errors_supported=no
> +fi
> + if test $_pkg_short_errors_supported = yes; then
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzstd" 2>&1`
> + else
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzstd" 2>&1`
> + fi
> + # Put the nasty error message in config.log where it belongs
> + echo "$ZSTD_PKG_ERRORS" >&5
> +
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +elif test $pkg_failed = untried; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +else
> + ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
> + ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +
> +$as_echo "#define HAVE_ZSTD 1" >>confdefs.h
> +
> +
> +fi
> +fi
> +
> +
> # Support for VMS timestamps via cross compile
>
> if test "$ac_cv_header_time_h" = yes; then
> diff --git a/gas/configure.ac b/gas/configure.ac
> index 21795a82bdd..8750ea21381 100644
> --- a/gas/configure.ac
> +++ b/gas/configure.ac
> @@ -1004,8 +1004,9 @@ AC_CHECK_DECLS([asprintf, mempcpy, stpcpy])
>
> BFD_BINARY_FOPEN
>
> -# Link in zlib if we can. This allows us to write compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to write compressed debug sections.
> AM_ZLIB
> +AM_ZSTD
>
> # Support for VMS timestamps via cross compile
>
> diff --git a/gas/doc/as.texi b/gas/doc/as.texi
> index e915893da86..01f49434021 100644
> --- a/gas/doc/as.texi
> +++ b/gas/doc/as.texi
> @@ -711,16 +711,19 @@ given section @emph{larger} then it is not compressed.
> @itemx --compress-debug-sections=zlib
> @itemx --compress-debug-sections=zlib-gnu
> @itemx --compress-debug-sections=zlib-gabi
> +@itemx --compress-debug-sections=zstd
> These options control how DWARF debug sections are compressed.
> @option{--compress-debug-sections=none} is equivalent to
> @option{--nocompress-debug-sections}.
> @option{--compress-debug-sections=zlib} and
> @option{--compress-debug-sections=zlib-gabi} are equivalent to
> @option{--compress-debug-sections}.
> -@option{--compress-debug-sections=zlib-gnu} compresses DWARF debug
> -sections using zlib. The debug sections are renamed to begin with
> -@samp{.zdebug}. Note if compression would make a given section
> -@emph{larger} then it is not compressed nor renamed.
> +@option{--compress-debug-sections=zlib-gnu} compresses DWARF debug sections
> +using the obsoleted zlib-gnu format. The debug sections are renamed to begin
> +with @samp{.zdebug}.
> +@option{--compress-debug-sections=zstd} compresses DWARF debug
> +sections using zstd. Note - if compression would actually make a section
> +@emph{larger}, then it is not compressed nor renamed.
>
> @end ifset
>
> diff --git a/gas/write.c b/gas/write.c
> index f76bbdb706e..0e49df7c03f 100644
> --- a/gas/write.c
> +++ b/gas/write.c
> @@ -1413,7 +1413,7 @@ write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
> }
>
> static int
> -compress_frag (struct z_stream_s *strm, const char *contents, int in_size,
> +compress_frag (bool use_zstd, void *ctx, const char *contents, int in_size,
> fragS **last_newf, struct obstack *ob)
> {
> int out_size;
> @@ -1442,10 +1442,10 @@ compress_frag (struct z_stream_s *strm, const char *contents, int in_size,
> as_fatal (_("can't extend frag"));
> next_out = obstack_next_free (ob);
> obstack_blank_fast (ob, avail_out);
> - out_size = compress_data (strm, &contents, &in_size,
> - &next_out, &avail_out);
> + out_size = compress_data (use_zstd, ctx, &contents, &in_size, &next_out,
> + &avail_out);
> if (out_size < 0)
> - return -1;
> + return -1;
>
> f->fr_fix += out_size;
> total_out_size += out_size;
> @@ -1471,7 +1471,6 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
> const char *section_name;
> char *compressed_name;
> char *header;
> - struct z_stream_s *strm;
> int x;
> flagword flags = bfd_section_flags (sec);
> unsigned int header_size, compression_header_size;
> @@ -1485,21 +1484,22 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
> if (!startswith (section_name, ".debug_"))
> return;
>
> - strm = compress_init ();
> - if (strm == NULL)
> + bool use_zstd = abfd->flags & BFD_COMPRESS_ZSTD;
> + void *ctx = compress_init (use_zstd);
> + if (ctx == NULL)
> return;
>
> - if (flag_compress_debug == COMPRESS_DEBUG_GABI_ZLIB)
> + if (flag_compress_debug == COMPRESS_DEBUG_GNU_ZLIB)
> + {
> + compression_header_size = 0;
> + header_size = 12;
> + }
> + else
> {
> compression_header_size
> = bfd_get_compression_header_size (stdoutput, NULL);
> header_size = compression_header_size;
> }
> - else
> - {
> - compression_header_size = 0;
> - header_size = 12;
> - }
>
> /* Create a new frag to contain the compression header. */
> first_newf = frag_alloc (ob);
> @@ -1531,7 +1531,7 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
> gas_assert (f->fr_type == rs_fill);
> if (f->fr_fix)
> {
> - out_size = compress_frag (strm, f->fr_literal, f->fr_fix,
> + out_size = compress_frag (use_zstd, ctx, f->fr_literal, f->fr_fix,
> &last_newf, ob);
> if (out_size < 0)
> return;
> @@ -1545,8 +1545,8 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
> {
> while (count--)
> {
> - out_size = compress_frag (strm, fill_literal, (int) fill_size,
> - &last_newf, ob);
> + out_size = compress_frag (use_zstd, ctx, fill_literal,
> + (int)fill_size, &last_newf, ob);
> if (out_size < 0)
> return;
> compressed_size += out_size;
> @@ -1579,7 +1579,7 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
> as_fatal (_("can't extend frag"));
> next_out = obstack_next_free (ob);
> obstack_blank_fast (ob, avail_out);
> - x = compress_finish (strm, &next_out, &avail_out, &out_size);
> + x = compress_finish (use_zstd, ctx, &next_out, &avail_out, &out_size);
> if (x < 0)
> return;
>
> @@ -2540,6 +2540,8 @@ write_object_file (void)
> {
> if (flag_compress_debug == COMPRESS_DEBUG_GABI_ZLIB)
> stdoutput->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI;
> + else if (flag_compress_debug == COMPRESS_DEBUG_ZSTD)
> + stdoutput->flags |= BFD_COMPRESS | BFD_COMPRESS_GABI | BFD_COMPRESS_ZSTD;
> else
> stdoutput->flags |= BFD_COMPRESS;
> bfd_map_over_sections (stdoutput, compress_debug, (char *) 0);
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 2598b81d205..c528ee5aa80 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -173,6 +173,9 @@ BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
> ZLIB = @zlibdir@ -lz
> ZLIBINC = @zlibinc@
>
> +ZSTD_CFLAGS = @ZSTD_CFLAGS@
> +ZSTD_LIBS = @ZSTD_LIBS@
> +
> # Where is the decnumber library? Typically in ../libdecnumber.
> LIBDECNUMBER_DIR = ../libdecnumber
> LIBDECNUMBER = $(LIBDECNUMBER_DIR)/libdecnumber.a
> @@ -625,7 +628,7 @@ INTERNAL_CPPFLAGS = $(CPPFLAGS) @GUILE_CPPFLAGS@ @PYTHON_CPPFLAGS@ \
> INTERNAL_CFLAGS_BASE = \
> $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
> $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) $(ZLIBINC) \
> - $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
> + $(ZSTD_CFLAGS) $(BFD_CFLAGS) $(INCLUDE_CFLAGS) $(LIBDECNUMBER_CFLAGS) \
> $(INTL_CFLAGS) $(INCGNU) $(INCSUPPORT) $(LIBBACKTRACE_INC) \
> $(ENABLE_CFLAGS) $(INTERNAL_CPPFLAGS) $(SRCHIGH_CFLAGS) \
> $(TOP_CFLAGS) $(PTHREAD_CFLAGS) $(DEBUGINFOD_CFLAGS)
> @@ -647,7 +650,7 @@ INTERNAL_LDFLAGS = \
> # Libraries and corresponding dependencies for compiling gdb.
> # XM_CLIBS, defined in *config files, have host-dependent libs.
> # LIBIBERTY appears twice on purpose.
> -CLIBS = $(SIM) $(READLINE) $(OPCODES) $(LIBCTF) $(BFD) $(ZLIB) \
> +CLIBS = $(SIM) $(READLINE) $(OPCODES) $(LIBCTF) $(BFD) $(ZLIB) $(ZSTD_LIBS) \
> $(LIBSUPPORT) $(INTL) $(LIBIBERTY) $(LIBDECNUMBER) \
> $(XM_CLIBS) $(GDBTKLIBS) $(LIBBACKTRACE_LIB) \
> @LIBS@ @GUILE_LIBS@ @PYTHON_LIBS@ \
> @@ -2298,6 +2301,7 @@ aclocal_m4_deps = \
> ../config/lcmessage.m4 \
> ../config/codeset.m4 \
> ../config/zlib.m4 \
> + ../config/zstd.m4 \
> ../config/ax_pthread.m4
>
> $(srcdir)/aclocal.m4: @MAINTAINER_MODE_TRUE@ $(aclocal_m4_deps)
> diff --git a/gdb/acinclude.m4 b/gdb/acinclude.m4
> index 95ff2b6f35e..28846119dcb 100644
> --- a/gdb/acinclude.m4
> +++ b/gdb/acinclude.m4
> @@ -43,6 +43,7 @@ m4_include([../config/lib-link.m4])
> m4_include([../config/iconv.m4])
>
> m4_include([../config/zlib.m4])
> +m4_include([../config/zstd.m4])
>
> m4_include([../gdbsupport/common.m4])
>
> @@ -233,7 +234,7 @@ AC_DEFUN([GDB_AC_CHECK_BFD], [
> # always want our bfd.
> CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS"
> ZLIBDIR=`echo $zlibdir | sed 's,\$(top_builddir)/,,g'`
> - LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $LDFLAGS"
> + LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $ZSTD_LIBS $LDFLAGS"
> intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'`
> LIBS="-lbfd -liberty -lz $intl $LIBS"
> AC_CACHE_CHECK(
> diff --git a/gdb/config.in b/gdb/config.in
> index a4975c68aad..e13a409ec2d 100644
> --- a/gdb/config.in
> +++ b/gdb/config.in
> @@ -589,6 +589,9 @@
> /* Define to 1 if you have the `XML_StopParser' function. */
> #undef HAVE_XML_STOPPARSER
>
> +/* Define to 1 if zstd is enabled. */
> +#undef HAVE_ZSTD
> +
> /* Define to 1 if your system has the _etext variable. */
> #undef HAVE__ETEXT
>
> diff --git a/gdb/configure b/gdb/configure
> index 4dbd0c3b13c..57cd165088a 100755
> --- a/gdb/configure
> +++ b/gdb/configure
> @@ -747,6 +747,8 @@ READLINE_DEPS
> READLINE
> LTLIBICONV
> LIBICONV
> +ZSTD_LIBS
> +ZSTD_CFLAGS
> zlibinc
> zlibdir
> MIG
> @@ -893,6 +895,7 @@ enable_codesign
> with_pkgversion
> with_bugurl
> with_system_zlib
> +with_zstd
> with_gnu_ld
> enable_rpath
> with_libiconv_prefix
> @@ -961,6 +964,8 @@ DEBUGINFOD_CFLAGS
> DEBUGINFOD_LIBS
> YACC
> YFLAGS
> +ZSTD_CFLAGS
> +ZSTD_LIBS
> XMKMF'
> ac_subdirs_all='testsuite
> gdbtk'
> @@ -1641,6 +1646,8 @@ Optional Packages:
> --with-pkgversion=PKG Use PKG in the version string in place of "GDB"
> --with-bugurl=URL Direct users to URL to report a bug
> --with-system-zlib use installed libz
> + --with-zstd support zstd compressed debug sections
> + (default=auto)
> --with-gnu-ld assume the C compiler uses GNU ld default=no
> --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
> --without-libiconv-prefix don't search for libiconv in includedir and libdir
> @@ -1721,6 +1728,8 @@ Some influential environment variables:
> YFLAGS The list of arguments that will be passed by default to $YACC.
> This script will default YFLAGS to the empty string to avoid a
> default value of `-d' given by some make applications.
> + ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
> + ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
> XMKMF Path to xmkmf, Makefile generator for X Window System
>
> Use these variables to override the choices made by `configure' or to help
> @@ -8242,7 +8251,8 @@ if test "$ac_res" != no; then :
> fi
>
>
> -# Link in zlib if we can. This allows us to read compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to read compressed debug
> +# sections.
>
> # Use the system's zlib library.
> zlibdir="-L\$(top_builddir)/../zlib"
> @@ -8262,6 +8272,126 @@ fi
>
>
>
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +else
> + with_zstd=auto
> +fi
> +
> +
> +if test "$with_zstd" != no; then
> +
> +pkg_failed=no
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzstd" >&5
> +$as_echo_n "checking for libzstd... " >&6; }
> +
> +if test -n "$ZSTD_CFLAGS"; then
> + pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +if test -n "$ZSTD_LIBS"; then
> + pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +
> +if test $pkg_failed = no; then
> + pkg_save_LDFLAGS="$LDFLAGS"
> + LDFLAGS="$LDFLAGS $pkg_cv_ZSTD_LIBS"
> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h. */
> +
> +int
> +main ()
> +{
> +
> + ;
> + return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +
> +else
> + pkg_failed=yes
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> + conftest$ac_exeext conftest.$ac_ext
> + LDFLAGS=$pkg_save_LDFLAGS
> +fi
> +
> +
> +
> +if test $pkg_failed = yes; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
> + _pkg_short_errors_supported=yes
> +else
> + _pkg_short_errors_supported=no
> +fi
> + if test $_pkg_short_errors_supported = yes; then
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzstd" 2>&1`
> + else
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzstd" 2>&1`
> + fi
> + # Put the nasty error message in config.log where it belongs
> + echo "$ZSTD_PKG_ERRORS" >&5
> +
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +elif test $pkg_failed = untried; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +else
> + ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
> + ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +
> +$as_echo "#define HAVE_ZSTD 1" >>confdefs.h
> +
> +
> +fi
> +fi
> +
> +
> +
> if test "X$prefix" = "XNONE"; then
> acl_final_prefix="$ac_default_prefix"
> else
> @@ -17281,7 +17411,7 @@ WIN32LIBS="$WIN32LIBS $WIN32APILIBS"
> # always want our bfd.
> CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS"
> ZLIBDIR=`echo $zlibdir | sed 's,\$(top_builddir)/,,g'`
> - LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $LDFLAGS"
> + LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $ZSTD_LIBS $LDFLAGS"
> intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'`
> LIBS="-lbfd -liberty -lz $intl $LIBS"
> { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ELF support in BFD" >&5
> @@ -17396,7 +17526,7 @@ fi
> # always want our bfd.
> CFLAGS="-I${srcdir}/../include -I../bfd -I${srcdir}/../bfd $CFLAGS"
> ZLIBDIR=`echo $zlibdir | sed 's,\$(top_builddir)/,,g'`
> - LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $LDFLAGS"
> + LDFLAGS="-L../bfd -L../libiberty $ZLIBDIR $ZSTD_LIBS $LDFLAGS"
> intl=`echo $LIBINTL | sed 's,${top_builddir}/,,g'`
> LIBS="-lbfd -liberty -lz $intl $LIBS"
> { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mach-O support in BFD" >&5
> diff --git a/gdb/configure.ac b/gdb/configure.ac
> index 215a91c5b27..e8cf808d280 100644
> --- a/gdb/configure.ac
> +++ b/gdb/configure.ac
> @@ -460,8 +460,10 @@ AC_SEARCH_LIBS(gethostbyname, nsl)
> # Some systems (e.g. Solaris) have `socketpair' in libsocket.
> AC_SEARCH_LIBS(socketpair, socket)
>
> -# Link in zlib if we can. This allows us to read compressed debug sections.
> +# Link in zlib/zstd if we can. This allows us to read compressed debug
> +# sections.
> AM_ZLIB
> +AM_ZSTD
>
> AM_ICONV
>
> diff --git a/ld/Makefile.am b/ld/Makefile.am
> index d31021c13e2..bbe25f3aca2 100644
> --- a/ld/Makefile.am
> +++ b/ld/Makefile.am
> @@ -45,7 +45,7 @@ ELF_CLFAGS=-DELF_LIST_OPTIONS=@elf_list_options@ \
> -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
> WARN_CFLAGS = @WARN_CFLAGS@
> NO_WERROR = @NO_WERROR@
> -AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS) $(ZSTD_CFLAGS)
>
> # We put the scripts in the directory $(scriptdir)/ldscripts.
> # We can't put the scripts in $(datadir) because the SEARCH_DIR
> @@ -959,7 +959,8 @@ ld_new_SOURCES = ldgram.y ldlex-wrapper.c lexsup.c ldlang.c mri.c ldctor.c ldmai
> ldbuildid.c
> ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \
> $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) $(JANSSON_LIBS)
> -ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(JANSSON_LIBS)
> +ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) \
> + $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(ZSTD_LIBS) $(JANSSON_LIBS)
>
> # Dependency tracking for the generated emulation files.
> EXTRA_ld_new_SOURCES += $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES)
> diff --git a/ld/Makefile.in b/ld/Makefile.in
> index ee0c98f65b0..400eed2717e 100644
> --- a/ld/Makefile.in
> +++ b/ld/Makefile.in
> @@ -126,7 +126,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \
> $(top_srcdir)/../config/plugins.m4 \
> $(top_srcdir)/../config/po.m4 \
> $(top_srcdir)/../config/progtest.m4 \
> - $(top_srcdir)/../config/zlib.m4 $(top_srcdir)/../libtool.m4 \
> + $(top_srcdir)/../config/zlib.m4 \
> + $(top_srcdir)/../config/zstd.m4 $(top_srcdir)/../libtool.m4 \
> $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
> $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
> $(top_srcdir)/../bfd/version.m4 $(top_srcdir)/configure.ac
> @@ -477,6 +478,8 @@ WARN_WRITE_STRINGS = @WARN_WRITE_STRINGS@
> XGETTEXT = @XGETTEXT@
> YACC = `if [ -f ../bison/bison ]; then echo ../bison/bison -y -L$(srcdir)/../bison/; else echo @YACC@; fi`
> YFLAGS = -d
> +ZSTD_CFLAGS = @ZSTD_CFLAGS@
> +ZSTD_LIBS = @ZSTD_LIBS@
> abs_builddir = @abs_builddir@
> abs_srcdir = @abs_srcdir@
> abs_top_builddir = @abs_top_builddir@
> @@ -564,7 +567,7 @@ ELF_CLFAGS = -DELF_LIST_OPTIONS=@elf_list_options@ \
> -DELF_SHLIB_LIST_OPTIONS=@elf_shlib_list_options@ \
> -DELF_PLT_UNWIND_LIST_OPTIONS=@elf_plt_unwind_list_options@
>
> -AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS)
> +AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS) $(JANSSON_CFLAGS) $(ZSTD_CFLAGS)
>
> # We put the scripts in the directory $(scriptdir)/ldscripts.
> # We can't put the scripts in $(datadir) because the SEARCH_DIR
> @@ -1011,7 +1014,9 @@ ld_new_SOURCES = ldgram.y ldlex-wrapper.c lexsup.c ldlang.c mri.c ldctor.c ldmai
> ld_new_DEPENDENCIES = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) \
> $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL_DEP) $(JANSSON_LIBS)
>
> -ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(JANSSON_LIBS)
> +ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBCTF) \
> + $(LIBIBERTY) $(LIBINTL) $(ZLIB) $(ZSTD_LIBS) $(JANSSON_LIBS)
> +
> #
> #
> # Build a dummy plugin using libtool.
> diff --git a/ld/aclocal.m4 b/ld/aclocal.m4
> index d20c542eed5..893e973e4f2 100644
> --- a/ld/aclocal.m4
> +++ b/ld/aclocal.m4
> @@ -1203,6 +1203,7 @@ m4_include([../config/plugins.m4])
> m4_include([../config/po.m4])
> m4_include([../config/progtest.m4])
> m4_include([../config/zlib.m4])
> +m4_include([../config/zstd.m4])
> m4_include([../libtool.m4])
> m4_include([../ltoptions.m4])
> m4_include([../ltsugar.m4])
> diff --git a/ld/config.in b/ld/config.in
> index 0ccd79d59cd..3916740eee4 100644
> --- a/ld/config.in
> +++ b/ld/config.in
> @@ -162,6 +162,9 @@
> /* Define to 1 if you have the <windows.h> header file. */
> #undef HAVE_WINDOWS_H
>
> +/* Define to 1 if zstd is enabled. */
> +#undef HAVE_ZSTD
> +
> /* Define to the sub-directory in which libtool stores uninstalled libraries.
> */
> #undef LT_OBJDIR
> diff --git a/ld/configure b/ld/configure
> index a1a07005400..175dd995b2b 100755
> --- a/ld/configure
> +++ b/ld/configure
> @@ -646,6 +646,8 @@ elf_plt_unwind_list_options
> elf_shlib_list_options
> elf_list_options
> STRINGIFY
> +ZSTD_LIBS
> +ZSTD_CFLAGS
> zlibinc
> zlibdir
> NATIVE_LIB_DIRS
> @@ -679,9 +681,6 @@ WARN_CFLAGS_FOR_BUILD
> WARN_CFLAGS
> JANSSON_LIBS
> JANSSON_CFLAGS
> -PKG_CONFIG_LIBDIR
> -PKG_CONFIG_PATH
> -PKG_CONFIG
> enable_libctf
> ENABLE_LIBCTF_FALSE
> ENABLE_LIBCTF_TRUE
> @@ -711,6 +710,9 @@ LD
> FGREP
> SED
> LIBTOOL
> +PKG_CONFIG_LIBDIR
> +PKG_CONFIG_PATH
> +PKG_CONFIG
> EGREP
> CPP
> GREP
> @@ -855,6 +857,7 @@ enable_werror
> enable_build_warnings
> enable_nls
> with_system_zlib
> +with_zstd
> '
> ac_precious_vars='build_alias
> host_alias
> @@ -868,14 +871,16 @@ CXX
> CXXFLAGS
> CCC
> CPP
> -CXXCPP
> PKG_CONFIG
> PKG_CONFIG_PATH
> PKG_CONFIG_LIBDIR
> +CXXCPP
> JANSSON_CFLAGS
> JANSSON_LIBS
> YACC
> -YFLAGS'
> +YFLAGS
> +ZSTD_CFLAGS
> +ZSTD_LIBS'
>
>
> # Initialize some variables set by options.
> @@ -1552,6 +1557,8 @@ Optional Packages:
> --with-lib-path=dir1:dir2... set default LIB_PATH
> --with-sysroot=DIR Search for usr/lib et al within DIR.
> --with-system-zlib use installed libz
> + --with-zstd support zstd compressed debug sections
> + (default=auto)
>
> Some influential environment variables:
> CC C compiler command
> @@ -1564,12 +1571,12 @@ Some influential environment variables:
> CXX C++ compiler command
> CXXFLAGS C++ compiler flags
> CPP C preprocessor
> - CXXCPP C++ preprocessor
> PKG_CONFIG path to pkg-config utility
> PKG_CONFIG_PATH
> directories to add to pkg-config's search path
> PKG_CONFIG_LIBDIR
> path overriding pkg-config's built-in search path
> + CXXCPP C++ preprocessor
> JANSSON_CFLAGS
> C compiler flags for JANSSON, overriding pkg-config
> JANSSON_LIBS
> @@ -1580,6 +1587,8 @@ Some influential environment variables:
> YFLAGS The list of arguments that will be passed by default to $YACC.
> This script will default YFLAGS to the empty string to avoid a
> default value of `-d' given by some make applications.
> + ZSTD_CFLAGS C compiler flags for ZSTD, overriding pkg-config
> + ZSTD_LIBS linker flags for ZSTD, overriding pkg-config
>
> Use these variables to override the choices made by `configure' or to help
> it to find libraries and programs with nonstandard names/locations.
> @@ -5388,6 +5397,126 @@ $as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
>
>
>
> +
> +
> +
> +
> +
> +
> +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
> + if test -n "$ac_tool_prefix"; then
> + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
> +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +PKG_CONFIG=$ac_cv_path_PKG_CONFIG
> +if test -n "$PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
> +$as_echo "$PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> +
> +fi
> +if test -z "$ac_cv_path_PKG_CONFIG"; then
> + ac_pt_PKG_CONFIG=$PKG_CONFIG
> + # Extract the first word of "pkg-config", so it can be a program name with args.
> +set dummy pkg-config; ac_word=$2
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> +$as_echo_n "checking for $ac_word... " >&6; }
> +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
> + $as_echo_n "(cached) " >&6
> +else
> + case $ac_pt_PKG_CONFIG in
> + [\\/]* | ?:[\\/]*)
> + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
> + ;;
> + *)
> + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> +for as_dir in $PATH
> +do
> + IFS=$as_save_IFS
> + test -z "$as_dir" && as_dir=.
> + for ac_exec_ext in '' $ac_executable_extensions; do
> + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> + break 2
> + fi
> +done
> + done
> +IFS=$as_save_IFS
> +
> + ;;
> +esac
> +fi
> +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
> +if test -n "$ac_pt_PKG_CONFIG"; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
> +$as_echo "$ac_pt_PKG_CONFIG" >&6; }
> +else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +fi
> +
> + if test "x$ac_pt_PKG_CONFIG" = x; then
> + PKG_CONFIG=""
> + else
> + case $cross_compiling:$ac_tool_warned in
> +yes:)
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
> +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
> +ac_tool_warned=yes ;;
> +esac
> + PKG_CONFIG=$ac_pt_PKG_CONFIG
> + fi
> +else
> + PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
> +fi
> +
> +fi
> +if test -n "$PKG_CONFIG"; then
> + _pkg_min_version=0.9.0
> + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
> +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
> + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> + else
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> + PKG_CONFIG=""
> + fi
> +fi
> +
> case `pwd` in
> *\ * | *\ *)
> { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
> @@ -11491,7 +11620,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 11494 "configure"
> +#line 11623 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -11597,7 +11726,7 @@ else
> lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
> lt_status=$lt_dlunknown
> cat > conftest.$ac_ext <<_LT_EOF
> -#line 11600 "configure"
> +#line 11729 "configure"
> #include "confdefs.h"
>
> #if HAVE_DLFCN_H
> @@ -15586,126 +15715,6 @@ fi
>
>
> if test "x$enable_jansson" != "xno"; then
> -
> -
> -
> -
> -
> -
> -
> -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
> - if test -n "$ac_tool_prefix"; then
> - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
> -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> -$as_echo_n "checking for $ac_word... " >&6; }
> -if ${ac_cv_path_PKG_CONFIG+:} false; then :
> - $as_echo_n "(cached) " >&6
> -else
> - case $PKG_CONFIG in
> - [\\/]* | ?:[\\/]*)
> - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
> - ;;
> - *)
> - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> -for as_dir in $PATH
> -do
> - IFS=$as_save_IFS
> - test -z "$as_dir" && as_dir=.
> - for ac_exec_ext in '' $ac_executable_extensions; do
> - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> - break 2
> - fi
> -done
> - done
> -IFS=$as_save_IFS
> -
> - ;;
> -esac
> -fi
> -PKG_CONFIG=$ac_cv_path_PKG_CONFIG
> -if test -n "$PKG_CONFIG"; then
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
> -$as_echo "$PKG_CONFIG" >&6; }
> -else
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> -$as_echo "no" >&6; }
> -fi
> -
> -
> -fi
> -if test -z "$ac_cv_path_PKG_CONFIG"; then
> - ac_pt_PKG_CONFIG=$PKG_CONFIG
> - # Extract the first word of "pkg-config", so it can be a program name with args.
> -set dummy pkg-config; ac_word=$2
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
> -$as_echo_n "checking for $ac_word... " >&6; }
> -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
> - $as_echo_n "(cached) " >&6
> -else
> - case $ac_pt_PKG_CONFIG in
> - [\\/]* | ?:[\\/]*)
> - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
> - ;;
> - *)
> - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
> -for as_dir in $PATH
> -do
> - IFS=$as_save_IFS
> - test -z "$as_dir" && as_dir=.
> - for ac_exec_ext in '' $ac_executable_extensions; do
> - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
> - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
> - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
> - break 2
> - fi
> -done
> - done
> -IFS=$as_save_IFS
> -
> - ;;
> -esac
> -fi
> -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
> -if test -n "$ac_pt_PKG_CONFIG"; then
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
> -$as_echo "$ac_pt_PKG_CONFIG" >&6; }
> -else
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> -$as_echo "no" >&6; }
> -fi
> -
> - if test "x$ac_pt_PKG_CONFIG" = x; then
> - PKG_CONFIG=""
> - else
> - case $cross_compiling:$ac_tool_warned in
> -yes:)
> -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
> -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
> -ac_tool_warned=yes ;;
> -esac
> - PKG_CONFIG=$ac_pt_PKG_CONFIG
> - fi
> -else
> - PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
> -fi
> -
> -fi
> -if test -n "$PKG_CONFIG"; then
> - _pkg_min_version=0.9.0
> - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
> -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
> - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> -$as_echo "yes" >&6; }
> - else
> - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> -$as_echo "no" >&6; }
> - PKG_CONFIG=""
> - fi
> -fi
> if test -n "$PKG_CONFIG"; then :
>
>
> @@ -17052,8 +17061,8 @@ $as_echo "#define HAVE_DECL_GETOPT 1" >>confdefs.h
>
> fi
>
> -# Link in zlib if we can. This allows us to read and write
> -# compressed CTF sections.
> +# Link in zlib/zstd if we can. This allows us to read and write
> +# compressed debug sections.
>
> # Use the system's zlib library.
> zlibdir="-L\$(top_builddir)/../zlib"
> @@ -17072,6 +17081,126 @@ fi
>
>
>
> +
> +# Check whether --with-zstd was given.
> +if test "${with_zstd+set}" = set; then :
> + withval=$with_zstd;
> +else
> + with_zstd=auto
> +fi
> +
> +
> +if test "$with_zstd" != no; then
> +
> +pkg_failed=no
> +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libzstd" >&5
> +$as_echo_n "checking for libzstd... " >&6; }
> +
> +if test -n "$ZSTD_CFLAGS"; then
> + pkg_cv_ZSTD_CFLAGS="$ZSTD_CFLAGS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_CFLAGS=`$PKG_CONFIG --cflags "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +if test -n "$ZSTD_LIBS"; then
> + pkg_cv_ZSTD_LIBS="$ZSTD_LIBS"
> + elif test -n "$PKG_CONFIG"; then
> + if test -n "$PKG_CONFIG" && \
> + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libzstd\""; } >&5
> + ($PKG_CONFIG --exists --print-errors "libzstd") 2>&5
> + ac_status=$?
> + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> + test $ac_status = 0; }; then
> + pkg_cv_ZSTD_LIBS=`$PKG_CONFIG --libs "libzstd" 2>/dev/null`
> + test "x$?" != "x0" && pkg_failed=yes
> +else
> + pkg_failed=yes
> +fi
> + else
> + pkg_failed=untried
> +fi
> +
> +if test $pkg_failed = no; then
> + pkg_save_LDFLAGS="$LDFLAGS"
> + LDFLAGS="$LDFLAGS $pkg_cv_ZSTD_LIBS"
> + cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> +/* end confdefs.h. */
> +
> +int
> +main ()
> +{
> +
> + ;
> + return 0;
> +}
> +_ACEOF
> +if ac_fn_c_try_link "$LINENO"; then :
> +
> +else
> + pkg_failed=yes
> +fi
> +rm -f core conftest.err conftest.$ac_objext \
> + conftest$ac_exeext conftest.$ac_ext
> + LDFLAGS=$pkg_save_LDFLAGS
> +fi
> +
> +
> +
> +if test $pkg_failed = yes; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
> + _pkg_short_errors_supported=yes
> +else
> + _pkg_short_errors_supported=no
> +fi
> + if test $_pkg_short_errors_supported = yes; then
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libzstd" 2>&1`
> + else
> + ZSTD_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libzstd" 2>&1`
> + fi
> + # Put the nasty error message in config.log where it belongs
> + echo "$ZSTD_PKG_ERRORS" >&5
> +
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +elif test $pkg_failed = untried; then
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
> +$as_echo "no" >&6; }
> +
> + if test "$with_zstd" = yes; then
> + as_fn_error $? "--with-zstd was given, but pkgconfig/libzstd.pc is not found" "$LINENO" 5
> + fi
> +
> +else
> + ZSTD_CFLAGS=$pkg_cv_ZSTD_CFLAGS
> + ZSTD_LIBS=$pkg_cv_ZSTD_LIBS
> + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
> +$as_echo "yes" >&6; }
> +
> +
> +$as_echo "#define HAVE_ZSTD 1" >>confdefs.h
> +
> +
> +fi
> +fi
> +
> +
> # When converting linker scripts into strings for use in emulation
> # files, use astring.sed if the compiler supports ANSI string
> # concatenation, or ostring.sed otherwise. This is to support the
> diff --git a/ld/configure.ac b/ld/configure.ac
> index eb55904c090..a491f9f1116 100644
> --- a/ld/configure.ac
> +++ b/ld/configure.ac
> @@ -34,6 +34,7 @@ AC_PROG_GREP
> AC_GNU_SOURCE
> AC_USE_SYSTEM_EXTENSIONS
> AC_PROG_INSTALL
> +PKG_PROG_PKG_CONFIG
>
> LT_INIT
> ACX_LARGEFILE
> @@ -297,7 +298,6 @@ AC_ARG_ENABLE([jansson],
> [enable_jansson="no"])
>
> if test "x$enable_jansson" != "xno"; then
> - PKG_PROG_PKG_CONFIG
> AS_IF([test -n "$PKG_CONFIG"],
> [
> PKG_CHECK_MODULES(JANSSON, [jansson],
> @@ -386,9 +386,10 @@ if test $ld_cv_decl_getopt_unistd_h = yes; then
> [Is the prototype for getopt in <unistd.h> in the expected format?])
> fi
>
> -# Link in zlib if we can. This allows us to read and write
> -# compressed CTF sections.
> +# Link in zlib/zstd if we can. This allows us to read and write
> +# compressed debug sections.
> AM_ZLIB
> +AM_ZSTD
>
> # When converting linker scripts into strings for use in emulation
> # files, use astring.sed if the compiler supports ANSI string
> diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
> index c52484f35d3..acd66f907d1 100644
> --- a/ld/emultempl/elf.em
> +++ b/ld/emultempl/elf.em
> @@ -668,6 +668,15 @@ gld${EMULATION_NAME}_handle_option (int optc)
> link_info.compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
> else if (strcasecmp (optarg, "zlib-gabi") == 0)
> link_info.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
> + else if (strcasecmp (optarg, "zstd") == 0)
> + {
> +#ifdef HAVE_ZSTD
> + link_info.compress_debug = COMPRESS_DEBUG_ZSTD;
> +#else
> + einfo (_ ("%F%P: --compress-debug-sections=zstd: ld is not built "
> + "with zstd support\n"));
> +#endif
> + }
> else
> einfo (_("%F%P: invalid --compress-debug-sections option: \`%s'\n"),
> optarg);
> diff --git a/ld/ld.texi b/ld/ld.texi
> index eabbec8faa9..9daed2e7e9f 100644
> --- a/ld/ld.texi
> +++ b/ld/ld.texi
> @@ -2863,10 +2863,12 @@ but for most Linux based systems it will be @code{both}.
> @kindex --compress-debug-sections=zlib
> @kindex --compress-debug-sections=zlib-gnu
> @kindex --compress-debug-sections=zlib-gabi
> +@kindex --compress-debug-sections=zstd
> @item --compress-debug-sections=none
> @itemx --compress-debug-sections=zlib
> @itemx --compress-debug-sections=zlib-gnu
> @itemx --compress-debug-sections=zlib-gabi
> +@itemx --compress-debug-sections=zstd
> On ELF platforms, these options control how DWARF debug sections are
> compressed using zlib.
>
> @@ -2880,6 +2882,9 @@ sets the SHF_COMPRESSED flag in the sections' headers.
> The @option{--compress-debug-sections=zlib} option is an alias for
> @option{--compress-debug-sections=zlib-gabi}.
>
> +@option{--compress-debug-sections=zstd} compresses DWARF debug sections using
> +zstd.
> +
> Note that this option overrides any compression in input debug
> sections, so if a binary is linked with @option{--compress-debug-sections=none}
> for example, then any compressed debug sections in input files will be
> diff --git a/ld/ldmain.c b/ld/ldmain.c
> index 1bbddaaad32..71af5935b74 100644
> --- a/ld/ldmain.c
> +++ b/ld/ldmain.c
> @@ -506,8 +506,12 @@ main (int argc, char **argv)
> if ((link_info.compress_debug & COMPRESS_DEBUG))
> {
> link_info.output_bfd->flags |= BFD_COMPRESS;
> - if (link_info.compress_debug == COMPRESS_DEBUG_GABI_ZLIB)
> - link_info.output_bfd->flags |= BFD_COMPRESS_GABI;
> + if (link_info.compress_debug != COMPRESS_DEBUG_GNU_ZLIB)
> + {
> + link_info.output_bfd->flags |= BFD_COMPRESS_GABI;
> + if (link_info.compress_debug == COMPRESS_DEBUG_ZSTD)
> + link_info.output_bfd->flags |= BFD_COMPRESS_ZSTD;
> + }
> }
>
> ldwrite ();
> diff --git a/ld/lexsup.c b/ld/lexsup.c
> index 9225f71b3ce..299371fb775 100644
> --- a/ld/lexsup.c
> +++ b/ld/lexsup.c
> @@ -2146,8 +2146,8 @@ elf_static_list_options (FILE *file)
> fprintf (file, _("\
> --package-metadata[=JSON] Generate package metadata note\n"));
> fprintf (file, _("\
> - --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi]\n\
> - Compress DWARF debug sections using zlib\n"));
> + --compress-debug-sections=[none|zlib|zlib-gnu|zlib-gabi|zstd]\n\
> + Compress DWARF debug sections\n"));
> #ifdef DEFAULT_FLAG_COMPRESS_DEBUG
> fprintf (file, _("\
> Default: zlib-gabi\n"));
> diff --git a/ld/testsuite/ld-elf/compress.exp b/ld/testsuite/ld-elf/compress.exp
> index cfdd767b8ab..7b8a31cc41d 100644
> --- a/ld/testsuite/ld-elf/compress.exp
> +++ b/ld/testsuite/ld-elf/compress.exp
> @@ -254,3 +254,20 @@ if { [regexp_diff tmpdir/$test.out $srcdir/$subdir/$test.rt] } then {
> } else {
> pass "$test_name"
> }
> +
> +if { ![ld_assemble $as "--compress-debug-sections=zstd $srcdir/$subdir/empty.s" tmpdir/emptyzstd.o ] } {
> + return
> +}
> +set build_tests {
> + {"Build libzstdfoo.so with zstd compressed debug sections"
> + "-shared" "-fPIC -g -Wa,--compress-debug-sections=zstd -Wl,--compress-debug-sections=zstd"
> + {foo.c} {} "libzstdfoo.so"}
> +}
> +set run_tests {
> + {"Run zstdnormal with libzstdfoo.so with zstd compressed debug sections"
> + "tmpdir/begin.o tmpdir/libzstdfoo.so tmpdir/end.o -Wl,--compress-debug-sections=zstd" ""
> + {main.c} "zstdnormal" "normal.out" "-Wa,--compress-debug-sections=zstd"}
> +}
> +
> +run_cc_link_tests $build_tests
> +run_ld_link_exec_tests $run_tests