diff options
author | Fangrui Song <maskray@google.com> | 2022-09-26 19:50:13 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2022-09-26 19:50:13 -0700 |
commit | 2cac01e3ffff74898c54fa5e6418817f5578adb6 (patch) | |
tree | c0209ba03d922dae339056488493fc16ebefe6d0 /binutils | |
parent | e122316b7ce78b999db944d7b524e11d642e2a49 (diff) | |
download | gdb-2cac01e3ffff74898c54fa5e6418817f5578adb6.zip gdb-2cac01e3ffff74898c54fa5e6418817f5578adb6.tar.gz gdb-2cac01e3ffff74898c54fa5e6418817f5578adb6.tar.bz2 |
binutils, gdb: support zstd compressed debug sections
PR29397 PR29563: Add new configure option --with-zstd which 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
...
```
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/Makefile.in | 5 | ||||
-rw-r--r-- | binutils/NEWS | 6 | ||||
-rw-r--r-- | binutils/aclocal.m4 | 1 | ||||
-rw-r--r-- | binutils/config.in | 3 | ||||
-rwxr-xr-x | binutils/configure | 136 | ||||
-rw-r--r-- | binutils/configure.ac | 3 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 16 | ||||
-rw-r--r-- | binutils/objcopy.c | 19 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/compress.exp | 44 |
9 files changed, 217 insertions, 16 deletions
diff --git a/binutils/Makefile.in b/binutils/Makefile.in index 78d32b3..6de4e23 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/NEWS b/binutils/NEWS index 8c2c416..83c73d0 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -1,5 +1,11 @@ -*- text -*- +* objcopy --decompress-debug-sections now supports zstd compressed debug + sections. The new option --compress-debug-sections=zstd compresses debug + sections with zstd. + +* addr2line and objdump --dwarf now support zstd compressed debug sections. + * The dlltool program now accepts --deterministic-libraries and --non-deterministic-libraries as command line options to control whether or not it generates deterministic output libraries. If neither of these options diff --git a/binutils/aclocal.m4 b/binutils/aclocal.m4 index a877fa7..28271f5 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 c5fb919..bee8c07 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 4c0c391..0d6bde7 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,127 @@ 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 0798d84..9b75396 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 +AC_ZSTD BFD_BINARY_FOPEN diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 1499db5..34a4164 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 4326175..fc668f0 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 c88da74..4e74c82 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 |