From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <3UNw3YwcKCAkvj1t0j7pxxpun.lxvkrw32ru11x30ln5j0n.x0p@flex--maskray.bounces.google.com> Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by sourceware.org (Postfix) with ESMTPS id 79B633858D1E for ; Sat, 1 Oct 2022 06:21:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 79B633858D1E Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=flex--maskray.bounces.google.com Received: by mail-yb1-xb4a.google.com with SMTP id b14-20020a056902030e00b006a827d81fd8so5613747ybs.17 for ; Fri, 30 Sep 2022 23:21:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:mime-version:date:from:to:cc:subject :date; bh=V2XI2G5oaWtCeW5PgmE/o0lastdBScVHTlk3MV6rmVU=; b=PDn2udQCEfDCWZ3dmri3x4rOQactMUYqyS3n9ANZKqC1diDla8JtigVm7YrCiA2yHj u7Vw0uZM9R0aR+Yc8y5ER40QgTZ6o8K/X/6BewdmrYtkPm/YhZIZuOIcSH+cvUn6bT4S 7EZ6F9USie7la9n9qntXoyqrGh5xcxxf54qbBnaXASrJgyLUkhUFlsupwHR4V94TXkVO p3BZbFFnwjixgR6L+5dBHC2+H6Aya79ijmgip2I1AROBgW3/tFhZ2IhMNfdYbAFGh8gy i0B7BPez57sCdKiAvgxJWphmcaEeyi3s3chjeVoXGTRMy5/BWbuW1h2fhZoDLZ91K93K EhGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:mime-version:date:x-gm-message-state :from:to:cc:subject:date; bh=V2XI2G5oaWtCeW5PgmE/o0lastdBScVHTlk3MV6rmVU=; b=ln3v8w+h63aR3477KqrSMFiFL5QulOxnEPLrXrvayD2hziPYOom8jAZChbFOpjOh7d 0GtzBXC05j7asD7uvOcsYKsFGiusVk6VN9vrNl9t/Q3KRdJNo+sGXbe2yZLaY8MCLrCI V/ISpAZXHGRyP5GFixrsG0nXbhqZcng7HRKaHHW6k09JLUjgz9nTAtx2UbqhJEDqJr3p yVObhRah6/SRlCeUwCTpQushdenYXkYAu5DD5lXy9CGL4DfHtlPzug7tWTWFFtDDS83v o9k3zoYGidm7eG0j3C2OHFDMoRzQNO+Tjpg/f2DK+QRdRkLoAiI2alJEY3Y4GZEi1RMq DiuA== X-Gm-Message-State: ACrzQf3UEizWpqZ0pHANvTbysMJ6RhjFODCAw35GnVk2JQOds0D0wtOn CLn8XpXqMDf/aaL2LhRmrmIvglBG81FsH4DkMKwHGbaeLnmDYbVd7ccdKm0m8NYG7e59UQY1Zer iNNBLG3PUcgTzhMDlAtNjvWA/bqiZLzPsrbWk04fiIY/zizWxfEwzgjraLggsllWNpw== X-Google-Smtp-Source: AMsMyM6Edevyplg7GSt0/mO52DT1ffD9w58K03phwYHx0Sbe+jWrJ71K7+T1eTFT8/cr5flxlnCMKBnBZHyE X-Received: from maskray1.svl.corp.google.com ([2620:15c:2ce:200:3a85:8afb:786d:5a2a]) (user=maskray job=sendgmr) by 2002:a25:8a0e:0:b0:692:8410:1a8e with SMTP id g14-20020a258a0e000000b0069284101a8emr10830600ybl.621.1664605264841; Fri, 30 Sep 2022 23:21:04 -0700 (PDT) Date: Fri, 30 Sep 2022 23:20:57 -0700 Mime-Version: 1.0 Message-ID: <20221001062057.681440-1-maskray@google.com> Subject: [PATCH] readelf: support zstd compressed debug sections [PR 29640] From: Fangrui Song To: binutils@sourceware.org Cc: Martin Liska , Fangrui Song Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-19.8 required=5.0 tests=BAYES_00,DKIMWL_WL_MED,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --- binutils/Makefile.am | 6 +-- binutils/Makefile.in | 6 +-- binutils/readelf.c | 112 +++++++++++++++++++++++++++---------------- 3 files changed, 78 insertions(+), 46 deletions(-) diff --git a/binutils/Makefile.am b/binutils/Makefile.am index 751fbacce12..b249af721ae 100644 --- a/binutils/Makefile.am +++ b/binutils/Makefile.am @@ -54,8 +54,8 @@ DEBUGINFOD_LIBS = @DEBUGINFOD_LIBS@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@ NO_WERROR = @NO_WERROR@ -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) -AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS) +AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) $(ZSTD_CFLAGS) LIBICONV = @LIBICONV@ # these two are almost the same program @@ -256,7 +256,7 @@ objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS) -readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(DEBUGINFOD_LIBS) $(MSGPACK_LIBS) +readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(ZSTD_LIBS) $(DEBUGINFOD_LIBS) $(MSGPACK_LIBS) elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) diff --git a/binutils/Makefile.in b/binutils/Makefile.in index 6de4e239408..7d9039e0f2f 100644 --- a/binutils/Makefile.in +++ b/binutils/Makefile.in @@ -651,8 +651,8 @@ am__skipyacc = # case both are empty. ZLIB = @zlibdir@ -lz ZLIBINC = @zlibinc@ -AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) -AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) +AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS) +AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) $(ZSTD_CFLAGS) # these two are almost the same program AR_PROG = ar @@ -790,7 +790,7 @@ size_SOURCES = size.c $(BULIBS) objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) strings_SOURCES = strings.c $(BULIBS) readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS) -readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(DEBUGINFOD_LIBS) $(MSGPACK_LIBS) +readelf_LDADD = $(LIBCTF_NOBFD) $(LIBINTL) $(LIBIBERTY) $(ZLIB) $(ZSTD_LIBS) $(DEBUGINFOD_LIBS) $(MSGPACK_LIBS) elfedit_SOURCES = elfedit.c version.c $(ELFLIBS) elfedit_LDADD = $(LIBINTL) $(LIBIBERTY) strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS) diff --git a/binutils/readelf.c b/binutils/readelf.c index 351571c8abb..04cda213f33 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef HAVE_ZSTD +#include +#endif #include #if defined HAVE_MSGPACK @@ -15170,48 +15173,56 @@ get_section_contents (Elf_Internal_Shdr * section, Filedata * filedata) _("section contents")); } -/* Uncompresses a section that was compressed using zlib, in place. */ +/* Uncompresses a section that was compressed using zlib/zstd, in place. */ static bool -uncompress_section_contents (unsigned char **buffer, - uint64_t uncompressed_size, - uint64_t *size) +uncompress_section_contents (bool is_zstd, unsigned char **buffer, + uint64_t uncompressed_size, uint64_t *size) { uint64_t compressed_size = *size; unsigned char *compressed_buffer = *buffer; - unsigned char *uncompressed_buffer; + unsigned char *uncompressed_buffer = xmalloc (uncompressed_size); z_stream strm; int rc; - /* It is possible the section consists of several compressed - buffers concatenated together, so we uncompress in a loop. */ - /* PR 18313: The state field in the z_stream structure is supposed - to be invisible to the user (ie us), but some compilers will - still complain about it being used without initialisation. So - we first zero the entire z_stream structure and then set the fields - that we need. */ - memset (& strm, 0, sizeof strm); - strm.avail_in = compressed_size; - strm.next_in = (Bytef *) compressed_buffer; - strm.avail_out = uncompressed_size; - uncompressed_buffer = (unsigned char *) xmalloc (uncompressed_size); + if (is_zstd) + { +#ifdef HAVE_ZSTD + size_t ret = ZSTD_decompress (uncompressed_buffer, uncompressed_size, + compressed_buffer, compressed_size); + if (ZSTD_isError (ret)) + goto fail; +#endif + } + else + { + /* It is possible the section consists of several compressed + buffers concatenated together, so we uncompress in a loop. */ + /* PR 18313: The state field in the z_stream structure is supposed + to be invisible to the user (ie us), but some compilers will + still complain about it being used without initialisation. So + we first zero the entire z_stream structure and then set the fields + that we need. */ + memset (&strm, 0, sizeof strm); + strm.avail_in = compressed_size; + strm.next_in = (Bytef *)compressed_buffer; + strm.avail_out = uncompressed_size; - rc = inflateInit (& strm); - while (strm.avail_in > 0) - { - if (rc != Z_OK) - break; - strm.next_out = ((Bytef *) uncompressed_buffer - + (uncompressed_size - strm.avail_out)); - rc = inflate (&strm, Z_FINISH); - if (rc != Z_STREAM_END) - break; - rc = inflateReset (& strm); + rc = inflateInit (&strm); + while (strm.avail_in > 0) + { + if (rc != Z_OK) + break; + strm.next_out = ((Bytef *)uncompressed_buffer + + (uncompressed_size - strm.avail_out)); + rc = inflate (&strm, Z_FINISH); + if (rc != Z_STREAM_END) + break; + rc = inflateReset (&strm); + } + if (inflateEnd (&strm) != Z_OK || rc != Z_OK || strm.avail_out != 0) + goto fail; } - if (inflateEnd (& strm) != Z_OK - || rc != Z_OK - || strm.avail_out != 0) - goto fail; *buffer = uncompressed_buffer; *size = uncompressed_size; @@ -15254,6 +15265,7 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) { uint64_t new_size = num_bytes; uint64_t uncompressed_size = 0; + bool is_zstd = false; if ((section->sh_flags & SHF_COMPRESSED) != 0) { @@ -15266,7 +15278,13 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) by get_compression_header. */ goto error_out; - if (chdr.ch_type != ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ELFCOMPRESS_ZLIB) + ; +#ifdef HAVE_ZSTD + else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + is_zstd = true; +#endif + else { warn (_("section '%s' has unsupported compress type: %d\n"), printable_section_name (filedata, section), chdr.ch_type); @@ -15295,8 +15313,8 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) if (uncompressed_size) { - if (uncompress_section_contents (& start, - uncompressed_size, & new_size)) + if (uncompress_section_contents (is_zstd, &start, uncompressed_size, + &new_size)) num_bytes = new_size; else { @@ -15470,6 +15488,7 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, { uint64_t new_size = section_size; uint64_t uncompressed_size = 0; + bool is_zstd = false; if ((section->sh_flags & SHF_COMPRESSED) != 0) { @@ -15482,7 +15501,13 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, by get_compression_header. */ goto error_out; - if (chdr.ch_type != ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ELFCOMPRESS_ZLIB) + ; +#ifdef HAVE_ZSTD + else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + is_zstd = true; +#endif + else { warn (_("section '%s' has unsupported compress type: %d\n"), printable_section_name (filedata, section), chdr.ch_type); @@ -15511,8 +15536,8 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, if (uncompressed_size) { - if (uncompress_section_contents (& start, uncompressed_size, - & new_size)) + if (uncompress_section_contents (is_zstd, &start, uncompressed_size, + &new_size)) { section_size = new_size; } @@ -15848,6 +15873,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, unsigned char *start = section->start; uint64_t size = sec->sh_size; uint64_t uncompressed_size = 0; + bool is_zstd = false; if ((sec->sh_flags & SHF_COMPRESSED) != 0) { @@ -15869,7 +15895,13 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, by get_compression_header. */ return false; - if (chdr.ch_type != ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ELFCOMPRESS_ZLIB) + ; +#ifdef HAVE_ZSTD + else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + is_zstd = true; +#endif + else { warn (_("section '%s' has unsupported compress type: %d\n"), section->name, chdr.ch_type); @@ -15898,7 +15930,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, if (uncompressed_size) { - if (uncompress_section_contents (&start, uncompressed_size, + if (uncompress_section_contents (is_zstd, &start, uncompressed_size, &size)) { /* Free the compressed buffer, update the section buffer -- 2.38.0.rc1.362.ged0d419d3c-goog