aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/NEWS5
-rw-r--r--ld/config.in3
-rwxr-xr-xld/configure60
-rw-r--r--ld/configure.ac22
-rw-r--r--ld/ld.texi22
-rw-r--r--ld/ldbuildid.c48
-rw-r--r--ld/lexsup.c9
-rw-r--r--ld/testsuite/ld-elf/build-id.exp107
-rw-r--r--ld/testsuite/ld-elf/pr28639e.rd6
9 files changed, 228 insertions, 54 deletions
diff --git a/ld/NEWS b/ld/NEWS
index bad8c3e..1f14dd6 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -1,5 +1,10 @@
-*- text -*-
+Changes in 2.44:
+
+* Add a "--build-id=xx" option, if built with the xxhash library. This
+ produces a 128-bit hash, 2-4x faster than md5 or sha1.
+
Changes in 2.43:
* Add support for LoongArch DT_RELR (compressed R_LARCH_RELATIVE).
diff --git a/ld/config.in b/ld/config.in
index f7c9da3..f2aaf0a 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -269,6 +269,9 @@
/* Version number of package */
#undef VERSION
+/* whether to use inline xxhash */
+#undef WITH_XXHASH
+
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#undef YYTEXT_POINTER
diff --git a/ld/configure b/ld/configure
index bf58214..af1b0d9 100755
--- a/ld/configure
+++ b/ld/configure
@@ -806,6 +806,7 @@ infodir
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -872,6 +873,7 @@ with_libiconv_prefix
with_libiconv_type
with_libintl_prefix
with_libintl_type
+with_xxhash
with_system_zlib
with_zstd
'
@@ -935,6 +937,7 @@ datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1187,6 +1190,15 @@ do
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1324,7 +1336,7 @@ fi
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
+ libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1477,6 +1489,7 @@ Fine tuning of the installation directories:
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -1589,6 +1602,8 @@ Optional Packages:
--with-libintl-prefix[=DIR] search for libintl in DIR/include and DIR/lib
--without-libintl-prefix don't search for libintl in includedir and libdir
--with-libintl-type=TYPE type of library to search for (auto/static/shared)
+ --with-xxhash use inlined libxxhash for hashing (faster)
+ (auto/yes/no)
--with-system-zlib use installed libz
--with-zstd support zstd compressed debug sections
(default=auto)
@@ -11683,7 +11698,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11686 "configure"
+#line 11701 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11789,7 +11804,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11792 "configure"
+#line 11807 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19086,6 +19101,45 @@ $as_echo "#define HAVE_DECL_GETOPT 1" >>confdefs.h
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use xxhash" >&5
+$as_echo_n "checking whether to use xxhash... " >&6; }
+
+# Check whether --with-xxhash was given.
+if test "${with_xxhash+set}" = set; then :
+ withval=$with_xxhash;
+else
+ with_xxhash=auto
+fi
+
+if test "x$with_xxhash" != "xno"; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define XXH_INLINE_ALL
+#include <xxhash.h>
+XXH128_hash_t r;
+void foo (void) { r = XXH128("foo", 3, 0); }
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ with_xxhash=yes
+
+$as_echo "#define WITH_XXHASH 1" >>confdefs.h
+
+
+else
+
+ if test "$with_xxhash" = yes; then
+ as_fn_error $? "xxhash is missing or unusable" "$LINENO" 5
+ fi
+ with_xxhash=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_xxhash" >&5
+$as_echo "$with_xxhash" >&6; }
+
# Link in zlib/zstd if we can. This allows us to read and write
# compressed debug sections.
diff --git a/ld/configure.ac b/ld/configure.ac
index bdf51a0..5d10b38 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -424,6 +424,28 @@ if test $ld_cv_decl_getopt_unistd_h = yes; then
[Is the prototype for getopt in <unistd.h> in the expected format?])
fi
+dnl xxhash support from gdbsupport/common.m4
+AC_MSG_CHECKING([whether to use xxhash])
+AC_ARG_WITH(xxhash,
+ AS_HELP_STRING([--with-xxhash], [use inlined libxxhash for hashing (faster) (auto/yes/no)]),
+ [], [with_xxhash=auto])
+if test "x$with_xxhash" != "xno"; then
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#define XXH_INLINE_ALL
+#include <xxhash.h>
+XXH128_hash_t r;
+void foo (void) { r = XXH128("foo", 3, 0); }
+])],[
+ with_xxhash=yes
+ AC_DEFINE([WITH_XXHASH], 1, [whether to use inline xxhash])
+],[
+ if test "$with_xxhash" = yes; then
+ AC_MSG_ERROR([xxhash is missing or unusable])
+ fi
+ with_xxhash=no])
+fi
+AC_MSG_RESULT([$with_xxhash])
+
# Link in zlib/zstd if we can. This allows us to read and write
# compressed debug sections.
AM_ZLIB
diff --git a/ld/ld.texi b/ld/ld.texi
index 24dcf9d..90182c4 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -3216,20 +3216,20 @@ maximum cache size to @var{size}.
Request the creation of a @code{.note.gnu.build-id} ELF note section
or a @code{.buildid} COFF section. The contents of the note are
unique bits identifying this linked file. @var{style} can be
-@code{uuid} to use 128 random bits, @code{sha1} to use a 160-bit
-@sc{SHA1} hash on the normative parts of the output contents,
-@code{md5} to use a 128-bit @sc{MD5} hash on the normative parts of
-the output contents, or @code{0x@var{hexstring}} to use a chosen bit
-string specified as an even number of hexadecimal digits (@code{-} and
+@code{uuid} to use 128 random bits; @code{sha1} to use a 160-bit
+@sc{SHA1} hash, @code{md5} to use a 128-bit @sc{MD5} hash, or @code{xx}
+to use a 128-bit @sc{XXHASH} on the normative parts of the output
+contents; or @code{0x@var{hexstring}} to use a chosen bit string
+specified as an even number of hexadecimal digits (@code{-} and
@code{:} characters between digit pairs are ignored). If @var{style}
is omitted, @code{sha1} is used.
-The @code{md5} and @code{sha1} styles produces an identifier
-that is always the same in an identical output file, but will be
-unique among all nonidentical output files. It is not intended
-to be compared as a checksum for the file's contents. A linked
-file may be changed later by other tools, but the build ID bit
-string identifying the original linked file does not change.
+The @code{md5}, @code{sha1}, and @code{xx} styles produces an
+identifier that is always the same in an identical output file, but
+are almost certainly unique among all nonidentical output files. It
+is not intended to be compared as a checksum for the file's contents.
+A linked file may be changed later by other tools, but the build ID
+bit string identifying the original linked file does not change.
Passing @code{none} for @var{style} disables the setting from any
@code{--build-id} options earlier on the command line.
diff --git a/ld/ldbuildid.c b/ld/ldbuildid.c
index 5ba9e50..2571f1a 100644
--- a/ld/ldbuildid.c
+++ b/ld/ldbuildid.c
@@ -23,6 +23,10 @@
#include "safe-ctype.h"
#include "md5.h"
#include "sha1.h"
+#ifdef WITH_XXHASH
+#define XXH_INLINE_ALL
+#include <xxhash.h>
+#endif
#include "ldbuildid.h"
#ifdef __MINGW32__
#include <windows.h>
@@ -35,6 +39,9 @@ bool
validate_build_id_style (const char *style)
{
if ((streq (style, "md5")) || (streq (style, "sha1"))
+#ifdef WITH_XXHASH
+ || (streq (style, "xx"))
+#endif
|| (streq (style, "uuid")) || (startswith (style, "0x")))
return true;
@@ -47,6 +54,11 @@ compute_build_id_size (const char *style)
if (streq (style, "md5") || streq (style, "uuid"))
return 128 / 8;
+#ifdef WITH_XXHASH
+ if (streq (style, "xx"))
+ return 128 / 8;
+#endif
+
if (streq (style, "sha1"))
return 160 / 8;
@@ -93,6 +105,16 @@ read_hex (const char xdigit)
return 0;
}
+
+#ifdef WITH_XXHASH
+static void
+xx_process_bytes(const void* buffer, size_t size, void* state)
+{
+ XXH3_128bits_update ((XXH3_state_t*) state, buffer, size);
+}
+#endif
+
+
bool
generate_build_id (bfd *abfd,
const char *style,
@@ -100,7 +122,31 @@ generate_build_id (bfd *abfd,
unsigned char *id_bits,
int size ATTRIBUTE_UNUSED)
{
- if (streq (style, "md5"))
+#ifdef WITH_XXHASH
+ if (streq (style, "xx"))
+ {
+ XXH3_state_t* state = XXH3_createState ();
+ if (!state)
+ {
+ return false;
+ }
+ XXH3_128bits_reset (state);
+ if (!(*checksum_contents) (abfd, &xx_process_bytes, state))
+ {
+ XXH3_freeState (state);
+ return false;
+ }
+ XXH128_hash_t result = XXH3_128bits_digest (state);
+ XXH3_freeState (state);
+ /* Use canonical-endianness output. */
+ XXH128_canonical_t result_canon;
+ XXH128_canonicalFromHash (&result_canon, result);
+ memcpy (id_bits, &result_canon,
+ (size_t) size < sizeof (result) ? (size_t) size : sizeof (result));
+ }
+ else
+#endif
+ if (streq (style, "md5"))
{
struct md5_ctx ctx;
diff --git a/ld/lexsup.c b/ld/lexsup.c
index 4aa0124..8982073 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -2278,6 +2278,15 @@ elf_static_list_options (FILE *file)
{
fprintf (file, _("\
--build-id[=STYLE] Generate build ID note\n"));
+ /* DEFAULT_BUILD_ID_STYLE n/a here */
+#ifdef WITH_XXHASH
+ fprintf (file, _("\
+ Styles: none,md5,sha1,xx,uuid,0xHEX\n"));
+ /* NB: testsuite/ld-elf/build-id.exp depends on this syntax */
+#else
+ fprintf (file, _("\
+ Styles: none,md5,sha1,uuid,0xHEX\n"));
+#endif
fprintf (file, _("\
--package-metadata[=JSON] Generate package metadata note\n"));
fprintf (file, _("\
diff --git a/ld/testsuite/ld-elf/build-id.exp b/ld/testsuite/ld-elf/build-id.exp
index 1bf258b..6bf8f3d 100644
--- a/ld/testsuite/ld-elf/build-id.exp
+++ b/ld/testsuite/ld-elf/build-id.exp
@@ -36,42 +36,71 @@ if { !([istarget *-*-linux*]
return
}
-run_ld_link_tests [list \
- [list \
- "pr28639a.o" \
- "-r --build-id=md5" \
- "" \
- "" \
- {start.s} \
- {{readelf {--notes} pr28639a.rd}} \
- "pr28639a.o" \
- ] \
- [list \
- "pr28639a.o" \
- "-r --build-id" \
- "" \
- "" \
- {dummy.s} \
- {{readelf {--notes} pr28639b.rd}} \
- "pr28639b.o" \
- ] \
- [list \
- "pr28639a" \
- "--build-id tmpdir/pr28639a.o tmpdir/pr28639b.o" \
- "" \
- "" \
- {dummy.s} \
- {{readelf {--notes} pr28639b.rd} \
- {readelf {--notes} pr28639c.rd}} \
- "pr28639a" \
- ] \
- [list \
- "pr28639b" \
- "--build-id=none tmpdir/pr28639a.o tmpdir/pr28639b.o" \
- "" \
- "" \
- {dummy.s} \
- {{readelf {--notes} pr28639d.rd}} \
- "pr28639b" \
- ] \
-]
+
+set stylelist {"" "--build-id" "--build-id=none" "--build-id=md5"
+ "--build-id=sha1" "--build-id=guid" "--build-id=0xdeadbeef"}
+
+run_ld_link_tests {
+ {
+ "pr28639a.o"
+ "-r --build-id=md5"
+ ""
+ ""
+ {start.s}
+ {{readelf {--notes} pr28639a.rd}}
+ "pr28639a.o"
+ }
+ {
+ "pr28639b.o"
+ "-r --build-id"
+ ""
+ ""
+ {dummy.s}
+ {{readelf {--notes} pr28639b.rd}}
+ "pr28639b.o"
+ }
+ {
+ "pr28639a.o deadbeef"
+ "-r --build-id=0xdeadbeef"
+ ""
+ ""
+ {start.s}
+ {{readelf {--notes} pr28639e.rd}}
+ "pr28639a.o"
+ }
+ {
+ "pr28639a"
+ "--build-id tmpdir/pr28639a.o tmpdir/pr28639b.o"
+ ""
+ ""
+ {dummy.s}
+ {{readelf {--notes} pr28639b.rd}
+ {readelf {--notes} pr28639c.rd}}
+ "pr28639a"
+ }
+ {
+ "pr28639b"
+ "--build-id=none tmpdir/pr28639a.o tmpdir/pr28639b.o"
+ ""
+ ""
+ {dummy.s}
+ {{readelf {--notes} pr28639d.rd}}
+ "pr28639b"
+ }
+}
+
+# see if linker supports xx style also
+catch "exec $ld --help | grep -A2 -- --build-id | grep Styles" tmp
+if {[string first ",xx," $tmp] >= 0} then {
+ run_ld_link_tests {
+ {
+ "pr28639a.o xx"
+ "-r --build-id=xx"
+ ""
+ ""
+ {start.s}
+ {{readelf {--notes} pr28639a.rd}} # 16 bytes
+ "pr28639a.o"
+ }
+ }
+}
diff --git a/ld/testsuite/ld-elf/pr28639e.rd b/ld/testsuite/ld-elf/pr28639e.rd
new file mode 100644
index 0000000..15157ba
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr28639e.rd
@@ -0,0 +1,6 @@
+#...
+Displaying notes found in: \.note\.gnu\.build-id
+ Owner Data size Description
+ GNU 0x00000004 NT_GNU_BUILD_ID \(unique build ID bitstring\)
+ Build ID: deadbeef
+#pass