mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
readelf: support zstd compressed debug sections [PR 29640]
This commit is contained in:
parent
2afd002ac6
commit
1f5a354612
@ -54,8 +54,8 @@ DEBUGINFOD_LIBS = @DEBUGINFOD_LIBS@
|
|||||||
WARN_CFLAGS = @WARN_CFLAGS@
|
WARN_CFLAGS = @WARN_CFLAGS@
|
||||||
WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@
|
WARN_CFLAGS_FOR_BUILD = @WARN_CFLAGS_FOR_BUILD@
|
||||||
NO_WERROR = @NO_WERROR@
|
NO_WERROR = @NO_WERROR@
|
||||||
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
|
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
|
||||||
AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC)
|
AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) $(ZSTD_CFLAGS)
|
||||||
LIBICONV = @LIBICONV@
|
LIBICONV = @LIBICONV@
|
||||||
|
|
||||||
# these two are almost the same program
|
# 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)
|
strings_SOURCES = strings.c $(BULIBS)
|
||||||
|
|
||||||
readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS)
|
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_SOURCES = elfedit.c version.c $(ELFLIBS)
|
||||||
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
|
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
|
||||||
|
@ -651,8 +651,8 @@ am__skipyacc =
|
|||||||
# case both are empty.
|
# case both are empty.
|
||||||
ZLIB = @zlibdir@ -lz
|
ZLIB = @zlibdir@ -lz
|
||||||
ZLIBINC = @zlibinc@
|
ZLIBINC = @zlibinc@
|
||||||
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC)
|
AM_CFLAGS = $(WARN_CFLAGS) $(ZLIBINC) $(ZSTD_CFLAGS)
|
||||||
AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC)
|
AM_CFLAGS_FOR_BUILD = $(WARN_CFLAGS_FOR_BUILD) $(ZLIBINC) $(ZSTD_CFLAGS)
|
||||||
|
|
||||||
# these two are almost the same program
|
# these two are almost the same program
|
||||||
AR_PROG = ar
|
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)
|
objcopy_SOURCES = objcopy.c not-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
|
||||||
strings_SOURCES = strings.c $(BULIBS)
|
strings_SOURCES = strings.c $(BULIBS)
|
||||||
readelf_SOURCES = readelf.c version.c unwind-ia64.c dwarf.c demanguse.c $(ELFLIBS)
|
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_SOURCES = elfedit.c version.c $(ELFLIBS)
|
||||||
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
|
elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
|
||||||
strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
|
strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
|
||||||
|
@ -44,6 +44,9 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#ifdef HAVE_ZSTD
|
||||||
|
#include <zstd.h>
|
||||||
|
#endif
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#if defined HAVE_MSGPACK
|
#if defined HAVE_MSGPACK
|
||||||
@ -15183,48 +15186,56 @@ get_section_contents (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||||||
_("section contents"));
|
_("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
|
static bool
|
||||||
uncompress_section_contents (unsigned char **buffer,
|
uncompress_section_contents (bool is_zstd, unsigned char **buffer,
|
||||||
uint64_t uncompressed_size,
|
uint64_t uncompressed_size, uint64_t *size)
|
||||||
uint64_t *size)
|
|
||||||
{
|
{
|
||||||
uint64_t compressed_size = *size;
|
uint64_t compressed_size = *size;
|
||||||
unsigned char *compressed_buffer = *buffer;
|
unsigned char *compressed_buffer = *buffer;
|
||||||
unsigned char *uncompressed_buffer;
|
unsigned char *uncompressed_buffer = xmalloc (uncompressed_size);
|
||||||
z_stream strm;
|
z_stream strm;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* It is possible the section consists of several compressed
|
if (is_zstd)
|
||||||
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);
|
|
||||||
|
|
||||||
rc = inflateInit (& strm);
|
|
||||||
while (strm.avail_in > 0)
|
|
||||||
{
|
{
|
||||||
if (rc != Z_OK)
|
#ifdef HAVE_ZSTD
|
||||||
break;
|
size_t ret = ZSTD_decompress (uncompressed_buffer, uncompressed_size,
|
||||||
strm.next_out = ((Bytef *) uncompressed_buffer
|
compressed_buffer, compressed_size);
|
||||||
+ (uncompressed_size - strm.avail_out));
|
if (ZSTD_isError (ret))
|
||||||
rc = inflate (&strm, Z_FINISH);
|
goto fail;
|
||||||
if (rc != Z_STREAM_END)
|
#endif
|
||||||
break;
|
}
|
||||||
rc = inflateReset (& strm);
|
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);
|
||||||
|
}
|
||||||
|
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;
|
*buffer = uncompressed_buffer;
|
||||||
*size = uncompressed_size;
|
*size = uncompressed_size;
|
||||||
@ -15267,6 +15278,7 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||||||
{
|
{
|
||||||
uint64_t new_size = num_bytes;
|
uint64_t new_size = num_bytes;
|
||||||
uint64_t uncompressed_size = 0;
|
uint64_t uncompressed_size = 0;
|
||||||
|
bool is_zstd = false;
|
||||||
|
|
||||||
if ((section->sh_flags & SHF_COMPRESSED) != 0)
|
if ((section->sh_flags & SHF_COMPRESSED) != 0)
|
||||||
{
|
{
|
||||||
@ -15279,7 +15291,13 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||||||
by get_compression_header. */
|
by get_compression_header. */
|
||||||
goto error_out;
|
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"),
|
warn (_("section '%s' has unsupported compress type: %d\n"),
|
||||||
printable_section_name (filedata, section), chdr.ch_type);
|
printable_section_name (filedata, section), chdr.ch_type);
|
||||||
@ -15308,8 +15326,8 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata)
|
|||||||
|
|
||||||
if (uncompressed_size)
|
if (uncompressed_size)
|
||||||
{
|
{
|
||||||
if (uncompress_section_contents (& start,
|
if (uncompress_section_contents (is_zstd, &start, uncompressed_size,
|
||||||
uncompressed_size, & new_size))
|
&new_size))
|
||||||
num_bytes = new_size;
|
num_bytes = new_size;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -15483,6 +15501,7 @@ dump_section_as_bytes (Elf_Internal_Shdr *section,
|
|||||||
{
|
{
|
||||||
uint64_t new_size = section_size;
|
uint64_t new_size = section_size;
|
||||||
uint64_t uncompressed_size = 0;
|
uint64_t uncompressed_size = 0;
|
||||||
|
bool is_zstd = false;
|
||||||
|
|
||||||
if ((section->sh_flags & SHF_COMPRESSED) != 0)
|
if ((section->sh_flags & SHF_COMPRESSED) != 0)
|
||||||
{
|
{
|
||||||
@ -15495,7 +15514,13 @@ dump_section_as_bytes (Elf_Internal_Shdr *section,
|
|||||||
by get_compression_header. */
|
by get_compression_header. */
|
||||||
goto error_out;
|
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"),
|
warn (_("section '%s' has unsupported compress type: %d\n"),
|
||||||
printable_section_name (filedata, section), chdr.ch_type);
|
printable_section_name (filedata, section), chdr.ch_type);
|
||||||
@ -15524,8 +15549,8 @@ dump_section_as_bytes (Elf_Internal_Shdr *section,
|
|||||||
|
|
||||||
if (uncompressed_size)
|
if (uncompressed_size)
|
||||||
{
|
{
|
||||||
if (uncompress_section_contents (& start, uncompressed_size,
|
if (uncompress_section_contents (is_zstd, &start, uncompressed_size,
|
||||||
& new_size))
|
&new_size))
|
||||||
{
|
{
|
||||||
section_size = new_size;
|
section_size = new_size;
|
||||||
}
|
}
|
||||||
@ -15861,6 +15886,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
|
|||||||
unsigned char *start = section->start;
|
unsigned char *start = section->start;
|
||||||
uint64_t size = sec->sh_size;
|
uint64_t size = sec->sh_size;
|
||||||
uint64_t uncompressed_size = 0;
|
uint64_t uncompressed_size = 0;
|
||||||
|
bool is_zstd = false;
|
||||||
|
|
||||||
if ((sec->sh_flags & SHF_COMPRESSED) != 0)
|
if ((sec->sh_flags & SHF_COMPRESSED) != 0)
|
||||||
{
|
{
|
||||||
@ -15882,7 +15908,13 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
|
|||||||
by get_compression_header. */
|
by get_compression_header. */
|
||||||
return false;
|
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"),
|
warn (_("section '%s' has unsupported compress type: %d\n"),
|
||||||
section->name, chdr.ch_type);
|
section->name, chdr.ch_type);
|
||||||
@ -15911,7 +15943,7 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
|
|||||||
|
|
||||||
if (uncompressed_size)
|
if (uncompressed_size)
|
||||||
{
|
{
|
||||||
if (uncompress_section_contents (&start, uncompressed_size,
|
if (uncompress_section_contents (is_zstd, &start, uncompressed_size,
|
||||||
&size))
|
&size))
|
||||||
{
|
{
|
||||||
/* Free the compressed buffer, update the section buffer
|
/* Free the compressed buffer, update the section buffer
|
||||||
|
Loading…
Reference in New Issue
Block a user