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 /ld | |
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 'ld')
-rw-r--r-- | ld/Makefile.am | 5 | ||||
-rw-r--r-- | ld/Makefile.in | 11 | ||||
-rw-r--r-- | ld/NEWS | 3 | ||||
-rw-r--r-- | ld/aclocal.m4 | 1 | ||||
-rw-r--r-- | ld/config.in | 3 | ||||
-rwxr-xr-x | ld/configure | 390 | ||||
-rw-r--r-- | ld/configure.ac | 6 | ||||
-rw-r--r-- | ld/emultempl/elf.em | 9 | ||||
-rw-r--r-- | ld/ld.texi | 5 | ||||
-rw-r--r-- | ld/ldmain.c | 8 | ||||
-rw-r--r-- | ld/lexsup.c | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-bootstrap/bootstrap.exp | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/compress.exp | 16 |
13 files changed, 324 insertions, 141 deletions
diff --git a/ld/Makefile.am b/ld/Makefile.am index d31021c..bbe25f3 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 ee0c98f..400eed2 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. @@ -1,5 +1,8 @@ -*- text -*- +* ld now supports zstd compressed debug sections. The new option + --compress-debug-sections=zstd compresses debug sections with zstd. + Changes in 2.39: * The ELF linker will now generate a warning message if the stack is made diff --git a/ld/aclocal.m4 b/ld/aclocal.m4 index d20c542..893e973 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 0ccd79d..3916740 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 4efe3ef..9dd3ed5 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 @@ -15585,126 +15714,6 @@ else 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 if test "x$enable_jansson" != "xno"; then : pkg_failed=no @@ -17041,8 +17050,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" @@ -17061,6 +17070,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 + + # 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 8a8bfc9..f1b2f98 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 @@ -377,9 +378,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 +AC_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 c52484f..acd66f9 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); @@ -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 e676c37..d63002c 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 9225f71..299371f 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-bootstrap/bootstrap.exp b/ld/testsuite/ld-bootstrap/bootstrap.exp index 52a91fc..99a1109 100644 --- a/ld/testsuite/ld-bootstrap/bootstrap.exp +++ b/ld/testsuite/ld-bootstrap/bootstrap.exp @@ -161,6 +161,10 @@ foreach flags $test_flags { set extralibs "$extralibs -lz" } + if { [lindex [remote_exec build grep "-q \"HAVE_ZSTD 1\" config.h" ] 0] == 0 } then { + set extralibs "$extralibs -lzstd" + } + # Check if the system's jansson library is used. If so, the object files will # be using symbols from it, so link to it. if { [lindex [remote_exec build grep "-q \"HAVE_JANSSON 1\" config.h" ] 0] == 0 } then { diff --git a/ld/testsuite/ld-elf/compress.exp b/ld/testsuite/ld-elf/compress.exp index cfdd767..28a8486 100644 --- a/ld/testsuite/ld-elf/compress.exp +++ b/ld/testsuite/ld-elf/compress.exp @@ -254,3 +254,19 @@ 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 ] } { + 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 +} |