From ded18a3683908e4121500e394278342f63764906 Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 25 Jul 2025 02:31:11 -0400 Subject: [PATCH 01/51] realtek: dsa: enhance pcs_get_state() for RTL83xx Currently the SerDes driven SFP ports give strange ethtool readings on RTL83xx devices. Especially duplex and speed are shown even if no link is up and running. That leads to confusion because the MAC reports arbitrary values. Enhance the readout by refactoring the pcs_get_state() function. Calculate speed/duplex/pause only if link is detected. Additionally add reporting of 10G for SFP+ on RTL839x. ethtool for empty SFP cage before/after root@OpenWrt:~# ethtool lan9 Settings for lan9: Supported ports: [ MII ] Supported link modes: 1000baseT/Full 1000baseKX/Full 1000baseX/Full 1000baseT1/Full Supported pause frame use: Symmetric Receive-only Supports auto-negotiation: Yes Supported FEC modes: Not reported Advertised link modes: 1000baseT/Full 1000baseKX/Full 1000baseX/Full 1000baseT1/Full Advertised pause frame use: Symmetric Receive-only Advertised auto-negotiation: Yes Advertised FEC modes: Not reported Speed: 10Mb/s Duplex: Half Port: MII PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: d Wake-on: d Link detected: no root@OpenWrt:~# ethtool lan9 Settings for lan9: Supported ports: [ MII ] Supported link modes: 1000baseT/Full 1000baseKX/Full 1000baseX/Full 1000baseT1/Full Supported pause frame use: Symmetric Receive-only Supports auto-negotiation: Yes Supported FEC modes: Not reported Advertised link modes: 1000baseT/Full 1000baseKX/Full 1000baseX/Full 1000baseT1/Full Advertised pause frame use: Symmetric Receive-only Advertised auto-negotiation: Yes Advertised FEC modes: Not reported Speed: Unknown! Duplex: Unknown! (255) Port: MII PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: d Wake-on: d Link detected: no ethtool with inserted but NOT connected 1G module before/after root@OpenWrt:~# ethtool lan9 Settings for lan9: Supported ports: [ FIBRE ] Supported link modes: 1000baseX/Full Supported pause frame use: Symmetric Receive-only Supports auto-negotiation: Yes Supported FEC modes: Not reported Advertised link modes: 1000baseX/Full Advertised pause frame use: Symmetric Receive-only Advertised auto-negotiation: Yes Advertised FEC modes: Not reported Speed: 1000Mb/s Duplex: Full Port: FIBRE PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: d Wake-on: d Link detected: no root@OpenWrt:~# ethtool lan9 Settings for lan9: Supported ports: [ FIBRE ] Supported link modes: 1000baseX/Full Supported pause frame use: Symmetric Receive-only Supports auto-negotiation: Yes Supported FEC modes: Not reported Advertised link modes: 1000baseX/Full Advertised pause frame use: Symmetric Receive-only Advertised auto-negotiation: Yes Advertised FEC modes: Not reported Speed: Unknown! Duplex: Unknown! (255) Port: FIBRE PHYAD: 0 Transceiver: internal Auto-negotiation: on Supports Wake-on: d Wake-on: d Link detected: no Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/19524 Signed-off-by: Robert Marko --- .../files-6.12/drivers/net/dsa/rtl83xx/dsa.c | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c index 1af34b4c5f..fd89105ae1 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/dsa.c @@ -340,51 +340,56 @@ static int rtl93xx_get_sds(struct phy_device *phydev) return sds_num; } -static void rtl83xx_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) +static void rtldsa_83xx_pcs_get_state(struct phylink_pcs *pcs, struct phylink_link_state *state) { struct rtl838x_pcs *rtpcs = container_of(pcs, struct rtl838x_pcs, pcs); struct rtl838x_switch_priv *priv = rtpcs->priv; int port = rtpcs->port; u64 speed; - u64 link; - - if (port < 0 || port > priv->cpu_port) { - state->link = false; - return; - } state->link = 0; - link = priv->r->get_port_reg_le(priv->r->mac_link_sts); - if (link & BIT_ULL(port)) - state->link = 1; - pr_debug("%s: link state port %d: %llx\n", __func__, port, link & BIT_ULL(port)); + state->speed = SPEED_UNKNOWN; + state->duplex = DUPLEX_UNKNOWN; + state->pause &= ~(MLO_PAUSE_RX | MLO_PAUSE_TX); + + if (port < 0 || port > priv->cpu_port) + return; + + if (!(priv->r->get_port_reg_le(priv->r->mac_link_sts) & BIT_ULL(port))) + return; + + state->link = 1; - state->duplex = 0; if (priv->r->get_port_reg_le(priv->r->mac_link_dup_sts) & BIT_ULL(port)) - state->duplex = 1; + state->duplex = DUPLEX_FULL; + else + state->duplex = DUPLEX_HALF; speed = priv->r->get_port_reg_le(priv->r->mac_link_spd_sts(port)); - speed >>= (port % 16) << 1; - switch (speed & 0x3) { - case 0: + speed = (speed >> ((port % 16) << 1)) & 0x3; + + switch (speed) { + case RTL_SPEED_10: state->speed = SPEED_10; break; - case 1: + case RTL_SPEED_100: state->speed = SPEED_100; break; - case 2: + case RTL_SPEED_1000: state->speed = SPEED_1000; break; case 3: - if (priv->family_id == RTL9300_FAMILY_ID - && (port == 24 || port == 26)) /* Internal serdes */ - state->speed = SPEED_2500; - else - state->speed = SPEED_100; /* Is in fact 500Mbit */ + /* + * This is ok so far but with minor inconsistencies. On RTL838x this setting is + * for either 500M or 2G. It might be that MAC_GLITE_STS register tells more. On + * RTL839x these vendor specifics are derived from MAC_LINK_500M_STS and mode 3 + * is 10G. This is of interest so resolve to it. Sadly it is off by one for the + * current RTL_SPEED_10000 (=4) definition for RTL93xx. + */ + state->speed = SPEED_10000; + break; } - state->pause &= (MLO_PAUSE_RX | MLO_PAUSE_TX); if (priv->r->get_port_reg_le(priv->r->mac_rx_pause_sts) & BIT_ULL(port)) state->pause |= MLO_PAUSE_RX; if (priv->r->get_port_reg_le(priv->r->mac_tx_pause_sts) & BIT_ULL(port)) @@ -2046,7 +2051,7 @@ static int rtl83xx_dsa_phy_write(struct dsa_switch *ds, int phy_addr, int phy_re const struct phylink_pcs_ops rtl83xx_pcs_ops = { .pcs_an_restart = rtl83xx_pcs_an_restart, - .pcs_get_state = rtl83xx_pcs_get_state, + .pcs_get_state = rtldsa_83xx_pcs_get_state, .pcs_config = rtl83xx_pcs_config, }; From 3e95b955fc98078aabe555bce688d33619cbec7b Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 24 Jun 2025 14:23:49 -0400 Subject: [PATCH 02/51] tools/bc: remove useless patch The remaining changes in this patch to the configure script has no effect at all since autoreconf is used with bc and the recent update to bc removed the need to patch the original set of changes in order to fix building. Remove the patch. Removed: - 002-fix-libmath.patch Fixes: abd424c3e ("tools/bc: update to 1.08.1") Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/bc/patches/002-fix-libmath.patch | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 tools/bc/patches/002-fix-libmath.patch diff --git a/tools/bc/patches/002-fix-libmath.patch b/tools/bc/patches/002-fix-libmath.patch deleted file mode 100644 index 2ec74e55ba..0000000000 --- a/tools/bc/patches/002-fix-libmath.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/configure -+++ b/configure -@@ -5926,7 +5926,7 @@ case $bcle-$bcrl-$LEX in - ?-?-flex) - LEX="flex -I -8" ;; - ?-y-*) -- as_fn_error $? "readline works only with flex." "$LINENO" 5 ;; -+ : ;; # as_fn_error $? "readline works only with flex." "$LINENO" 5 ;; - esac - - case $LEX-`uname -s` in From 46506776e6d28263e21540c99575ea5c5de1c7af Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 24 Jun 2025 15:32:09 -0400 Subject: [PATCH 03/51] tools/bc: override SUBDIRS variable with Makefile Instead of editing the SUBDIRS variable with a patch, it can be overriden at the end of the command line when invoking Make. Also, remove use of autoreconf, as this patch was the only one that made it necessary. Removed: - 001-no_doc.patch Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/bc/Makefile | 5 +++-- tools/bc/patches/001-no_doc.patch | 21 --------------------- 2 files changed, 3 insertions(+), 23 deletions(-) delete mode 100644 tools/bc/patches/001-no_doc.patch diff --git a/tools/bc/Makefile b/tools/bc/Makefile index f2a19eb266..e86a68c05b 100644 --- a/tools/bc/Makefile +++ b/tools/bc/Makefile @@ -13,13 +13,14 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/bc PKG_HASH:=515430115b3334c636317503460a0950dff79940aa3259ce2c1aa67c2881d023 -PKG_FIXUP := autoreconf PKG_CPE_ID:=cpe:/a:gnu:bc +PKG_SUBDIRS:=lib bc dc + include $(INCLUDE_DIR)/host-build.mk define Host/Uninstall - -$(call Host/Compile/Default,uninstall) + -$(call Host/Compile/Default,uninstall SUBDIRS='lib bc dc') endef $(eval $(call HostBuild)) diff --git a/tools/bc/patches/001-no_doc.patch b/tools/bc/patches/001-no_doc.patch deleted file mode 100644 index 0768e626e8..0000000000 --- a/tools/bc/patches/001-no_doc.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/Makefile.am -+++ b/Makefile.am -@@ -1,6 +1,6 @@ - ## Process this file with automake to produce Makefile.in - --SUBDIRS = lib bc dc doc -+SUBDIRS = lib bc dc - - MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \ - stamp-h $(distdir).tar.gz h/number.h depcomp missing ---- a/Makefile.in -+++ b/Makefile.in -@@ -305,7 +305,7 @@ target_alias = @target_alias@ - top_build_prefix = @top_build_prefix@ - top_builddir = @top_builddir@ - top_srcdir = @top_srcdir@ --SUBDIRS = lib bc dc doc -+SUBDIRS = lib bc dc - MAINTAINERCLEANFILES = aclocal.m4 config.h.in configure Makefile.in \ - stamp-h $(distdir).tar.gz h/number.h depcomp missing - From 346872e7201b79a1f353e2846ab93a71d2357946 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 24 Jun 2025 15:35:33 -0400 Subject: [PATCH 04/51] tools/bc: let getopt() prototype be defined normally Add a patch in order to remove an obsolete workaround that is currently causing issues on some macOS systems. Add patch: - 000-getopt-prototype.patch Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/bc/patches/000-getopt-prototype.patch | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tools/bc/patches/000-getopt-prototype.patch diff --git a/tools/bc/patches/000-getopt-prototype.patch b/tools/bc/patches/000-getopt-prototype.patch new file mode 100644 index 0000000000..ca6246963b --- /dev/null +++ b/tools/bc/patches/000-getopt-prototype.patch @@ -0,0 +1,18 @@ +--- a/h/getopt.h ++++ b/h/getopt.h +@@ -135,15 +135,7 @@ struct option + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +-#ifdef __GNU_LIBRARY__ +-/* Many other libraries have conflicting prototypes for getopt, with +- differences in the consts, in stdlib.h. To avoid compilation +- errors, only prototype getopt for the GNU C library. */ + extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); +-#else /* not __GNU_LIBRARY__ */ +-extern int getopt (); +-#endif /* __GNU_LIBRARY__ */ +- + #ifndef __need_getopt + extern int getopt_long (int ___argc, char *const *___argv, + const char *__shortopts, From 89056bd7b109ff4264f07cf721e6d9f4b7ad983e Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 3 Jul 2025 15:09:25 -0400 Subject: [PATCH 05/51] tools/util-linux: include macOS system uuid header The type definition of uuid_string_t and possibly other details used by macOS SDKs like XCode is missing from util-linux. Headers on macOS have a different inclusion guard compared to the unique util-linux "_UL" prefix. This uuid.h header is guaranteed to be present since macOS 10.8 and iOS 6 even without the presence of XCode or other SDKs on the system, so adding an include_next directive is safe after checking for clang. Link: https://developer.apple.com/documentation/foundation/uuid Link: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/uuid.3.html Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/util-linux/patches/102-macos-uuid-next.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tools/util-linux/patches/102-macos-uuid-next.patch diff --git a/tools/util-linux/patches/102-macos-uuid-next.patch b/tools/util-linux/patches/102-macos-uuid-next.patch new file mode 100644 index 0000000000..36346fd522 --- /dev/null +++ b/tools/util-linux/patches/102-macos-uuid-next.patch @@ -0,0 +1,13 @@ +--- a/libuuid/src/uuid.h ++++ b/libuuid/src/uuid.h +@@ -35,6 +35,10 @@ + #ifndef _UL_LIBUUID_UUID_H + #define _UL_LIBUUID_UUID_H + ++#if defined(__clang__) && defined(__APPLE__) ++#include_next ++#endif ++ + #include + #ifndef _WIN32 + #include From 793be94a3ad8f1304dcd01f1535f1dc5af2eca1c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 11 May 2025 12:23:17 -0400 Subject: [PATCH 06/51] tools/automake: hardcode portable location for Perl The latest automake version 1.17 includes a restriction against whitespace for the configure variable $PERL, which is set to "/usr/bin/env perl" for portability reasons with products like the SDK. Instead of waiting until the next version of automake is released for this error to be converted to a warning, set the shebang of automake and aclocal manually with a patch. In past git history, these lines have been patched before, but only to remove the "-w" flag in favor of setting global warnings in the script itself so that env does not strip the option. The other purposes of Perl during building can use the static staging directory path without any limitations. Also, the configure variable "am_cv_prog_PERL_ithreads" for the detection of Perl threads support has been removed since 2013 in favor of dynamic runtime detection. Remove our manual setting of this variable value as it has no effect. Ref: 1ef07eee4 ("automake: forcibly disable perl ithreads support") Ref: 182626687 ("ithreads: use runtime (not configure time) detection of perl threads") # automake.git Ref: f6c581cc3 ("automake: portability fixes") Ref: 87f3365d9 ("Revert "tools/automake: bump to 1.17"") Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/automake/Makefile | 3 +-- tools/automake/patches/000-relocatable.patch | 12 ++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/automake/Makefile b/tools/automake/Makefile index 7f129c1d83..b698dd5a71 100644 --- a/tools/automake/Makefile +++ b/tools/automake/Makefile @@ -21,8 +21,7 @@ HOST_CONFIGURE_ARGS += \ --disable-silent-rules HOST_CONFIGURE_VARS += \ - PERL="/usr/bin/env perl" \ - am_cv_prog_PERL_ithreads=no + # temporary patch alternative for PERL="/usr/bin/env perl" define Host/Configure (cd $(HOST_BUILD_DIR); $(AM_TOOL_PATHS) STAGING_DIR_HOST="" ./bootstrap) diff --git a/tools/automake/patches/000-relocatable.patch b/tools/automake/patches/000-relocatable.patch index 0b61eaeb45..7d62435cb2 100644 --- a/tools/automake/patches/000-relocatable.patch +++ b/tools/automake/patches/000-relocatable.patch @@ -11,6 +11,12 @@ # We need at least this version for CLONE support. --- a/bin/aclocal.in +++ b/bin/aclocal.in +@@ -1,4 +1,4 @@ +-#!@PERL@ ++#!/usr/bin/env perl + # aclocal - create aclocal.m4 by scanning configure.ac -*- perl -*- + # @configure_input@ + # Copyright (C) 1996-2021 Free Software Foundation, Inc. @@ -23,9 +23,11 @@ use 5.006; use strict; use warnings FATAL => 'all'; @@ -37,6 +43,12 @@ my $install = 0; --- a/bin/automake.in +++ b/bin/automake.in +@@ -1,4 +1,4 @@ +-#!@PERL@ ++#!/usr/bin/env perl + # automake - create Makefile.in from Makefile.am -*- perl -*- + # @configure_input@ + # Copyright (C) 1994-2021 Free Software Foundation, Inc. @@ -26,9 +26,11 @@ use 5.006; use strict; use warnings FATAL => 'all'; From 03b9b7e894ba889edd2e72ca41a12422598dc885 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 11 May 2025 03:06:41 -0400 Subject: [PATCH 07/51] tools/automake: update to 1.17 Update to the latest stable release. This is the automake API that newer packages such as libtool 2.5.4 is bootstrapped with, and is required for bootstrapping it again. Manually Adjusted: - 000-relocatable.patch All other patches are automatically refreshed. Link: https://lists.gnu.org/archive/html/autotools-announce/2024-07/msg00000.html Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/automake/Makefile | 4 ++-- tools/automake/patches/000-relocatable.patch | 10 +++++----- .../100-aclocal-skip-not-existing-directories.patch | 2 +- tools/automake/patches/101-do-not-require-files.patch | 6 +++--- .../patches/200-other-V-values-for-verbosity.patch | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tools/automake/Makefile b/tools/automake/Makefile index b698dd5a71..f281583f05 100644 --- a/tools/automake/Makefile +++ b/tools/automake/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=automake PKG_CPE_ID:=cpe:/a:gnu:automake -PKG_VERSION:=1.16.5 +PKG_VERSION:=1.17 PKG_API_VERSION:=$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/automake -PKG_HASH:=07bd24ad08a64bc17250ce09ec56e921d6343903943e99ccf63bbf0705e34605 +PKG_HASH:=397767d4db3018dd4440825b60c64258b636eaf6bf99ac8b0897f06c89310acd include $(INCLUDE_DIR)/host-build.mk diff --git a/tools/automake/patches/000-relocatable.patch b/tools/automake/patches/000-relocatable.patch index 7d62435cb2..d3a9e178e4 100644 --- a/tools/automake/patches/000-relocatable.patch +++ b/tools/automake/patches/000-relocatable.patch @@ -16,7 +16,7 @@ +#!/usr/bin/env perl # aclocal - create aclocal.m4 by scanning configure.ac -*- perl -*- # @configure_input@ - # Copyright (C) 1996-2021 Free Software Foundation, Inc. + # Copyright (C) 1996-2024 Free Software Foundation, Inc. @@ -23,9 +23,11 @@ use 5.006; use strict; use warnings FATAL => 'all'; @@ -31,16 +31,16 @@ } @@ -65,8 +67,8 @@ $perl_threads = 0; - # ACLOCAL_PATH environment variable, and reset with the '--system-acdir' - # option. + # --aclocal-path option/ACLOCAL_PATH environment variable, and reset + # with the '--system-acdir' option. my @user_includes = (); -my @automake_includes = ('@datadir@/aclocal-' . $APIVERSION); -my @system_includes = ('@datadir@/aclocal'); +my @automake_includes = ($ENV{'STAGING_DIR_HOST'} ? $ENV{'STAGING_DIR_HOST'} . "/share/aclocal-$APIVERSION" : "@datadir@/aclocal-$APIVERSION"); +my @system_includes = ($ENV{'STAGING_DIR_HOST'} ? $ENV{'STAGING_DIR_HOST'} . '/share/aclocal' : '@datadir@/aclocal'); + my $aclocal_path = ''; # Whether we should copy M4 file in $user_includes[0]. - my $install = 0; --- a/bin/automake.in +++ b/bin/automake.in @@ -1,4 +1,4 @@ @@ -48,7 +48,7 @@ +#!/usr/bin/env perl # automake - create Makefile.in from Makefile.am -*- perl -*- # @configure_input@ - # Copyright (C) 1994-2021 Free Software Foundation, Inc. + # Copyright (C) 1994-2024 Free Software Foundation, Inc. @@ -26,9 +26,11 @@ use 5.006; use strict; use warnings FATAL => 'all'; diff --git a/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch index a0d04e21e5..6fa23c49e8 100644 --- a/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch +++ b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch @@ -1,6 +1,6 @@ --- a/bin/aclocal.in +++ b/bin/aclocal.in -@@ -371,6 +371,12 @@ sub scan_m4_dirs ($$@) +@@ -372,6 +372,12 @@ sub scan_m4_dirs ($$@) foreach my $m4dir (@dirlist) { diff --git a/tools/automake/patches/101-do-not-require-files.patch b/tools/automake/patches/101-do-not-require-files.patch index 3a8c9fcb47..26847bc680 100644 --- a/tools/automake/patches/101-do-not-require-files.patch +++ b/tools/automake/patches/101-do-not-require-files.patch @@ -1,6 +1,6 @@ --- a/bin/automake.in +++ b/bin/automake.in -@@ -4513,7 +4513,7 @@ sub handle_gettext () +@@ -4552,7 +4552,7 @@ sub handle_gettext () && grep ($_ eq 'intl', @subdirs)); } @@ -9,7 +9,7 @@ } # Emit makefile footer. -@@ -5641,7 +5641,7 @@ sub check_gnu_standards () +@@ -5677,7 +5677,7 @@ sub check_gnu_standards () # otherwise require non-.md. my $required = (! -f $file && -f "$file.md") ? "$file.md" : $file; @@ -18,7 +18,7 @@ } # Accept one of these three licenses; default to COPYING. -@@ -5655,7 +5655,7 @@ sub check_gnu_standards () +@@ -5691,7 +5691,7 @@ sub check_gnu_standards () last; } } diff --git a/tools/automake/patches/200-other-V-values-for-verbosity.patch b/tools/automake/patches/200-other-V-values-for-verbosity.patch index 1ea9d38b0e..8a5a2d31bd 100644 --- a/tools/automake/patches/200-other-V-values-for-verbosity.patch +++ b/tools/automake/patches/200-other-V-values-for-verbosity.patch @@ -9,8 +9,8 @@ Subject: [PATCH] Allow other V values for verbosity --- a/m4/silent.m4 +++ b/m4/silent.m4 -@@ -43,7 +43,7 @@ else - fi]) +@@ -53,7 +53,7 @@ case $enable_silent_rules in @%:@ ((( + esac if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. - AM_V='$(V)' From b07b8c8b4331d4ffcdbb5112f007778451dfa3f5 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 6 May 2025 13:57:24 -0400 Subject: [PATCH 08/51] tools/gnulib: update to branch stable-202407 Bump to the next stable branch with the May 2025 update. Add a patch to compensate for gnulib-tool being further split up into independent shell and python implementations by using a non-hidden version of the main.py file. Add a patch for the python implementation of gnulib-tool in order to ignore the required version of autoconf in configure.ac being lower than the required version of autoconf for gnulib if the version that is being run exceeds the required version for both, and adjust existing autoconf version shell script patch to new filename. Backport a patch for a change in function naming convention for forward compatibility with tool releases after this stable branch. Added: - 020-python-version.patch - 021-python-main.patch - 500-acl-function-name.patch Manually Adjusted: - 010-autoconf-version.patch - 160-flag-reallocarray.patch Existing patches are automatically refreshed. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/gnulib/Makefile | 4 +- tools/gnulib/patches/000-bootstrap.patch | 2 +- .../gnulib/patches/010-autoconf-version.patch | 8 +- tools/gnulib/patches/020-python-version.patch | 47 +++++++ tools/gnulib/patches/021-python-main.patch | 15 +++ .../patches/150-portable-tdestroy.patch | 10 +- .../patches/160-flag-reallocarray.patch | 17 ++- .../200-force-disable-after-configure.patch | 2 +- .../patches/320-modules-fallocate-posix.patch | 8 +- .../patches/500-acl-function-name.patch | 120 ++++++++++++++++++ 10 files changed, 207 insertions(+), 26 deletions(-) create mode 100644 tools/gnulib/patches/020-python-version.patch create mode 100644 tools/gnulib/patches/021-python-main.patch create mode 100644 tools/gnulib/patches/500-acl-function-name.patch diff --git a/tools/gnulib/Makefile b/tools/gnulib/Makefile index 5119355522..f708299549 100644 --- a/tools/gnulib/Makefile +++ b/tools/gnulib/Makefile @@ -2,11 +2,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gnulib PKG_CPE_ID:=cpe:/a:gnu:$(PKG_NAME) -PKG_VERSION:=c99c8d491850dc3a6e0b8604a2729d8bc5c0eff1# # stable-202401 +PKG_VERSION:=320db6ee7a3cd44ee77f09d30c8a9002159beb4b# # stable-202407 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://git.savannah.gnu.org/cgit/$(PKG_NAME).git/snapshot -PKG_HASH:=8e6f4a907d9677b55fd452e1340a3e030a6f530b138d420c11975da33f086b1e +PKG_HASH:=0be734e8c5f88e259bd593d63da2be275b93aedb551ccdcd78db9825bddeb94e include $(INCLUDE_DIR)/host-build.mk diff --git a/tools/gnulib/patches/000-bootstrap.patch b/tools/gnulib/patches/000-bootstrap.patch index 120586694e..30a62e9bdb 100644 --- a/tools/gnulib/patches/000-bootstrap.patch +++ b/tools/gnulib/patches/000-bootstrap.patch @@ -43,7 +43,7 @@ if [ ! "$inst_ver" ]; then warn_ "Error: '$app' not found" ret=1 -@@ -1157,7 +1157,7 @@ autogen() +@@ -1178,7 +1178,7 @@ autogen() # two just-pre-run programs. # Import from gettext. diff --git a/tools/gnulib/patches/010-autoconf-version.patch b/tools/gnulib/patches/010-autoconf-version.patch index a091bb2e1d..7726cc47a1 100644 --- a/tools/gnulib/patches/010-autoconf-version.patch +++ b/tools/gnulib/patches/010-autoconf-version.patch @@ -1,6 +1,6 @@ ---- a/gnulib-tool -+++ b/gnulib-tool -@@ -346,6 +346,34 @@ Options for --import, --add/remove-impor +--- a/gnulib-tool.sh ++++ b/gnulib-tool.sh +@@ -343,6 +343,34 @@ Options for --import, --add/remove-impor Report bugs to ." } @@ -35,7 +35,7 @@ # func_version # outputs to stdout the --version message. func_version () -@@ -1620,6 +1648,9 @@ func_determine_path_separator +@@ -1665,6 +1693,9 @@ func_determine_path_separator fi case "$autoconf_minversion" in 1.* | 2.[0-5]* | 2.6[0-3]*) diff --git a/tools/gnulib/patches/020-python-version.patch b/tools/gnulib/patches/020-python-version.patch new file mode 100644 index 0000000000..f0182438d5 --- /dev/null +++ b/tools/gnulib/patches/020-python-version.patch @@ -0,0 +1,47 @@ +--- a/pygnulib/functions.py ++++ b/pygnulib/functions.py +@@ -16,6 +16,8 @@ + from __future__ import annotations + + import os.path ++import re ++import subprocess as sp + from .constants import substart + from .GLConfig import GLConfig + +@@ -50,3 +52,15 @@ def rewrite_file_name(file_name: str, co + else: # file is not a special file + result = file_name + return os.path.normpath(result) ++ ++def get_version(app: str) -> str: ++ result = sp.run([app, '--version'], capture_output=True, text=True) ++ version = re.sub(r".*[v ]([0-9])", r"\1", result.stdout) ++ version_lines = [line for line in version.splitlines() if re.search(r"^[0-9]", line)] ++ version = '\n'.join(version_lines) + "\n" ++ version = re.sub(r"[^.a-z0-9-\n].*", r"", version) ++ version = re.sub(r"^([0-9]*)[a-z-].*", r"\1", version, 1) ++ version = re.sub(r"\.0*([1-9])", r".\1", version) ++ version_lines = [line for line in version.splitlines() if line.strip()] ++ version = ''.join(version_lines[0]) + "\n" ++ return version.strip() +--- a/pygnulib/GLImport.py ++++ b/pygnulib/GLImport.py +@@ -40,6 +40,7 @@ from .constants import ( + rmtree, + ) + from .functions import rewrite_file_name ++from .functions import get_version + from .GLError import GLError + from .GLConfig import GLConfig + from .GLModuleSystem import GLModuleTable +@@ -125,7 +126,8 @@ class GLImport: + for version in versions }) + self.config.setAutoconfVersion(version) + if version < 2.64: +- raise GLError(4, version) ++ # If the version of autoconf in use is high enough, do not error. ++ if float(get_version('autoconf')) < 2.64: raise GLError(4, version) + + # Get other cached variables. + path = joinpath(self.config['m4base'], 'gnulib-cache.m4') diff --git a/tools/gnulib/patches/021-python-main.patch b/tools/gnulib/patches/021-python-main.patch new file mode 100644 index 0000000000..1edb1d28a9 --- /dev/null +++ b/tools/gnulib/patches/021-python-main.patch @@ -0,0 +1,15 @@ +--- /dev/null ++++ b/gnulib-tool-main.py +@@ -0,0 +1,4 @@ ++from pygnulib import main ++ ++if __name__ == '__main__': ++ main.main_with_exception_handling() +--- a/gnulib-tool.py ++++ b/gnulib-tool.py +@@ -157,4 +157,4 @@ fi + profiler_args= + # For profiling, cf. . + #profiler_args="-m cProfile -s tottime" +-exec python3 $profiler_args "$gnulib_dir/.gnulib-tool.py" "$@" ++exec python3 $profiler_args "$gnulib_dir/gnulib-tool-main.py" "$@" diff --git a/tools/gnulib/patches/150-portable-tdestroy.patch b/tools/gnulib/patches/150-portable-tdestroy.patch index 39c291f196..ae08d4c303 100644 --- a/tools/gnulib/patches/150-portable-tdestroy.patch +++ b/tools/gnulib/patches/150-portable-tdestroy.patch @@ -107,7 +107,7 @@ +#endif /* defined(_LIBC) || GNULIB_defined_tdestroy */ --- a/m4/search_h.m4 +++ b/m4/search_h.m4 -@@ -39,7 +39,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], +@@ -40,7 +40,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], dnl Check for declarations of anything we want to poison if the dnl corresponding gnulib module is not in use. gl_WARN_ON_USE_PREPARE([[#include @@ -116,7 +116,7 @@ AC_REQUIRE([AC_C_RESTRICT]) ]) -@@ -75,8 +75,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], +@@ -76,8 +76,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LFIND], [1]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LSEARCH], [1]) dnl Assume proper GNU behavior unless another module says otherwise. @@ -133,7 +133,7 @@ ]) --- a/m4/tsearch.m4 +++ b/m4/tsearch.m4 -@@ -9,6 +9,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], +@@ -10,6 +10,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], AC_REQUIRE([gl_SEARCH_H_DEFAULTS]) gl_CHECK_FUNCS_ANDROID([tsearch], [[#include ]]) gl_CHECK_FUNCS_ANDROID([twalk], [[#include ]]) @@ -141,7 +141,7 @@ if test $ac_cv_func_tsearch = yes; then dnl On OpenBSD 4.0, the return value of tdelete() is incorrect. AC_REQUIRE([AC_PROG_CC]) -@@ -50,6 +51,7 @@ main () +@@ -51,6 +52,7 @@ main () *no) REPLACE_TSEARCH=1 REPLACE_TWALK=1 @@ -149,7 +149,7 @@ ;; esac else -@@ -64,6 +66,12 @@ main () +@@ -65,6 +67,12 @@ main () future*) REPLACE_TWALK=1 ;; esac fi diff --git a/tools/gnulib/patches/160-flag-reallocarray.patch b/tools/gnulib/patches/160-flag-reallocarray.patch index 8ffe273e11..f758b86e70 100644 --- a/tools/gnulib/patches/160-flag-reallocarray.patch +++ b/tools/gnulib/patches/160-flag-reallocarray.patch @@ -21,7 +21,7 @@ --- a/lib/xmalloc.c +++ b/lib/xmalloc.c @@ -51,12 +51,16 @@ ximalloc (idx_t s) - return nonnull (imalloc (s)); + return check_nonnull (imalloc (s)); } +#if GNULIB_REALLOCARRAY @@ -38,7 +38,7 @@ with error checking. */ @@ -75,6 +79,8 @@ xirealloc (void *p, idx_t s) - return nonnull (irealloc (p, s)); + return check_nonnull (irealloc (p, s)); } +#if GNULIB_REALLOCARRAY @@ -76,16 +76,15 @@ --- a/lib/safe-alloc.h +++ b/lib/safe-alloc.h -@@ -36,6 +36,8 @@ _GL_INLINE_HEADER_BEGIN - # define SAFE_ALLOC_INLINE _GL_INLINE +@@ -40,6 +40,7 @@ _GL_INLINE_HEADER_BEGIN + extern "C" { #endif +#if GNULIB_REALLOCARRAY -+ + /* Don't call these directly - use the macros below. */ SAFE_ALLOC_INLINE void * - safe_alloc_realloc_n (void *ptr, size_t count, size_t size) -@@ -51,6 +53,9 @@ safe_alloc_realloc_n (void *ptr, size_t +@@ -56,6 +57,9 @@ safe_alloc_realloc_n (void *ptr, size_t #endif return ptr; } @@ -95,7 +94,7 @@ _GL_ATTRIBUTE_NODISCARD SAFE_ALLOC_INLINE int safe_alloc_check (void *ptr) { -@@ -84,6 +89,8 @@ safe_alloc_check (void *ptr) +@@ -89,6 +93,8 @@ safe_alloc_check (void *ptr) #define ALLOC_N(ptr, count) \ safe_alloc_check ((ptr) = calloc (count, sizeof *(ptr))) @@ -104,7 +103,7 @@ /** * ALLOC_N_UNINITIALIZED: * @ptr: pointer to allocated memory -@@ -112,6 +119,8 @@ safe_alloc_check (void *ptr) +@@ -117,6 +123,8 @@ safe_alloc_check (void *ptr) #define REALLOC_N(ptr, count) \ safe_alloc_check ((ptr) = safe_alloc_realloc_n (ptr, count, sizeof *(ptr))) diff --git a/tools/gnulib/patches/200-force-disable-after-configure.patch b/tools/gnulib/patches/200-force-disable-after-configure.patch index 55335b27d2..34ca77610a 100644 --- a/tools/gnulib/patches/200-force-disable-after-configure.patch +++ b/tools/gnulib/patches/200-force-disable-after-configure.patch @@ -20,7 +20,7 @@ { --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h -@@ -1447,10 +1447,16 @@ _GL_FUNCDECL_RPL (reallocarray, void *, +@@ -1508,10 +1508,16 @@ _GL_FUNCDECL_RPL (reallocarray, void *, (void *ptr, size_t nmemb, size_t size)); _GL_CXXALIAS_RPL (reallocarray, void *, (void *ptr, size_t nmemb, size_t size)); diff --git a/tools/gnulib/patches/320-modules-fallocate-posix.patch b/tools/gnulib/patches/320-modules-fallocate-posix.patch index e30a7172aa..d6f614eaa7 100644 --- a/tools/gnulib/patches/320-modules-fallocate-posix.patch +++ b/tools/gnulib/patches/320-modules-fallocate-posix.patch @@ -69,7 +69,7 @@ +AC_DEFUN([gl_PREREQ_POSIX_FALLOCATE], [:]) --- a/m4/fcntl_h.m4 +++ b/m4/fcntl_h.m4 -@@ -23,7 +23,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H], +@@ -25,7 +25,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H], dnl corresponding gnulib module is not in use, if it is not common dnl enough to be declared everywhere. gl_WARN_ON_USE_PREPARE([[#include @@ -78,7 +78,7 @@ ]) # gl_FCNTL_MODULE_INDICATOR([modulename]) -@@ -50,6 +50,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], +@@ -52,6 +52,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_NONBLOCKING]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPENAT]) @@ -86,7 +86,7 @@ dnl Support Microsoft deprecated alias function names by default. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_CREAT], [1]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_OPEN], [1]) -@@ -61,10 +62,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], +@@ -63,10 +64,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], AC_DEFUN([gl_FCNTL_H_DEFAULTS], [ dnl Assume proper GNU behavior unless another module says otherwise. @@ -127,7 +127,7 @@ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h -@@ -238,6 +238,33 @@ _GL_WARN_ON_USE (openat, "openat is not +@@ -239,6 +239,33 @@ _GL_WARN_ON_USE (openat, "openat is not # endif #endif diff --git a/tools/gnulib/patches/500-acl-function-name.patch b/tools/gnulib/patches/500-acl-function-name.patch new file mode 100644 index 0000000000..372a80d10d --- /dev/null +++ b/tools/gnulib/patches/500-acl-function-name.patch @@ -0,0 +1,120 @@ +From 8a71833114c376212ecdd56495604905f6aa218d Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Sat, 24 Aug 2024 17:58:48 +0200 +Subject: acl: First step towards more consistent function names. + +* lib/acl.h (xset_acl): New declaration. +(set_acl): Mark deprecated. +(xcopy_acl): New declaration. +(copy_acl): Mark deprecated. +* lib/set-acl.c (xset_acl): Renamed from set_acl. +(set_acl): New function. +* lib/copy-acl.c (xcopy_acl): Renamed from copy_acl. +(copy_acl): New function. +* tests/test-set-mode-acl.c (main): Test xset_acl instead of set_acl. +* tests/test-copy-acl.c (main): Test xcopy_acl instead of copy_acl. +--- + lib/acl.h | 14 +++++++++++--- + lib/copy-acl.c | 11 +++++++++-- + lib/set-acl.c | 8 +++++++- + tests/test-copy-acl.c | 2 +- + tests/test-set-mode-acl.c | 2 +- + +--- a/lib/acl.h ++++ b/lib/acl.h +@@ -20,7 +20,7 @@ + #ifndef _GL_ACL_H + #define _GL_ACL_H 1 + +-/* This file uses _GL_ATTRIBUTE_CONST. */ ++/* This file uses _GL_ATTRIBUTE_CONST, _GL_ATTRIBUTE_DEPRECATED. */ + #if !_GL_CONFIG_H_INCLUDED + #error "Please include config.h first." + #endif +@@ -35,10 +35,18 @@ extern "C" { + + bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; + int file_has_acl (char const *, struct stat const *); ++ + int qset_acl (char const *, int, mode_t); +-int set_acl (char const *, int, mode_t); ++int xset_acl (char const *, int, mode_t); ++/* Old name of xset_acl. */ ++_GL_ATTRIBUTE_DEPRECATED int set_acl (char const *, int, mode_t); ++ + int qcopy_acl (char const *, int, char const *, int, mode_t); +-int copy_acl (char const *, int, char const *, int, mode_t); ++int xcopy_acl (char const *, int, char const *, int, mode_t); ++/* Old name of xcopy_acl. */ ++_GL_ATTRIBUTE_DEPRECATED int copy_acl (char const *, int, char const *, int, ++ mode_t); ++ + int chmod_or_fchmod (char const *, int, mode_t); + + +--- a/lib/copy-acl.c ++++ b/lib/copy-acl.c +@@ -40,8 +40,8 @@ + negative error code. */ + + int +-copy_acl (const char *src_name, int source_desc, const char *dst_name, +- int dest_desc, mode_t mode) ++xcopy_acl (const char *src_name, int source_desc, const char *dst_name, ++ int dest_desc, mode_t mode) + { + int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); + switch (ret) +@@ -59,3 +59,10 @@ copy_acl (const char *src_name, int sour + } + return ret; + } ++ ++int ++copy_acl (const char *src_name, int source_desc, const char *dst_name, ++ int dest_desc, mode_t mode) ++{ ++ return xcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); ++} +--- a/lib/set-acl.c ++++ b/lib/set-acl.c +@@ -39,10 +39,16 @@ + return -1. */ + + int +-set_acl (char const *name, int desc, mode_t mode) ++xset_acl (char const *name, int desc, mode_t mode) + { + int ret = qset_acl (name, desc, mode); + if (ret != 0) + error (0, errno, _("setting permissions for %s"), quote (name)); + return ret; + } ++ ++int ++set_acl (char const *name, int desc, mode_t mode) ++{ ++ return xset_acl (name, desc, mode); ++} +--- a/tests/test-copy-acl.c ++++ b/tests/test-copy-acl.c +@@ -60,7 +60,7 @@ main (int argc, char *argv[]) + } + + #if USE_ACL +- if (copy_acl (file1, fd1, file2, fd2, mode)) ++ if (xcopy_acl (file1, fd1, file2, fd2, mode)) + exit (EXIT_FAILURE); + #else + chmod (file2, mode); +--- a/tests/test-set-mode-acl.c ++++ b/tests/test-set-mode-acl.c +@@ -35,7 +35,7 @@ main (int argc, char *argv[]) + file = argv[1]; + mode = strtol (argv[2], NULL, 8); + +- set_acl (file, -1, mode); ++ xset_acl (file, -1, mode); + + return test_exit_status; + } From 774ce21c6671427e5a28c5183acb0065549feeea Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 31 May 2025 14:07:05 -0400 Subject: [PATCH 09/51] tools/gnulib: use exact directory copy for install The python implementation of gnulib-tool uses a hidden file as the independent main function. A copy with glob ('*') does not include hidden files at the top level directory, so use whole directory copy instead and remove the patch for a non-hidden python file. Ensure the directory does not already exist by attempting uninstall first to remove it and by not using "install" to create a directory. Rename the clean target to uninstall, as it handles the staging directory and not the build directory. Removed: - 021-python-main.patch Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/gnulib/Makefile | 6 +++--- tools/gnulib/patches/021-python-main.patch | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) delete mode 100644 tools/gnulib/patches/021-python-main.patch diff --git a/tools/gnulib/Makefile b/tools/gnulib/Makefile index f708299549..245ba6be7d 100644 --- a/tools/gnulib/Makefile +++ b/tools/gnulib/Makefile @@ -14,14 +14,14 @@ define Host/Configure endef define Host/Install + $(call Host/Uninstall) $(INSTALL_DIR) $(1)/share/aclocal $(INSTALL_DATA) $(HOST_BUILD_DIR)/m4/*.m4 $(1)/share/aclocal/ - $(INSTALL_DIR) $(1)/share/gnulib - $(CP) $(HOST_BUILD_DIR)/* $(1)/share/gnulib/ + $(CP) $(HOST_BUILD_DIR)/ $(1)/share/gnulib/ ln -sf ../share/gnulib/gnulib-tool $(STAGING_DIR_HOST)/bin/gnulib-tool endef -define Host/Clean +define Host/Uninstall rm -rf $(STAGING_DIR_HOST)/bin/gnulib-tool $(STAGING_DIR_HOST)/share/gnulib endef diff --git a/tools/gnulib/patches/021-python-main.patch b/tools/gnulib/patches/021-python-main.patch deleted file mode 100644 index 1edb1d28a9..0000000000 --- a/tools/gnulib/patches/021-python-main.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- /dev/null -+++ b/gnulib-tool-main.py -@@ -0,0 +1,4 @@ -+from pygnulib import main -+ -+if __name__ == '__main__': -+ main.main_with_exception_handling() ---- a/gnulib-tool.py -+++ b/gnulib-tool.py -@@ -157,4 +157,4 @@ fi - profiler_args= - # For profiling, cf. . - #profiler_args="-m cProfile -s tottime" --exec python3 $profiler_args "$gnulib_dir/.gnulib-tool.py" "$@" -+exec python3 $profiler_args "$gnulib_dir/gnulib-tool-main.py" "$@" From 685fc753a7fd0e87cf61204620348ec0b40ba426 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 31 May 2025 14:00:45 -0400 Subject: [PATCH 10/51] download: add support for gitweb snapshots When downloading a snapshot archive from gitweb, the filename is not part of the URL, and adding the filename to the URL causes errors. The gitweb API exclusively uses query parameters instead of paths in order to execute snapshot downloads. Add a condition to the Perl download script that removes the filename if the relevant query parameter matches in the URL. Also, to reduce server load of the original sources try the Openwrt CDN servers first for these downloads. Even though snapshot downloads are not ideal due to the impact on the source's server health, they are better for download performance than using git only. Therefore, attempting it last will reduce the impact and thus encourage maintainers to keep the option enabled. This change is partly inspired by a conversation linked below about snapshot downloads and server performance issues which led to the feature being disabled for a particular server. Link: https://lists.gnu.org/archive/html/bug-gnulib/2024-12/msg00124.html Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- scripts/download.pl | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/download.pl b/scripts/download.pl index c6c9b8e56c..09dc91b04b 100755 --- a/scripts/download.pl +++ b/scripts/download.pl @@ -163,6 +163,7 @@ sub download my $mirror = shift; my $download_filename = shift; my @additional_mirrors = @_; + my @cmd; $mirror =~ s!/$!!; @@ -209,7 +210,11 @@ sub download } }; } else { - my @cmd = download_cmd("$mirror/$download_filename", $download_filename, @additional_mirrors); + if ($mirror =~ /a=snapshot/) { + @cmd = download_cmd("$mirror", $download_filename, @additional_mirrors); + } else { + @cmd = download_cmd("$mirror/$download_filename", $download_filename, @additional_mirrors); + } print STDERR "+ ".join(" ",@cmd)."\n"; open(FETCH_FD, '-|', @cmd) or die "Cannot launch aria2c, curl or wget.\n"; $hash_cmd and do { @@ -317,14 +322,23 @@ if (-f "$target/$filename") { $download_tool = select_tool(); +my $mirror = shift @mirrors; + +# Try snapshot original source last +if ($mirror =~ /snapshot/) { + push @mirrors, $mirror; + $mirror = shift @mirrors; +} + while (!-f "$target/$filename") { - my $mirror = shift @mirrors; $mirror or die "No more mirrors to try - giving up.\n"; download($mirror, $url_filename, @mirrors); if (!-f "$target/$filename" && $url_filename ne $filename) { download($mirror, $filename, @mirrors); } + + $mirror = shift @mirrors; } $SIG{INT} = \&cleanup; From 222a1bed794c83298ae6e7dfddbe0eed7dcab0fc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 8 Jul 2025 14:57:58 -0400 Subject: [PATCH 11/51] tools/gnulib: use git archive as download source Snapshot downloads, whether from GNU cgit or GNU gitweb, are becoming more unreliable and unstable. Use the GNU gnulib git repository server for downloads because GNU has disabled cgit server snapshots due to performance issues. Other possible options include GNU gitweb snapshot or a git bundle download but these methods either may also have similar performance issues or require additions to the build system to handle the method beyond the previous commit. In case snapshots are to be used again for build tools in the future, the previous commit reduces the tarball generation attempts for the original source of snapshots in order to reduce server impact. A conversation regarding server performance issues and alternatives is linked. Link: https://lists.gnu.org/archive/html/bug-gnulib/2024-12/msg00124.html Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/gnulib/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnulib/Makefile b/tools/gnulib/Makefile index 245ba6be7d..33e6aba1cc 100644 --- a/tools/gnulib/Makefile +++ b/tools/gnulib/Makefile @@ -2,11 +2,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gnulib PKG_CPE_ID:=cpe:/a:gnu:$(PKG_NAME) -PKG_VERSION:=320db6ee7a3cd44ee77f09d30c8a9002159beb4b# # stable-202407 -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://git.savannah.gnu.org/cgit/$(PKG_NAME).git/snapshot -PKG_HASH:=0be734e8c5f88e259bd593d63da2be275b93aedb551ccdcd78db9825bddeb94e +PKG_SOURCE_URL=git://git.git.savannah.gnu.org/$(PKG_NAME).git +PKG_SOURCE_DATE:=2025-05-03 +PKG_SOURCE_VERSION:=320db6ee7a3cd44ee77f09d30c8a9002159beb4b# # stable-202407 +PKG_MIRROR_HASH:=0c3d39a0d26381b042ac8e95d22b88bda99bc8cc3974b151b1de184c0f4ac1bf include $(INCLUDE_DIR)/host-build.mk From 9ea963e471d642c94159ab484f84b88ee3844201 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 4 Oct 2024 01:25:13 -0400 Subject: [PATCH 12/51] tools/automake: do not delete Makefile in clean targets For the building of some packages, it is sometimes helpful to completely clean the packaged release copy of the source, however this usually both requires and deletes the Makefile, causing the need to run the configure stage twice. Not deleting the Makefile allows compilation to continue directly after cleaning pre-generated files in the package distribution. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/automake/patches/999-clean-am.patch | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tools/automake/patches/999-clean-am.patch diff --git a/tools/automake/patches/999-clean-am.patch b/tools/automake/patches/999-clean-am.patch new file mode 100644 index 0000000000..87a0d6f3f6 --- /dev/null +++ b/tools/automake/patches/999-clean-am.patch @@ -0,0 +1,20 @@ +--- a/lib/am/clean.am ++++ b/lib/am/clean.am +@@ -39,7 +39,7 @@ distclean-generic: + ## If you change distclean here, you probably also want to change + ## maintainer-clean below. + distclean: +- -rm -f %MAKEFILE% ++ -touch %MAKEFILE% + + maintainer-clean-am: maintainer-clean-generic distclean-am + maintainer-clean-generic: +@@ -51,7 +51,7 @@ maintainer-clean-generic: + + ## See comment for distclean. + maintainer-clean: +- -rm -f %MAKEFILE% ++ -touch %MAKEFILE% + + .PHONY: clean mostlyclean distclean maintainer-clean \ + clean-generic mostlyclean-generic distclean-generic maintainer-clean-generic From c7554019ddf0d597cb4921788b04b843ab05e2a4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 22 Sep 2024 23:38:21 -0400 Subject: [PATCH 13/51] tools/libtool: add maintainer-clean to clean target Use the clean recipe during build, so that files already generated by the bootstrapping within the release are removed before the bootstrap script is run again. Override an automake variable "am__CONFIG_DISTCLEAN_FILES" and related variables for their dependencies in order to prevent removing config.status and other configure files so that configure stage does not need to be ran twice. Automake with modified rules must be ran in order to generate a Makefile that does not delete itself. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/libtool/Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/libtool/Makefile b/tools/libtool/Makefile index 761f7dc06b..4992fa7710 100644 --- a/tools/libtool/Makefile +++ b/tools/libtool/Makefile @@ -23,6 +23,10 @@ export GNULIB_SRCDIR:=$(HOST_GNULIB_SRCDIR) HOST_CONFIGURE_VARS += \ lt_cv_sys_dlsearch_path="" +HOST_MAKE_FLAGS += \ + am__CONFIG_DISTCLEAN_FILES= \ + CONFIG_STATUS_DEPENDENCIES= + define Host/Bootstrap ( \ cd $(HOST_BUILD_DIR); \ @@ -45,6 +49,7 @@ endef define Host/Configure $(if $(QUILT),$(call Host/Bootstrap)) $(call Host/Configure/Default) + $(call Host/Uninstall) endef define Host/Install @@ -54,6 +59,7 @@ endef define Host/Uninstall -$(call Host/Compile/Default,uninstall) + -$(call Host/Compile/Default,maintainer-clean) # Clean bootstrap files from the release (cd $(STAGING_DIR_HOST)/share/aclocal/ && rm -f libtool.m4 ltdl.m4 lt~obsolete.m4 ltoptions.m4 ltsugar.m4 ltversion.m4) endef From fddac9af6f03f6a6649e851de09b20e5f5f6c4e2 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 24 Sep 2024 18:17:09 -0400 Subject: [PATCH 14/51] tools/libtool: remove parallel building There is only one subdirectory for libtool that actually compiles, so enabling parallel building has no significant beneficial effects. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/libtool/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/libtool/Makefile b/tools/libtool/Makefile index 4992fa7710..dde4ff3130 100644 --- a/tools/libtool/Makefile +++ b/tools/libtool/Makefile @@ -14,8 +14,6 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/$(PKG_NAME) PKG_HASH:=da8ebb2ce4dcf46b90098daf962cffa68f4b4f62ea60f798d0ef12929ede6adf -HOST_BUILD_PARALLEL:=1 - include $(INCLUDE_DIR)/host-build.mk export GNULIB_SRCDIR:=$(HOST_GNULIB_SRCDIR) From 6d2bfe50d32bcaa53a1dd5012653661b29233dcc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 8 Oct 2024 06:55:47 -0400 Subject: [PATCH 15/51] tools/automake: control all cleaning with clean variables Automake previously makes rules for the target maintainer-clean to remove both the contents of MAINTAINERCLEANFILES and BUILT_SOURCES. In order to have finer control over what is removed, let there only be a rule for deleting MAINTAINERCLEANFILES, and set MAINTAINERCLEANFILES to a default value of BUILT_SOURCES if only conditional or missing, and append BUILT_SOURCES if user-defined. In order to maintain conditional values for MAINTAINERCLEANFILES while keeping a default value, change the behavior of automake to output unconditional definitions before conditions. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- .../patches/300-output-TRUE-cond-first.patch | 34 +++++++++++++ .../310-maintainer-clean-built_sources.patch | 49 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tools/automake/patches/300-output-TRUE-cond-first.patch create mode 100644 tools/automake/patches/310-maintainer-clean-built_sources.patch diff --git a/tools/automake/patches/300-output-TRUE-cond-first.patch b/tools/automake/patches/300-output-TRUE-cond-first.patch new file mode 100644 index 0000000000..1bfc0203dd --- /dev/null +++ b/tools/automake/patches/300-output-TRUE-cond-first.patch @@ -0,0 +1,34 @@ +--- a/lib/Automake/Variable.pm ++++ b/lib/Automake/Variable.pm +@@ -1259,8 +1259,15 @@ sub output_variables () + foreach my $var (@vars) + { + my $v = rvar $var; ++ # Output unconditional definitions before conditional ones. ++ if ($v->def (TRUE)) { ++ $res .= $v->output (TRUE) ++ if $v->rdef (TRUE)->owner == VAR_AUTOMAKE; ++ } + foreach my $cond ($v->conditions->conds) + { ++ # TRUE is handled already. ++ next if $cond->string eq "TRUE"; + $res .= $v->output ($cond) + if $v->rdef ($cond)->owner == VAR_AUTOMAKE; + } +@@ -1270,8 +1277,15 @@ sub output_variables () + foreach my $var (@vars) + { + my $v = rvar $var; ++ # Output unconditional definitions before conditional ones. ++ if ($v->def (TRUE)) { ++ $res .= $v->output (TRUE) ++ if $v->rdef (TRUE)->owner != VAR_AUTOMAKE; ++ } + foreach my $cond ($v->conditions->conds) + { ++ # TRUE is handled already. ++ next if $cond->string eq "TRUE"; + $res .= $v->output ($cond) + if $v->rdef ($cond)->owner != VAR_AUTOMAKE; + } diff --git a/tools/automake/patches/310-maintainer-clean-built_sources.patch b/tools/automake/patches/310-maintainer-clean-built_sources.patch new file mode 100644 index 0000000000..5737a65023 --- /dev/null +++ b/tools/automake/patches/310-maintainer-clean-built_sources.patch @@ -0,0 +1,49 @@ +--- a/bin/automake.in ++++ b/bin/automake.in +@@ -4745,12 +4745,42 @@ sub handle_clean + if var ('CLEANFILES'); + $clean_files{'$(DISTCLEANFILES)'} = DIST_CLEAN + if var ('DISTCLEANFILES'); +- $clean_files{'$(MAINTAINERCLEANFILES)'} = MAINTAINER_CLEAN +- if var ('MAINTAINERCLEANFILES'); + + # Built sources are automatically removed by maintainer-clean. +- $clean_files{'$(BUILT_SOURCES)'} = MAINTAINER_CLEAN +- if var ('BUILT_SOURCES'); ++ # For each defined condition of the maintainer-clean variable, append built sources ++ # and create an unconditional definition with built sources if not already defined. ++ # Then, for each definition of built sources without maintainer-clean defined, define it. ++ # Otherwise, if the variable is not user-defined, define it with built sources. ++ my $mcleanvar = var ('MAINTAINERCLEANFILES'); ++ if ($mcleanvar) { ++ foreach my $rcond ($mcleanvar->conditions->conds) ++ { ++ if (! grep { $_ eq '$(BUILT_SOURCES)' } $mcleanvar->value_as_list ($rcond)) { ++ Automake::Variable::define ($mcleanvar->name, VAR_MAKEFILE, '+', $rcond, ++ '$(BUILT_SOURCES)', '', INTERNAL, VAR_ASIS) ++ if vardef ('BUILT_SOURCES', $rcond); ++ } ++ } ++ my $bsources = var ('BUILT_SOURCES'); ++ if ($bsources) { ++ foreach my $rcond ($bsources->conditions->conds) ++ { ++ Automake::Variable::define ($mcleanvar->name, VAR_MAKEFILE, '', $rcond, ++ '$(BUILT_SOURCES)', '', INTERNAL, VAR_ASIS) ++ if ! vardef ($mcleanvar, $rcond); ++ } ++ if (! vardef ($mcleanvar, TRUE)) { ++ Automake::Variable::define ($mcleanvar->name, VAR_MAKEFILE, '', TRUE, ++ '$(BUILT_SOURCES)', '', INTERNAL, VAR_ASIS); ++ } ++ } ++ } else { ++ Automake::Variable::define ('MAINTAINERCLEANFILES', VAR_MAKEFILE, '', TRUE, ++ '$(BUILT_SOURCES)', '', INTERNAL, VAR_ASIS) ++ if var ('BUILT_SOURCES'); ++ } ++ $clean_files{'$(MAINTAINERCLEANFILES)'} = MAINTAINER_CLEAN ++ if var ('MAINTAINERCLEANFILES'); + + # Compute a list of "rm"s to run for each target. + my %rms = (MOSTLY_CLEAN, [], From 40c241d85738c08c5ef8db78ff008197f05c6b88 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 15 May 2025 14:02:02 -0400 Subject: [PATCH 16/51] tools/coreutils: do not require gettext or gperf The bootstrap configuration is set to require gettext and gperf for regenerating documentation and headers. However, these steps are skipped in favor of not building documentation and using existing headers. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/patches/000-bootstrap.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tools/coreutils/patches/000-bootstrap.patch b/tools/coreutils/patches/000-bootstrap.patch index 68db19084f..ea0ea7e37e 100644 --- a/tools/coreutils/patches/000-bootstrap.patch +++ b/tools/coreutils/patches/000-bootstrap.patch @@ -43,3 +43,17 @@ grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \ with_gettext=no +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -349,11 +349,8 @@ gnulib_tool_option_extras="--tests-base= + buildreq="\ + autoconf 2.64 + automake 1.11.2 +-autopoint 0.19.2 + bison - +-gettext 0.19.2 + git 1.4.4 +-gperf - + gzip - + m4 - + makeinfo 6.1 From 199afe9ef79d00ddda8ac161062ca3b1429d1200 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 6 May 2025 14:54:55 -0400 Subject: [PATCH 17/51] tools/coreutils: update to 9.6 Update to the next stable release. Prevent the need for gperf to build gperf based headers due to new gnulib versions by skipping replacement of gperf files. Without Automake, there are some existing macro conflicts due to the new version of gnulib, causing build errors with some source files, so skip those file replacements. All patches are automatically refreshed. Link: https://lists.gnu.org/archive/html/coreutils/2025-01/msg00049.html Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 20 +++++++++++++++----- tools/coreutils/patches/000-bootstrap.patch | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index 73b95912ee..d1948042b9 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=coreutils PKG_CPE_ID:=cpe:/a:gnu:coreutils -PKG_VERSION:=9.5 +PKG_VERSION:=9.6 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/coreutils -PKG_HASH:=767ae6a22950ec42f3ba5f7c1de79dd27800ee8e9b8642da5dedb5974a1741e5 +PKG_HASH:=2bec616375002c92c1ed5ead32a092b174fe44c14bc736d32e5961053b821d84 HOST_BUILD_PARALLEL := 1 @@ -23,10 +23,20 @@ include $(INCLUDE_DIR)/host-build.mk export GNULIB_SRCDIR:=$(HOST_GNULIB_SRCDIR) HOST_GNULIB_SKIP := \ - lib/nstrftime.c \ - lib/fprintftime.c \ + lib/c++defs.h \ + lib/realloc.c \ + lib/reallocarray.c \ + lib/savedir.c \ lib/fcntl.in.h \ - lib/locale.in.h + lib/stdio.in.h \ + lib/stdlib.in.h \ + lib/se-selinux.in.h \ + lib/iconv_open-aix.gperf \ + lib/iconv_open-hpux.gperf \ + lib/iconv_open-irix.gperf \ + lib/iconv_open-osf.gperf \ + lib/iconv_open-solaris.gperf \ + lib/iconv_open-zos.gperf HOST_CONFIGURE_ARGS += \ --enable-install-program=$(subst $(space),$(comma),$(strip $(PKG_PROGRAMS))) diff --git a/tools/coreutils/patches/000-bootstrap.patch b/tools/coreutils/patches/000-bootstrap.patch index ea0ea7e37e..1edf879e0e 100644 --- a/tools/coreutils/patches/000-bootstrap.patch +++ b/tools/coreutils/patches/000-bootstrap.patch @@ -34,7 +34,7 @@ if [ ! "$inst_ver" ]; then warn_ "Error: '$app' not found" ret=1 -@@ -1157,7 +1157,7 @@ autogen() +@@ -1205,7 +1205,7 @@ autogen() # two just-pre-run programs. # Import from gettext. @@ -45,7 +45,7 @@ --- a/bootstrap.conf +++ b/bootstrap.conf -@@ -349,11 +349,8 @@ gnulib_tool_option_extras="--tests-base= +@@ -354,11 +354,8 @@ gnulib_tool_option_extras="--tests-base= buildreq="\ autoconf 2.64 automake 1.11.2 From 26f8a3874b1d1a393cbd081b4e5a05a5aa3b534c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 6 Oct 2024 04:13:16 -0400 Subject: [PATCH 18/51] tools/coreutils: use automake during bootstrap This was previously not possible because part of the source code for coreutils in the form of extra gnulib modules was missing from the release distribution. Now that the local modules from coreutils source is included in coreutils releases, the bootstrap script can be ran without skipping automake in the autoreconf stage after importing modules by using fake paths to each autotools program, and instead use the real paths to our modified autotools. Because we do not require tools for building documentation, continue to fake the paths to autopoint and gtkdocize. Remove the skipping of imports of some source files which is no longer necessary. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index d1948042b9..3dc82afafc 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -23,14 +23,6 @@ include $(INCLUDE_DIR)/host-build.mk export GNULIB_SRCDIR:=$(HOST_GNULIB_SRCDIR) HOST_GNULIB_SKIP := \ - lib/c++defs.h \ - lib/realloc.c \ - lib/reallocarray.c \ - lib/savedir.c \ - lib/fcntl.in.h \ - lib/stdio.in.h \ - lib/stdlib.in.h \ - lib/se-selinux.in.h \ lib/iconv_open-aix.gperf \ lib/iconv_open-hpux.gperf \ lib/iconv_open-irix.gperf \ @@ -42,14 +34,14 @@ HOST_CONFIGURE_ARGS += \ --enable-install-program=$(subst $(space),$(comma),$(strip $(PKG_PROGRAMS))) HOST_MAKE_FLAGS += \ - $(AM_TOOL_PATHS_FAKE) \ + $(AM_TOOL_PATHS) AUTOPOINT="$(TRUE)" GTKDOCIZE="$(TRUE)" \ PROGRAMS="$(patsubst %,src/%,$(PKG_PROGRAMS))" \ LIBRARIES= MANS= SUBDIRS=. define Host/Bootstrap ( \ cd $(HOST_BUILD_DIR); \ - $(AM_TOOL_PATHS_FAKE) \ + $(AM_TOOL_PATHS) AUTOPOINT="$(TRUE)" GTKDOCIZE="$(TRUE)" \ ./bootstrap \ --bootstrap-sync \ --force \ From 6a3cfeb4a66763630cca9cb100ec86f5fddbd79b Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 26 Sep 2024 23:30:51 -0400 Subject: [PATCH 19/51] tools/coreutils: add maintainer-clean to clean target Use the clean recipe during build, so that files already generated by the bootstrapping within the release are removed before the bootstrap script is run again. Automake with modified rules must be ran in order to generate a Makefile that does not delete itself. Override an automake variable "am__CONFIG_DISTCLEAN_FILES" in order to prevent removing config.status and other configure files so that configure stage does not need to be ran twice. Redefine MAINTAINERCLEANFILES with Make functions to avoid deleting the targets of gettext and gperf rules. In order to prevent an inconsistent state of `install` since this utility must always be available as a prerequisite, do not allow it to be removed. Instead of preventing the removal of the config.h header, the Makefile supports regenerating it quickly. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index 3dc82afafc..42f03317d9 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -35,6 +35,8 @@ HOST_CONFIGURE_ARGS += \ HOST_MAKE_FLAGS += \ $(AM_TOOL_PATHS) AUTOPOINT="$(TRUE)" GTKDOCIZE="$(TRUE)" \ + am__CONFIG_DISTCLEAN_FILES= \ + MAINTAINERCLEANFILES='$$$$(filter-out lib/iconv_open% %.texi,$$$$(BUILT_SOURCES))' \ PROGRAMS="$(patsubst %,src/%,$(PKG_PROGRAMS))" \ LIBRARIES= MANS= SUBDIRS=. @@ -60,6 +62,8 @@ define Host/Configure $(if $(QUILT),$(call Host/Bootstrap)) $(foreach src,$(HOST_GNULIB_SKIP),mv -f $(HOST_BUILD_DIR)/$(src)~ $(HOST_BUILD_DIR)/$(src) || true; ) $(call Host/Configure/Default) + $(call Host/Uninstall) + $(call Host/Compile/Default,lib/config.h) endef define Host/Install @@ -69,8 +73,8 @@ define Host/Install endef define Host/Uninstall - rm -f $(STAGING_DIR_HOST)/bin/install -$(call Host/Compile/Default,uninstall) + -$(call Host/Compile/Default,maintainer-clean) # Clean bootstrap files from the release endef $(eval $(call HostBuild)) From 5c832d783381831289c4f65d2a821a0eecfc435f Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 30 Sep 2024 15:59:06 -0400 Subject: [PATCH 20/51] tools/coreutils: disable uninstall target GNU coreutils is a unique case where we require some of the utilities on the host machine before anything is built. The prerequisite is handled by symlinks to the host binaries in the staging directory that are installed by the build system and that are expected to remain as long as the corresponding stampfile exists. Because the binaries built by coreutils will replace the symlinks, the uninstall target will actually delete the symlinks long before the build finishes whenever it is ran. This can cause the utilities to be temporarily missing from the controlled part of the shell's PATH, so disable the removal of the coreutils utilities. The appropriate way to clear all of the programs and links would be `make dirclean`. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index 42f03317d9..84aba9e64a 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -73,7 +73,7 @@ define Host/Install endef define Host/Uninstall - -$(call Host/Compile/Default,uninstall) + #$(call Host/Compile/Default,uninstall) # Removes necessary symlinks -$(call Host/Compile/Default,maintainer-clean) # Clean bootstrap files from the release endef From b8c0ed469238291298732512045ed8659ac22ea8 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 30 Sep 2024 03:55:14 -0400 Subject: [PATCH 21/51] tools/coreutils: replace symlinks to build prerequisites Before building, symlinks are made from existing utilities on the host machine, because they are necessary before coreutils can be built. Instead of leaving these utilities as symlinks, replace them with the copy provided by the coreutils build in order to increase version control for these utilities and to have a real copy for targets like the SDK. The utilities required before building and provided by coreutils are cp, install, realpath, seq, and stat. Let all of the utilities be installed with the "g" prefix, then, existing symlinks named without the "g" prefix are safely replaced with a new symlink using the coreutils version of `ln` just built in order to prevent an inconsistent state of the file since these utilities must always be available. While at it, sort the list alphabetically. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index 84aba9e64a..fcd2fa76bb 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -16,7 +16,7 @@ PKG_HASH:=2bec616375002c92c1ed5ead32a092b174fe44c14bc736d32e5961053b821d84 HOST_BUILD_PARALLEL := 1 -PKG_PROGRAMS:=date readlink touch ln chown ginstall +PKG_PROGRAMS:=chown cp date ginstall ln readlink realpath seq stat touch include $(INCLUDE_DIR)/host-build.mk @@ -68,8 +68,10 @@ endef define Host/Install $(INSTALL_DIR) $(1)/bin - $(INSTALL_BIN) $(patsubst %,$(HOST_BUILD_DIR)/src/%,$(PKG_PROGRAMS)) $(1)/bin/ - ln -sf ginstall $(1)/bin/install + $(foreach prog,$(filter-out g%,$(PKG_PROGRAMS)),$(INSTALL_BIN) $(patsubst %,$(HOST_BUILD_DIR)/src/%,$(prog)) $(1)/bin/g$(prog); ) + $(foreach prog,$(filter g%,$(PKG_PROGRAMS)),$(INSTALL_BIN) $(patsubst %,$(HOST_BUILD_DIR)/src/%,$(prog)) $(1)/bin/$(prog); ) + $(foreach prog,$(filter-out g%,$(PKG_PROGRAMS)),g$(LN) g$(prog) $(1)/bin/$(prog); ) + $(foreach prog,$(filter g%,$(PKG_PROGRAMS)),g$(LN) $(prog) $(1)/bin/$(patsubst g%,%,$(prog)); ) endef define Host/Uninstall From 90262c6f6e111d6efff134d74d180114af2d5655 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 26 Sep 2024 23:17:41 -0400 Subject: [PATCH 22/51] tools/coreutils: provide the rmdir utility Use the rmdir utility provided by GNU coreutils for macOS in order to be able to use the option "--ignore-fail-on-non-empty". Some other tools such as elfutils use this while building. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/coreutils/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index fcd2fa76bb..a0443b214c 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -16,7 +16,7 @@ PKG_HASH:=2bec616375002c92c1ed5ead32a092b174fe44c14bc736d32e5961053b821d84 HOST_BUILD_PARALLEL := 1 -PKG_PROGRAMS:=chown cp date ginstall ln readlink realpath seq stat touch +PKG_PROGRAMS:=chown cp date ginstall ln readlink realpath rmdir seq stat touch include $(INCLUDE_DIR)/host-build.mk From 660e398f92472fd31dc6947f669268301c96b547 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 3 Oct 2024 00:49:10 -0400 Subject: [PATCH 23/51] prereq: add support for creating relative symlinks For targets that install symlinks, like coreutils, if the links happen to be deleted, let prereq stage be capable of creating them again with a relative path. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- include/prereq.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/prereq.mk b/include/prereq.mk index 1039c5540c..23287eade4 100644 --- a/include/prereq.mk +++ b/include/prereq.mk @@ -113,7 +113,7 @@ define SetupHostCommand [ -x "$(STAGING_DIR_HOST)/bin/$(strip $(1))" ] && exit 0 \ ;; \ esac; \ - ln -sf "$$$$$$$$bin" "$(STAGING_DIR_HOST)/bin/$(strip $(1))"; \ + ln -sf "$$$$$$$${bin#$(STAGING_DIR_HOST)/bin/}" "$(STAGING_DIR_HOST)/bin/$(strip $(1))"; \ exit 1; \ fi; \ fi; \ From f197b5827a2836d87b95c95f9a638b1073a33e61 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 3 Oct 2024 00:57:29 -0400 Subject: [PATCH 24/51] prereq: prefer existing built coreutils as symlink target For the utilities provided by coreutils but required before coreutils is built, if coreutils is actually built already, prefer a symlink to the built versions instead of the host machine's version. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- include/prereq-build.mk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/prereq-build.mk b/include/prereq-build.mk index 913888e0ad..b913e62e43 100644 --- a/include/prereq-build.mk +++ b/include/prereq-build.mk @@ -126,10 +126,12 @@ $(eval $(call SetupHostCommand,diff,Please install GNU diffutils, \ diff --version 2>&1 | grep GNU)) $(eval $(call SetupHostCommand,cp,Please install GNU fileutils, \ + $(TOPDIR)/staging_dir/host/bin/gcp --help 2>&1 | grep 'Copy SOURCE', \ gcp --help 2>&1 | grep 'Copy SOURCE', \ cp --help 2>&1 | grep 'Copy SOURCE')) $(eval $(call SetupHostCommand,seq,Please install seq, \ + $(TOPDIR)/staging_dir/host/bin/gseq --version, \ gseq --version, \ seq --version 2>&1 | grep seq)) @@ -153,10 +155,12 @@ $(eval $(call SetupHostCommand,getopt, \ /opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--')) $(eval $(call SetupHostCommand,realpath,Please install a 'realpath' utility, \ + $(TOPDIR)/staging_dir/host/bin/grealpath /, \ grealpath /, \ realpath /)) $(eval $(call SetupHostCommand,stat,Cannot find a file stat utility, \ + $(TOPDIR)/staging_dir/host/bin/gstat -c%s $(TOPDIR)/Makefile, \ gnustat -c%s $(TOPDIR)/Makefile, \ gstat -c%s $(TOPDIR)/Makefile, \ stat -c%s $(TOPDIR)/Makefile)) @@ -175,6 +179,7 @@ $(eval $(call SetupHostCommand,wget,Please install GNU 'wget', \ wget --version | grep GNU)) $(eval $(call SetupHostCommand,install,Please install GNU 'install', \ + $(TOPDIR)/staging_dir/host/bin/ginstall --version | grep GNU, \ install --version | grep GNU, \ ginstall --version | grep GNU)) From f7fd8303be53598633426830f31b9818b32d2521 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 3 Oct 2024 01:06:04 -0400 Subject: [PATCH 25/51] tools: build coreutils for development targets Include the coreutils utilities required for macOS and other non-GNU friendly OSs to products like the SDK. This also allows manually building coreutils on Linux without having to manually edit this Makefile. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/Makefile | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index c2b36361a4..81d034f993 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -97,6 +97,7 @@ $(curdir)/bison/compile := $(curdir)/flex/compile $(curdir)/bzip2/compile := $(curdir)/cmake/compile $(curdir)/cbootimage/compile += $(curdir)/automake/compile $(curdir)/cmake/compile += $(curdir)/libressl/compile $(curdir)/ninja/compile $(curdir)/expat/compile $(curdir)/xz/compile $(curdir)/zlib/compile $(curdir)/zstd/compile +$(curdir)/coreutils/compile := $(curdir)/automake/compile $(curdir)/bison/compile $(curdir)/gnulib/compile $(curdir)/dosfstools/compile := $(curdir)/automake/compile $(curdir)/e2fsprogs/compile := $(curdir)/libtool/compile $(curdir)/util-linux/compile $(curdir)/elfutils/compile := $(curdir)/m4/compile $(curdir)/zlib/compile $(curdir)/gnulib/compile $(curdir)/libtool/compile @@ -136,10 +137,14 @@ $(curdir)/util-linux/compile := $(curdir)/bison/compile $(curdir)/automake/compi $(curdir)/yafut/compile := $(curdir)/cmake/compile ifneq ($(HOST_OS),Linux) - $(curdir)/coreutils/compile += $(curdir)/automake/compile $(curdir)/bison/compile $(curdir)/gnulib/compile - $(curdir)/squashfs4/compile += $(curdir)/coreutils/compile tools-y += coreutils +else + tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_SDK),y) += coreutils endif +ifneq ($(filter coreutils,$(tools-y)),) + $(curdir)/squashfs4/compile += $(curdir)/coreutils/compile +endif + ifeq ($(HOST_OS),Darwin) tools-y += bash else From e776c9fe4ef9823993e230f2795d4255876e5ca2 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 26 Sep 2024 23:20:38 -0400 Subject: [PATCH 26/51] tools: require coreutils to build elfutils The version of the rmdir utility in macOS is POSIX-only while elfutils uses the GNU extended options while building. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/Makefile b/tools/Makefile index 81d034f993..e86e2789e6 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -142,6 +142,7 @@ else tools-$(if $(CONFIG_BUILD_ALL_HOST_TOOLS)$(CONFIG_SDK),y) += coreutils endif ifneq ($(filter coreutils,$(tools-y)),) + $(curdir)/elfutils/compile += $(curdir)/coreutils/compile $(curdir)/squashfs4/compile += $(curdir)/coreutils/compile endif From 405652469fc4d8bd589031c39693434be52d39e7 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 27 Sep 2024 01:18:03 -0400 Subject: [PATCH 27/51] tools: require coreutils to build findutils The install stage of findutils uses the install utility with GNU options which is provided to macOS by coreutils. Before, Make coincidentally built them in the right order, this makes the prerequisite explicit. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/Makefile b/tools/Makefile index e86e2789e6..e01d95d0ec 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -143,6 +143,7 @@ else endif ifneq ($(filter coreutils,$(tools-y)),) $(curdir)/elfutils/compile += $(curdir)/coreutils/compile + $(curdir)/findutils/compile += $(curdir)/coreutils/compile $(curdir)/squashfs4/compile += $(curdir)/coreutils/compile endif From 7a8fd735489e6d02ecccfe63ffdf7c3694ee8dbc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 27 Sep 2024 00:20:38 -0400 Subject: [PATCH 28/51] tools: require coreutils to build util-linux The install stage of util-linux uses the install utility with GNU options which is provided to macOS by coreutils. Before, Make coincidentally built them in the right order, this makes the prerequisite explicit. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/Makefile b/tools/Makefile index e01d95d0ec..800647762f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -145,6 +145,7 @@ ifneq ($(filter coreutils,$(tools-y)),) $(curdir)/elfutils/compile += $(curdir)/coreutils/compile $(curdir)/findutils/compile += $(curdir)/coreutils/compile $(curdir)/squashfs4/compile += $(curdir)/coreutils/compile + $(curdir)/util-linux/compile += $(curdir)/coreutils/compile endif ifeq ($(HOST_OS),Darwin) From 30105c77efc09ec5edbaba4741f4f8f265f1f2aa Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 6 Oct 2024 04:23:10 -0400 Subject: [PATCH 29/51] tools/automake: do not delete libtool in clean targets For the building of some packages, it is helpful to completely clean the packaged release copy of the source, however this usually deletes libtool if used, otherwise causing the need to run the bootstrap script twice. Not deleting libtool allows compilation to continue directly after cleaning pre-generated files in the package distribution. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/automake/patches/999-clean-am.patch | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/automake/patches/999-clean-am.patch b/tools/automake/patches/999-clean-am.patch index 87a0d6f3f6..a9642d1c79 100644 --- a/tools/automake/patches/999-clean-am.patch +++ b/tools/automake/patches/999-clean-am.patch @@ -18,3 +18,11 @@ .PHONY: clean mostlyclean distclean maintainer-clean \ clean-generic mostlyclean-generic distclean-generic maintainer-clean-generic +--- a/lib/am/libtool.am ++++ b/lib/am/libtool.am +@@ -25,4 +25,4 @@ clean-libtool: + + ?TOPDIR_P?distclean-am: distclean-libtool + ?TOPDIR_P?distclean-libtool: +-?TOPDIR_P? -rm -f libtool config.lt ++?TOPDIR_P? -touch libtool config.lt From 8f920d2f94b0878e9b4291ffa18cfc9e02828f77 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 20 Oct 2024 07:49:50 -0400 Subject: [PATCH 30/51] tools/elfutils: replace dependency hack with upstream include path fix In order to solve the problem of the possibility that the "stack" binary is incorrectly included as a header while the compiler looks for the standard C++ header "stack", a workaround forcing a dependency between building "stack" and the C++ program was introduced. This upstream fix uses the compiler "-iquote" option in order to avoid looking for standard headers in the current working directory and blocks the default inclusion of "-I ." to the compiler flags. The upstream fix happens to be incomplete, so add an extra patch to fix an additional instance and then remove the workaround. Also, adjust the way DEFAULT_INCLUDES is overridden in the build Makefile by using the "-iquote" option in the same manner in order to remove all instances of the default inclusion for the current directory. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/elfutils/Makefile | 2 +- .../patches/000-backport-iquote-include.patch | 37 +++++++++++++++++++ .../001-fix-backport-iquote-include.patch | 12 ++++++ tools/elfutils/patches/100-portability.patch | 10 ----- 4 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 tools/elfutils/patches/000-backport-iquote-include.patch create mode 100644 tools/elfutils/patches/001-fix-backport-iquote-include.patch diff --git a/tools/elfutils/Makefile b/tools/elfutils/Makefile index ae829cd340..6aa23bfbc5 100644 --- a/tools/elfutils/Makefile +++ b/tools/elfutils/Makefile @@ -55,7 +55,7 @@ export $(PKG_GNULIB_BASE)_fallocate-posix=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$ export $(PKG_GNULIB_BASE)_tsearch=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-tsearch.o HOST_MAKE_FLAGS += \ - DEFAULT_INCLUDES='-I. -I$$$$(top_builddir) -I$$$$(top_srcdir)/$(PKG_GNULIB_BASE)' \ + DEFAULT_INCLUDES='-iquote . -I$$$$(top_builddir) -I$$$$(top_srcdir)/$(PKG_GNULIB_BASE)' \ AM_LDFLAGS='$$$$(STACK_USAGE_NO_ERROR)' \ LIBS+='$$$$(if $$$$(findstring $(lastword $(PKG_SUBDIRS)),$$$$(subdir)), $$$$($(PKG_GNULIB_BASE)))' \ LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_fallocate-posix))' \ diff --git a/tools/elfutils/patches/000-backport-iquote-include.patch b/tools/elfutils/patches/000-backport-iquote-include.patch new file mode 100644 index 0000000000..2c7657fc8c --- /dev/null +++ b/tools/elfutils/patches/000-backport-iquote-include.patch @@ -0,0 +1,37 @@ +From b426c4db31e7c80d4262abdd845d2ece0c9a841c Mon Sep 17 00:00:00 2001 +From: Alfred Wingate +Date: Wed, 14 Aug 2024 12:14:38 -0400 +Subject: [PATCH] Avoid overriding libcxx system header + +Replace -I with -iquote to avoid overriding stack system header from libcxx-18 +with the previously built stack binary. Override DEFAULT_INLCUDES because m4 +adds -I. by default. + +Signed-off-by: Aaron Merey +--- + config/eu.am | 2 +- + src/Makefile.am | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +--- a/config/eu.am ++++ b/config/eu.am +@@ -31,7 +31,7 @@ + ## + + DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' +-AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. ++AM_CPPFLAGS = -iquote . -I$(srcdir) -I$(top_srcdir)/lib -I.. + + # Drop the 'u' flag that automake adds by default. It is incompatible + # with deterministic archives. +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -19,6 +19,8 @@ + include $(top_srcdir)/config/eu.am + DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRED@ \ + -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\" ++ ++DEFAULT_INCLUDES = + AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ + -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ + -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm -I../debuginfod diff --git a/tools/elfutils/patches/001-fix-backport-iquote-include.patch b/tools/elfutils/patches/001-fix-backport-iquote-include.patch new file mode 100644 index 0000000000..62ed84dd27 --- /dev/null +++ b/tools/elfutils/patches/001-fix-backport-iquote-include.patch @@ -0,0 +1,12 @@ +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -21,7 +21,8 @@ DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRE + -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\" + + DEFAULT_INCLUDES = +-AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ ++AM_CPPFLAGS = -iquote . -iquote $(srcdir) -I$(top_srcdir)/lib \ ++ -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ + -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ + -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm -I../debuginfod + diff --git a/tools/elfutils/patches/100-portability.patch b/tools/elfutils/patches/100-portability.patch index 2cc8a4c56e..be97f95faa 100644 --- a/tools/elfutils/patches/100-portability.patch +++ b/tools/elfutils/patches/100-portability.patch @@ -288,13 +288,3 @@ /* Definitions of arguments for argp functions. */ static const struct argp_option options[] = ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -92,6 +92,7 @@ strings_LDADD = $(libelf) $(libeu) $(arg - ar_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD) $(obstack_LIBS) - unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) - stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) $(demanglelib) -+EXTRA_stack_DEPENDENCIES = $(if $(findstring srcfiles,$(bin_PROGRAMS)),$(srcfiles_OBJECTS)) - elfcompress_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) - elfclassify_LDADD = $(libelf) $(libdw) $(libeu) $(argp_LDADD) - srcfiles_SOURCES = srcfiles.cxx From c16ed51e0606833f9094f0d9b44f7db7f85b2988 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 20 Oct 2024 08:33:21 -0400 Subject: [PATCH 31/51] tools/elfutils: backport version 0.192 portability patches These patches will be present in version 0.192 release. Include them before the update to support changes before updating and in order to have a more organized git history. Manually refreshed patch: - 110-objects-manifest.patch Add patch: - 095-src-unused-variable.patch - 096-lib-config_h.patch - 097-libcpu-config_h.patch - 098-libdw-maintainer-clean.patch - 099-remove-unlocked-stdio.patch Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- .../patches/095-src-unused-variable.patch | 29 + tools/elfutils/patches/096-lib-config_h.patch | 29 + .../patches/097-libcpu-config_h.patch | 47 ++ .../patches/098-libdw-maintainer-clean.patch | 43 ++ .../patches/099-remove-unlocked-stdio.patch | 687 ++++++++++++++++++ tools/elfutils/patches/100-portability.patch | 22 - .../patches/101-shared-conditional.patch | 4 +- .../patches/110-objects-manifest.patch | 5 +- 8 files changed, 840 insertions(+), 26 deletions(-) create mode 100644 tools/elfutils/patches/095-src-unused-variable.patch create mode 100644 tools/elfutils/patches/096-lib-config_h.patch create mode 100644 tools/elfutils/patches/097-libcpu-config_h.patch create mode 100644 tools/elfutils/patches/098-libdw-maintainer-clean.patch create mode 100644 tools/elfutils/patches/099-remove-unlocked-stdio.patch diff --git a/tools/elfutils/patches/095-src-unused-variable.patch b/tools/elfutils/patches/095-src-unused-variable.patch new file mode 100644 index 0000000000..be5d285574 --- /dev/null +++ b/tools/elfutils/patches/095-src-unused-variable.patch @@ -0,0 +1,29 @@ +From ef8a4b841aaf26326b8961a651dbe915d54d23e7 Mon Sep 17 00:00:00 2001 +From: Jose Quaresma +Date: Tue, 19 Mar 2024 10:34:33 +0000 +Subject: [PATCH] srcfiles: fix unused variable BUFFER_SIZE + +The const variable BUFFER_SIZE is used only on the zip_files +function witch is only available with LIBARCHIVE. + +| ../../elfutils-0.191/src/srcfiles.cxx:81:18: error: unused variable 'BUFFER_SIZE' [-Werror,-Wunused-const-variable] +| 81 | constexpr size_t BUFFER_SIZE = 8192; +| | ^~~~~~~~~~~ + +Signed-off-by: Jose Quaresma +--- + src/srcfiles.cxx | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/src/srcfiles.cxx ++++ b/src/srcfiles.cxx +@@ -78,7 +78,9 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_ve + /* Bug report address. */ + ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; + ++#ifdef HAVE_LIBARCHIVE + constexpr size_t BUFFER_SIZE = 8192; ++#endif + + /* Definitions of arguments for argp functions. */ + static const struct argp_option options[] = diff --git a/tools/elfutils/patches/096-lib-config_h.patch b/tools/elfutils/patches/096-lib-config_h.patch new file mode 100644 index 0000000000..cc31fcfff2 --- /dev/null +++ b/tools/elfutils/patches/096-lib-config_h.patch @@ -0,0 +1,29 @@ +From c981e61aa301d389f18df5fd279c1ca4d39d38a0 Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Thu, 10 Oct 2024 10:26:54 +0000 +Subject: [PATCH] lib: Add missing config.h include to next_prime.c + +This is the last remaining C source file as of this commit +without the standard conditional inclusion of config.h +as the very first header. + + * lib/next_prime.c: add missing config.h header. + +Signed-off-by: Michael Pratt +--- + lib/next_prime.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/lib/next_prime.c ++++ b/lib/next_prime.c +@@ -27,6 +27,10 @@ + the GNU Lesser General Public License along with this program. If + not, see . */ + ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ + #include + + diff --git a/tools/elfutils/patches/097-libcpu-config_h.patch b/tools/elfutils/patches/097-libcpu-config_h.patch new file mode 100644 index 0000000000..7bcd858696 --- /dev/null +++ b/tools/elfutils/patches/097-libcpu-config_h.patch @@ -0,0 +1,47 @@ +From 7f06ac2b3fc0077f29bcc68064ca8e91fa7cd080 Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Thu, 10 Oct 2024 10:27:02 +0000 +Subject: [PATCH] libcpu: Include config.h before standard headers in lexer + source + +As part of the processing of flex, definitions and headers +are added to output source before any literal text or generated code. + +This causes standard headers to come before config.h +unless config.h is included in a %top block instead +as specified in the flex manual, section 5.1 "Format of the Definitions". + +The %top block is non-POSIX, so using it reinforces +the requirement of "flex" over a standardized "lex" even more. + + * libcpu/i386_lex.l (%top): add flex %top block + and move config.h header inclusion to it. + +Signed-off-by: Michael Pratt +--- + libcpu/i386_lex.l | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/libcpu/i386_lex.l ++++ b/libcpu/i386_lex.l +@@ -1,3 +1,9 @@ ++%top{ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++} ++ + %{ + /* Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc. + Written by Ulrich Drepper , 2004. +@@ -26,10 +32,6 @@ + the GNU Lesser General Public License along with this program. If + not, see . */ + +-#ifdef HAVE_CONFIG_H +-# include +-#endif +- + #include + + #include diff --git a/tools/elfutils/patches/098-libdw-maintainer-clean.patch b/tools/elfutils/patches/098-libdw-maintainer-clean.patch new file mode 100644 index 0000000000..f502af226f --- /dev/null +++ b/tools/elfutils/patches/098-libdw-maintainer-clean.patch @@ -0,0 +1,43 @@ +From b68f34725229b08380a1612899b0537f8f597dad Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Thu, 10 Oct 2024 10:27:09 +0000 +Subject: [PATCH] libdw: Let clean targets be unconditional + +The automake rule "maintainer-clean-generic" +is always available and never conditional, +so let the variable that uses it be define +non-conditionally. + +If one actually wants conditional cleaning +they should write a custom rule and set it +as a dependency of a "*clean-local" automake rule. + +There is no need to do conditional cleaning here, +so move the MAINTAINERCLEANFILES variable definition +to the end of the Makefile.am file as it is +in the rest of the project. + + * libdw/Makefile.am: move MAINTAINERCLEANFILES + variable to the end of the file + as a non-conditional definition. + +Signed-off-by: Michael Pratt +--- + libdw/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/libdw/Makefile.am ++++ b/libdw/Makefile.am +@@ -97,7 +97,6 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_be + + if MAINTAINER_MODE + BUILT_SOURCES = $(srcdir)/known-dwarf.h +-MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h + $(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h + gawk -f $^ > $@.new + mv -f $@.new $@ +@@ -154,3 +153,4 @@ noinst_HEADERS = libdwP.h memory-access. + EXTRA_DIST = libdw.map + + MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so libdw.so.$(VERSION) ++MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h diff --git a/tools/elfutils/patches/099-remove-unlocked-stdio.patch b/tools/elfutils/patches/099-remove-unlocked-stdio.patch new file mode 100644 index 0000000000..a0089a3a4c --- /dev/null +++ b/tools/elfutils/patches/099-remove-unlocked-stdio.patch @@ -0,0 +1,687 @@ +From 12d58cf3e30dee91ed7aadb6475a15c6e74cc88b Mon Sep 17 00:00:00 2001 +From: Michael Pratt +Date: Wed, 16 Oct 2024 19:53:52 +0000 +Subject: [PATCH] Remove usage of "unlocked" variant of stdio print functions + +These "unlocked" Linux Standard Base variants of standard functions +are not available on some systems that are still capable +of building Linux and ELFs. + +The difference is negligible for simple printing to stdout. + +POSIX also states for the similar putc_unlocked(): + + These functions can safely be used in a multi-threaded program + if and only if they are called while the invoking thread owns + the (FILE *) object, as is the case after a successful call + to the flockfile() or ftrylockfile() functions. + +... + + These unlocked versions can be safely used + only within explicitly locked program regions, + using exported locking primitives. + +and these precautions were never done. + +Use the standard forms of these print functions. + +There is inconsistent use of fputc_unlocked() with putc_unlocked(), +so consistently use the safer fputc() instead. + +Signed-off-by: Michael Pratt +--- + libasm/asm_align.c | 4 +- + libcpu/i386_parse.y | 4 +- + libebl/eblobjnote.c | 4 +- + src/nm.c | 20 +++++----- + src/objdump.c | 24 ++++++------ + src/readelf.c | 90 ++++++++++++++++++++++----------------------- + src/size.c | 8 ++-- + src/strings.c | 20 +++++----- + tests/showptable.c | 8 ++-- + 9 files changed, 91 insertions(+), 91 deletions(-) + +--- a/libasm/asm_align.c ++++ b/libasm/asm_align.c +@@ -60,13 +60,13 @@ asm_align (AsmScn_t *asmscn, GElf_Word v + fprintf (asmscn->ctx->out.file, "%02hhx\n", asmscn->pattern->bytes[0]); + else + { +- fputc_unlocked ('"', asmscn->ctx->out.file); ++ fputc ('"', asmscn->ctx->out.file); + + for (size_t cnt = 0; cnt < asmscn->pattern->len; ++cnt) + fprintf (asmscn->ctx->out.file, "\\x%02hhx", + asmscn->pattern->bytes[cnt]); + +- fputs_unlocked ("\"\n", asmscn->ctx->out.file); ++ fputs ("\"\n", asmscn->ctx->out.file); + } + return 0; + } +--- a/libcpu/i386_parse.y ++++ b/libcpu/i386_parse.y +@@ -1158,7 +1158,7 @@ instrtable_out (void) + EMIT_SUFFIX (w1); + EMIT_SUFFIX (W1); + +- fputc_unlocked ('\n', outfile); ++ fputc ('\n', outfile); + + for (int i = 0; i < 3; ++i) + { +@@ -1333,7 +1333,7 @@ instrtable_out (void) + b = b->next; + } + +- fputc_unlocked ('\n', outfile); ++ fputc ('\n', outfile); + } + fputs ("};\n", outfile); + } +--- a/libebl/eblobjnote.c ++++ b/libebl/eblobjnote.c +@@ -643,10 +643,10 @@ ebl_object_note (Ebl *ebl, uint32_t name + for (size_t cnt = 1; cnt < descsz / 4; ++cnt) + { + if (cnt > 1) +- putchar_unlocked ('.'); ++ putchar ('.'); + printf ("%" PRIu32, buf[cnt]); + } +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + if (descsz / 4 > FIXED_TAG_BYTES) + free (buf); +--- a/src/nm.c ++++ b/src/nm.c +@@ -439,7 +439,7 @@ handle_ar (int fd, Elf *elf, const char + Elf_Arhdr *arhdr = NULL; + size_t arhdr_off = 0; /* Note: 0 is no valid offset. */ + +- fputs_unlocked (_("\nArchive index:\n"), stdout); ++ fputs (_("\nArchive index:\n"), stdout); + + while (arsym->as_off != 0) + { +@@ -825,8 +825,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word s + /* If we have to precede the line with the file name. */ + if (print_file_name) + { +- fputs_unlocked (fullname, stdout); +- putchar_unlocked (':'); ++ fputs (fullname, stdout); ++ putchar (':'); + } + + /* Convert the address. */ +@@ -972,8 +972,8 @@ show_symbols_bsd (Elf *elf, const GElf_E + /* If we have to precede the line with the file name. */ + if (print_file_name) + { +- fputs_unlocked (fullname, stdout); +- putchar_unlocked (':'); ++ fputs (fullname, stdout); ++ putchar (':'); + } + + bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS; +@@ -1046,8 +1046,8 @@ show_symbols_bsd (Elf *elf, const GElf_E + } + + if (color_mode) +- fputs_unlocked (color_off, stdout); +- putchar_unlocked ('\n'); ++ fputs (color_off, stdout); ++ putchar ('\n'); + } + + #ifdef USE_DEMANGLE +@@ -1104,9 +1104,9 @@ show_symbols_posix (Elf *elf, const GElf + /* If we have to precede the line with the file name. */ + if (print_file_name) + { +- fputs_unlocked (fullname, stdout); +- putchar_unlocked (':'); +- putchar_unlocked (' '); ++ fputs (fullname, stdout); ++ putchar (':'); ++ putchar (' '); + } + + printf ("%s %c%s", symstr, +--- a/src/objdump.c ++++ b/src/objdump.c +@@ -580,12 +580,12 @@ show_full_content (Ebl *ebl, const char + printf ("%02hhx%02hhx%02hhx%02hhx ", + cp[inner], cp[inner + 1], cp[inner + 2], + cp[inner + 3]); +- fputc_unlocked (' ', stdout); ++ fputc (' ', stdout); + + for (size_t inner = 0; inner < 16; ++inner) +- fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) ++ fputc (isascii (cp[inner]) && isprint (cp[inner]) + ? cp[inner] : '.', stdout); +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + } + + printf (" %04zx ", cnt); +@@ -601,14 +601,14 @@ show_full_content (Ebl *ebl, const char + + for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0; + --inner) +- fputc_unlocked (' ', stdout); ++ fputc (' ', stdout); + + for (inner = 0; inner < remaining; ++inner) +- fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) ++ fputc (isascii (cp[inner]) && isprint (cp[inner]) + ? cp[inner] : '.', stdout); +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + } + } + +@@ -640,12 +640,12 @@ disasm_output (char *buf, size_t buflen, + printf ("%8" PRIx64 ": ", (uint64_t) info->addr); + + if (info->bytes_color != NULL) +- fputs_unlocked (info->bytes_color, stdout); ++ fputs (info->bytes_color, stdout); + size_t cnt; + for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt) + printf (" %02" PRIx8, info->last_end[cnt]); + if (info->bytes_color != NULL) +- fputs_unlocked (color_off, stdout); ++ fputs (color_off, stdout); + + printf ("%*s %.*s\n", + (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf); +@@ -663,12 +663,12 @@ disasm_output (char *buf, size_t buflen, + printf ("%8" PRIx64 ": ", (uint64_t) info->addr); + + if (info->bytes_color != NULL) +- fputs_unlocked (info->bytes_color, stdout); ++ fputs (info->bytes_color, stdout); + for (; cnt < (size_t) (info->cur - info->last_end); ++cnt) + printf (" %02" PRIx8, info->last_end[cnt]); + if (info->bytes_color != NULL) +- fputs_unlocked (color_off, stdout); +- putchar_unlocked ('\n'); ++ fputs (color_off, stdout); ++ putchar ('\n'); + info->addr += info->cur - info->last_end - 8; + } + +--- a/src/readelf.c ++++ b/src/readelf.c +@@ -1127,7 +1127,7 @@ print_file_type (unsigned short int e_ty + static void + print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) + { +- fputs_unlocked (_("ELF Header:\n Magic: "), stdout); ++ fputs (_("ELF Header:\n Magic: "), stdout); + for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt) + printf (" %02hhx", ehdr->e_ident[cnt]); + +@@ -1154,7 +1154,7 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) + printf (_(" ABI Version: %hhd\n"), + ehdr->e_ident[EI_ABIVERSION]); + +- fputs_unlocked (_(" Type: "), stdout); ++ fputs (_(" Type: "), stdout); + print_file_type (ehdr->e_type); + + const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine); +@@ -1196,9 +1196,9 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) + printf (_(" (%" PRIu32 " in [0].sh_info)"), + (uint32_t) shdr->sh_info); + else +- fputs_unlocked (_(" ([0] not available)"), stdout); ++ fputs (_(" ([0] not available)"), stdout); + } +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + + printf (_(" Size of section header entries: %" PRId16 " %s\n"), + ehdr->e_shentsize, _("(bytes)")); +@@ -1213,9 +1213,9 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) + printf (_(" (%" PRIu32 " in [0].sh_size)"), + (uint32_t) shdr->sh_size); + else +- fputs_unlocked (_(" ([0] not available)"), stdout); ++ fputs (_(" ([0] not available)"), stdout); + } +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + + if (unlikely (ehdr->e_shstrndx == SHN_XINDEX)) + { +@@ -1406,7 +1406,7 @@ There are %zd section headers, starting + } + } + +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + } + + +@@ -1552,22 +1552,22 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) + && shdr->sh_addr >= relro_from + && shdr->sh_addr + shdr->sh_size <= relro_to) + { +- fputs_unlocked (" [RELRO:", stdout); ++ fputs (" [RELRO:", stdout); + in_relro = true; + } + else if (has_relro && in_relro && shdr->sh_addr >= relro_to) + { +- fputs_unlocked ("]", stdout); ++ fputs ("]", stdout); + in_relro = false; + } + else if (has_relro && in_relro + && shdr->sh_addr + shdr->sh_size > relro_to) +- fputs_unlocked ("] p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0) + { + if (!in_ro) + { +- fputs_unlocked (" [RO:", stdout); ++ fputs (" [RO:", stdout); + in_ro = true; + } + } +@@ -1592,12 +1592,12 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) + { + if ((phdr2->p_flags & PF_W) == 0 && !in_ro) + { +- fputs_unlocked (" [RO:", stdout); ++ fputs (" [RO:", stdout); + in_ro = true; + } + else if ((phdr2->p_flags & PF_W) != 0 && in_ro) + { +- fputs_unlocked ("]", stdout); ++ fputs ("]", stdout); + in_ro = false; + } + } +@@ -1610,16 +1610,16 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) + if (has_relro && in_relro + && shdr->sh_addr + shdr->sh_size > relro_to) + { +- fputs_unlocked (">", stdout); ++ fputs (">", stdout); + in_relro = false; + } + } + } + if (in_relro || in_ro) +- fputs_unlocked ("]", stdout); ++ fputs ("]", stdout); + + /* Finish the line. */ +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + } + } + +@@ -1788,8 +1788,8 @@ print_flags (int class, GElf_Xword d_val + if (d_val & flags[cnt].mask) + { + if (!first) +- putchar_unlocked (' '); +- fputs_unlocked (flags[cnt].str, stdout); ++ putchar (' '); ++ fputs (flags[cnt].str, stdout); + d_val &= ~flags[cnt].mask; + first = false; + } +@@ -1797,11 +1797,11 @@ print_flags (int class, GElf_Xword d_val + if (d_val != 0) + { + if (!first) +- putchar_unlocked (' '); ++ putchar (' '); + printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val); + } + +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + + +@@ -1909,7 +1909,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, + phdr->p_offset); + } + +- fputs_unlocked (_(" Type Value\n"), stdout); ++ fputs (_(" Type Value\n"), stdout); + + /* if --use-dynamic option is enabled, + use the string table to get the related library info. */ +@@ -1953,7 +1953,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, + case DT_BIND_NOW: + case DT_TEXTREL: + /* No further output. */ +- fputc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + break; + + case DT_NEEDED: +@@ -2147,7 +2147,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * + elf_strptr (ebl->elf, shstrndx, shdr->sh_name), + shdr->sh_offset, + nentries); +- fputs_unlocked (class == ELFCLASS32 ++ fputs (class == ELFCLASS32 + ? _("\ + Offset Type Value Name\n") + : _("\ +@@ -2384,7 +2384,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr + elf_strptr (ebl->elf, shstrndx, shdr->sh_name), + shdr->sh_offset, + nentries); +- fputs_unlocked (class == ELFCLASS32 ++ fputs (class == ELFCLASS32 + ? _("\ + Offset Type Value Addend Name\n") + : _("\ +@@ -2891,7 +2891,7 @@ process_symtab (Ebl *ebl, unsigned int n + } + } + +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + } + +@@ -2973,7 +2973,7 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, G + (unsigned int) shdr->sh_link, + elf_strptr (ebl->elf, shstrndx, glink->sh_name)); + +- fputs_unlocked (class == ELFCLASS32 ++ fputs (class == ELFCLASS32 + ? _("\ + Num: Value Size Type Bind Vis Ndx Name\n") + : _("\ +@@ -3649,12 +3649,12 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, G + { + ssize_t n; + case 0: +- fputs_unlocked (_(" 0 *local* "), ++ fputs (_(" 0 *local* "), + stdout); + break; + + case 1: +- fputs_unlocked (_(" 1 *global* "), ++ fputs (_(" 1 *global* "), + stdout); + break; + +@@ -3671,7 +3671,7 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, G + break; + } + } +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + + +@@ -3718,7 +3718,7 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, + uint64_t success = 0; + + /* xgettext:no-c-format */ +- fputs_unlocked (_("\ ++ fputs (_("\ + Length Number % of total Coverage\n"), stdout); + printf (_(" 0 %6" PRIu32 " %5.1f%%\n"), + counts[0], (counts[0] * 100.0) / nbucket); +@@ -4140,7 +4140,7 @@ print_attributes (Ebl *ebl, const GElf_E + if (unlikely (*p++ != 'A')) + return; + +- fputs_unlocked (_(" Owner Size\n"), stdout); ++ fputs (_(" Owner Size\n"), stdout); + + /* Loop over the sections. */ + while (left (data, p) >= 4) +@@ -7233,7 +7233,7 @@ print_encoding_base (const char *pfx, un + if (w & 0x70) + { + if (w != fde_encoding) +- fputc_unlocked (' ', stdout); ++ fputc (' ', stdout); + + w = print_relinfo (w); + } +@@ -9772,7 +9772,7 @@ print_debug_line_section (Dwfl_Module *d + { + get_uleb128 (u128, linep, lineendp); + if (n != standard_opcode_lengths[opcode]) +- putc_unlocked (',', stdout); ++ fputc (',', stdout); + printf (" %u", u128); + } + +@@ -10525,7 +10525,7 @@ print_debug_macinfo_section (Dwfl_Module + \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, shdr), + (uint64_t) shdr->sh_offset); +- putc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + + /* There is no function in libdw to iterate over the raw content of + the section but it is easy enough to do. */ +@@ -10687,7 +10687,7 @@ print_debug_macro_section (Dwfl_Module * + \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, shdr), + (uint64_t) shdr->sh_offset); +- putc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + + /* Get the source file information for all CUs. Uses same + datastructure as macinfo. But uses offset field to directly +@@ -10840,15 +10840,15 @@ print_debug_macro_section (Dwfl_Module * + goto invalid_data; + args--; + if (args > 0) +- putchar_unlocked (','); ++ putchar (','); + } + } + else + printf (_(" no arguments.")); +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + } +- putchar_unlocked ('\n'); ++ putchar ('\n'); + + int level = 1; + if (readp + 1 > readendp) +@@ -11025,14 +11025,14 @@ print_debug_macro_section (Dwfl_Module * + if (args > 0) + printf (", "); + } +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + + if (readp + 1 > readendp) + goto invalid_data; + opcode = *readp++; + if (opcode == 0) +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + } + } +@@ -11368,7 +11368,7 @@ print_debug_frame_hdr_section (Dwfl_Modu + /* +4 because of the 4 byte header of the section. */ + (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr); + +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + + uint64_t fde_count = 0; +@@ -11546,7 +11546,7 @@ print_debug_exception_table (Dwfl_Module + else if (ar_disp != 0) + puts (" -> ???"); + else +- putchar_unlocked ('\n'); ++ putchar ('\n'); + ++u; + } + while (readp < action_table_end); +@@ -13200,19 +13200,19 @@ handle_core_note (Ebl *ebl, const GElf_N + nregloc == 0 ? nhdr->n_descsz : 0, + items, nitems); + if (colno != 0) +- putchar_unlocked ('\n'); ++ putchar ('\n'); + + colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset, + reglocs, nregloc); + if (colno != 0) +- putchar_unlocked ('\n'); ++ putchar ('\n'); + } + + static void + handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, + GElf_Off start, Elf_Data *data) + { +- fputs_unlocked (_(" Owner Data size Type\n"), stdout); ++ fputs (_(" Owner Data size Type\n"), stdout); + + if (data == NULL) + goto bad_note; +--- a/src/size.c ++++ b/src/size.c +@@ -411,7 +411,7 @@ show_sysv (Elf *elf, const char *prefix, + maxlen = MAX (maxlen, (int) strlen (name)); + } + +- fputs_unlocked (fname, stdout); ++ fputs (fname, stdout); + if (prefix != NULL) + printf (_(" (ex %s)"), prefix); + printf (":\n%-*s %*s %*s\n", +@@ -483,7 +483,7 @@ show_sysv_one_line (Elf *elf) + continue; + + if (! first) +- fputs_unlocked (" + ", stdout); ++ fputs (" + ", stdout); + first = false; + + printf ((radix == radix_hex ? "%" PRIx64 "(%s)" +@@ -555,7 +555,7 @@ show_bsd (Elf *elf, const char *prefix, + fname); + if (prefix != NULL) + printf (_(" (ex %s)"), prefix); +- fputs_unlocked ("\n", stdout); ++ fputs ("\n", stdout); + + total_textsize += textsize; + total_datasize += datasize; +@@ -607,7 +607,7 @@ show_segments (Elf *elf, const char *ful + continue; + + if (! first) +- fputs_unlocked (" + ", stdout); ++ fputs (" + ", stdout); + first = false; + + printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)" +--- a/src/strings.c ++++ b/src/strings.c +@@ -345,8 +345,8 @@ process_chunk_mb (const char *fname, con + /* We found a match. */ + if (unlikely (fname != NULL)) + { +- fputs_unlocked (fname, stdout); +- fputs_unlocked (": ", stdout); ++ fputs (fname, stdout); ++ fputs (": ", stdout); + } + + if (unlikely (radix != radix_none)) +@@ -357,7 +357,7 @@ process_chunk_mb (const char *fname, con + + if (unlikely (*unprinted != NULL)) + { +- fputs_unlocked (*unprinted, stdout); ++ fputs (*unprinted, stdout); + free (*unprinted); + *unprinted = NULL; + } +@@ -366,8 +366,8 @@ process_chunk_mb (const char *fname, con + assume the file data is encoded in UCS-2/UTF-16 or + UCS-4/UTF-32 respectively we could convert the string. + But there is no such guarantee. */ +- fwrite_unlocked (start, 1, buf - start, stdout); +- putc_unlocked ('\n', stdout); ++ fwrite (start, 1, buf - start, stdout); ++ fputc ('\n', stdout); + } + + start = ++buf; +@@ -413,8 +413,8 @@ process_chunk (const char *fname, const + /* We found a match. */ + if (likely (fname != NULL)) + { +- fputs_unlocked (fname, stdout); +- fputs_unlocked (": ", stdout); ++ fputs (fname, stdout); ++ fputs (": ", stdout); + } + + if (likely (radix != radix_none)) +@@ -425,12 +425,12 @@ process_chunk (const char *fname, const + + if (unlikely (*unprinted != NULL)) + { +- fputs_unlocked (*unprinted, stdout); ++ fputs (*unprinted, stdout); + free (*unprinted); + *unprinted = NULL; + } +- fwrite_unlocked (start, 1, buf - start, stdout); +- putc_unlocked ('\n', stdout); ++ fwrite (start, 1, buf - start, stdout); ++ fputc ('\n', stdout); + } + + start = ++buf; +--- a/tests/showptable.c ++++ b/tests/showptable.c +@@ -111,11 +111,11 @@ main (int argc, char *argv[]) + (unsigned long long int) phdr->p_memsz, + (unsigned long long int) phdr->p_align); + +- putc_unlocked ((phdr->p_flags & PF_X) ? 'X' : ' ', stdout); +- putc_unlocked ((phdr->p_flags & PF_W) ? 'W' : ' ', stdout); +- putc_unlocked ((phdr->p_flags & PF_R) ? 'R' : ' ', stdout); ++ fputc ((phdr->p_flags & PF_X) ? 'X' : ' ', stdout); ++ fputc ((phdr->p_flags & PF_W) ? 'W' : ' ', stdout); ++ fputc ((phdr->p_flags & PF_R) ? 'R' : ' ', stdout); + +- putc_unlocked ('\n', stdout); ++ fputc ('\n', stdout); + + if (phdr->p_type == PT_INTERP) + { diff --git a/tools/elfutils/patches/100-portability.patch b/tools/elfutils/patches/100-portability.patch index be97f95faa..c2d14e575f 100644 --- a/tools/elfutils/patches/100-portability.patch +++ b/tools/elfutils/patches/100-portability.patch @@ -235,16 +235,6 @@ Cflags: -I${includedir} Requires.private: zlib @LIBZSTD@ ---- a/lib/next_prime.c -+++ b/lib/next_prime.c -@@ -27,6 +27,7 @@ - the GNU Lesser General Public License along with this program. If - not, see . */ - -+#include - #include - - --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -200,8 +200,6 @@ static bool default_object_note (const c @@ -276,15 +266,3 @@ static bool default_check_special_symbol (Elf *elf __attribute__ ((unused)), ---- a/src/srcfiles.cxx -+++ b/src/srcfiles.cxx -@@ -78,7 +78,9 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_ve - /* Bug report address. */ - ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; - -+#ifdef HAVE_LIBARCHIVE - constexpr size_t BUFFER_SIZE = 8192; -+#endif - - /* Definitions of arguments for argp functions. */ - static const struct argp_option options[] = diff --git a/tools/elfutils/patches/101-shared-conditional.patch b/tools/elfutils/patches/101-shared-conditional.patch index 17d8cc72a1..800aa079a1 100644 --- a/tools/elfutils/patches/101-shared-conditional.patch +++ b/tools/elfutils/patches/101-shared-conditional.patch @@ -64,7 +64,7 @@ include_HEADERS = dwarf.h pkginclude_HEADERS = libdw.h known-dwarf.h -@@ -121,11 +123,13 @@ libdw.so: $(srcdir)/libdw.map $(libdw_so +@@ -120,11 +122,13 @@ libdw.so: $(srcdir)/libdw.map $(libdw_so @$(textrel_check) $(AM_V_at)ln -fs $@ $@.$(VERSION) @@ -78,7 +78,7 @@ uninstall: uninstall-am rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so -@@ -148,6 +152,10 @@ libdw_a_LIBADD += $(addprefix ../backend +@@ -147,6 +151,10 @@ libdw_a_LIBADD += $(addprefix ../backend libcpu_objects = $(shell $(AR) t ../libcpu/libcpu.a) libdw_a_LIBADD += $(addprefix ../libcpu/,$(libcpu_objects)) diff --git a/tools/elfutils/patches/110-objects-manifest.patch b/tools/elfutils/patches/110-objects-manifest.patch index 1f5b5d2138..983331dfa7 100644 --- a/tools/elfutils/patches/110-objects-manifest.patch +++ b/tools/elfutils/patches/110-objects-manifest.patch @@ -1,6 +1,6 @@ --- a/libdw/Makefile.am +++ b/libdw/Makefile.am -@@ -137,19 +137,19 @@ uninstall: uninstall-am +@@ -136,19 +136,19 @@ uninstall: uninstall-am rm -f $(DESTDIR)$(libdir)/libdw.so rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils @@ -25,7 +25,7 @@ libdw_a_LIBADD += $(addprefix ../libcpu/,$(libcpu_objects)) if !BUILD_SHARED -@@ -161,4 +161,9 @@ noinst_HEADERS = libdwP.h memory-access. +@@ -160,5 +160,10 @@ noinst_HEADERS = libdwP.h memory-access. EXTRA_DIST = libdw.map @@ -36,6 +36,7 @@ + echo $^ > $@ + +MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) $(EXTRA_libdw_a_DEPENDENCIES) libdw.so libdw.so.$(VERSION) + MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am @@ -93,4 +93,10 @@ am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_S From c83941d288408308126a6f6bda12eca06a43253c Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Tue, 24 Sep 2024 18:50:15 -0400 Subject: [PATCH 32/51] tools/elfutils: add maintainer-clean to clean target Use the clean recipe during build, so that files already generated by the bootstrapping within the release are removed before the bootstrap script is run again. Automake with modified rules must be ran in order to generate a Makefile that does delete itself or libtool. In order to enable rules for building what is removed, maintainer mode is required for configuring. Building from tracked sources only with maintainer mode requires a lexical analyzer, so add dependency for bison. Override an automake variable "am__CONFIG_DISTCLEAN_FILES" in order to prevent removing config.status and other configure files so that configure stage does not need to be ran twice. The function obstack_printf() is not present on macOS, so use the available gnulib module and their dependencies. Many more modules from gnulib are now needed, and some replacements of some functions must be skipped to prevent build errors at link time. Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/Makefile | 2 +- tools/elfutils/Makefile | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/Makefile b/tools/Makefile index 800647762f..9188622eb9 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -100,7 +100,7 @@ $(curdir)/cmake/compile += $(curdir)/libressl/compile $(curdir)/ninja/compile $( $(curdir)/coreutils/compile := $(curdir)/automake/compile $(curdir)/bison/compile $(curdir)/gnulib/compile $(curdir)/dosfstools/compile := $(curdir)/automake/compile $(curdir)/e2fsprogs/compile := $(curdir)/libtool/compile $(curdir)/util-linux/compile -$(curdir)/elfutils/compile := $(curdir)/m4/compile $(curdir)/zlib/compile $(curdir)/gnulib/compile $(curdir)/libtool/compile +$(curdir)/elfutils/compile := $(curdir)/bison/compile $(curdir)/gnulib/compile $(curdir)/m4/compile $(curdir)/zlib/compile $(curdir)/erofs-utils/compile := $(curdir)/libtool/compile $(curdir)/xz/compile $(curdir)/lz4/compile $(curdir)/util-linux/compile $(curdir)/fakeroot/compile := $(curdir)/libtool/compile $(curdir)/findutils/compile := $(curdir)/bison/compile diff --git a/tools/elfutils/Makefile b/tools/elfutils/Makefile index 6aa23bfbc5..625cecf58c 100644 --- a/tools/elfutils/Makefile +++ b/tools/elfutils/Makefile @@ -43,7 +43,7 @@ PKG_GNULIB_MODS = \ fallocate-posix \ fnmatch-gnu \ fts \ - obstack \ + obstack-printf-posix \ progname \ strchrnul \ tsearch @@ -51,16 +51,39 @@ PKG_GNULIB_MODS = \ include $(INCLUDE_DIR)/host-build.mk export $(PKG_GNULIB_BASE)=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/.libs/$(PKG_GNULIB_BASE).a + +export $(PKG_GNULIB_BASE)_exitfail=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-exitfail.o export $(PKG_GNULIB_BASE)_fallocate-posix=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-posix_fallocate.o +export $(PKG_GNULIB_BASE)_mbszero=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-mbszero.o +export $(PKG_GNULIB_BASE)_obstack=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-obstack.o +export $(PKG_GNULIB_BASE)_obstack-printf=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-obstack_printf.o +export $(PKG_GNULIB_BASE)_printf-args=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-printf-args.o +export $(PKG_GNULIB_BASE)_printf-frexp=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-printf-frexp.o +export $(PKG_GNULIB_BASE)_printf-frexpl=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-printf-frexpl.o +export $(PKG_GNULIB_BASE)_printf-parse=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-printf-parse.o export $(PKG_GNULIB_BASE)_tsearch=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-tsearch.o +export $(PKG_GNULIB_BASE)_vasnprintf=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-vasnprintf.o +export $(PKG_GNULIB_BASE)_xsize=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/$(PKG_GNULIB_BASE)_la-xsize.o HOST_MAKE_FLAGS += \ + am__CONFIG_DISTCLEAN_FILES= \ DEFAULT_INCLUDES='-iquote . -I$$$$(top_builddir) -I$$$$(top_srcdir)/$(PKG_GNULIB_BASE)' \ AM_LDFLAGS='$$$$(STACK_USAGE_NO_ERROR)' \ LIBS+='$$$$(if $$$$(findstring $(lastword $(PKG_SUBDIRS)),$$$$(subdir)), $$$$($(PKG_GNULIB_BASE)))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_exitfail))' \ LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_fallocate-posix))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_mbszero))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_obstack))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_obstack-printf))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_printf-args))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_printf-frexp))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_printf-frexpl))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_printf-parse))' \ LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_tsearch))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_vasnprintf))' \ + LIBS+='$$$$(wildcard $$$$($(PKG_GNULIB_BASE)_xsize))' \ REPLACE_FCNTL=0 REPLACE_FREE=0 REPLACE_FSTAT=0 REPLACE_OPEN=0 \ + REPLACE_OBSTACK=0 REPLACE_OBSTACK_PRINTF=0 \ bin_PROGRAMS='$(PKG_PROGRAMS)' EXEEXT= HOST_CPPFLAGS += "'-I$$$$(top_srcdir)/lib'" @@ -72,6 +95,7 @@ endif HOST_CFLAGS += -Wno-error -fPIC -std=gnu17 HOST_CONFIGURE_ARGS += \ + --enable-maintainer-mode \ --without-libintl-prefix \ --without-libiconv-prefix \ --disable-debuginfod \ @@ -96,8 +120,14 @@ HOST_CONFIGURE_VARS += \ Hooks/HostConfigure/Pre := Host/Gnulib/Prepare $(Hooks/HostConfigure/Pre) Hooks/HostCompile/Pre := Host/Gnulib/Compile $(Hooks/HostCompile/Pre) +define Host/Configure + $(call Host/Configure/Default) + $(call Host/Uninstall) +endef + define Host/Uninstall -$(call Host/Compile/Default,uninstall) + -$(call Host/Compile/Default,maintainer-clean) # Clean bootstrap files from the release endef $(eval $(call HostBuild)) From 5bb84fb53bb5fa1215ddcd245ecdd94975484170 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 21 Oct 2024 09:47:25 -0400 Subject: [PATCH 33/51] tools/elfutils: update MIPS support patches The original patch series partially added by commit f97da2c61 ("tools/elfutils: add missing MIPS reloc support") now has a v3 which has half of it's commits accepted. To prepare for updating to the new release, use the new series that includes backports. Manually adjusted patch: - 010-backport-mips-support-reloc.patch Add patch: - 011-backport-mips-support-strip.patch - 012-backport-mips-support-readelf.patch - 013-backport-mips-support-elflint.patch - 014-backport-mips-support-stack.patch - 015-backport-mips-support-regs.patch Tested-by: Tony Ambardar Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- .../010-backport-mips-support-reloc.patch | 2239 +---------------- .../011-backport-mips-support-strip.patch | 230 ++ .../012-backport-mips-support-readelf.patch | 1079 ++++++++ .../013-backport-mips-support-elflint.patch | 156 ++ .../014-backport-mips-support-stack.patch | 273 ++ .../015-backport-mips-support-regs.patch | 475 ++++ 6 files changed, 2220 insertions(+), 2232 deletions(-) create mode 100644 tools/elfutils/patches/011-backport-mips-support-strip.patch create mode 100644 tools/elfutils/patches/012-backport-mips-support-readelf.patch create mode 100644 tools/elfutils/patches/013-backport-mips-support-elflint.patch create mode 100644 tools/elfutils/patches/014-backport-mips-support-stack.patch create mode 100644 tools/elfutils/patches/015-backport-mips-support-regs.patch diff --git a/tools/elfutils/patches/010-backport-mips-support-reloc.patch b/tools/elfutils/patches/010-backport-mips-support-reloc.patch index 8a65e4e464..e9ef3997d2 100644 --- a/tools/elfutils/patches/010-backport-mips-support-reloc.patch +++ b/tools/elfutils/patches/010-backport-mips-support-reloc.patch @@ -1,7 +1,7 @@ -From 8d3bb7db9d6f07decfc59d83988cda54e5a8b0cd Mon Sep 17 00:00:00 2001 +From e259f126f5077923e415e306915de50ed0f0db56 Mon Sep 17 00:00:00 2001 From: Ying Huang Date: Tue, 5 Mar 2024 17:51:17 +0800 -Subject: [PATCH 1/7] Support Mips architecture +Subject: [PATCH] Support Mips architecture * backends/Makefile.am (modules): Add mips. (mips_SRCS): New var for mips_init.c mips_symbol.c. @@ -37,13 +37,11 @@ Signed-off-by: Ying Huang i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \ i386_retval.c i386_regs.c i386_auxv.c \ -@@ -102,12 +102,16 @@ loongarch_SRCS = loongarch_init.c loonga +@@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loonga arc_SRCS = arc_init.c arc_symbol.c -+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ -+ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \ -+ mips_corenote.c mips64_corenote.c ++mips_SRCS = mips_init.c mips_symbol.c + libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ @@ -57,7 +55,7 @@ Signed-off-by: Ying Huang am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os) --- /dev/null +++ b/backends/mips_init.c -@@ -0,0 +1,74 @@ +@@ -0,0 +1,52 @@ +/* Initialization of MIPS specific backend library. + Copyright (C) 2024 CIP United Inc. + This file is part of elfutils. @@ -100,8 +98,6 @@ Signed-off-by: Ying Huang +/* This defines the common reloc hooks based on mips_reloc.def. */ +#include "common-reloc.c" + -+extern __typeof (EBLHOOK (core_note)) mips64_core_note attribute_hidden; -+ +Ebl * +mips_init (Elf *elf __attribute__ ((unused)), + GElf_Half machine __attribute__ ((unused)), @@ -110,26 +106,6 @@ Signed-off-by: Ying Huang + /* We handle it. */ + mips_init_reloc (eh); + HOOK (eh, reloc_simple_type); -+ HOOK (eh, section_type_name); -+ HOOK (eh, machine_flag_check); -+ HOOK (eh, machine_flag_name); -+ HOOK (eh, machine_section_flag_check); -+ HOOK (eh, segment_type_name); -+ HOOK (eh, dynamic_tag_check); -+ HOOK (eh, dynamic_tag_name); -+ HOOK (eh, check_object_attribute); -+ HOOK (eh, check_special_symbol); -+ HOOK (eh, check_reloc_target_type); -+ HOOK (eh, set_initial_registers_tid); -+ HOOK (eh, abi_cfi); -+ HOOK (eh, unwind); -+ HOOK (eh, register_info); -+ HOOK (eh, return_value_location); -+ if (eh->class == ELFCLASS64) -+ eh->core_note = mips64_core_note; -+ else -+ HOOK (eh, core_note); -+ eh->frame_nregs = 71; + return eh; +} --- /dev/null @@ -230,7 +206,7 @@ Signed-off-by: Ying Huang +RELOC_TYPE (GNU_VTENTRY, REL) --- /dev/null +++ b/backends/mips_symbol.c -@@ -0,0 +1,671 @@ +@@ -0,0 +1,63 @@ +/* MIPS specific symbolic name handling. + Copyright (C) 2024 CIP United Inc. + This file is part of elfutils. @@ -294,614 +270,6 @@ Signed-off-by: Ying Huang + return ELF_T_NUM; + } +} -+ -+/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name */ -+const char * -+mips_section_type_name (int type, -+ char *buf __attribute__ ((unused)), -+ size_t len __attribute__ ((unused))) -+{ -+ switch (type) -+ { -+ case SHT_MIPS_LIBLIST: -+ return "MIPS_LIBLIST"; -+ case SHT_MIPS_MSYM: -+ return "MIPS_MSYM"; -+ case SHT_MIPS_CONFLICT: -+ return "MIPS_CONFLICT"; -+ case SHT_MIPS_GPTAB: -+ return "MIPS_GPTAB"; -+ case SHT_MIPS_UCODE: -+ return "MIPS_UCODE"; -+ case SHT_MIPS_DEBUG: -+ return "MIPS_DEBUG"; -+ case SHT_MIPS_REGINFO: -+ return "MIPS_REGINFO"; -+ case SHT_MIPS_PACKAGE: -+ return "MIPS_PACKAGE"; -+ case SHT_MIPS_PACKSYM: -+ return "MIPS_PACKSYM"; -+ case SHT_MIPS_RELD: -+ return "MIPS_RELD"; -+ case SHT_MIPS_IFACE: -+ return "MIPS_IFACE"; -+ case SHT_MIPS_CONTENT: -+ return "MIPS_CONTENT"; -+ case SHT_MIPS_OPTIONS: -+ return "MIPS_OPTIONS"; -+ case SHT_MIPS_SHDR: -+ return "MIPS_SHDR"; -+ case SHT_MIPS_FDESC: -+ return "MIPS_FDESC"; -+ case SHT_MIPS_EXTSYM: -+ return "MIPS_EXTSYM"; -+ case SHT_MIPS_DENSE: -+ return "MIPS_DENSE"; -+ case SHT_MIPS_PDESC: -+ return "MIPS_PDESC"; -+ case SHT_MIPS_LOCSYM: -+ return "MIPS_LOCSYM"; -+ case SHT_MIPS_AUXSYM: -+ return "MIPS_AUXSYM"; -+ case SHT_MIPS_OPTSYM: -+ return "MIPS_OPTSYM"; -+ case SHT_MIPS_LOCSTR: -+ return "MIPS_LOCSTR"; -+ case SHT_MIPS_LINE: -+ return "MIPS_LINE"; -+ case SHT_MIPS_RFDESC: -+ return "MIPS_RFDESC"; -+ case SHT_MIPS_DELTASYM: -+ return "MIPS_DELTASYM"; -+ case SHT_MIPS_DELTAINST: -+ return "MIPS_DELTAINST"; -+ case SHT_MIPS_DELTACLASS: -+ return "MIPS_DELTACLASS"; -+ case SHT_MIPS_DWARF: -+ return "MIPS_DWARF"; -+ case SHT_MIPS_DELTADECL: -+ return "MIPS_DELTADECL"; -+ case SHT_MIPS_SYMBOL_LIB: -+ return "MIPS_SYMBOL_LIB"; -+ case SHT_MIPS_EVENTS: -+ return "MIPS_EVENTS"; -+ case SHT_MIPS_TRANSLATE: -+ return "MIPS_TRANSLATE"; -+ case SHT_MIPS_PIXIE: -+ return "MIPS_PIXIE"; -+ case SHT_MIPS_XLATE: -+ return "MIPS_XLATE"; -+ case SHT_MIPS_XLATE_DEBUG: -+ return "MIPS_XLATE_DEBUG"; -+ case SHT_MIPS_WHIRL: -+ return "MIPS_WHIRL"; -+ case SHT_MIPS_EH_REGION: -+ return "MIPS_EH_REGION"; -+ case SHT_MIPS_XLATE_OLD: -+ return "MIPS_XLATE_OLD"; -+ case SHT_MIPS_PDR_EXCEPTION: -+ return "MIPS_PDR_EXCEPTION"; -+ case SHT_MIPS_ABIFLAGS: -+ return "MIPS_ABIFLAGS"; -+ case SHT_MIPS_XHASH: -+ return "MIPS_XHASH"; -+ default: -+ break; -+ } -+ return NULL; -+} -+ -+bool -+mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type) -+{ -+ return (sh_type == SHT_MIPS_DWARF); -+} -+ -+/* Check whether given symbol's st_value and st_size are OK despite failing -+ normal checks. */ -+bool -+mips_check_special_symbol (Elf *elf, -+ const GElf_Sym *sym __attribute__ ((unused)), -+ const char *name __attribute__ ((unused)), -+ const GElf_Shdr *destshdr) -+{ -+ size_t shstrndx; -+ if (elf_getshdrstrndx (elf, &shstrndx) != 0) -+ return false; -+ const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); -+ if (sname == NULL) -+ return false; -+ return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0); -+} -+ -+/* Check whether SHF_MASKPROC flags are valid. */ -+bool -+mips_machine_section_flag_check (GElf_Xword sh_flags) -+{ -+ return ((sh_flags &~ (SHF_MIPS_GPREL | -+ SHF_MIPS_MERGE | -+ SHF_MIPS_ADDR | -+ SHF_MIPS_STRINGS | -+ SHF_MIPS_NOSTRIP | -+ SHF_MIPS_LOCAL | -+ SHF_MIPS_NAMES | -+ SHF_MIPS_NODUPE)) == 0); -+} -+ -+/* Check whether machine flags are valid. */ -+bool -+mips_machine_flag_check (GElf_Word flags) -+{ -+ if ((flags &~ (EF_MIPS_NOREORDER | -+ EF_MIPS_PIC | -+ EF_MIPS_CPIC | -+ EF_MIPS_UCODE | -+ EF_MIPS_ABI2 | -+ EF_MIPS_OPTIONS_FIRST | -+ EF_MIPS_32BITMODE | -+ EF_MIPS_NAN2008 | -+ EF_MIPS_FP64 | -+ EF_MIPS_ARCH_ASE_MDMX | -+ EF_MIPS_ARCH_ASE_M16 | -+ EF_MIPS_ARCH_ASE_MICROMIPS)) == 0) -+ return false; -+ -+ switch(flags & EF_MIPS_MACH) -+ { -+ case EF_MIPS_MACH_3900: -+ case EF_MIPS_MACH_4010: -+ case EF_MIPS_MACH_4100: -+ case EF_MIPS_MACH_4111: -+ case EF_MIPS_MACH_4120: -+ case EF_MIPS_MACH_4650: -+ case EF_MIPS_MACH_5400: -+ case EF_MIPS_MACH_5500: -+ case EF_MIPS_MACH_5900: -+ case EF_MIPS_MACH_SB1: -+ case EF_MIPS_MACH_9000: -+ case EF_MIPS_MACH_LS2E: -+ case EF_MIPS_MACH_LS2F: -+ case EF_MIPS_MACH_GS464: -+ case EF_MIPS_MACH_GS464E: -+ case EF_MIPS_MACH_GS264E: -+ case EF_MIPS_MACH_OCTEON: -+ case EF_MIPS_MACH_OCTEON2: -+ case EF_MIPS_MACH_OCTEON3: -+ case EF_MIPS_MACH_XLR: -+ case EF_MIPS_MACH_IAMR2: -+ case 0: -+ break; -+ default: -+ return false; -+ } -+ -+ switch ((flags & EF_MIPS_ABI)) -+ { -+ case EF_MIPS_ABI_O32: -+ case EF_MIPS_ABI_O64: -+ case EF_MIPS_ABI_EABI32: -+ case EF_MIPS_ABI_EABI64: -+ case 0: -+ break; -+ default: -+ return false; -+ } -+ -+ switch ((flags & EF_MIPS_ARCH)) -+ { -+ case EF_MIPS_ARCH_1: -+ case EF_MIPS_ARCH_2: -+ case EF_MIPS_ARCH_3: -+ case EF_MIPS_ARCH_4: -+ case EF_MIPS_ARCH_5: -+ case EF_MIPS_ARCH_32: -+ case EF_MIPS_ARCH_32R2: -+ case EF_MIPS_ARCH_32R6: -+ case EF_MIPS_ARCH_64: -+ case EF_MIPS_ARCH_64R2: -+ case EF_MIPS_ARCH_64R6: -+ return true; -+ default: -+ return false; -+ } -+ return false; -+} -+ -+/* copy binutils-2.34/binutils/readelf.c get_machine_flags */ -+const char * -+mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref) -+{ -+ if (*flagref & EF_MIPS_NOREORDER) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER); -+ return "noreorder"; -+ } -+ -+ if (*flagref & EF_MIPS_PIC) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_PIC); -+ return "pic"; -+ } -+ -+ if (*flagref & EF_MIPS_CPIC) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_CPIC); -+ return "cpic"; -+ } -+ -+ if (*flagref & EF_MIPS_UCODE) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_UCODE); -+ return "ugen_reserved"; -+ } -+ -+ if (*flagref & EF_MIPS_ABI2) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI2); -+ return "abi2"; -+ } -+ -+ if (*flagref & EF_MIPS_OPTIONS_FIRST) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST); -+ return "odk first"; -+ } -+ -+ if (*flagref & EF_MIPS_32BITMODE) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE); -+ return "32bitmode"; -+ } -+ -+ if (*flagref & EF_MIPS_NAN2008) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008); -+ return "nan2008"; -+ } -+ -+ if (*flagref & EF_MIPS_FP64) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_FP64); -+ return "fp64"; -+ } -+ -+ switch (*flagref & EF_MIPS_MACH) -+ { -+ case EF_MIPS_MACH_3900: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900); -+ return "3900"; -+ case EF_MIPS_MACH_4010: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010); -+ return "4010"; -+ case EF_MIPS_MACH_4100: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100); -+ return "4100"; -+ case EF_MIPS_MACH_4111: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111); -+ return "4111"; -+ case EF_MIPS_MACH_4120: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120); -+ return "4120"; -+ case EF_MIPS_MACH_4650: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650); -+ return "4650"; -+ case EF_MIPS_MACH_5400: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400); -+ return "5400"; -+ case EF_MIPS_MACH_5500: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500); -+ return "5500"; -+ case EF_MIPS_MACH_5900: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900); -+ return "5900"; -+ case EF_MIPS_MACH_SB1: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1); -+ return "sb1"; -+ case EF_MIPS_MACH_9000: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000); -+ return "9000"; -+ case EF_MIPS_MACH_LS2E: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E); -+ return "loongson-2e"; -+ case EF_MIPS_MACH_LS2F: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F); -+ return "loongson-2f"; -+ case EF_MIPS_MACH_GS464: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464); -+ return "gs464"; -+ case EF_MIPS_MACH_GS464E: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E); -+ return "gs464e"; -+ case EF_MIPS_MACH_GS264E: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E); -+ return "gs264e"; -+ case EF_MIPS_MACH_OCTEON: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON); -+ return "octeon"; -+ case EF_MIPS_MACH_OCTEON2: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2); -+ return "octeon2"; -+ case EF_MIPS_MACH_OCTEON3: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3); -+ return "octeon3"; -+ case EF_MIPS_MACH_XLR: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR); -+ return "xlr"; -+ case EF_MIPS_MACH_IAMR2: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_IAMR2); -+ return "interaptiv-mr2"; -+ case 0: -+ /* We simply ignore the field in this case to avoid confusion: -+ MIPS ELF does not specify EF_MIPS_MACH, it is a GNU -+ extension. */ -+ break; -+ default: -+ *flagref &= ~((Elf64_Word) EF_MIPS_MACH); -+ return "unknown CPU"; -+ } -+ switch (*flagref & EF_MIPS_ABI) -+ { -+ case EF_MIPS_ABI_O32: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32); -+ return "o32"; -+ case EF_MIPS_ABI_O64: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64); -+ return "o64"; -+ case EF_MIPS_ABI_EABI32: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32); -+ return "eabi32"; -+ case EF_MIPS_ABI_EABI64: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI64); -+ return "eabi64"; -+ case 0: -+ /* We simply ignore the field in this case to avoid confusion: -+ MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension. -+ This means it is likely to be an o32 file, but not for -+ sure. */ -+ break; -+ default: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ABI); -+ return "unknown ABI"; -+ } -+ -+ if (*flagref & EF_MIPS_ARCH_ASE_MDMX) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX); -+ return "mdmx"; -+ } -+ -+ if (*flagref & EF_MIPS_ARCH_ASE_M16) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16); -+ return "mips16"; -+ } -+ -+ if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS) -+ { -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS); -+ return "micromips"; -+ } -+ -+ switch (*flagref & EF_MIPS_ARCH) -+ { -+ case EF_MIPS_ARCH_1: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1); -+ return "mips1"; -+ case EF_MIPS_ARCH_2: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2); -+ return "mips2"; -+ case EF_MIPS_ARCH_3: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3); -+ return "mips3"; -+ case EF_MIPS_ARCH_4: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4); -+ return "mips4"; -+ case EF_MIPS_ARCH_5: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5); -+ return "mips5"; -+ case EF_MIPS_ARCH_32: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32); -+ return "mips32"; -+ case EF_MIPS_ARCH_32R2: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2); -+ return "mips32r2"; -+ case EF_MIPS_ARCH_32R6: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6); -+ return "mips32r6"; -+ case EF_MIPS_ARCH_64: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64); -+ return "mips64"; -+ case EF_MIPS_ARCH_64R2: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2); -+ return "mips64r2"; -+ case EF_MIPS_ARCH_64R6: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R6); -+ return "mips64r6"; -+ default: -+ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH); -+ return "unknown ISA"; -+ } -+ return NULL; -+} -+ -+/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type */ -+const char * -+mips_segment_type_name (int segment, char *buf __attribute__ ((unused)), -+ size_t len __attribute__ ((unused))) -+{ -+ switch (segment) -+ { -+ case PT_MIPS_REGINFO: -+ return "REGINFO"; -+ case PT_MIPS_RTPROC: -+ return "RTPROC"; -+ case PT_MIPS_OPTIONS: -+ return "OPTIONS"; -+ case PT_MIPS_ABIFLAGS: -+ return "ABIFLAGS"; -+ default: -+ return NULL; -+ } -+} -+ -+bool -+mips_dynamic_tag_check (int64_t tag) -+{ -+ return ((tag &~ (DT_MIPS_RLD_VERSION -+ | DT_MIPS_TIME_STAMP -+ | DT_MIPS_ICHECKSUM -+ | DT_MIPS_IVERSION -+ | DT_MIPS_FLAGS -+ | DT_MIPS_BASE_ADDRESS -+ | DT_MIPS_MSYM -+ | DT_MIPS_CONFLICT -+ | DT_MIPS_LIBLIST -+ | DT_MIPS_LOCAL_GOTNO -+ | DT_MIPS_CONFLICTNO -+ | DT_MIPS_LIBLISTNO -+ | DT_MIPS_SYMTABNO -+ | DT_MIPS_UNREFEXTNO -+ | DT_MIPS_GOTSYM -+ | DT_MIPS_HIPAGENO -+ | DT_MIPS_RLD_MAP -+ | DT_MIPS_DELTA_CLASS -+ | DT_MIPS_DELTA_CLASS_NO -+ | DT_MIPS_DELTA_INSTANCE -+ | DT_MIPS_DELTA_INSTANCE_NO -+ | DT_MIPS_DELTA_RELOC -+ | DT_MIPS_DELTA_RELOC_NO -+ | DT_MIPS_DELTA_SYM -+ | DT_MIPS_DELTA_SYM_NO -+ | DT_MIPS_DELTA_CLASSSYM -+ | DT_MIPS_DELTA_CLASSSYM_NO -+ | DT_MIPS_CXX_FLAGS -+ | DT_MIPS_PIXIE_INIT -+ | DT_MIPS_SYMBOL_LIB -+ | DT_MIPS_LOCALPAGE_GOTIDX -+ | DT_MIPS_LOCAL_GOTIDX -+ | DT_MIPS_HIDDEN_GOTIDX -+ | DT_MIPS_PROTECTED_GOTIDX -+ | DT_MIPS_OPTIONS -+ | DT_MIPS_INTERFACE -+ | DT_MIPS_DYNSTR_ALIGN -+ | DT_MIPS_INTERFACE_SIZE -+ | DT_MIPS_RLD_TEXT_RESOLVE_ADDR -+ | DT_MIPS_PERF_SUFFIX -+ | DT_MIPS_COMPACT_SIZE -+ | DT_MIPS_GP_VALUE -+ | DT_MIPS_AUX_DYNAMIC -+ | DT_MIPS_PLTGOT -+ | DT_MIPS_RWPLT -+ | DT_MIPS_RLD_MAP_REL -+ | DT_MIPS_XHASH)) == 0); -+} -+ -+/* copy binutils-2.34/binutils/readelf.c get_mips_dynamic_type*/ -+const char * -+mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)), -+ size_t len __attribute__ ((unused))) -+{ -+ switch (tag) -+ { -+ case DT_MIPS_RLD_VERSION: -+ return "MIPS_RLD_VERSION"; -+ case DT_MIPS_TIME_STAMP: -+ return "MIPS_TIME_STAMP"; -+ case DT_MIPS_ICHECKSUM: -+ return "MIPS_ICHECKSUM"; -+ case DT_MIPS_IVERSION: -+ return "MIPS_IVERSION"; -+ case DT_MIPS_FLAGS: -+ return "MIPS_FLAGS"; -+ case DT_MIPS_BASE_ADDRESS: -+ return "MIPS_BASE_ADDRESS"; -+ case DT_MIPS_MSYM: -+ return "MIPS_MSYM"; -+ case DT_MIPS_CONFLICT: -+ return "MIPS_CONFLICT"; -+ case DT_MIPS_LIBLIST: -+ return "MIPS_LIBLIST"; -+ case DT_MIPS_LOCAL_GOTNO: -+ return "MIPS_LOCAL_GOTNO"; -+ case DT_MIPS_CONFLICTNO: -+ return "MIPS_CONFLICTNO"; -+ case DT_MIPS_LIBLISTNO: -+ return "MIPS_LIBLISTNO"; -+ case DT_MIPS_SYMTABNO: -+ return "MIPS_SYMTABNO"; -+ case DT_MIPS_UNREFEXTNO: -+ return "MIPS_UNREFEXTNO"; -+ case DT_MIPS_GOTSYM: -+ return "MIPS_GOTSYM"; -+ case DT_MIPS_HIPAGENO: -+ return "MIPS_HIPAGENO"; -+ case DT_MIPS_RLD_MAP: -+ return "MIPS_RLD_MAP"; -+ case DT_MIPS_RLD_MAP_REL: -+ return "MIPS_RLD_MAP_REL"; -+ case DT_MIPS_DELTA_CLASS: -+ return "MIPS_DELTA_CLASS"; -+ case DT_MIPS_DELTA_CLASS_NO: -+ return "MIPS_DELTA_CLASS_NO"; -+ case DT_MIPS_DELTA_INSTANCE: -+ return "MIPS_DELTA_INSTANCE"; -+ case DT_MIPS_DELTA_INSTANCE_NO: -+ return "MIPS_DELTA_INSTANCE_NO"; -+ case DT_MIPS_DELTA_RELOC: -+ return "MIPS_DELTA_RELOC"; -+ case DT_MIPS_DELTA_RELOC_NO: -+ return "MIPS_DELTA_RELOC_NO"; -+ case DT_MIPS_DELTA_SYM: -+ return "MIPS_DELTA_SYM"; -+ case DT_MIPS_DELTA_SYM_NO: -+ return "MIPS_DELTA_SYM_NO"; -+ case DT_MIPS_DELTA_CLASSSYM: -+ return "MIPS_DELTA_CLASSSYM"; -+ case DT_MIPS_DELTA_CLASSSYM_NO: -+ return "MIPS_DELTA_CLASSSYM_NO"; -+ case DT_MIPS_CXX_FLAGS: -+ return "MIPS_CXX_FLAGS"; -+ case DT_MIPS_PIXIE_INIT: -+ return "MIPS_PIXIE_INIT"; -+ case DT_MIPS_SYMBOL_LIB: -+ return "MIPS_SYMBOL_LIB"; -+ case DT_MIPS_LOCALPAGE_GOTIDX: -+ return "MIPS_LOCALPAGE_GOTIDX"; -+ case DT_MIPS_LOCAL_GOTIDX: -+ return "MIPS_LOCAL_GOTIDX"; -+ case DT_MIPS_HIDDEN_GOTIDX: -+ return "MIPS_HIDDEN_GOTIDX"; -+ case DT_MIPS_PROTECTED_GOTIDX: -+ return "MIPS_PROTECTED_GOTIDX"; -+ case DT_MIPS_OPTIONS: -+ return "MIPS_OPTIONS"; -+ case DT_MIPS_INTERFACE: -+ return "MIPS_INTERFACE"; -+ case DT_MIPS_DYNSTR_ALIGN: -+ return "MIPS_DYNSTR_ALIGN"; -+ case DT_MIPS_INTERFACE_SIZE: -+ return "MIPS_INTERFACE_SIZE"; -+ case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: -+ return "MIPS_RLD_TEXT_RESOLVE_ADDR"; -+ case DT_MIPS_PERF_SUFFIX: -+ return "MIPS_PERF_SUFFIX"; -+ case DT_MIPS_COMPACT_SIZE: -+ return "MIPS_COMPACT_SIZE"; -+ case DT_MIPS_GP_VALUE: -+ return "MIPS_GP_VALUE"; -+ case DT_MIPS_AUX_DYNAMIC: -+ return "MIPS_AUX_DYNAMIC"; -+ case DT_MIPS_PLTGOT: -+ return "MIPS_PLTGOT"; -+ case DT_MIPS_RWPLT: -+ return "MIPS_RWPLT"; -+ case DT_MIPS_XHASH: -+ return "MIPS_XHASH"; -+ default: -+ return NULL; -+ } -+ return NULL; -+} --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c @@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl * @@ -922,1604 +290,11 @@ Signed-off-by: Ying Huang --- a/libelf/libelfP.h +++ b/libelf/libelfP.h -@@ -617,4 +617,8 @@ extern void __libelf_reset_rawdata (Elf_ +@@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_ #define INVALID_NDX(ndx, type, data) \ unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx)) +#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) -+#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF) #endif /* libelfP.h */ ---- /dev/null -+++ b/backends/mips_cfi.c -@@ -0,0 +1,68 @@ -+/* MIPS ABI-specified defaults for DWARF CFI. -+ Copyright (C) 2009 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+int -+mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) -+{ -+ static const uint8_t abi_cfi[] = -+ { -+ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0), -+ /* Callee-saved regs. */ -+ DW_CFA_same_value, ULEB128_7 (16), /* s0 */ -+ DW_CFA_same_value, ULEB128_7 (17), /* s1 */ -+ DW_CFA_same_value, ULEB128_7 (18), /* s2 */ -+ DW_CFA_same_value, ULEB128_7 (19), /* s3 */ -+ DW_CFA_same_value, ULEB128_7 (20), /* s4 */ -+ DW_CFA_same_value, ULEB128_7 (21), /* s5 */ -+ DW_CFA_same_value, ULEB128_7 (22), /* s6 */ -+ DW_CFA_same_value, ULEB128_7 (23), /* s7 */ -+ DW_CFA_same_value, ULEB128_7 (28), /* gp */ -+ DW_CFA_same_value, ULEB128_7 (29), /* sp */ -+ DW_CFA_same_value, ULEB128_7 (30), /* fp */ -+ -+ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0), -+ }; -+ -+ abi_info->initial_instructions = abi_cfi; -+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; -+ abi_info->data_alignment_factor = 8; -+ -+ abi_info->return_address_register = 31; /* %ra */ -+ -+ return 0; -+} ---- /dev/null -+++ b/backends/mips_initreg.c -@@ -0,0 +1,61 @@ -+/* Fetch live process registers from TID. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__) -+# include -+# include -+#include -+#endif -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+ -+bool -+mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), -+ ebl_tid_registers_t *setfunc __attribute__ ((unused)), -+ void *arg __attribute__ ((unused))) -+{ -+#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__) -+ return false; -+#else /* __mips__ */ -+/* For PTRACE_GETREGS */ -+ -+ struct pt_regs gregs; -+ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0) -+ return false; -+ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg)) -+ return false; -+ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg); -+#endif /* __mips__ */ -+} ---- /dev/null -+++ b/backends/mips_unwind.c -@@ -0,0 +1,84 @@ -+/* Get previous frame state for an existing frame state. -+ Copyright (C) 2016 The Qt Company Ltd. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#define BACKEND mips_ -+#define SP_REG 29 -+#define FP_REG 30 -+#define LR_REG 31 -+#define FP_OFFSET 0 -+#define LR_OFFSET 8 -+#define SP_OFFSET 16 -+ -+#include "libebl_CPU.h" -+ -+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ -+ -+bool -+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)), -+ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc, -+ ebl_pid_memory_read_t *readfunc, void *arg, -+ bool *signal_framep __attribute__ ((unused))) -+{ -+ Dwarf_Word fp, lr, sp; -+ -+ if (!getfunc(LR_REG, 1, &lr, arg)) -+ return false; -+ -+ if (lr == 0 || !setfunc(-1, 1, &lr, arg)) -+ return false; -+ -+ if (!getfunc(FP_REG, 1, &fp, arg)) -+ fp = 0; -+ -+ if (!getfunc(SP_REG, 1, &sp, arg)) -+ sp = 0; -+ -+ Dwarf_Word newLr, newFp, newSp; -+ -+ if (!readfunc(fp + LR_OFFSET, &newLr, arg)) -+ newLr = 0; -+ -+ if (!readfunc(fp + FP_OFFSET, &newFp, arg)) -+ newFp = 0; -+ -+ newSp = fp + SP_OFFSET; -+ -+ // These are not fatal if they don't work. They will just prevent unwinding at the next frame. -+ setfunc(LR_REG, 1, &newLr, arg); -+ setfunc(FP_REG, 1, &newFp, arg); -+ setfunc(SP_REG, 1, &newSp, arg); -+ -+ // If the fp is invalid, we might still have a valid lr. -+ // But if the fp is valid, then the stack should be moving in the right direction. -+ return fp == 0 || newSp > sp; -+} ---- /dev/null -+++ b/backends/mips_corenote.c -@@ -0,0 +1,104 @@ -+/* MIPS specific core note handling. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include "libebl_CPU.h" -+ -+#ifndef BITS -+# define BITS 32 -+#define BACKEND mips_ -+#else -+# define BITS 64 -+# define BACKEND mips64_ -+#endif -+ -+#define PRSTATUS_REGS_SIZE (45 * (BITS / 8)) -+static const Ebl_Register_Location prstatus_regs[] = -+ { -+ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS }, -+ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS }, -+ }; -+ -+#define PRSTATUS_REGSET_ITEMS \ -+ { \ -+ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \ -+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \ -+ .group = "register", \ -+ .pc_register = true \ -+ } -+ -+static const Ebl_Register_Location mips_fpregset_regs[] = -+ { -+ { .offset = 0, .regno = 38, .count = 32, .bits = 64 }, /* fp0-fp31 */ -+ }; -+ -+static const Ebl_Core_Item mips_fpregset_items[] = -+ { -+ { -+ .name = "fcs", .type = ELF_T_WORD, .format = 'x', -+ .offset = 32 * 8, .group = "register" -+ }, -+ { -+ .name = "fir", .type = ELF_T_WORD, .format = 'x', -+ .offset = 32 * 8 + 4, .group = "register" -+ } -+ }; -+ -+#if BITS == 32 -+# define ULONG uint32_t -+# define ALIGN_ULONG 4 -+# define TYPE_ULONG ELF_T_WORD -+#define TYPE_LONG ELF_T_SWORD -+#else -+#define ULONG uint64_t -+#define ALIGN_ULONG 8 -+#define TYPE_ULONG ELF_T_XWORD -+#define TYPE_LONG ELF_T_SXWORD -+#endif -+#define PID_T int32_t -+#define UID_T uint32_t -+#define GID_T uint32_t -+#define ALIGN_PID_T 4 -+#define ALIGN_UID_T 4 -+#define ALIGN_GID_T 4 -+#define TYPE_PID_T ELF_T_SWORD -+#define TYPE_UID_T ELF_T_WORD -+#define TYPE_GID_T ELF_T_WORD -+ -+#define EXTRA_NOTES \ -+ EXTRA_REGSET_ITEMS (NT_FPREGSET, 32 * 8 + 4 * 2, mips_fpregset_regs, mips_fpregset_items) -+ -+#include "linux-core-note.c" ---- /dev/null -+++ b/backends/mips_regs.c -@@ -0,0 +1,135 @@ -+/* Register names and numbers for mips DWARF. -+ Copyright (C) 2006 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+#include -+ssize_t -+mips_register_info (Ebl *ebl __attribute__ ((unused)), -+ int regno, char *name, size_t namelen, -+ const char **prefix, const char **setname, -+ int *bits, int *type) -+{ -+ if (name == NULL) -+ return 72; -+ -+ if (regno < 0 || regno > 71 || namelen < 4) -+ return -1; -+ -+ *prefix = "$"; -+ if (regno < 38) -+ { -+ *setname = "integer"; -+ *type = DW_ATE_signed; -+ *bits = 32; -+ } -+ else -+ { -+ *setname = "FPU"; -+ *type = DW_ATE_float; -+ *bits = 64; -+ } -+ -+ if (regno < 32) -+ { -+ if (regno < 10) -+ { -+ name[0] = regno + '0'; -+ namelen = 1; -+ } -+ else -+ { -+ name[0] = (regno / 10) + '0'; -+ name[1] = (regno % 10) + '0'; -+ namelen = 2; -+ } -+ if (regno == 28 || regno == 29 || regno == 31) -+ *type = DW_ATE_address; -+ } -+ else if (regno == 32) -+ { -+ return stpcpy (name, "lo") + 1 - name; -+ } -+ else if (regno == 33) -+ { -+ return stpcpy (name, "hi") + 1 - name; -+ } -+ else if (regno == 34) -+ { -+ return stpcpy (name, "pc") + 1 - name; -+ } -+ else if (regno == 35) -+ { -+ *type = DW_ATE_address; -+ return stpcpy (name, "bad") + 1 - name; -+ } -+ else if (regno == 36) -+ { -+ return stpcpy (name, "sr") + 1 - name; -+ } -+ else if (regno == 37) -+ { -+ *type = DW_ATE_address; -+ return stpcpy (name, "cause") + 1 - name; -+ } -+ else if (regno < 70) -+ { -+ name[0] = 'f'; -+ if (regno < 38 + 10) -+ { -+ name[1] = (regno - 38) + '0'; -+ namelen = 2; -+ } -+ else -+ { -+ name[1] = (regno - 38) / 10 + '0'; -+ name[2] = (regno - 38) % 10 + '0'; -+ namelen = 3; -+ } -+ } -+ else if (regno == 70) -+ { -+ return stpcpy (name, "fsr") + 1 - name; -+ } -+ else if (regno == 71) -+ { -+ return stpcpy (name, "fir") + 1 - name; -+ } -+ -+ name[namelen++] = '\0'; -+ return namelen; -+} ---- /dev/null -+++ b/backends/mips_retval.c -@@ -0,0 +1,196 @@ -+/* Function return value location for Linux/mips ABI. -+ Copyright (C) 2005 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+#include "libdwP.h" -+#include -+ -+/* $v0 or pair $v0, $v1 */ -+static const Dwarf_Op loc_intreg_o32[] = -+ { -+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 }, -+ }; -+ -+static const Dwarf_Op loc_intreg[] = -+ { -+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 }, -+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 }, -+ }; -+#define nloc_intreg 1 -+#define nloc_intregpair 4 -+ -+/* $f0 (float), or pair $f0, $f1 (double). -+ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */ -+static const Dwarf_Op loc_fpreg_o32[] = -+ { -+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 }, -+ }; -+ -+/* $f0, or pair $f0, $f2. */ -+static const Dwarf_Op loc_fpreg[] = -+ { -+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 }, -+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 }, -+ }; -+#define nloc_fpreg 1 -+#define nloc_fpregpair 4 -+#define nloc_fpregquad 8 -+ -+/* The return value is a structure and is actually stored in stack space -+ passed in a hidden argument by the caller. But, the compiler -+ helpfully returns the address of that space in $v0. */ -+static const Dwarf_Op loc_aggregate[] = -+ { -+ { .atom = DW_OP_breg2, .number = 0 } -+ }; -+#define nloc_aggregate 1 -+ -+int -+mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) -+{ -+ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8; -+ if (!regsize) -+ return -2; -+ -+ /* Start with the function's type, and get the DW_AT_type attribute, -+ which is the type of the return value. */ -+ -+ Dwarf_Attribute attr_mem; -+ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); -+ if (attr == NULL) -+ /* The function has no return value, like a `void' function in C. */ -+ return 0; -+ -+ Dwarf_Die die_mem; -+ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); -+ int tag = dwarf_tag (typedie); -+ -+ /* Follow typedefs and qualifiers to get to the actual type. */ -+ while (tag == DW_TAG_typedef -+ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type -+ || tag == DW_TAG_restrict_type) -+ { -+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); -+ typedie = dwarf_formref_die (attr, &die_mem); -+ tag = dwarf_tag (typedie); -+ } -+ -+ switch (tag) -+ { -+ case -1: -+ return -1; -+ -+ case DW_TAG_subrange_type: -+ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) -+ { -+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); -+ typedie = dwarf_formref_die (attr, &die_mem); -+ tag = dwarf_tag (typedie); -+ } -+ /* Fall through. */ -+ FALLTHROUGH; -+ -+ case DW_TAG_base_type: -+ case DW_TAG_enumeration_type: -+ CASE_POINTER: -+ { -+ Dwarf_Word size; -+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, -+ &attr_mem), &size) != 0) -+ { -+ if (dwarf_is_pointer (tag)) -+ size = regsize; -+ else -+ return -1; -+ } -+ if (tag == DW_TAG_base_type) -+ { -+ Dwarf_Word encoding; -+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, -+ &attr_mem), &encoding) != 0) -+ return -1; -+ -+#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc)) -+ -+ if (encoding == DW_ATE_float) -+ { -+ *locp = ARCH_LOC(loc_fpreg, regsize); -+ if (size <= regsize) -+ return nloc_fpreg; -+ -+ if (size <= 2*regsize) -+ return nloc_fpregpair; -+ -+ if (size <= 4*regsize) -+ return nloc_fpregquad; -+ -+ goto aggregate; -+ } -+ } -+ *locp = ARCH_LOC(loc_intreg, regsize); -+ if (size <= regsize) -+ return nloc_intreg; -+ if (size <= 2*regsize) -+ return nloc_intregpair; -+ -+ /* Else fall through. Shouldn't happen though (at least with gcc) */ -+ } -+ FALLTHROUGH; -+ -+ case DW_TAG_structure_type: -+ case DW_TAG_class_type: -+ case DW_TAG_union_type: -+ case DW_TAG_array_type: -+ aggregate: -+ *locp = loc_aggregate; -+ return nloc_aggregate; -+ case DW_TAG_unspecified_type: -+ return 0; -+ } -+ -+ /* XXX We don't have a good way to return specific errors from ebl calls. -+ This value means we do not understand the type, but it is well-formed -+ DWARF and might be valid. */ -+ return -2; -+} ---- a/libelf/elf_getdata.c -+++ b/libelf/elf_getdata.c -@@ -135,6 +135,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int - - /* Convert the data in the current section. */ - static void -+convert_data_for_mips64el (Elf_Scn *scn, int eclass, -+ int data, size_t size, Elf_Type type) -+{ -+ /* Do we need to convert the data and/or adjust for alignment? */ -+ if (data == MY_ELFDATA || type == ELF_T_BYTE) -+ { -+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert -+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so -+ we need to malloc and memcpy raw data to avoid segment fault. After modification, -+ the correct value are saved in the malloced memory not in process address space. */ -+ scn->data_base = malloc (size); -+ if (scn->data_base == NULL) -+ { -+ __libelf_seterrno (ELF_E_NOMEM); -+ return; -+ } -+ -+ /* The copy will be appropriately aligned for direct access. */ -+ memcpy (scn->data_base, scn->rawdata_base, size); -+ } -+ else -+ { -+ xfct_t fp; -+ -+ scn->data_base = malloc (size); -+ if (scn->data_base == NULL) -+ { -+ __libelf_seterrno (ELF_E_NOMEM); -+ return; -+ } -+ -+ /* Make sure the source is correctly aligned for the conversion -+ function to directly access the data elements. */ -+ char *rawdata_source; -+ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert -+ relocation info(raw data). Some eu-utils use read-mmap method to map file, so -+ we need to malloc and memcpy raw data to avoid segment fault. After modification, -+ the correct value are saved in the malloced memory not in process address space. */ -+ rawdata_source = malloc (size); -+ if (rawdata_source == NULL) -+ { -+ __libelf_seterrno (ELF_E_NOMEM); -+ return; -+ } -+ -+ /* The copy will be appropriately aligned for direct access. */ -+ memcpy (rawdata_source, scn->rawdata_base, size); -+ -+ /* Get the conversion function. */ -+ fp = __elf_xfctstom[eclass - 1][type]; -+ -+ fp (scn->data_base, rawdata_source, size, 0); -+ -+ if (rawdata_source != scn->rawdata_base) -+ free (rawdata_source); -+ } -+ -+ scn->data_list.data.d.d_buf = scn->data_base; -+ scn->data_list.data.d.d_size = size; -+ scn->data_list.data.d.d_type = type; -+ scn->data_list.data.d.d_off = scn->rawdata.d.d_off; -+ scn->data_list.data.d.d_align = scn->rawdata.d.d_align; -+ scn->data_list.data.d.d_version = scn->rawdata.d.d_version; -+ -+ scn->data_list.data.s = scn; -+ -+ /* In mips64 little-endian, r_info consists of four byte fields(contains -+ three reloc types) and a 32-bit symbol index. In order to adapt -+ GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol -+ index and type. */ -+ /* references: -+ https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf -+ Page40 && Page41 */ -+ GElf_Shdr shdr_mem; -+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); -+ if (shdr->sh_type == SHT_REL) -+ { -+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); -+ int nentries = shdr->sh_size / sh_entsize; -+ for (int cnt = 0; cnt < nentries; ++cnt) -+ { -+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; -+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; -+ Elf64_Xword info = value->r_info; -+ value->r_info = (((info & 0xffffffff) << 32) -+ | ((info >> 56) & 0xff) -+ | ((info >> 40) & 0xff00) -+ | ((info >> 24) & 0xff0000) -+ | ((info >> 8) & 0xff000000)); -+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; -+ } -+ } -+ else if (shdr->sh_type == SHT_RELA) -+ { -+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); -+ int nentries = shdr->sh_size / sh_entsize; -+ for (int cnt = 0; cnt < nentries; cnt++) -+ { -+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; -+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; -+ Elf64_Xword info = value->r_info; -+ value->r_info = (((info & 0xffffffff) << 32) -+ | ((info >> 56) & 0xff) -+ | ((info >> 40) & 0xff00) -+ | ((info >> 24) & 0xff0000) -+ | ((info >> 8) & 0xff000000)); -+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; -+ } -+ } -+} -+ -+/* Convert the data in the current section. */ -+static void - convert_data (Elf_Scn *scn, int eclass, - int data, size_t size, Elf_Type type) - { -@@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn * - return; - } - -- /* Convert according to the version and the type. */ -- convert_data (scn, elf->class, -+ GElf_Shdr shdr_mem; -+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); -+ GElf_Ehdr ehdr_mem; -+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); -+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && -+ scn->elf->class == ELFCLASS64 && ehdr != NULL && -+ ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) -+ convert_data_for_mips64el (scn, elf->class, -+ (elf->class == ELFCLASS32 -+ || (offsetof (struct Elf, state.elf32.ehdr) -+ == offsetof (struct Elf, state.elf64.ehdr)) -+ ? elf->state.elf32.ehdr->e_ident[EI_DATA] -+ : elf->state.elf64.ehdr->e_ident[EI_DATA]), -+ scn->rawdata.d.d_size, scn->rawdata.d.d_type); -+ else -+ /* Convert according to the version and the type. */ -+ convert_data (scn, elf->class, - (elf->class == ELFCLASS32 - || (offsetof (struct Elf, state.elf32.ehdr) - == offsetof (struct Elf, state.elf64.ehdr)) ---- a/libelf/elf_update.c -+++ b/libelf/elf_update.c -@@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd) - size = -1; - } - else -+ { -+ /* Because we converted the relocation info in mips order when we call elf_getdata.c, -+ so we need to convert the modified data in original order bits before writing the -+ data to the file. */ -+ Elf_Scn *scn = NULL; -+ while ((scn = elf_nextscn (elf, scn)) != NULL) -+ { -+ GElf_Shdr shdr_mem; -+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); -+ GElf_Ehdr ehdr_mem; -+ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); -+ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && -+ scn->elf->class == ELFCLASS64 && -+ ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) -+ { -+ Elf_Data *d = elf_getdata (scn, NULL); -+ if (shdr->sh_type == SHT_REL) -+ { -+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); -+ int nentries = shdr->sh_size / sh_entsize; -+ for (int cnt = 0; cnt < nentries; ++cnt) -+ { -+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; -+ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; -+ Elf64_Xword info = value->r_info; -+ value->r_info = (info >> 32 -+ | ((info << 56) & 0xff00000000000000) -+ | ((info << 40) & 0xff000000000000) -+ | ((info << 24) & 0xff0000000000) -+ | ((info << 8) & 0xff00000000)); -+ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; -+ } -+ } -+ else if (shdr->sh_type == SHT_RELA) -+ { -+ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); -+ int nentries = shdr->sh_size / sh_entsize; -+ for (int cnt = 0; cnt < nentries; cnt++) -+ { -+ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; -+ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; -+ Elf64_Xword info = value->r_info; -+ value->r_info = (info >> 32 -+ | ((info << 56) & 0xff00000000000000) -+ | ((info << 40) & 0xff000000000000) -+ | ((info << 24) & 0xff0000000000) -+ | ((info << 8) & 0xff00000000)); -+ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; -+ } -+ } -+ } -+ } - size = write_file (elf, size, change_bo, shnum); -+ } - } - - out: ---- /dev/null -+++ b/backends/mips_attrs.c -@@ -0,0 +1,140 @@ -+/* Object attribute tags for MIPS. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+#define KNOWN_VALUES(...) do \ -+ { \ -+ static const char *table[] = { __VA_ARGS__ }; \ -+ if (value < sizeof table / sizeof table[0]) \ -+ *value_name = table[value]; \ -+ } while (0) -+ -+//copy gnu attr tags from binutils-2.34/elfcpp/mips.h -+/* Object attribute tags. */ -+enum -+{ -+ /* 0-3 are generic. */ -+ -+ /* Floating-point ABI used by this object file. */ -+ Tag_GNU_MIPS_ABI_FP = 4, -+ -+ /* MSA ABI used by this object file. */ -+ Tag_GNU_MIPS_ABI_MSA = 8, -+}; -+ -+/* Object attribute values. */ -+enum -+{ -+ /* Values defined for Tag_GNU_MIPS_ABI_MSA. */ -+ -+ /* Not tagged or not using any ABIs affected by the differences. */ -+ Val_GNU_MIPS_ABI_MSA_ANY = 0, -+ -+ /* Using 128-bit MSA. */ -+ Val_GNU_MIPS_ABI_MSA_128 = 1, -+}; -+ -+/* Object attribute values. */ -+enum -+{ -+ /* This is reserved for backward-compatibility with an earlier -+ implementation of the MIPS NaN2008 functionality. */ -+ Val_GNU_MIPS_ABI_FP_NAN2008 = 8, -+}; -+ -+/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */ -+bool -+mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)), -+ const char *vendor, int tag, uint64_t value, -+ const char **tag_name, const char **value_name) -+{ -+ if (!strcmp (vendor, "gnu")) -+ switch (tag) -+ { -+ case Tag_GNU_MIPS_ABI_FP: -+ *tag_name = "Tag_GNU_MIPS_ABI_FP"; -+ switch (value) -+ { -+ case Val_GNU_MIPS_ABI_FP_ANY: -+ *value_name = "Hard or soft float"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_DOUBLE: -+ *value_name = "Hard float (double precision)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_SINGLE: -+ *value_name = "Hard float (single precision)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_SOFT: -+ *value_name = "Soft float"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_OLD_64: -+ *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_XX: -+ *value_name = "Hard float (32-bit CPU, Any FPU)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_64: -+ *value_name = "Hard float (32-bit CPU, 64-bit FPU)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_64A: -+ *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)"; -+ return true; -+ case Val_GNU_MIPS_ABI_FP_NAN2008: -+ *value_name = "NaN 2008 compatibility"; -+ return true; -+ default: -+ return true; -+ } -+ return true; -+ case Tag_GNU_MIPS_ABI_MSA: -+ *tag_name = "Tag_GNU_MIPS_ABI_MSA"; -+ switch (value) -+ { -+ case Val_GNU_MIPS_ABI_MSA_ANY: -+ *value_name = "Any MSA or not"; -+ return true; -+ case Val_GNU_MIPS_ABI_MSA_128: -+ *value_name = "128-bit MSA"; -+ return true; -+ default: -+ return true; -+ } -+ return true; -+ } -+ -+ return false; -+} ---- a/src/readelf.c -+++ b/src/readelf.c -@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * - (long int) GELF_R_SYM (rel->r_info)); - } - else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) -- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", -- class == ELFCLASS32 ? 10 : 18, rel->r_offset, -- likely (ebl_reloc_type_check (ebl, -- GELF_R_TYPE (rel->r_info))) -- /* Avoid the leading R_ which isn't carrying any -- information. */ -- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -- buf, sizeof (buf)) + 2 -- : _(""), -- class == ELFCLASS32 ? 10 : 18, sym->st_value, -- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); -+ { -+ unsigned long inf = rel->r_info; -+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", -+ class == ELFCLASS32 ? 10 : 18, rel->r_offset, -+ likely (ebl_reloc_type_check (ebl, -+ GELF_R_TYPE (rel->r_info))) -+ /* Avoid the leading R_ which isn't carrying any -+ information. */ -+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -+ buf, sizeof (buf)) + 2 -+ : _(""), -+ class == ELFCLASS32 ? 10 : 18, sym->st_value, -+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); -+ -+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ -+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) -+ { -+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); -+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); -+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; -+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; -+ printf(" Type2: "); -+ if (rtype2 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); -+ else -+ printf ("%s", rtype2); -+ -+ printf ("\n Type3: "); -+ if (rtype3 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); -+ else -+ printf ("%s", rtype3); -+ printf("\n"); -+ } -+ } - else - { - /* This is a relocation against a STT_SECTION symbol. */ -@@ -2253,16 +2277,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * - (long int) (sym->st_shndx == SHN_XINDEX - ? xndx : sym->st_shndx)); - else -- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", -- class == ELFCLASS32 ? 10 : 18, rel->r_offset, -- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) -- /* Avoid the leading R_ which isn't carrying any -- information. */ -- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -- buf, sizeof (buf)) + 2 -- : _(""), -- class == ELFCLASS32 ? 10 : 18, sym->st_value, -- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); -+ { -+ unsigned long inf = rel->r_info; -+ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", -+ class == ELFCLASS32 ? 10 : 18, rel->r_offset, -+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) -+ /* Avoid the leading R_ which isn't carrying any -+ information. */ -+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -+ buf, sizeof (buf)) + 2 -+ : _(""), -+ class == ELFCLASS32 ? 10 : 18, sym->st_value, -+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); -+ -+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ -+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) -+ { -+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); -+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); -+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; -+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; -+ printf(" Type2: "); -+ if (rtype2 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); -+ else -+ printf ("%s", rtype2); -+ -+ printf ("\n Type3: "); -+ if (rtype3 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); -+ else -+ printf ("%s", rtype3); -+ printf("\n"); -+ } -+ } - } - } - } -@@ -2410,19 +2458,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr - (long int) GELF_R_SYM (rel->r_info)); - } - else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) -- printf ("\ -+ { -+ unsigned long inf = rel->r_info; -+ printf ("\ - %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", -- class == ELFCLASS32 ? 10 : 18, rel->r_offset, -- likely (ebl_reloc_type_check (ebl, -- GELF_R_TYPE (rel->r_info))) -- /* Avoid the leading R_ which isn't carrying any -- information. */ -- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -- buf, sizeof (buf)) + 2 -- : _(""), -- class == ELFCLASS32 ? 10 : 18, sym->st_value, -- rel->r_addend, -- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); -+ class == ELFCLASS32 ? 10 : 18, rel->r_offset, -+ likely (ebl_reloc_type_check (ebl, -+ GELF_R_TYPE (rel->r_info))) -+ /* Avoid the leading R_ which isn't carrying any -+ information. */ -+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -+ buf, sizeof (buf)) + 2 -+ : _(""), -+ class == ELFCLASS32 ? 10 : 18, sym->st_value, -+ rel->r_addend, -+ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); -+ -+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ -+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) -+ { -+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); -+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); -+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; -+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; -+ printf(" Type2: "); -+ if (rtype2 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); -+ else -+ printf ("%s", rtype2); -+ -+ printf ("\n Type3: "); -+ if (rtype3 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); -+ else -+ printf ("%s", rtype3); -+ printf("\n"); -+ } -+ } - else - { - /* This is a relocation against a STT_SECTION symbol. */ -@@ -2446,18 +2518,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr - (long int) (sym->st_shndx == SHN_XINDEX - ? xndx : sym->st_shndx)); - else -- printf ("\ -+ { -+ unsigned long inf = rel->r_info; -+ printf ("\ - %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", -- class == ELFCLASS32 ? 10 : 18, rel->r_offset, -- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) -- /* Avoid the leading R_ which isn't carrying any -- information. */ -- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -- buf, sizeof (buf)) + 2 -- : _(""), -- class == ELFCLASS32 ? 10 : 18, sym->st_value, -- rel->r_addend, -- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); -+ class == ELFCLASS32 ? 10 : 18, rel->r_offset, -+ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) -+ /* Avoid the leading R_ which isn't carrying any -+ information. */ -+ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), -+ buf, sizeof (buf)) + 2 -+ : _(""), -+ class == ELFCLASS32 ? 10 : 18, sym->st_value, -+ rel->r_addend, -+ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); -+ -+ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ -+ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) -+ { -+ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); -+ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); -+ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; -+ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; -+ printf(" Type2: "); -+ if (rtype2 == NULL) -+ printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff); -+ else -+ printf ("%s", rtype2); -+ -+ printf ("\n Type3: "); -+ if (rtype3 == NULL) -+ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); -+ else -+ printf ("%s", rtype3); -+ printf("\n"); -+ } -+ } - } - } - } -@@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - -- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS) -+ if (shdr != NULL && is_debug_section_type(shdr->sh_type)) - { - const char *name = elf_strptr (ebl->elf, shstrndx, - shdr->sh_name); -@@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * - GElf_Shdr shdr_mem; - GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); - -- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS) -+ if (shdr != NULL && is_debug_section_type(shdr->sh_type)) - { - static const struct - { ---- a/tests/Makefile.am -+++ b/tests/Makefile.am -@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s - run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ - run-readelf-dw-form-indirect.sh run-strip-largealign.sh \ - run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \ -- run-declfiles.sh -+ run-declfiles.sh run-readelf-reloc.sh - - if !BIARCH - export ELFUTILS_DISABLE_BIARCH = 1 -@@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymt - testfile-dwp-5-cu-index-overflow.dwp.bz2 \ - testfile-dwp-4-cu-index-overflow.bz2 \ - testfile-dwp-4-cu-index-overflow.dwp.bz2 \ -- testfile-dwp-cu-index-overflow.source -+ testfile-dwp-cu-index-overflow.source \ -+ run-readelf-reloc.sh - - - if USE_VALGRIND ---- /dev/null -+++ b/tests/run-readelf-reloc.sh -@@ -0,0 +1,42 @@ -+#! /bin/bash -+# Copyright (C) 2024 CIP United Inc. -+# This file is part of elfutils. -+# -+# This file is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 3 of the License, or -+# (at your option) any later version. -+# -+# elfutils is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program. If not, see . -+ -+. $srcdir/test-subr.sh -+ -+tempfiles test-readelf-h.txt test-readelf-reloc.txt -+testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt -+machine=`cat test-readelf-h.txt | grep Machine` -+class=`cat test-readelf-h.txt | grep Class` -+endian=`cat test-readelf-h.txt | grep Data` -+if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then -+testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt -+ -+testrun_compare cat test-readelf-reloc.txt << EOF -+ Offset Type Value Addend Name -+ 0x0000000000000008 MIPS_GPREL16 000000000000000000 +0 .text -+ Type2: MIPS_SUB -+ Type3: MIPS_HI16 -+ 0x0000000000000010 MIPS_GPREL16 000000000000000000 +0 .text -+ Type2: MIPS_SUB -+ Type3: MIPS_LO16 -+ 0x0000000000000014 MIPS_CALL16 000000000000000000 +0 gelf_getehdr -+ Type2: MIPS_NONE -+ Type3: MIPS_NONE -+EOF -+fi -+ -+exit 0 ---- a/src/elflint.c -+++ b/src/elflint.c -@@ -936,7 +936,9 @@ section [%2d] '%s': symbol %zu (%s): non - } - - if (GELF_ST_TYPE (sym->st_info) == STT_SECTION -- && GELF_ST_BIND (sym->st_info) != STB_LOCAL) -+ && GELF_ST_BIND (sym->st_info) != STB_LOCAL -+ && ehdr->e_machine != EM_MIPS -+ && strcmp (name, "_DYNAMIC_LINKING") != 0) - ERROR (_("\ - section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"), - idx, section_name (ebl, idx), cnt, name); -@@ -3828,6 +3830,10 @@ cannot get section header for section [% - && ebl_bss_plt_p (ebl)) - good_type = SHT_NOBITS; - -+ if (ehdr->e_machine == EM_MIPS -+ && (strstr(special_sections[s].name, ".debug") != NULL)) -+ good_type = SHT_MIPS_DWARF; -+ - /* In a debuginfo file, any normal section can be SHT_NOBITS. - This is only invalid for DWARF sections and .shstrtab. */ - if (shdr->sh_type != good_type -@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o - ERROR (_("section [%2zu] '%s'" - " contains invalid processor-specific flag(s)" - " %#" PRIx64 "\n"), -- cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); -+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); - sh_flags &= ~(GElf_Xword) SHF_MASKPROC; - } - if (sh_flags & SHF_MASKOS) -- if (gnuld) -- sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; -+ { -+ if (gnuld) -+ sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; -+ if (!ebl_machine_section_flag_check (ebl, -+ sh_flags & SHF_MASKOS)) -+ ERROR (_("section [%2zu] '%s'" -+ " contains invalid os-specific flag(s)" -+ " %#" PRIx64 "\n"), -+ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKOS); -+ sh_flags &= ~(GElf_Xword) SHF_MASKOS; -+ } - if (sh_flags != 0) - ERROR (_("section [%2zu] '%s' contains unknown flag(s)" - " %#" PRIx64 "\n"), -@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but - switch (shdr->sh_type) - { - case SHT_PROGBITS: -+ case SHT_MIPS_DWARF: - break; - - case SHT_NOBITS: -@@ -4716,7 +4732,7 @@ program header offset in ELF header and - if (shdr != NULL - && ((is_debuginfo && shdr->sh_type == SHT_NOBITS) - || (! is_debuginfo -- && (shdr->sh_type == SHT_PROGBITS -+ && (is_debug_section_type(shdr->sh_type) - || shdr->sh_type == SHT_X86_64_UNWIND))) - && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL - && ! strcmp (".eh_frame_hdr", ---- /dev/null -+++ b/backends/mips64_corenote.c -@@ -0,0 +1,2 @@ -+#define BITS 64 -+#include "mips_corenote.c" ---- a/libebl/eblcorenotetypename.c -+++ b/libebl/eblcorenotetypename.c -@@ -94,6 +94,8 @@ ebl_core_note_type_name (Ebl *ebl, uint3 - KNOWNSTYPE (ARM_SYSTEM_CALL); - KNOWNSTYPE (SIGINFO); - KNOWNSTYPE (FILE); -+ KNOWNSTYPE (MIPS_FP_MODE); -+ KNOWNSTYPE (MIPS_MSA); - #undef KNOWNSTYPE - - default: ---- a/tests/run-allregs.sh -+++ b/tests/run-allregs.sh -@@ -2904,4 +2904,83 @@ FPU registers: - 62: ft10 (ft10), float 64 bits - 63: ft11 (ft11), float 64 bits - EOF -+ -+# See run-readelf-mixed-corenote.sh for instructions to regenerate -+# this core file. -+regs_test testfile-mips64-core <<\EOF -+integer registers: -+ 0: $0 (0), signed 32 bits -+ 1: $1 (1), signed 32 bits -+ 2: $2 (2), signed 32 bits -+ 3: $3 (3), signed 32 bits -+ 4: $4 (4), signed 32 bits -+ 5: $5 (5), signed 32 bits -+ 6: $6 (6), signed 32 bits -+ 7: $7 (7), signed 32 bits -+ 8: $8 (8), signed 32 bits -+ 9: $9 (9), signed 32 bits -+ 10: $10 (10), signed 32 bits -+ 11: $11 (11), signed 32 bits -+ 12: $12 (12), signed 32 bits -+ 13: $13 (13), signed 32 bits -+ 14: $14 (14), signed 32 bits -+ 15: $15 (15), signed 32 bits -+ 16: $16 (16), signed 32 bits -+ 17: $17 (17), signed 32 bits -+ 18: $18 (18), signed 32 bits -+ 19: $19 (19), signed 32 bits -+ 20: $20 (20), signed 32 bits -+ 21: $21 (21), signed 32 bits -+ 22: $22 (22), signed 32 bits -+ 23: $23 (23), signed 32 bits -+ 24: $24 (24), signed 32 bits -+ 25: $25 (25), signed 32 bits -+ 26: $26 (26), signed 32 bits -+ 27: $27 (27), signed 32 bits -+ 28: $28 (28), address 32 bits -+ 29: $29 (29), address 32 bits -+ 30: $30 (30), signed 32 bits -+ 31: $31 (31), address 32 bits -+ 32: $lo (lo), signed 32 bits -+ 33: $hi (hi), signed 32 bits -+ 34: $pc (pc), signed 32 bits -+ 35: $bad (bad), address 32 bits -+ 36: $sr (sr), signed 32 bits -+ 37: $cause (cause), address 32 bits -+FPU registers: -+ 38: $f0 (f0), float 64 bits -+ 39: $f1 (f1), float 64 bits -+ 40: $f2 (f2), float 64 bits -+ 41: $f3 (f3), float 64 bits -+ 42: $f4 (f4), float 64 bits -+ 43: $f5 (f5), float 64 bits -+ 44: $f6 (f6), float 64 bits -+ 45: $f7 (f7), float 64 bits -+ 46: $f8 (f8), float 64 bits -+ 47: $f9 (f9), float 64 bits -+ 48: $f10 (f10), float 64 bits -+ 49: $f11 (f11), float 64 bits -+ 50: $f12 (f12), float 64 bits -+ 51: $f13 (f13), float 64 bits -+ 52: $f14 (f14), float 64 bits -+ 53: $f15 (f15), float 64 bits -+ 54: $f16 (f16), float 64 bits -+ 55: $f17 (f17), float 64 bits -+ 56: $f18 (f18), float 64 bits -+ 57: $f19 (f19), float 64 bits -+ 58: $f20 (f20), float 64 bits -+ 59: $f21 (f21), float 64 bits -+ 60: $f22 (f22), float 64 bits -+ 61: $f23 (f23), float 64 bits -+ 62: $f24 (f24), float 64 bits -+ 63: $f25 (f25), float 64 bits -+ 64: $f26 (f26), float 64 bits -+ 65: $f27 (f27), float 64 bits -+ 66: $f28 (f28), float 64 bits -+ 67: $f29 (f29), float 64 bits -+ 68: $f30 (f30), float 64 bits -+ 69: $f31 (f31), float 64 bits -+ 70: $fsr (fsr), float 64 bits -+ 71: $fir (fir), float 64 bits -+EOF - exit 0 ---- a/tests/run-readelf-mixed-corenote.sh -+++ b/tests/run-readelf-mixed-corenote.sh -@@ -716,4 +716,101 @@ Note segment of 1408 bytes at offset 0x3 - 2000155000-2000157000 00122000 8192 /lib64/libc-2.27.so - EOF - -+# To reproduce this core dump, do this on a mips machine: -+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }') -+# $ ./a.out -+testfiles testfile-mips64-core -+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-mips64-core <<\EOF -+ -+Note segment of 2572 bytes at offset 0x3c0: -+ Owner Data size Type -+ CORE 480 PRSTATUS -+ info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11 -+ sigpend: <> -+ sighold: <> -+ pid: 1660204, ppid: 1457483, pgrp: 1660204, sid: 1457483 -+ utime: 0.000000, stime: 0.012000, cutime: 0.000000, cstime: 0.000000 -+ pc: 0x000000aaacce0a64, fpvalid: 1 -+ bad: 0x12345678 sr: 0 cause: 0x0400ccf3 -+ f0: 0x1000000800000000 f1: 0x0000000000000000 f2: 0x0000000000000000 -+ f3: 0x0000000000000000 f4: 0x0000000000000000 f5: 0x0000000000000000 -+ f6: 0x0000000000000000 -+ 0: 0 1: 0 2: 1 -+ 3: 0 4: 305419896 5: 0 -+ 6: -73593800 7: 255 8: 1 -+ 9: 0 10: -73593464 11: 255 -+ 12: -73593448 13: 255 14: 0 -+ 15: 0 16: -244869184 17: 255 -+ 18: -244886336 19: 255 20: -73593472 -+ 21: 255 22: -1 23: -1 -+ 24: 3 25: 0 26: 3167716 -+ 27: 0 28: 0x00000024 29: 0x00000000 -+ 30: 49495 31: 0x00000000 lo: -73593464 -+ hi: 255 bad: 0x12345678 sr: 0 -+ cause: 0x0400ccf3 f0: 0x1000000800000000 -+ f1: 0x0000000000000000 f2: 0x0000000000000000 -+ f3: 0x0000000000000000 f4: 0x0000000000000000 -+ f5: 0x0000000000000000 f6: 0x0000000000000000 -+ CORE 136 PRPSINFO -+ state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000402600 -+ uid: 1014, gid: 100, pid: 1660204, ppid: 1457483, pgrp: 1660204 -+ sid: 1457483 -+ fname: a.out, psargs: ./a.out -+ CORE 128 SIGINFO -+ si_signo: 11, si_errno: 1, si_code: 0 -+ sender PID: 305419896, sender UID: 0 -+ CORE 320 AUXV -+ SYSINFO_EHDR: 0xffff14c000 -+ HWCAP: 0x7806 -+ PAGESZ: 16384 -+ CLKTCK: 100 -+ PHDR: 0xaaacce0040 -+ PHENT: 56 -+ PHNUM: 9 -+ BASE: 0xfff1694000 -+ FLAGS: 0 -+ ENTRY: 0xaaacce08d0 -+ UID: 1014 -+ EUID: 1014 -+ GID: 100 -+ EGID: 100 -+ SECURE: 0 -+ RANDOM: 0xfffb9d0f9c -+ EXECFN: 0xfffb9d3ff0 -+ PLATFORM: 0xfffb9d0fb5 -+ BASE_PLATFORM: 0xfffb9d0fac -+ NULL -+ CORE 549 FILE -+ 9 files: -+ aaacce0000-aaacce4000 00000000 16384 /tmp/a.out -+ aaaccf0000-aaaccf4000 00000000 16384 /tmp/a.out -+ fff1470000-fff165c000 00000000 2015232 /usr/lib/mips64el-linux-gnuabi64/libc.so.6 -+ fff165c000-fff1668000 001ec000 49152 /usr/lib/mips64el-linux-gnuabi64/libc.so.6 -+ fff1668000-fff1670000 001e8000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6 -+ fff1670000-fff1678000 001f0000 32768 /usr/lib/mips64el-linux-gnuabi64/libc.so.6 -+ fff1694000-fff16c4000 00000000 196608 /usr/lib/mips64el-linux-gnuabi64/ld.so.1 -+ fff16d0000-fff16d4000 0002c000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1 -+ fff16d4000-fff16d8000 00030000 16384 /usr/lib/mips64el-linux-gnuabi64/ld.so.1 -+ CORE 264 FPREGSET -+ fcs: 0x000c0000, fir: 0x00f70501 -+ f0: 0xffffffffffffffff f1: 0xffffffffffffffff -+ f2: 0xffffffffffffffff f3: 0xffffffffffffffff -+ f4: 0xffffffffffffffff f5: 0xffffffffffffffff -+ f6: 0xffffffffffffffff f7: 0xffffffffffffffff -+ f8: 0xffffffffffffffff f9: 0xffffffffffffffff -+ f10: 0xffffffffffffffff f11: 0xffffffffffffffff -+ f12: 0xffffffffffffffff f13: 0xffffffffffffffff -+ f14: 0xffffffffffffffff f15: 0xffffffffffffffff -+ f16: 0xffffffffffffffff f17: 0xffffffffffffffff -+ f18: 0xffffffffffffffff f19: 0xffffffffffffffff -+ f20: 0xffffffffffffffff f21: 0xffffffffffffffff -+ f22: 0xffffffffffffffff f23: 0xffffffffffffffff -+ f24: 0xffffffffffffffff f25: 0xffffffffffffffff -+ f26: 0xffffffffffffffff f27: 0xffffffffffffffff -+ f28: 0xffffffffffffffff f29: 0xffffffffffffffff -+ f30: 0xffffffffffffffff f31: 0xffffffffffffffff -+ LINUX 4 MIPS_FP_MODE -+ LINUX 528 MIPS_MSA -+EOF -+ - exit 0 diff --git a/tools/elfutils/patches/011-backport-mips-support-strip.patch b/tools/elfutils/patches/011-backport-mips-support-strip.patch new file mode 100644 index 0000000000..7ea9bedc1a --- /dev/null +++ b/tools/elfutils/patches/011-backport-mips-support-strip.patch @@ -0,0 +1,230 @@ +In mips64 little-endian, r_info consists of four byte fields(contains +three reloc types) and a 32-bit symbol index. In order to adapt +GELF_R_SYM and GELF_R_TYPE, need convert raw data to get correct symbol +index and type. + + libelf/elf_getdata.c: Some eu-utils use read-mmap method to map file, +so we need to malloc and memcpy raw data to avoid segment fault. After +modification, the correct value are saved in the malloced memory not in +process address space. + libelf/elf_updata.c: Because we converted the relocation info in mips +order when we call elf_getdata.c, so we need to convert the modified data +in original order bits before writing the data to the file. + +Signed-off-by: Ying Huang +--- + libelf/elf_getdata.c | 132 ++++++++++++++++++++++++++++++++++++++++++- + libelf/elf_update.c | 53 +++++++++++++++++ + 2 files changed, 183 insertions(+), 2 deletions(-) + +--- a/libelf/elf_getdata.c ++++ b/libelf/elf_getdata.c +@@ -135,6 +135,119 @@ __libelf_data_type (GElf_Ehdr *ehdr, int + + /* Convert the data in the current section. */ + static void ++convert_data_for_mips64el (Elf_Scn *scn, int eclass, ++ int data, size_t size, Elf_Type type) ++{ ++ /* Do we need to convert the data and/or adjust for alignment? */ ++ if (data == MY_ELFDATA || type == ELF_T_BYTE) ++ { ++ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert ++ relocation info(raw data). Some eu-utils use read-mmap method to map file, so ++ we need to malloc and memcpy raw data to avoid segment fault. After modification, ++ the correct value are saved in the malloced memory not in process address space. */ ++ scn->data_base = malloc (size); ++ if (scn->data_base == NULL) ++ { ++ __libelf_seterrno (ELF_E_NOMEM); ++ return; ++ } ++ ++ /* The copy will be appropriately aligned for direct access. */ ++ memcpy (scn->data_base, scn->rawdata_base, size); ++ } ++ else ++ { ++ xfct_t fp; ++ ++ scn->data_base = malloc (size); ++ if (scn->data_base == NULL) ++ { ++ __libelf_seterrno (ELF_E_NOMEM); ++ return; ++ } ++ ++ /* Make sure the source is correctly aligned for the conversion ++ function to directly access the data elements. */ ++ char *rawdata_source; ++ /* In order to adapt macro GELF_R_SYM and GELF_R_TYPE on mips64, need to convert ++ relocation info(raw data). Some eu-utils use read-mmap method to map file, so ++ we need to malloc and memcpy raw data to avoid segment fault. After modification, ++ the correct value are saved in the malloced memory not in process address space. */ ++ rawdata_source = malloc (size); ++ if (rawdata_source == NULL) ++ { ++ __libelf_seterrno (ELF_E_NOMEM); ++ return; ++ } ++ ++ /* The copy will be appropriately aligned for direct access. */ ++ memcpy (rawdata_source, scn->rawdata_base, size); ++ ++ /* Get the conversion function. */ ++ fp = __elf_xfctstom[eclass - 1][type]; ++ ++ fp (scn->data_base, rawdata_source, size, 0); ++ ++ if (rawdata_source != scn->rawdata_base) ++ free (rawdata_source); ++ } ++ ++ scn->data_list.data.d.d_buf = scn->data_base; ++ scn->data_list.data.d.d_size = size; ++ scn->data_list.data.d.d_type = type; ++ scn->data_list.data.d.d_off = scn->rawdata.d.d_off; ++ scn->data_list.data.d.d_align = scn->rawdata.d.d_align; ++ scn->data_list.data.d.d_version = scn->rawdata.d.d_version; ++ ++ scn->data_list.data.s = scn; ++ ++ /* In mips64 little-endian, r_info consists of four byte fields(contains ++ three reloc types) and a 32-bit symbol index. In order to adapt ++ GELF_R_SYM and GELF_R_TYPE, need to convert r_info to get correct symbol ++ index and type. */ ++ /* references: ++ https://www.linux-mips.org/pub/linux/mips/doc/ABI/elf64-2.4.pdf ++ Page40 && Page41 */ ++ GElf_Shdr shdr_mem; ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ if (shdr->sh_type == SHT_REL) ++ { ++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); ++ int nentries = shdr->sh_size / sh_entsize; ++ for (int cnt = 0; cnt < nentries; ++cnt) ++ { ++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; ++ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; ++ Elf64_Xword info = value->r_info; ++ value->r_info = (((info & 0xffffffff) << 32) ++ | ((info >> 56) & 0xff) ++ | ((info >> 40) & 0xff00) ++ | ((info >> 24) & 0xff0000) ++ | ((info >> 8) & 0xff000000)); ++ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; ++ } ++ } ++ else if (shdr->sh_type == SHT_RELA) ++ { ++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); ++ int nentries = shdr->sh_size / sh_entsize; ++ for (int cnt = 0; cnt < nentries; cnt++) ++ { ++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) &scn->data_list.data.d; ++ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; ++ Elf64_Xword info = value->r_info; ++ value->r_info = (((info & 0xffffffff) << 32) ++ | ((info >> 56) & 0xff) ++ | ((info >> 40) & 0xff00) ++ | ((info >> 24) & 0xff0000) ++ | ((info >> 8) & 0xff000000)); ++ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; ++ } ++ } ++} ++ ++/* Convert the data in the current section. */ ++static void + convert_data (Elf_Scn *scn, int eclass, + int data, size_t size, Elf_Type type) + { +@@ -451,8 +564,23 @@ __libelf_set_data_list_rdlock (Elf_Scn * + return; + } + +- /* Convert according to the version and the type. */ +- convert_data (scn, elf->class, ++ GElf_Shdr shdr_mem; ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ GElf_Ehdr ehdr_mem; ++ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); ++ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && ++ scn->elf->class == ELFCLASS64 && ehdr != NULL && ++ ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) ++ convert_data_for_mips64el (scn, elf->class, ++ (elf->class == ELFCLASS32 ++ || (offsetof (struct Elf, state.elf32.ehdr) ++ == offsetof (struct Elf, state.elf64.ehdr)) ++ ? elf->state.elf32.ehdr->e_ident[EI_DATA] ++ : elf->state.elf64.ehdr->e_ident[EI_DATA]), ++ scn->rawdata.d.d_size, scn->rawdata.d.d_type); ++ else ++ /* Convert according to the version and the type. */ ++ convert_data (scn, elf->class, + (elf->class == ELFCLASS32 + || (offsetof (struct Elf, state.elf32.ehdr) + == offsetof (struct Elf, state.elf64.ehdr)) +--- a/libelf/elf_update.c ++++ b/libelf/elf_update.c +@@ -228,7 +228,60 @@ elf_update (Elf *elf, Elf_Cmd cmd) + size = -1; + } + else ++ { ++ /* Because we converted the relocation info in mips order when we call elf_getdata.c, ++ so we need to convert the modified data in original order bits before writing the ++ data to the file. */ ++ Elf_Scn *scn = NULL; ++ while ((scn = elf_nextscn (elf, scn)) != NULL) ++ { ++ GElf_Shdr shdr_mem; ++ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ++ GElf_Ehdr ehdr_mem; ++ GElf_Ehdr *ehdr = gelf_getehdr (scn->elf, &ehdr_mem); ++ if (shdr != NULL && (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && ++ scn->elf->class == ELFCLASS64 && ++ ehdr != NULL && ehdr->e_machine == EM_MIPS && ehdr->e_ident[EI_DATA] == ELFDATA2LSB) ++ { ++ Elf_Data *d = elf_getdata (scn, NULL); ++ if (shdr->sh_type == SHT_REL) ++ { ++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_REL, 1, EV_CURRENT); ++ int nentries = shdr->sh_size / sh_entsize; ++ for (int cnt = 0; cnt < nentries; ++cnt) ++ { ++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; ++ Elf64_Rel *value = &((Elf64_Rel *) data_scn->d.d_buf)[cnt]; ++ Elf64_Xword info = value->r_info; ++ value->r_info = (info >> 32 ++ | ((info << 56) & 0xff00000000000000) ++ | ((info << 40) & 0xff000000000000) ++ | ((info << 24) & 0xff0000000000) ++ | ((info << 8) & 0xff00000000)); ++ ((Elf64_Rel *) data_scn->d.d_buf)[cnt] = *value; ++ } ++ } ++ else if (shdr->sh_type == SHT_RELA) ++ { ++ size_t sh_entsize = gelf_fsize (scn->elf, ELF_T_RELA, 1, EV_CURRENT); ++ int nentries = shdr->sh_size / sh_entsize; ++ for (int cnt = 0; cnt < nentries; cnt++) ++ { ++ Elf_Data_Scn *data_scn = (Elf_Data_Scn *) d; ++ Elf64_Rela *value = &((Elf64_Rela *) data_scn->d.d_buf)[cnt]; ++ Elf64_Xword info = value->r_info; ++ value->r_info = (info >> 32 ++ | ((info << 56) & 0xff00000000000000) ++ | ((info << 40) & 0xff000000000000) ++ | ((info << 24) & 0xff0000000000) ++ | ((info << 8) & 0xff00000000)); ++ ((Elf64_Rela *) data_scn->d.d_buf)[cnt] = *value; ++ } ++ } ++ } ++ } + size = write_file (elf, size, change_bo, shnum); ++ } + } + + out: diff --git a/tools/elfutils/patches/012-backport-mips-support-readelf.patch b/tools/elfutils/patches/012-backport-mips-support-readelf.patch new file mode 100644 index 0000000000..cf2b7c827b --- /dev/null +++ b/tools/elfutils/patches/012-backport-mips-support-readelf.patch @@ -0,0 +1,1079 @@ +-h: support show Flags name +-S: support show mips related section type +-r: support show type of Relocation section +-w: can work and can show correct "strp" contents +-l: support show mips related program header entry type +-d: can show mips related Dynamic type name +-a: support show complete Object attribute section ".gnu.attributes" + +Also add test/run-readelf-reloc.sh file to test new type2/type3 of +src/readelf -r. + +Signed-off-by: Ying Huang +--- + backends/Makefile.am | 2 +- + backends/mips_attrs.c | 140 +++++++++ + backends/mips_init.c | 7 + + backends/mips_symbol.c | 571 +++++++++++++++++++++++++++++++++++++ + libelf/libelfP.h | 1 + + src/readelf.c | 188 +++++++++--- + tests/Makefile.am | 5 +- + tests/run-readelf-reloc.sh | 42 +++ + 8 files changed, 907 insertions(+), 49 deletions(-) + create mode 100644 backends/mips_attrs.c + create mode 100755 tests/run-readelf-reloc.sh + +--- a/backends/Makefile.am ++++ b/backends/Makefile.am +@@ -102,7 +102,7 @@ loongarch_SRCS = loongarch_init.c loonga + + arc_SRCS = arc_init.c arc_symbol.c + +-mips_SRCS = mips_init.c mips_symbol.c ++mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c + + libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ + $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ +--- /dev/null ++++ b/backends/mips_attrs.c +@@ -0,0 +1,140 @@ ++/* Object attribute tags for MIPS. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++ ++#define KNOWN_VALUES(...) do \ ++ { \ ++ static const char *table[] = { __VA_ARGS__ }; \ ++ if (value < sizeof table / sizeof table[0]) \ ++ *value_name = table[value]; \ ++ } while (0) ++ ++//copy gnu attr tags from binutils-2.34/elfcpp/mips.h ++/* Object attribute tags. */ ++enum ++{ ++ /* 0-3 are generic. */ ++ ++ /* Floating-point ABI used by this object file. */ ++ Tag_GNU_MIPS_ABI_FP = 4, ++ ++ /* MSA ABI used by this object file. */ ++ Tag_GNU_MIPS_ABI_MSA = 8, ++}; ++ ++/* Object attribute values. */ ++enum ++{ ++ /* Values defined for Tag_GNU_MIPS_ABI_MSA. */ ++ ++ /* Not tagged or not using any ABIs affected by the differences. */ ++ Val_GNU_MIPS_ABI_MSA_ANY = 0, ++ ++ /* Using 128-bit MSA. */ ++ Val_GNU_MIPS_ABI_MSA_128 = 1, ++}; ++ ++/* Object attribute values. */ ++enum ++{ ++ /* This is reserved for backward-compatibility with an earlier ++ implementation of the MIPS NaN2008 functionality. */ ++ Val_GNU_MIPS_ABI_FP_NAN2008 = 8, ++}; ++ ++/* copy binutils-2.34/binutils/readelf.c display_mips_gnu_attribute */ ++bool ++mips_check_object_attribute (Ebl *ebl __attribute__ ((unused)), ++ const char *vendor, int tag, uint64_t value, ++ const char **tag_name, const char **value_name) ++{ ++ if (!strcmp (vendor, "gnu")) ++ switch (tag) ++ { ++ case Tag_GNU_MIPS_ABI_FP: ++ *tag_name = "Tag_GNU_MIPS_ABI_FP"; ++ switch (value) ++ { ++ case Val_GNU_MIPS_ABI_FP_ANY: ++ *value_name = "Hard or soft float"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_DOUBLE: ++ *value_name = "Hard float (double precision)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_SINGLE: ++ *value_name = "Hard float (single precision)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_SOFT: ++ *value_name = "Soft float"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_OLD_64: ++ *value_name = "Hard float (MIPS32r2 64-bit FPU 12 callee-saved)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_XX: ++ *value_name = "Hard float (32-bit CPU, Any FPU)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_64: ++ *value_name = "Hard float (32-bit CPU, 64-bit FPU)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_64A: ++ *value_name = "Hard float compat (32-bit CPU, 64-bit FPU)"; ++ return true; ++ case Val_GNU_MIPS_ABI_FP_NAN2008: ++ *value_name = "NaN 2008 compatibility"; ++ return true; ++ default: ++ return true; ++ } ++ return true; ++ case Tag_GNU_MIPS_ABI_MSA: ++ *tag_name = "Tag_GNU_MIPS_ABI_MSA"; ++ switch (value) ++ { ++ case Val_GNU_MIPS_ABI_MSA_ANY: ++ *value_name = "Any MSA or not"; ++ return true; ++ case Val_GNU_MIPS_ABI_MSA_128: ++ *value_name = "128-bit MSA"; ++ return true; ++ default: ++ return true; ++ } ++ return true; ++ } ++ ++ return false; ++} +--- a/backends/mips_init.c ++++ b/backends/mips_init.c +@@ -48,5 +48,12 @@ mips_init (Elf *elf __attribute__ ((unus + /* We handle it. */ + mips_init_reloc (eh); + HOOK (eh, reloc_simple_type); ++ HOOK (eh, section_type_name); ++ HOOK (eh, machine_flag_check); ++ HOOK (eh, machine_flag_name); ++ HOOK (eh, segment_type_name); ++ HOOK (eh, dynamic_tag_check); ++ HOOK (eh, dynamic_tag_name); ++ HOOK (eh, check_object_attribute); + return eh; + } +--- a/backends/mips_symbol.c ++++ b/backends/mips_symbol.c +@@ -61,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int ty + return ELF_T_NUM; + } + } ++ ++/* copy binutils-2.34/binutils/readelf.c get_mips_section_type_name */ ++const char * ++mips_section_type_name (int type, ++ char *buf __attribute__ ((unused)), ++ size_t len __attribute__ ((unused))) ++{ ++ switch (type) ++ { ++ case SHT_MIPS_LIBLIST: ++ return "MIPS_LIBLIST"; ++ case SHT_MIPS_MSYM: ++ return "MIPS_MSYM"; ++ case SHT_MIPS_CONFLICT: ++ return "MIPS_CONFLICT"; ++ case SHT_MIPS_GPTAB: ++ return "MIPS_GPTAB"; ++ case SHT_MIPS_UCODE: ++ return "MIPS_UCODE"; ++ case SHT_MIPS_DEBUG: ++ return "MIPS_DEBUG"; ++ case SHT_MIPS_REGINFO: ++ return "MIPS_REGINFO"; ++ case SHT_MIPS_PACKAGE: ++ return "MIPS_PACKAGE"; ++ case SHT_MIPS_PACKSYM: ++ return "MIPS_PACKSYM"; ++ case SHT_MIPS_RELD: ++ return "MIPS_RELD"; ++ case SHT_MIPS_IFACE: ++ return "MIPS_IFACE"; ++ case SHT_MIPS_CONTENT: ++ return "MIPS_CONTENT"; ++ case SHT_MIPS_OPTIONS: ++ return "MIPS_OPTIONS"; ++ case SHT_MIPS_SHDR: ++ return "MIPS_SHDR"; ++ case SHT_MIPS_FDESC: ++ return "MIPS_FDESC"; ++ case SHT_MIPS_EXTSYM: ++ return "MIPS_EXTSYM"; ++ case SHT_MIPS_DENSE: ++ return "MIPS_DENSE"; ++ case SHT_MIPS_PDESC: ++ return "MIPS_PDESC"; ++ case SHT_MIPS_LOCSYM: ++ return "MIPS_LOCSYM"; ++ case SHT_MIPS_AUXSYM: ++ return "MIPS_AUXSYM"; ++ case SHT_MIPS_OPTSYM: ++ return "MIPS_OPTSYM"; ++ case SHT_MIPS_LOCSTR: ++ return "MIPS_LOCSTR"; ++ case SHT_MIPS_LINE: ++ return "MIPS_LINE"; ++ case SHT_MIPS_RFDESC: ++ return "MIPS_RFDESC"; ++ case SHT_MIPS_DELTASYM: ++ return "MIPS_DELTASYM"; ++ case SHT_MIPS_DELTAINST: ++ return "MIPS_DELTAINST"; ++ case SHT_MIPS_DELTACLASS: ++ return "MIPS_DELTACLASS"; ++ case SHT_MIPS_DWARF: ++ return "MIPS_DWARF"; ++ case SHT_MIPS_DELTADECL: ++ return "MIPS_DELTADECL"; ++ case SHT_MIPS_SYMBOL_LIB: ++ return "MIPS_SYMBOL_LIB"; ++ case SHT_MIPS_EVENTS: ++ return "MIPS_EVENTS"; ++ case SHT_MIPS_TRANSLATE: ++ return "MIPS_TRANSLATE"; ++ case SHT_MIPS_PIXIE: ++ return "MIPS_PIXIE"; ++ case SHT_MIPS_XLATE: ++ return "MIPS_XLATE"; ++ case SHT_MIPS_XLATE_DEBUG: ++ return "MIPS_XLATE_DEBUG"; ++ case SHT_MIPS_WHIRL: ++ return "MIPS_WHIRL"; ++ case SHT_MIPS_EH_REGION: ++ return "MIPS_EH_REGION"; ++ case SHT_MIPS_XLATE_OLD: ++ return "MIPS_XLATE_OLD"; ++ case SHT_MIPS_PDR_EXCEPTION: ++ return "MIPS_PDR_EXCEPTION"; ++ case SHT_MIPS_ABIFLAGS: ++ return "MIPS_ABIFLAGS"; ++ case SHT_MIPS_XHASH: ++ return "MIPS_XHASH"; ++ default: ++ break; ++ } ++ return NULL; ++} ++ ++/* Check whether machine flags are valid. */ ++bool ++mips_machine_flag_check (GElf_Word flags) ++{ ++ if ((flags &~ (EF_MIPS_NOREORDER | ++ EF_MIPS_PIC | ++ EF_MIPS_CPIC | ++ EF_MIPS_UCODE | ++ EF_MIPS_ABI2 | ++ EF_MIPS_OPTIONS_FIRST | ++ EF_MIPS_32BITMODE | ++ EF_MIPS_NAN2008 | ++ EF_MIPS_FP64 | ++ EF_MIPS_ARCH_ASE_MDMX | ++ EF_MIPS_ARCH_ASE_M16 | ++ EF_MIPS_ARCH_ASE_MICROMIPS)) == 0) ++ return false; ++ ++ switch(flags & EF_MIPS_MACH) ++ { ++ case EF_MIPS_MACH_3900: ++ case EF_MIPS_MACH_4010: ++ case EF_MIPS_MACH_4100: ++ case EF_MIPS_MACH_4111: ++ case EF_MIPS_MACH_4120: ++ case EF_MIPS_MACH_4650: ++ case EF_MIPS_MACH_5400: ++ case EF_MIPS_MACH_5500: ++ case EF_MIPS_MACH_5900: ++ case EF_MIPS_MACH_SB1: ++ case EF_MIPS_MACH_9000: ++ case EF_MIPS_MACH_LS2E: ++ case EF_MIPS_MACH_LS2F: ++ case EF_MIPS_MACH_GS464: ++ case EF_MIPS_MACH_GS464E: ++ case EF_MIPS_MACH_GS264E: ++ case EF_MIPS_MACH_OCTEON: ++ case EF_MIPS_MACH_OCTEON2: ++ case EF_MIPS_MACH_OCTEON3: ++ case EF_MIPS_MACH_XLR: ++ case EF_MIPS_MACH_IAMR2: ++ case 0: ++ break; ++ default: ++ return false; ++ } ++ ++ switch ((flags & EF_MIPS_ABI)) ++ { ++ case EF_MIPS_ABI_O32: ++ case EF_MIPS_ABI_O64: ++ case EF_MIPS_ABI_EABI32: ++ case EF_MIPS_ABI_EABI64: ++ case 0: ++ break; ++ default: ++ return false; ++ } ++ ++ switch ((flags & EF_MIPS_ARCH)) ++ { ++ case EF_MIPS_ARCH_1: ++ case EF_MIPS_ARCH_2: ++ case EF_MIPS_ARCH_3: ++ case EF_MIPS_ARCH_4: ++ case EF_MIPS_ARCH_5: ++ case EF_MIPS_ARCH_32: ++ case EF_MIPS_ARCH_32R2: ++ case EF_MIPS_ARCH_32R6: ++ case EF_MIPS_ARCH_64: ++ case EF_MIPS_ARCH_64R2: ++ case EF_MIPS_ARCH_64R6: ++ return true; ++ default: ++ return false; ++ } ++ return false; ++} ++ ++/* copy binutils-2.34/binutils/readelf.c get_machine_flags */ ++const char * ++mips_machine_flag_name (Elf64_Word orig __attribute__ ((unused)), Elf64_Word *flagref) ++{ ++ if (*flagref & EF_MIPS_NOREORDER) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_NOREORDER); ++ return "noreorder"; ++ } ++ ++ if (*flagref & EF_MIPS_PIC) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_PIC); ++ return "pic"; ++ } ++ ++ if (*flagref & EF_MIPS_CPIC) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_CPIC); ++ return "cpic"; ++ } ++ ++ if (*flagref & EF_MIPS_UCODE) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_UCODE); ++ return "ugen_reserved"; ++ } ++ ++ if (*flagref & EF_MIPS_ABI2) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI2); ++ return "abi2"; ++ } ++ ++ if (*flagref & EF_MIPS_OPTIONS_FIRST) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_OPTIONS_FIRST); ++ return "odk first"; ++ } ++ ++ if (*flagref & EF_MIPS_32BITMODE) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_32BITMODE); ++ return "32bitmode"; ++ } ++ ++ if (*flagref & EF_MIPS_NAN2008) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_NAN2008); ++ return "nan2008"; ++ } ++ ++ if (*flagref & EF_MIPS_FP64) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_FP64); ++ return "fp64"; ++ } ++ ++ switch (*flagref & EF_MIPS_MACH) ++ { ++ case EF_MIPS_MACH_3900: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_3900); ++ return "3900"; ++ case EF_MIPS_MACH_4010: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4010); ++ return "4010"; ++ case EF_MIPS_MACH_4100: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4100); ++ return "4100"; ++ case EF_MIPS_MACH_4111: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4111); ++ return "4111"; ++ case EF_MIPS_MACH_4120: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4120); ++ return "4120"; ++ case EF_MIPS_MACH_4650: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_4650); ++ return "4650"; ++ case EF_MIPS_MACH_5400: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5400); ++ return "5400"; ++ case EF_MIPS_MACH_5500: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5500); ++ return "5500"; ++ case EF_MIPS_MACH_5900: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_5900); ++ return "5900"; ++ case EF_MIPS_MACH_SB1: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_SB1); ++ return "sb1"; ++ case EF_MIPS_MACH_9000: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_9000); ++ return "9000"; ++ case EF_MIPS_MACH_LS2E: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2E); ++ return "loongson-2e"; ++ case EF_MIPS_MACH_LS2F: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_LS2F); ++ return "loongson-2f"; ++ case EF_MIPS_MACH_GS464: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464); ++ return "gs464"; ++ case EF_MIPS_MACH_GS464E: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS464E); ++ return "gs464e"; ++ case EF_MIPS_MACH_GS264E: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_GS264E); ++ return "gs264e"; ++ case EF_MIPS_MACH_OCTEON: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON); ++ return "octeon"; ++ case EF_MIPS_MACH_OCTEON2: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON2); ++ return "octeon2"; ++ case EF_MIPS_MACH_OCTEON3: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_OCTEON3); ++ return "octeon3"; ++ case EF_MIPS_MACH_XLR: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_XLR); ++ return "xlr"; ++ case EF_MIPS_MACH_IAMR2: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH_IAMR2); ++ return "interaptiv-mr2"; ++ case 0: ++ /* We simply ignore the field in this case to avoid confusion: ++ MIPS ELF does not specify EF_MIPS_MACH, it is a GNU ++ extension. */ ++ break; ++ default: ++ *flagref &= ~((Elf64_Word) EF_MIPS_MACH); ++ return "unknown CPU"; ++ } ++ switch (*flagref & EF_MIPS_ABI) ++ { ++ case EF_MIPS_ABI_O32: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O32); ++ return "o32"; ++ case EF_MIPS_ABI_O64: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_O64); ++ return "o64"; ++ case EF_MIPS_ABI_EABI32: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI32); ++ return "eabi32"; ++ case EF_MIPS_ABI_EABI64: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI_EABI64); ++ return "eabi64"; ++ case 0: ++ /* We simply ignore the field in this case to avoid confusion: ++ MIPS ELF does not specify EF_MIPS_ABI, it is a GNU extension. ++ This means it is likely to be an o32 file, but not for ++ sure. */ ++ break; ++ default: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ABI); ++ return "unknown ABI"; ++ } ++ ++ if (*flagref & EF_MIPS_ARCH_ASE_MDMX) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MDMX); ++ return "mdmx"; ++ } ++ ++ if (*flagref & EF_MIPS_ARCH_ASE_M16) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_M16); ++ return "mips16"; ++ } ++ ++ if (*flagref & EF_MIPS_ARCH_ASE_MICROMIPS) ++ { ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_ASE_MICROMIPS); ++ return "micromips"; ++ } ++ ++ switch (*flagref & EF_MIPS_ARCH) ++ { ++ case EF_MIPS_ARCH_1: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_1); ++ return "mips1"; ++ case EF_MIPS_ARCH_2: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_2); ++ return "mips2"; ++ case EF_MIPS_ARCH_3: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_3); ++ return "mips3"; ++ case EF_MIPS_ARCH_4: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_4); ++ return "mips4"; ++ case EF_MIPS_ARCH_5: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_5); ++ return "mips5"; ++ case EF_MIPS_ARCH_32: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32); ++ return "mips32"; ++ case EF_MIPS_ARCH_32R2: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R2); ++ return "mips32r2"; ++ case EF_MIPS_ARCH_32R6: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_32R6); ++ return "mips32r6"; ++ case EF_MIPS_ARCH_64: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64); ++ return "mips64"; ++ case EF_MIPS_ARCH_64R2: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R2); ++ return "mips64r2"; ++ case EF_MIPS_ARCH_64R6: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH_64R6); ++ return "mips64r6"; ++ default: ++ *flagref &= ~((Elf64_Word) EF_MIPS_ARCH); ++ return "unknown ISA"; ++ } ++ return NULL; ++} ++ ++/* copy binutils-2.34/binutils/readelf.c get_mips_segment_type */ ++const char * ++mips_segment_type_name (int segment, char *buf __attribute__ ((unused)), ++ size_t len __attribute__ ((unused))) ++{ ++ switch (segment) ++ { ++ case PT_MIPS_REGINFO: ++ return "REGINFO"; ++ case PT_MIPS_RTPROC: ++ return "RTPROC"; ++ case PT_MIPS_OPTIONS: ++ return "OPTIONS"; ++ case PT_MIPS_ABIFLAGS: ++ return "ABIFLAGS"; ++ default: ++ return NULL; ++ } ++} ++ ++bool ++mips_dynamic_tag_check (int64_t tag) ++{ ++ return ((tag &~ (DT_MIPS_RLD_VERSION ++ | DT_MIPS_TIME_STAMP ++ | DT_MIPS_ICHECKSUM ++ | DT_MIPS_IVERSION ++ | DT_MIPS_FLAGS ++ | DT_MIPS_BASE_ADDRESS ++ | DT_MIPS_MSYM ++ | DT_MIPS_CONFLICT ++ | DT_MIPS_LIBLIST ++ | DT_MIPS_LOCAL_GOTNO ++ | DT_MIPS_CONFLICTNO ++ | DT_MIPS_LIBLISTNO ++ | DT_MIPS_SYMTABNO ++ | DT_MIPS_UNREFEXTNO ++ | DT_MIPS_GOTSYM ++ | DT_MIPS_HIPAGENO ++ | DT_MIPS_RLD_MAP ++ | DT_MIPS_DELTA_CLASS ++ | DT_MIPS_DELTA_CLASS_NO ++ | DT_MIPS_DELTA_INSTANCE ++ | DT_MIPS_DELTA_INSTANCE_NO ++ | DT_MIPS_DELTA_RELOC ++ | DT_MIPS_DELTA_RELOC_NO ++ | DT_MIPS_DELTA_SYM ++ | DT_MIPS_DELTA_SYM_NO ++ | DT_MIPS_DELTA_CLASSSYM ++ | DT_MIPS_DELTA_CLASSSYM_NO ++ | DT_MIPS_CXX_FLAGS ++ | DT_MIPS_PIXIE_INIT ++ | DT_MIPS_SYMBOL_LIB ++ | DT_MIPS_LOCALPAGE_GOTIDX ++ | DT_MIPS_LOCAL_GOTIDX ++ | DT_MIPS_HIDDEN_GOTIDX ++ | DT_MIPS_PROTECTED_GOTIDX ++ | DT_MIPS_OPTIONS ++ | DT_MIPS_INTERFACE ++ | DT_MIPS_DYNSTR_ALIGN ++ | DT_MIPS_INTERFACE_SIZE ++ | DT_MIPS_RLD_TEXT_RESOLVE_ADDR ++ | DT_MIPS_PERF_SUFFIX ++ | DT_MIPS_COMPACT_SIZE ++ | DT_MIPS_GP_VALUE ++ | DT_MIPS_AUX_DYNAMIC ++ | DT_MIPS_PLTGOT ++ | DT_MIPS_RWPLT ++ | DT_MIPS_RLD_MAP_REL ++ | DT_MIPS_XHASH)) == 0); ++} ++ ++/* copy binutils-2.34/binutils/readelf.c get_mips_dynamic_type*/ ++const char * ++mips_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)), ++ size_t len __attribute__ ((unused))) ++{ ++ switch (tag) ++ { ++ case DT_MIPS_RLD_VERSION: ++ return "MIPS_RLD_VERSION"; ++ case DT_MIPS_TIME_STAMP: ++ return "MIPS_TIME_STAMP"; ++ case DT_MIPS_ICHECKSUM: ++ return "MIPS_ICHECKSUM"; ++ case DT_MIPS_IVERSION: ++ return "MIPS_IVERSION"; ++ case DT_MIPS_FLAGS: ++ return "MIPS_FLAGS"; ++ case DT_MIPS_BASE_ADDRESS: ++ return "MIPS_BASE_ADDRESS"; ++ case DT_MIPS_MSYM: ++ return "MIPS_MSYM"; ++ case DT_MIPS_CONFLICT: ++ return "MIPS_CONFLICT"; ++ case DT_MIPS_LIBLIST: ++ return "MIPS_LIBLIST"; ++ case DT_MIPS_LOCAL_GOTNO: ++ return "MIPS_LOCAL_GOTNO"; ++ case DT_MIPS_CONFLICTNO: ++ return "MIPS_CONFLICTNO"; ++ case DT_MIPS_LIBLISTNO: ++ return "MIPS_LIBLISTNO"; ++ case DT_MIPS_SYMTABNO: ++ return "MIPS_SYMTABNO"; ++ case DT_MIPS_UNREFEXTNO: ++ return "MIPS_UNREFEXTNO"; ++ case DT_MIPS_GOTSYM: ++ return "MIPS_GOTSYM"; ++ case DT_MIPS_HIPAGENO: ++ return "MIPS_HIPAGENO"; ++ case DT_MIPS_RLD_MAP: ++ return "MIPS_RLD_MAP"; ++ case DT_MIPS_RLD_MAP_REL: ++ return "MIPS_RLD_MAP_REL"; ++ case DT_MIPS_DELTA_CLASS: ++ return "MIPS_DELTA_CLASS"; ++ case DT_MIPS_DELTA_CLASS_NO: ++ return "MIPS_DELTA_CLASS_NO"; ++ case DT_MIPS_DELTA_INSTANCE: ++ return "MIPS_DELTA_INSTANCE"; ++ case DT_MIPS_DELTA_INSTANCE_NO: ++ return "MIPS_DELTA_INSTANCE_NO"; ++ case DT_MIPS_DELTA_RELOC: ++ return "MIPS_DELTA_RELOC"; ++ case DT_MIPS_DELTA_RELOC_NO: ++ return "MIPS_DELTA_RELOC_NO"; ++ case DT_MIPS_DELTA_SYM: ++ return "MIPS_DELTA_SYM"; ++ case DT_MIPS_DELTA_SYM_NO: ++ return "MIPS_DELTA_SYM_NO"; ++ case DT_MIPS_DELTA_CLASSSYM: ++ return "MIPS_DELTA_CLASSSYM"; ++ case DT_MIPS_DELTA_CLASSSYM_NO: ++ return "MIPS_DELTA_CLASSSYM_NO"; ++ case DT_MIPS_CXX_FLAGS: ++ return "MIPS_CXX_FLAGS"; ++ case DT_MIPS_PIXIE_INIT: ++ return "MIPS_PIXIE_INIT"; ++ case DT_MIPS_SYMBOL_LIB: ++ return "MIPS_SYMBOL_LIB"; ++ case DT_MIPS_LOCALPAGE_GOTIDX: ++ return "MIPS_LOCALPAGE_GOTIDX"; ++ case DT_MIPS_LOCAL_GOTIDX: ++ return "MIPS_LOCAL_GOTIDX"; ++ case DT_MIPS_HIDDEN_GOTIDX: ++ return "MIPS_HIDDEN_GOTIDX"; ++ case DT_MIPS_PROTECTED_GOTIDX: ++ return "MIPS_PROTECTED_GOTIDX"; ++ case DT_MIPS_OPTIONS: ++ return "MIPS_OPTIONS"; ++ case DT_MIPS_INTERFACE: ++ return "MIPS_INTERFACE"; ++ case DT_MIPS_DYNSTR_ALIGN: ++ return "MIPS_DYNSTR_ALIGN"; ++ case DT_MIPS_INTERFACE_SIZE: ++ return "MIPS_INTERFACE_SIZE"; ++ case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: ++ return "MIPS_RLD_TEXT_RESOLVE_ADDR"; ++ case DT_MIPS_PERF_SUFFIX: ++ return "MIPS_PERF_SUFFIX"; ++ case DT_MIPS_COMPACT_SIZE: ++ return "MIPS_COMPACT_SIZE"; ++ case DT_MIPS_GP_VALUE: ++ return "MIPS_GP_VALUE"; ++ case DT_MIPS_AUX_DYNAMIC: ++ return "MIPS_AUX_DYNAMIC"; ++ case DT_MIPS_PLTGOT: ++ return "MIPS_PLTGOT"; ++ case DT_MIPS_RWPLT: ++ return "MIPS_RWPLT"; ++ case DT_MIPS_XHASH: ++ return "MIPS_XHASH"; ++ default: ++ return NULL; ++ } ++ return NULL; ++} +--- a/libelf/libelfP.h ++++ b/libelf/libelfP.h +@@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_ + #define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) + #define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) + #define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) ++#define is_debug_section_type(type) (type == SHT_PROGBITS || type == SHT_MIPS_DWARF) + #endif /* libelfP.h */ +--- a/src/readelf.c ++++ b/src/readelf.c +@@ -2219,17 +2219,41 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * + (long int) GELF_R_SYM (rel->r_info)); + } + else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) +- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", +- class == ELFCLASS32 ? 10 : 18, rel->r_offset, +- likely (ebl_reloc_type_check (ebl, +- GELF_R_TYPE (rel->r_info))) +- /* Avoid the leading R_ which isn't carrying any +- information. */ +- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), +- buf, sizeof (buf)) + 2 +- : _(""), +- class == ELFCLASS32 ? 10 : 18, sym->st_value, +- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); ++ { ++ unsigned long inf = rel->r_info; ++ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", ++ class == ELFCLASS32 ? 10 : 18, rel->r_offset, ++ likely (ebl_reloc_type_check (ebl, ++ GELF_R_TYPE (rel->r_info))) ++ /* Avoid the leading R_ which isn't carrying any ++ information. */ ++ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), ++ buf, sizeof (buf)) + 2 ++ : _(""), ++ class == ELFCLASS32 ? 10 : 18, sym->st_value, ++ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); ++ ++ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ ++ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) ++ { ++ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); ++ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); ++ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; ++ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; ++ printf(" Type2: "); ++ if (rtype2 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); ++ else ++ printf ("%s", rtype2); ++ ++ printf ("\n Type3: "); ++ if (rtype3 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); ++ else ++ printf ("%s", rtype3); ++ printf("\n"); ++ } ++ } + else + { + /* This is a relocation against a STT_SECTION symbol. */ +@@ -2253,16 +2277,40 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * + (long int) (sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx)); + else +- printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", +- class == ELFCLASS32 ? 10 : 18, rel->r_offset, +- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) +- /* Avoid the leading R_ which isn't carrying any +- information. */ +- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), +- buf, sizeof (buf)) + 2 +- : _(""), +- class == ELFCLASS32 ? 10 : 18, sym->st_value, +- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); ++ { ++ unsigned long inf = rel->r_info; ++ printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", ++ class == ELFCLASS32 ? 10 : 18, rel->r_offset, ++ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) ++ /* Avoid the leading R_ which isn't carrying any ++ information. */ ++ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), ++ buf, sizeof (buf)) + 2 ++ : _(""), ++ class == ELFCLASS32 ? 10 : 18, sym->st_value, ++ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); ++ ++ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ ++ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) ++ { ++ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); ++ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); ++ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; ++ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; ++ printf(" Type2: "); ++ if (rtype2 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); ++ else ++ printf ("%s", rtype2); ++ ++ printf ("\n Type3: "); ++ if (rtype3 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); ++ else ++ printf ("%s", rtype3); ++ printf("\n"); ++ } ++ } + } + } + } +@@ -2410,19 +2458,43 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr + (long int) GELF_R_SYM (rel->r_info)); + } + else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) +- printf ("\ ++ { ++ unsigned long inf = rel->r_info; ++ printf ("\ + %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", +- class == ELFCLASS32 ? 10 : 18, rel->r_offset, +- likely (ebl_reloc_type_check (ebl, +- GELF_R_TYPE (rel->r_info))) +- /* Avoid the leading R_ which isn't carrying any +- information. */ +- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), +- buf, sizeof (buf)) + 2 +- : _(""), +- class == ELFCLASS32 ? 10 : 18, sym->st_value, +- rel->r_addend, +- elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); ++ class == ELFCLASS32 ? 10 : 18, rel->r_offset, ++ likely (ebl_reloc_type_check (ebl, ++ GELF_R_TYPE (rel->r_info))) ++ /* Avoid the leading R_ which isn't carrying any ++ information. */ ++ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), ++ buf, sizeof (buf)) + 2 ++ : _(""), ++ class == ELFCLASS32 ? 10 : 18, sym->st_value, ++ rel->r_addend, ++ elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name)); ++ ++ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ ++ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) ++ { ++ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); ++ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); ++ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; ++ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; ++ printf(" Type2: "); ++ if (rtype2 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type2 & 0xffffffff); ++ else ++ printf ("%s", rtype2); ++ ++ printf ("\n Type3: "); ++ if (rtype3 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); ++ else ++ printf ("%s", rtype3); ++ printf("\n"); ++ } ++ } + else + { + /* This is a relocation against a STT_SECTION symbol. */ +@@ -2446,18 +2518,42 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr + (long int) (sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx)); + else +- printf ("\ ++ { ++ unsigned long inf = rel->r_info; ++ printf ("\ + %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", +- class == ELFCLASS32 ? 10 : 18, rel->r_offset, +- ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) +- /* Avoid the leading R_ which isn't carrying any +- information. */ +- ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), +- buf, sizeof (buf)) + 2 +- : _(""), +- class == ELFCLASS32 ? 10 : 18, sym->st_value, +- rel->r_addend, +- elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); ++ class == ELFCLASS32 ? 10 : 18, rel->r_offset, ++ ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) ++ /* Avoid the leading R_ which isn't carrying any ++ information. */ ++ ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), ++ buf, sizeof (buf)) + 2 ++ : _(""), ++ class == ELFCLASS32 ? 10 : 18, sym->st_value, ++ rel->r_addend, ++ elf_strptr (ebl->elf, shstrndx, secshdr->sh_name)); ++ ++ /* copy binutils-2.34/binutils/readelf.c dump_relocations+1753 */ ++ if(ebl->elf->class == ELFCLASS64 && ebl->elf->state.elf64.ehdr->e_machine == EM_MIPS) ++ { ++ unsigned int type2 = ELF64_MIPS_R_TYPE2 (inf); ++ unsigned int type3 = ELF64_MIPS_R_TYPE3 (inf); ++ const char * rtype2 = ebl_reloc_type_name (ebl, type2, buf, sizeof (buf)) + 2; ++ const char * rtype3 = ebl_reloc_type_name (ebl, type3, buf, sizeof (buf)) + 2; ++ printf(" Type2: "); ++ if (rtype2 == NULL) ++ printf (_("unrecognized: %-7lx"), (unsigned long) type2 & 0xffffffff); ++ else ++ printf ("%s", rtype2); ++ ++ printf ("\n Type3: "); ++ if (rtype3 == NULL) ++ printf (_("unrecognized: %lx"), (unsigned long) type3 & 0xffffffff); ++ else ++ printf ("%s", rtype3); ++ printf("\n"); ++ } ++ } + } + } + } +@@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + +- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS) ++ if (shdr != NULL && is_debug_section_type(shdr->sh_type)) + { + const char *name = elf_strptr (ebl->elf, shstrndx, + shdr->sh_name); +@@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + +- if (shdr != NULL && shdr->sh_type == SHT_PROGBITS) ++ if (shdr != NULL && is_debug_section_type(shdr->sh_type)) + { + static const struct + { +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s + run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ + run-readelf-dw-form-indirect.sh run-strip-largealign.sh \ + run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \ +- run-declfiles.sh ++ run-declfiles.sh run-readelf-reloc.sh + + if !BIARCH + export ELFUTILS_DISABLE_BIARCH = 1 +@@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymt + testfile-dwp-5-cu-index-overflow.dwp.bz2 \ + testfile-dwp-4-cu-index-overflow.bz2 \ + testfile-dwp-4-cu-index-overflow.dwp.bz2 \ +- testfile-dwp-cu-index-overflow.source ++ testfile-dwp-cu-index-overflow.source \ ++ run-readelf-reloc.sh + + + if USE_VALGRIND +--- /dev/null ++++ b/tests/run-readelf-reloc.sh +@@ -0,0 +1,42 @@ ++#! /bin/bash ++# Copyright (C) 2024 CIP United Inc. ++# This file is part of elfutils. ++# ++# This file is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# elfutils is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++. $srcdir/test-subr.sh ++ ++tempfiles test-readelf-h.txt test-readelf-reloc.txt ++testrun ${abs_top_builddir}/src/readelf -h ${abs_top_builddir}/src/strip.o > test-readelf-h.txt ++machine=`cat test-readelf-h.txt | grep Machine` ++class=`cat test-readelf-h.txt | grep Class` ++endian=`cat test-readelf-h.txt | grep Data` ++if [[ "$machine" == *MIPS* && "$class" == *ELF64 && "$endian" == *little* ]]; then ++testrun ${abs_top_builddir}/src/readelf -r ${abs_top_builddir}/src/strip.o | head -n 12 | tail -n 10 > test-readelf-reloc.txt ++ ++testrun_compare cat test-readelf-reloc.txt << EOF ++ Offset Type Value Addend Name ++ 0x0000000000000008 MIPS_GPREL16 000000000000000000 +0 .text ++ Type2: MIPS_SUB ++ Type3: MIPS_HI16 ++ 0x0000000000000010 MIPS_GPREL16 000000000000000000 +0 .text ++ Type2: MIPS_SUB ++ Type3: MIPS_LO16 ++ 0x0000000000000014 MIPS_CALL16 000000000000000000 +0 gelf_getehdr ++ Type2: MIPS_NONE ++ Type3: MIPS_NONE ++EOF ++fi ++ ++exit 0 diff --git a/tools/elfutils/patches/013-backport-mips-support-elflint.patch b/tools/elfutils/patches/013-backport-mips-support-elflint.patch new file mode 100644 index 0000000000..906a3bf0f2 --- /dev/null +++ b/tools/elfutils/patches/013-backport-mips-support-elflint.patch @@ -0,0 +1,156 @@ +The errors were: +$ src/elflint --gnu src/nm +section [ 2] '.MIPS.options' contains unknown flag(s) 0x8000000 +section [ 7] '.dynsym': symbol 165 (_DYNAMIC_LINKING): non-local section symbol +section [24] '.got' contains invalid processor-specific flag(s) 0x10000000 +section [25] '.sdata' contains invalid processor-specific flag(s) 0x10000000 +section [29] '.debug_aranges' has wrong type: expected PROGBITS, is MIPS_DWARF +section [30] '.debug_info' has wrong type: expected PROGBITS, is MIPS_DWARF +section [31] '.debug_abbrev' has wrong type: expected PROGBITS, is MIPS_DWARF +section [32] '.debug_line' has wrong type: expected PROGBITS, is MIPS_DWARF +section [33] '.debug_frame' has wrong type: expected PROGBITS, is MIPS_DWARF +section [34] '.debug_str' has wrong type: expected PROGBITS, is MIPS_DWARF +section [35] '.debug_loc' has wrong type: expected PROGBITS, is MIPS_DWARF +section [36] '.debug_ranges' has wrong type: expected PROGBITS, is MIPS_DWARF +section [38] '.symtab': symbol 785 (_gp): st_value out of bounds +section [38] '.symtab': symbol 910 (_fbss): st_value out of bounds +section [38] '.symtab': symbol 1051 (_DYNAMIC_LINKING): non-local section symbol + +After fixing: +$ src/elflint --gnu src/nm +No errors + +Signed-off-by: Ying Huang +--- + backends/mips_init.c | 3 +++ + backends/mips_symbol.c | 37 +++++++++++++++++++++++++++++++++++++ + src/elflint.c | 26 +++++++++++++++++++++----- + 3 files changed, 61 insertions(+), 5 deletions(-) + +--- a/backends/mips_init.c ++++ b/backends/mips_init.c +@@ -51,9 +51,12 @@ mips_init (Elf *elf __attribute__ ((unus + HOOK (eh, section_type_name); + HOOK (eh, machine_flag_check); + HOOK (eh, machine_flag_name); ++ HOOK (eh, machine_section_flag_check); + HOOK (eh, segment_type_name); + HOOK (eh, dynamic_tag_check); + HOOK (eh, dynamic_tag_name); + HOOK (eh, check_object_attribute); ++ HOOK (eh, check_special_symbol); ++ HOOK (eh, check_reloc_target_type); + return eh; + } +--- a/backends/mips_symbol.c ++++ b/backends/mips_symbol.c +@@ -158,6 +158,43 @@ mips_section_type_name (int type, + return NULL; + } + ++bool ++mips_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type) ++{ ++ return (sh_type == SHT_MIPS_DWARF); ++} ++ ++/* Check whether given symbol's st_value and st_size are OK despite failing ++ normal checks. */ ++bool ++mips_check_special_symbol (Elf *elf, ++ const GElf_Sym *sym __attribute__ ((unused)), ++ const char *name __attribute__ ((unused)), ++ const GElf_Shdr *destshdr) ++{ ++ size_t shstrndx; ++ if (elf_getshdrstrndx (elf, &shstrndx) != 0) ++ return false; ++ const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name); ++ if (sname == NULL) ++ return false; ++ return (strcmp (sname, ".got") == 0 || strcmp (sname, ".bss") == 0); ++} ++ ++/* Check whether SHF_MASKPROC flags are valid. */ ++bool ++mips_machine_section_flag_check (GElf_Xword sh_flags) ++{ ++ return ((sh_flags &~ (SHF_MIPS_GPREL | ++ SHF_MIPS_MERGE | ++ SHF_MIPS_ADDR | ++ SHF_MIPS_STRINGS | ++ SHF_MIPS_NOSTRIP | ++ SHF_MIPS_LOCAL | ++ SHF_MIPS_NAMES | ++ SHF_MIPS_NODUPE)) == 0); ++} ++ + /* Check whether machine flags are valid. */ + bool + mips_machine_flag_check (GElf_Word flags) +--- a/src/elflint.c ++++ b/src/elflint.c +@@ -936,7 +936,9 @@ section [%2d] '%s': symbol %zu (%s): non + } + + if (GELF_ST_TYPE (sym->st_info) == STT_SECTION +- && GELF_ST_BIND (sym->st_info) != STB_LOCAL) ++ && GELF_ST_BIND (sym->st_info) != STB_LOCAL ++ && ehdr->e_machine != EM_MIPS ++ && strcmp (name, "_DYNAMIC_LINKING") != 0) + ERROR (_("\ + section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"), + idx, section_name (ebl, idx), cnt, name); +@@ -3828,6 +3830,10 @@ cannot get section header for section [% + && ebl_bss_plt_p (ebl)) + good_type = SHT_NOBITS; + ++ if (ehdr->e_machine == EM_MIPS ++ && (strstr(special_sections[s].name, ".debug") != NULL)) ++ good_type = SHT_MIPS_DWARF; ++ + /* In a debuginfo file, any normal section can be SHT_NOBITS. + This is only invalid for DWARF sections and .shstrtab. */ + if (shdr->sh_type != good_type +@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o + ERROR (_("section [%2zu] '%s'" + " contains invalid processor-specific flag(s)" + " %#" PRIx64 "\n"), +- cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); ++ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC); + sh_flags &= ~(GElf_Xword) SHF_MASKPROC; + } + if (sh_flags & SHF_MASKOS) +- if (gnuld) +- sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; ++ { ++ if (gnuld) ++ sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN; ++ if (!ebl_machine_section_flag_check (ebl, ++ sh_flags & SHF_MASKOS)) ++ ERROR (_("section [%2zu] '%s'" ++ " contains invalid os-specific flag(s)" ++ " %#" PRIx64 "\n"), ++ cnt, section_name (ebl, cnt), sh_flags & SHF_MASKOS); ++ sh_flags &= ~(GElf_Xword) SHF_MASKOS; ++ } + if (sh_flags != 0) + ERROR (_("section [%2zu] '%s' contains unknown flag(s)" + " %#" PRIx64 "\n"), +@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but + switch (shdr->sh_type) + { + case SHT_PROGBITS: ++ case SHT_MIPS_DWARF: + break; + + case SHT_NOBITS: +@@ -4716,7 +4732,7 @@ program header offset in ELF header and + if (shdr != NULL + && ((is_debuginfo && shdr->sh_type == SHT_NOBITS) + || (! is_debuginfo +- && (shdr->sh_type == SHT_PROGBITS ++ && (is_debug_section_type(shdr->sh_type) + || shdr->sh_type == SHT_X86_64_UNWIND))) + && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL + && ! strcmp (".eh_frame_hdr", diff --git a/tools/elfutils/patches/014-backport-mips-support-stack.patch b/tools/elfutils/patches/014-backport-mips-support-stack.patch new file mode 100644 index 0000000000..9907a30264 --- /dev/null +++ b/tools/elfutils/patches/014-backport-mips-support-stack.patch @@ -0,0 +1,273 @@ +From f2acb06970522a9563d82490f2f1b8fc0bb5b720 Mon Sep 17 00:00:00 2001 +From: Ying Huang +Date: Tue, 5 Mar 2024 17:51:21 +0800 +Subject: [PATCH] stack: Fix stack unwind failure on mips + +Add abi_cfi, set_initial_registers_tid, unwind on mips. + + * backends/Makefile.am (mips_SRCS): Add mips_initreg.c, + mips_cfi.c and mips_unwind.c. + * backends/mips_init.c (mips_init): HOOK abi_cfi, unwind and + set_initial_registers_tid. Set frame_nregs to 71. + * backends/mips_cfi.c: New file. + * backends/mips_initreg.c: Likewise. + * backends/mips_unwind.c: Likewise. + +Signed-off-by: Ying Huang +--- + backends/Makefile.am | 3 +- + backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++ + backends/mips_init.c | 4 ++ + backends/mips_initreg.c | 61 ++++++++++++++++++++++++++++++ + backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 219 insertions(+), 1 deletion(-) + create mode 100644 backends/mips_cfi.c + create mode 100644 backends/mips_initreg.c + create mode 100644 backends/mips_unwind.c + +--- a/backends/Makefile.am ++++ b/backends/Makefile.am +@@ -102,7 +102,8 @@ loongarch_SRCS = loongarch_init.c loonga + + arc_SRCS = arc_init.c arc_symbol.c + +-mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c ++mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ ++ mips_cfi.c mips_unwind.c + + libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ + $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ +--- /dev/null ++++ b/backends/mips_cfi.c +@@ -0,0 +1,68 @@ ++/* MIPS ABI-specified defaults for DWARF CFI. ++ Copyright (C) 2009 Red Hat, Inc. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++ ++int ++mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) ++{ ++ static const uint8_t abi_cfi[] = ++ { ++ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0), ++ /* Callee-saved regs. */ ++ DW_CFA_same_value, ULEB128_7 (16), /* s0 */ ++ DW_CFA_same_value, ULEB128_7 (17), /* s1 */ ++ DW_CFA_same_value, ULEB128_7 (18), /* s2 */ ++ DW_CFA_same_value, ULEB128_7 (19), /* s3 */ ++ DW_CFA_same_value, ULEB128_7 (20), /* s4 */ ++ DW_CFA_same_value, ULEB128_7 (21), /* s5 */ ++ DW_CFA_same_value, ULEB128_7 (22), /* s6 */ ++ DW_CFA_same_value, ULEB128_7 (23), /* s7 */ ++ DW_CFA_same_value, ULEB128_7 (28), /* gp */ ++ DW_CFA_same_value, ULEB128_7 (29), /* sp */ ++ DW_CFA_same_value, ULEB128_7 (30), /* fp */ ++ ++ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0), ++ }; ++ ++ abi_info->initial_instructions = abi_cfi; ++ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; ++ abi_info->data_alignment_factor = 8; ++ ++ abi_info->return_address_register = 31; /* %ra */ ++ ++ return 0; ++} +--- a/backends/mips_init.c ++++ b/backends/mips_init.c +@@ -58,5 +58,9 @@ mips_init (Elf *elf __attribute__ ((unus + HOOK (eh, check_object_attribute); + HOOK (eh, check_special_symbol); + HOOK (eh, check_reloc_target_type); ++ HOOK (eh, set_initial_registers_tid); ++ HOOK (eh, abi_cfi); ++ HOOK (eh, unwind); ++ eh->frame_nregs = 71; + return eh; + } +--- /dev/null ++++ b/backends/mips_initreg.c +@@ -0,0 +1,61 @@ ++/* Fetch live process registers from TID. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__) ++# include ++# include ++#include ++#endif ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++ ++ ++bool ++mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), ++ ebl_tid_registers_t *setfunc __attribute__ ((unused)), ++ void *arg __attribute__ ((unused))) ++{ ++#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__) ++ return false; ++#else /* __mips__ */ ++/* For PTRACE_GETREGS */ ++ ++ struct pt_regs gregs; ++ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0) ++ return false; ++ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg)) ++ return false; ++ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg); ++#endif /* __mips__ */ ++} +--- /dev/null ++++ b/backends/mips_unwind.c +@@ -0,0 +1,84 @@ ++/* Get previous frame state for an existing frame state. ++ Copyright (C) 2016 The Qt Company Ltd. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#define BACKEND mips_ ++#define SP_REG 29 ++#define FP_REG 30 ++#define LR_REG 31 ++#define FP_OFFSET 0 ++#define LR_OFFSET 8 ++#define SP_OFFSET 16 ++ ++#include "libebl_CPU.h" ++ ++/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ ++ ++bool ++EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)), ++ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc, ++ ebl_pid_memory_read_t *readfunc, void *arg, ++ bool *signal_framep __attribute__ ((unused))) ++{ ++ Dwarf_Word fp, lr, sp; ++ ++ if (!getfunc(LR_REG, 1, &lr, arg)) ++ return false; ++ ++ if (lr == 0 || !setfunc(-1, 1, &lr, arg)) ++ return false; ++ ++ if (!getfunc(FP_REG, 1, &fp, arg)) ++ fp = 0; ++ ++ if (!getfunc(SP_REG, 1, &sp, arg)) ++ sp = 0; ++ ++ Dwarf_Word newLr, newFp, newSp; ++ ++ if (!readfunc(fp + LR_OFFSET, &newLr, arg)) ++ newLr = 0; ++ ++ if (!readfunc(fp + FP_OFFSET, &newFp, arg)) ++ newFp = 0; ++ ++ newSp = fp + SP_OFFSET; ++ ++ // These are not fatal if they don't work. They will just prevent unwinding at the next frame. ++ setfunc(LR_REG, 1, &newLr, arg); ++ setfunc(FP_REG, 1, &newFp, arg); ++ setfunc(SP_REG, 1, &newSp, arg); ++ ++ // If the fp is invalid, we might still have a valid lr. ++ // But if the fp is valid, then the stack should be moving in the right direction. ++ return fp == 0 || newSp > sp; ++} diff --git a/tools/elfutils/patches/015-backport-mips-support-regs.patch b/tools/elfutils/patches/015-backport-mips-support-regs.patch new file mode 100644 index 0000000000..7547a12140 --- /dev/null +++ b/tools/elfutils/patches/015-backport-mips-support-regs.patch @@ -0,0 +1,475 @@ +From db33cb0cac3253c34881c0377ada51d9803eaae0 Mon Sep 17 00:00:00 2001 +From: Ying Huang +Date: Tue, 5 Mar 2024 17:51:22 +0800 +Subject: [PATCH] backends: Add register_info, return_value_location, core_note + on mips + + * backends/Makefile.am (mips_SRCS): Add mips_regs.c, + mips_retval.c and mips_corenote.c. + * backends/mips_init.c (mips_init): HOOK register_info, + return_value_location and core_note. + * backends/mips_corenote.c: New file. + * backends/mips_regs.c: Likewise. + * backends/mips_retval.c: Likewise. + +Signed-off-by: Ying Huang +--- + backends/Makefile.am | 3 +- + backends/mips_corenote.c | 85 +++++++++++++++++ + backends/mips_init.c | 3 + + backends/mips_regs.c | 135 +++++++++++++++++++++++++++ + backends/mips_retval.c | 196 +++++++++++++++++++++++++++++++++++++++ + 5 files changed, 421 insertions(+), 1 deletion(-) + create mode 100644 backends/mips_corenote.c + create mode 100644 backends/mips_regs.c + create mode 100644 backends/mips_retval.c + +--- a/backends/Makefile.am ++++ b/backends/Makefile.am +@@ -103,7 +103,8 @@ loongarch_SRCS = loongarch_init.c loonga + arc_SRCS = arc_init.c arc_symbol.c + + mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ +- mips_cfi.c mips_unwind.c ++ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \ ++ mips_corenote.c + + libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ + $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ +--- /dev/null ++++ b/backends/mips_corenote.c +@@ -0,0 +1,85 @@ ++/* MIPS specific core note handling. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++ ++#define BITS 64 ++#ifndef BITS ++# define BITS 32 ++#else ++# define BITS 64 ++#endif ++ ++#define PRSTATUS_REGS_SIZE (45 * (BITS / 8)) ++static const Ebl_Register_Location prstatus_regs[] = ++ { ++ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS }, ++ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS }, ++ }; ++ ++#define PRSTATUS_REGSET_ITEMS \ ++ { \ ++ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \ ++ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \ ++ .group = "register", \ ++ .pc_register = true \ ++ } ++ ++#if BITS == 32 ++# define ULONG uint32_t ++# define ALIGN_ULONG 4 ++# define TYPE_ULONG ELF_T_WORD ++#define TYPE_LONG ELF_T_SWORD ++#else ++#define ULONG uint64_t ++#define ALIGN_ULONG 8 ++#define TYPE_ULONG ELF_T_XWORD ++#define TYPE_LONG ELF_T_SXWORD ++#endif ++#define PID_T int32_t ++#define UID_T uint32_t ++#define GID_T uint32_t ++#define ALIGN_PID_T 4 ++#define ALIGN_UID_T 4 ++#define ALIGN_GID_T 4 ++#define TYPE_PID_T ELF_T_SWORD ++#define TYPE_UID_T ELF_T_WORD ++#define TYPE_GID_T ELF_T_WORD ++ ++#include "linux-core-note.c" +--- a/backends/mips_init.c ++++ b/backends/mips_init.c +@@ -61,6 +61,9 @@ mips_init (Elf *elf __attribute__ ((unus + HOOK (eh, set_initial_registers_tid); + HOOK (eh, abi_cfi); + HOOK (eh, unwind); ++ HOOK (eh, register_info); ++ HOOK (eh, return_value_location); ++ HOOK (eh, core_note); + eh->frame_nregs = 71; + return eh; + } +--- /dev/null ++++ b/backends/mips_regs.c +@@ -0,0 +1,135 @@ ++/* Register names and numbers for mips DWARF. ++ Copyright (C) 2006 Red Hat, Inc. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++#include ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++#include ++ssize_t ++mips_register_info (Ebl *ebl __attribute__ ((unused)), ++ int regno, char *name, size_t namelen, ++ const char **prefix, const char **setname, ++ int *bits, int *type) ++{ ++ if (name == NULL) ++ return 72; ++ ++ if (regno < 0 || regno > 71 || namelen < 4) ++ return -1; ++ ++ *prefix = "$"; ++ if (regno < 38) ++ { ++ *setname = "integer"; ++ *type = DW_ATE_signed; ++ *bits = 32; ++ } ++ else ++ { ++ *setname = "FPU"; ++ *type = DW_ATE_float; ++ *bits = 64; ++ } ++ ++ if (regno < 32) ++ { ++ if (regno < 10) ++ { ++ name[0] = regno + '0'; ++ namelen = 1; ++ } ++ else ++ { ++ name[0] = (regno / 10) + '0'; ++ name[1] = (regno % 10) + '0'; ++ namelen = 2; ++ } ++ if (regno == 28 || regno == 29 || regno == 31) ++ *type = DW_ATE_address; ++ } ++ else if (regno == 32) ++ { ++ return stpcpy (name, "lo") + 1 - name; ++ } ++ else if (regno == 33) ++ { ++ return stpcpy (name, "hi") + 1 - name; ++ } ++ else if (regno == 34) ++ { ++ return stpcpy (name, "pc") + 1 - name; ++ } ++ else if (regno == 35) ++ { ++ *type = DW_ATE_address; ++ return stpcpy (name, "bad") + 1 - name; ++ } ++ else if (regno == 36) ++ { ++ return stpcpy (name, "sr") + 1 - name; ++ } ++ else if (regno == 37) ++ { ++ *type = DW_ATE_address; ++ return stpcpy (name, "cause") + 1 - name; ++ } ++ else if (regno < 70) ++ { ++ name[0] = 'f'; ++ if (regno < 38 + 10) ++ { ++ name[1] = (regno - 38) + '0'; ++ namelen = 2; ++ } ++ else ++ { ++ name[1] = (regno - 38) / 10 + '0'; ++ name[2] = (regno - 38) % 10 + '0'; ++ namelen = 3; ++ } ++ } ++ else if (regno == 70) ++ { ++ return stpcpy (name, "fsr") + 1 - name; ++ } ++ else if (regno == 71) ++ { ++ return stpcpy (name, "fir") + 1 - name; ++ } ++ ++ name[namelen++] = '\0'; ++ return namelen; ++} +--- /dev/null ++++ b/backends/mips_retval.c +@@ -0,0 +1,196 @@ ++/* Function return value location for Linux/mips ABI. ++ Copyright (C) 2005 Red Hat, Inc. ++ Copyright (C) 2024 CIP United Inc. ++ This file is part of elfutils. ++ ++ This file is free software; you can redistribute it and/or modify ++ it under the terms of either ++ ++ * the GNU Lesser General Public License as published by the Free ++ Software Foundation; either version 3 of the License, or (at ++ your option) any later version ++ ++ or ++ ++ * the GNU General Public License as published by the Free ++ Software Foundation; either version 2 of the License, or (at ++ your option) any later version ++ ++ or both in parallel, as here. ++ ++ elfutils is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received copies of the GNU General Public License and ++ the GNU Lesser General Public License along with this program. If ++ not, see . */ ++ ++#ifdef HAVE_CONFIG_H ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define BACKEND mips_ ++#include "libebl_CPU.h" ++#include "libdwP.h" ++#include ++ ++/* $v0 or pair $v0, $v1 */ ++static const Dwarf_Op loc_intreg_o32[] = ++ { ++ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 }, ++ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 }, ++ }; ++ ++static const Dwarf_Op loc_intreg[] = ++ { ++ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 }, ++ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 }, ++ }; ++#define nloc_intreg 1 ++#define nloc_intregpair 4 ++ ++/* $f0 (float), or pair $f0, $f1 (double). ++ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */ ++static const Dwarf_Op loc_fpreg_o32[] = ++ { ++ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 }, ++ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 }, ++ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 }, ++ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 }, ++ }; ++ ++/* $f0, or pair $f0, $f2. */ ++static const Dwarf_Op loc_fpreg[] = ++ { ++ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 }, ++ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 }, ++ }; ++#define nloc_fpreg 1 ++#define nloc_fpregpair 4 ++#define nloc_fpregquad 8 ++ ++/* The return value is a structure and is actually stored in stack space ++ passed in a hidden argument by the caller. But, the compiler ++ helpfully returns the address of that space in $v0. */ ++static const Dwarf_Op loc_aggregate[] = ++ { ++ { .atom = DW_OP_breg2, .number = 0 } ++ }; ++#define nloc_aggregate 1 ++ ++int ++mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) ++{ ++ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8; ++ if (!regsize) ++ return -2; ++ ++ /* Start with the function's type, and get the DW_AT_type attribute, ++ which is the type of the return value. */ ++ ++ Dwarf_Attribute attr_mem; ++ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); ++ if (attr == NULL) ++ /* The function has no return value, like a `void' function in C. */ ++ return 0; ++ ++ Dwarf_Die die_mem; ++ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); ++ int tag = dwarf_tag (typedie); ++ ++ /* Follow typedefs and qualifiers to get to the actual type. */ ++ while (tag == DW_TAG_typedef ++ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type ++ || tag == DW_TAG_restrict_type) ++ { ++ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); ++ typedie = dwarf_formref_die (attr, &die_mem); ++ tag = dwarf_tag (typedie); ++ } ++ ++ switch (tag) ++ { ++ case -1: ++ return -1; ++ ++ case DW_TAG_subrange_type: ++ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) ++ { ++ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); ++ typedie = dwarf_formref_die (attr, &die_mem); ++ tag = dwarf_tag (typedie); ++ } ++ /* Fall through. */ ++ FALLTHROUGH; ++ ++ case DW_TAG_base_type: ++ case DW_TAG_enumeration_type: ++ CASE_POINTER: ++ { ++ Dwarf_Word size; ++ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, ++ &attr_mem), &size) != 0) ++ { ++ if (dwarf_is_pointer (tag)) ++ size = regsize; ++ else ++ return -1; ++ } ++ if (tag == DW_TAG_base_type) ++ { ++ Dwarf_Word encoding; ++ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, ++ &attr_mem), &encoding) != 0) ++ return -1; ++ ++#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc)) ++ ++ if (encoding == DW_ATE_float) ++ { ++ *locp = ARCH_LOC(loc_fpreg, regsize); ++ if (size <= regsize) ++ return nloc_fpreg; ++ ++ if (size <= 2*regsize) ++ return nloc_fpregpair; ++ ++ if (size <= 4*regsize) ++ return nloc_fpregquad; ++ ++ goto aggregate; ++ } ++ } ++ *locp = ARCH_LOC(loc_intreg, regsize); ++ if (size <= regsize) ++ return nloc_intreg; ++ if (size <= 2*regsize) ++ return nloc_intregpair; ++ ++ /* Else fall through. Shouldn't happen though (at least with gcc) */ ++ } ++ FALLTHROUGH; ++ ++ case DW_TAG_structure_type: ++ case DW_TAG_class_type: ++ case DW_TAG_union_type: ++ case DW_TAG_array_type: ++ aggregate: ++ *locp = loc_aggregate; ++ return nloc_aggregate; ++ case DW_TAG_unspecified_type: ++ return 0; ++ } ++ ++ /* XXX We don't have a good way to return specific errors from ebl calls. ++ This value means we do not understand the type, but it is well-formed ++ DWARF and might be valid. */ ++ return -2; ++} From abf243eae87e4cf2886bfa4c6271e8bb3aebcb18 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 21 Oct 2024 15:31:29 -0400 Subject: [PATCH 34/51] tools/elfutils: update to 0.192 Update to the next release. Removed upstream patch: - 000-backport-iquote-include.patch - 010-backport-mips-support-reloc.patch - 014-backport-mips-support-stack.patch - 015-backport-mips-support-regs.patch - 095-src-unused-variable.patch - 096-lib-config_h.patch - 097-libcpu-config_h.patch - 098-libdw-maintainer-clean.patch - 099-remove-unlocked-stdio.patch Manually adjusted patch: - 012-backport-mips-support-readelf.patch - 013-backport-mips-support-elflint.patch - 101-shared-conditional.patch All other patches are automatically refreshed. Link: https://sourceware.org/pipermail/elfutils-devel/2024q4/007540.html Tested-by: Georgi Valkov # macOS Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/elfutils/Makefile | 6 +- .../patches/000-backport-iquote-include.patch | 37 - .../010-backport-mips-support-reloc.patch | 300 -------- .../012-backport-mips-support-readelf.patch | 40 +- .../013-backport-mips-support-elflint.patch | 15 +- .../014-backport-mips-support-stack.patch | 273 ------- .../015-backport-mips-support-regs.patch | 475 ------------ .../patches/095-src-unused-variable.patch | 29 - tools/elfutils/patches/096-lib-config_h.patch | 29 - .../patches/097-libcpu-config_h.patch | 47 -- .../patches/098-libdw-maintainer-clean.patch | 43 -- .../patches/099-remove-unlocked-stdio.patch | 687 ------------------ tools/elfutils/patches/100-portability.patch | 20 +- .../patches/101-shared-conditional.patch | 21 +- .../patches/110-objects-manifest.patch | 10 +- 15 files changed, 57 insertions(+), 1975 deletions(-) delete mode 100644 tools/elfutils/patches/000-backport-iquote-include.patch delete mode 100644 tools/elfutils/patches/010-backport-mips-support-reloc.patch delete mode 100644 tools/elfutils/patches/014-backport-mips-support-stack.patch delete mode 100644 tools/elfutils/patches/015-backport-mips-support-regs.patch delete mode 100644 tools/elfutils/patches/095-src-unused-variable.patch delete mode 100644 tools/elfutils/patches/096-lib-config_h.patch delete mode 100644 tools/elfutils/patches/097-libcpu-config_h.patch delete mode 100644 tools/elfutils/patches/098-libdw-maintainer-clean.patch delete mode 100644 tools/elfutils/patches/099-remove-unlocked-stdio.patch diff --git a/tools/elfutils/Makefile b/tools/elfutils/Makefile index 625cecf58c..ce711ac66c 100644 --- a/tools/elfutils/Makefile +++ b/tools/elfutils/Makefile @@ -3,12 +3,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=elfutils -PKG_VERSION:=0.191 -PKG_RELEASE:=2 +PKG_VERSION:=0.192 +PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://sourceware.org/$(PKG_NAME)/ftp/$(PKG_VERSION) -PKG_HASH:=df76db71366d1d708365fc7a6c60ca48398f14367eb2b8954efc8897147ad871 +PKG_HASH:=616099beae24aba11f9b63d86ca6cc8d566d968b802391334c91df54eab416b4 PKG_LICENSE:=GPL-3.0-or-later PKG_LICENSE_FILES:=COPYING COPYING-GPLV2 COPYING-LGPLV3 diff --git a/tools/elfutils/patches/000-backport-iquote-include.patch b/tools/elfutils/patches/000-backport-iquote-include.patch deleted file mode 100644 index 2c7657fc8c..0000000000 --- a/tools/elfutils/patches/000-backport-iquote-include.patch +++ /dev/null @@ -1,37 +0,0 @@ -From b426c4db31e7c80d4262abdd845d2ece0c9a841c Mon Sep 17 00:00:00 2001 -From: Alfred Wingate -Date: Wed, 14 Aug 2024 12:14:38 -0400 -Subject: [PATCH] Avoid overriding libcxx system header - -Replace -I with -iquote to avoid overriding stack system header from libcxx-18 -with the previously built stack binary. Override DEFAULT_INLCUDES because m4 -adds -I. by default. - -Signed-off-by: Aaron Merey ---- - config/eu.am | 2 +- - src/Makefile.am | 2 ++ - 2 files changed, 3 insertions(+), 1 deletion(-) - ---- a/config/eu.am -+++ b/config/eu.am -@@ -31,7 +31,7 @@ - ## - - DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"' --AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I.. -+AM_CPPFLAGS = -iquote . -I$(srcdir) -I$(top_srcdir)/lib -I.. - - # Drop the 'u' flag that automake adds by default. It is incompatible - # with deterministic archives. ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -19,6 +19,8 @@ - include $(top_srcdir)/config/eu.am - DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRED@ \ - -DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\" -+ -+DEFAULT_INCLUDES = - AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \ - -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \ - -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm -I../debuginfod diff --git a/tools/elfutils/patches/010-backport-mips-support-reloc.patch b/tools/elfutils/patches/010-backport-mips-support-reloc.patch deleted file mode 100644 index e9ef3997d2..0000000000 --- a/tools/elfutils/patches/010-backport-mips-support-reloc.patch +++ /dev/null @@ -1,300 +0,0 @@ -From e259f126f5077923e415e306915de50ed0f0db56 Mon Sep 17 00:00:00 2001 -From: Ying Huang -Date: Tue, 5 Mar 2024 17:51:17 +0800 -Subject: [PATCH] Support Mips architecture - - * backends/Makefile.am (modules): Add mips. - (mips_SRCS): New var for mips_init.c mips_symbol.c. - (libebl_backends_a_SOURCES): Add mips_SRCS. - * backends/mips_init.c: New file. - * backends/mips_reloc.def: Likewise. - * backends/mips_symbol.c: Likewise. - * libebl/eblopenbackend.c (mips_init): Declare. - (machines): Add mips. - * libelf/libelfP.h: Add ELF64_MIPS_R_TYPE{1,2,3} - -Signed-off-by: Ying Huang ---- - backends/Makefile.am | 6 ++- - backends/mips_init.c | 52 +++++++++++++++++++++++ - backends/mips_reloc.def | 93 +++++++++++++++++++++++++++++++++++++++++ - backends/mips_symbol.c | 63 ++++++++++++++++++++++++++++ - libebl/eblopenbackend.c | 2 + - libelf/libelfP.h | 3 ++ - 6 files changed, 217 insertions(+), 2 deletions(-) - create mode 100644 backends/mips_init.c - create mode 100644 backends/mips_reloc.def - create mode 100644 backends/mips_symbol.c - ---- a/backends/Makefile.am -+++ b/backends/Makefile.am -@@ -37,7 +37,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/libebl -I - noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a - - modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \ -- m68k bpf riscv csky loongarch arc -+ m68k bpf riscv csky loongarch arc mips - - i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \ - i386_retval.c i386_regs.c i386_auxv.c \ -@@ -102,12 +102,14 @@ loongarch_SRCS = loongarch_init.c loonga - - arc_SRCS = arc_init.c arc_symbol.c - -+mips_SRCS = mips_init.c mips_symbol.c -+ - libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ - $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ - $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \ - $(ppc64_SRCS) $(s390_SRCS) \ - $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \ -- $(loongarch_SRCS) $(arc_SRCS) -+ $(loongarch_SRCS) $(arc_SRCS) $(mips_SRCS) - - libebl_backends_pic_a_SOURCES = - am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os) ---- /dev/null -+++ b/backends/mips_init.c -@@ -0,0 +1,52 @@ -+/* Initialization of MIPS specific backend library. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#define BACKEND mips_ -+#define RELOC_PREFIX R_MIPS_ -+#include "libebl_CPU.h" -+#include "libelfP.h" -+ -+#define RELOC_TYPE_ID(type) ((type) & 0xff) -+ -+/* This defines the common reloc hooks based on mips_reloc.def. */ -+#include "common-reloc.c" -+ -+Ebl * -+mips_init (Elf *elf __attribute__ ((unused)), -+ GElf_Half machine __attribute__ ((unused)), -+ Ebl *eh) -+{ -+ /* We handle it. */ -+ mips_init_reloc (eh); -+ HOOK (eh, reloc_simple_type); -+ return eh; -+} ---- /dev/null -+++ b/backends/mips_reloc.def -@@ -0,0 +1,93 @@ -+/* List the relocation types for MIPS. -*- C -*- -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+/* NAME, REL|EXEC|DYN */ -+ -+ -+RELOC_TYPE (NONE, REL|EXEC|DYN) -+RELOC_TYPE (16, REL|EXEC|DYN) -+RELOC_TYPE (32, REL) -+RELOC_TYPE (REL32, REL|EXEC|DYN) -+RELOC_TYPE (26, REL|DYN) -+RELOC_TYPE (HI16, REL) -+RELOC_TYPE (LO16, REL|EXEC|DYN) -+RELOC_TYPE (GPREL16, REL|EXEC|DYN) -+RELOC_TYPE (LITERAL, REL|EXEC|DYN) -+RELOC_TYPE (GOT16, REL|EXEC|DYN) -+RELOC_TYPE (PC16, REL) -+RELOC_TYPE (CALL16, REL) -+RELOC_TYPE (GPREL32, REL) -+RELOC_TYPE (SHIFT5, REL) -+RELOC_TYPE (SHIFT6, REL) -+RELOC_TYPE (64, REL) -+RELOC_TYPE (GOT_DISP, REL) -+RELOC_TYPE (GOT_PAGE, REL) -+RELOC_TYPE (GOT_OFST, REL) -+RELOC_TYPE (GOT_HI16, REL) -+RELOC_TYPE (GOT_LO16, REL) -+RELOC_TYPE (SUB, REL) -+RELOC_TYPE (INSERT_A, REL) -+RELOC_TYPE (INSERT_B, REL) -+RELOC_TYPE (DELETE, REL) -+RELOC_TYPE (HIGHER, REL) -+RELOC_TYPE (HIGHEST, REL) -+RELOC_TYPE (CALL_HI16, REL) -+RELOC_TYPE (CALL_LO16, REL) -+RELOC_TYPE (SCN_DISP, REL) -+RELOC_TYPE (REL16, REL) -+RELOC_TYPE (ADD_IMMEDIATE, REL) -+RELOC_TYPE (PJUMP, REL) -+RELOC_TYPE (RELGOT, REL) -+RELOC_TYPE (JALR, REL) -+RELOC_TYPE (TLS_DTPMOD32, DYN) -+RELOC_TYPE (TLS_DTPREL32, REL) -+RELOC_TYPE (TLS_DTPMOD64, DYN) -+RELOC_TYPE (TLS_DTPREL64, REL) -+RELOC_TYPE (TLS_GD, REL) -+RELOC_TYPE (TLS_LDM, REL) -+RELOC_TYPE (TLS_DTPREL_HI16, REL) -+RELOC_TYPE (TLS_DTPREL_LO16, REL) -+RELOC_TYPE (TLS_GOTTPREL, REL) -+RELOC_TYPE (TLS_TPREL32, REL) -+RELOC_TYPE (TLS_TPREL64, REL) -+RELOC_TYPE (TLS_TPREL_HI16, REL) -+RELOC_TYPE (TLS_TPREL_LO16, REL) -+RELOC_TYPE (GLOB_DAT, REL) -+RELOC_TYPE (PC21_S2, REL) -+RELOC_TYPE (PC26_S2, REL) -+RELOC_TYPE (PC18_S3, REL) -+RELOC_TYPE (PC19_S2, REL) -+RELOC_TYPE (PCHI16, REL) -+RELOC_TYPE (PCLO16, REL) -+RELOC_TYPE (COPY, REL) -+RELOC_TYPE (JUMP_SLOT, REL) -+RELOC_TYPE (PC32, REL) -+RELOC_TYPE (EH, REL) -+RELOC_TYPE (GNU_REL16_S2, REL) -+RELOC_TYPE (GNU_VTINHERIT, REL) -+RELOC_TYPE (GNU_VTENTRY, REL) ---- /dev/null -+++ b/backends/mips_symbol.c -@@ -0,0 +1,63 @@ -+/* MIPS specific symbolic name handling. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+ -+#include -+#include -+#include -+#include -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+#include "libelfP.h" -+ -+/* Check for the simple reloc types. */ -+Elf_Type -+mips_reloc_simple_type (Ebl *ebl, int type, -+ int *addsub __attribute__ ((unused))) -+{ -+ int typeNew = type; -+ if(ebl->elf->class == ELFCLASS64) -+ typeNew = ELF64_MIPS_R_TYPE1(type); -+ switch (typeNew) -+ { -+ case R_MIPS_64: -+ return ELF_T_XWORD; -+ case R_MIPS_32: -+ return ELF_T_WORD; -+ case R_MIPS_16: -+ return ELF_T_HALF; -+ -+ default: -+ return ELF_T_NUM; -+ } -+} ---- a/libebl/eblopenbackend.c -+++ b/libebl/eblopenbackend.c -@@ -57,6 +57,7 @@ Ebl *riscv_init (Elf *, GElf_Half, Ebl * - Ebl *csky_init (Elf *, GElf_Half, Ebl *); - Ebl *loongarch_init (Elf *, GElf_Half, Ebl *); - Ebl *arc_init (Elf *, GElf_Half, Ebl *); -+Ebl *mips_init (Elf *, GElf_Half, Ebl *); - - /* This table should contain the complete list of architectures as far - as the ELF specification is concerned. */ -@@ -154,6 +155,7 @@ static const struct - { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB }, - { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB }, - { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB }, -+ { mips_init, "elf_mips", "mips", 4, EM_MIPS, 0, 0 }, - }; - #define nmachines (sizeof (machines) / sizeof (machines[0])) - ---- a/libelf/libelfP.h -+++ b/libelf/libelfP.h -@@ -617,4 +617,7 @@ extern void __libelf_reset_rawdata (Elf_ - #define INVALID_NDX(ndx, type, data) \ - unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx)) - -+#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) -+#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) -+#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) - #endif /* libelfP.h */ diff --git a/tools/elfutils/patches/012-backport-mips-support-readelf.patch b/tools/elfutils/patches/012-backport-mips-support-readelf.patch index cf2b7c827b..3a61acde6e 100644 --- a/tools/elfutils/patches/012-backport-mips-support-readelf.patch +++ b/tools/elfutils/patches/012-backport-mips-support-readelf.patch @@ -29,11 +29,11 @@ Signed-off-by: Ying Huang arc_SRCS = arc_init.c arc_symbol.c --mips_SRCS = mips_init.c mips_symbol.c -+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c +-mips_SRCS = mips_init.c mips_symbol.c mips_initreg.c \ ++mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ + mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \ + mips_corenote.c - libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ - $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ --- /dev/null +++ b/backends/mips_attrs.c @@ -0,0 +1,140 @@ @@ -179,7 +179,7 @@ Signed-off-by: Ying Huang +} --- a/backends/mips_init.c +++ b/backends/mips_init.c -@@ -48,5 +48,12 @@ mips_init (Elf *elf __attribute__ ((unus +@@ -48,6 +48,13 @@ mips_init (Elf *elf __attribute__ ((unus /* We handle it. */ mips_init_reloc (eh); HOOK (eh, reloc_simple_type); @@ -190,8 +190,9 @@ Signed-off-by: Ying Huang + HOOK (eh, dynamic_tag_check); + HOOK (eh, dynamic_tag_name); + HOOK (eh, check_object_attribute); - return eh; - } + HOOK (eh, set_initial_registers_tid); + HOOK (eh, abi_cfi); + HOOK (eh, unwind); --- a/backends/mips_symbol.c +++ b/backends/mips_symbol.c @@ -61,3 +61,574 @@ mips_reloc_simple_type (Ebl *ebl, int ty @@ -771,7 +772,7 @@ Signed-off-by: Ying Huang +} --- a/libelf/libelfP.h +++ b/libelf/libelfP.h -@@ -620,4 +620,5 @@ extern void __libelf_reset_rawdata (Elf_ +@@ -624,4 +624,5 @@ extern void __libelf_reset_rawdata (Elf_ #define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) #define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) #define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) @@ -993,7 +994,7 @@ Signed-off-by: Ying Huang } } } -@@ -12043,7 +12139,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * +@@ -12037,7 +12133,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); @@ -1002,7 +1003,7 @@ Signed-off-by: Ying Huang { const char *name = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); -@@ -12073,7 +12169,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * +@@ -12067,7 +12163,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl * GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); @@ -1013,25 +1014,24 @@ Signed-off-by: Ying Huang { --- a/tests/Makefile.am +++ b/tests/Makefile.am -@@ -214,7 +214,7 @@ TESTS = run-arextract.sh run-arsymtest.s +@@ -216,7 +216,7 @@ TESTS = run-arextract.sh run-arsymtest.s run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \ run-readelf-dw-form-indirect.sh run-strip-largealign.sh \ run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \ -- run-declfiles.sh -+ run-declfiles.sh run-readelf-reloc.sh +- run-declfiles.sh \ ++ run-declfiles.sh run-readelf-reloc.sh \ + run-sysroot.sh if !BIARCH - export ELFUTILS_DISABLE_BIARCH = 1 -@@ -646,7 +646,8 @@ EXTRA_DIST = run-arextract.sh run-arsymt - testfile-dwp-5-cu-index-overflow.dwp.bz2 \ +@@ -684,7 +684,7 @@ EXTRA_DIST = run-arextract.sh run-arsymt testfile-dwp-4-cu-index-overflow.bz2 \ testfile-dwp-4-cu-index-overflow.dwp.bz2 \ -- testfile-dwp-cu-index-overflow.source -+ testfile-dwp-cu-index-overflow.source \ -+ run-readelf-reloc.sh + testfile-dwp-cu-index-overflow.source \ +- testfile-define-file.bz2 \ ++ run-readelf-reloc.sh testfile-define-file.bz2 \ + testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh - if USE_VALGRIND --- /dev/null +++ b/tests/run-readelf-reloc.sh @@ -0,0 +1,42 @@ diff --git a/tools/elfutils/patches/013-backport-mips-support-elflint.patch b/tools/elfutils/patches/013-backport-mips-support-elflint.patch index 906a3bf0f2..2ef9304bd1 100644 --- a/tools/elfutils/patches/013-backport-mips-support-elflint.patch +++ b/tools/elfutils/patches/013-backport-mips-support-elflint.patch @@ -29,7 +29,7 @@ Signed-off-by: Ying Huang --- a/backends/mips_init.c +++ b/backends/mips_init.c -@@ -51,9 +51,12 @@ mips_init (Elf *elf __attribute__ ((unus +@@ -51,10 +51,13 @@ mips_init (Elf *elf __attribute__ ((unus HOOK (eh, section_type_name); HOOK (eh, machine_flag_check); HOOK (eh, machine_flag_name); @@ -40,8 +40,9 @@ Signed-off-by: Ying Huang HOOK (eh, check_object_attribute); + HOOK (eh, check_special_symbol); + HOOK (eh, check_reloc_target_type); - return eh; - } + HOOK (eh, set_initial_registers_tid); + HOOK (eh, abi_cfi); + HOOK (eh, unwind); --- a/backends/mips_symbol.c +++ b/backends/mips_symbol.c @@ -158,6 +158,43 @@ mips_section_type_name (int type, @@ -101,7 +102,7 @@ Signed-off-by: Ying Huang ERROR (_("\ section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"), idx, section_name (ebl, idx), cnt, name); -@@ -3828,6 +3830,10 @@ cannot get section header for section [% +@@ -3829,6 +3831,10 @@ cannot get section header for section [% && ebl_bss_plt_p (ebl)) good_type = SHT_NOBITS; @@ -112,7 +113,7 @@ Signed-off-by: Ying Huang /* In a debuginfo file, any normal section can be SHT_NOBITS. This is only invalid for DWARF sections and .shstrtab. */ if (shdr->sh_type != good_type -@@ -3988,12 +3994,21 @@ section [%2zu] '%s': size not multiple o +@@ -3989,12 +3995,21 @@ section [%2zu] '%s': size not multiple o ERROR (_("section [%2zu] '%s'" " contains invalid processor-specific flag(s)" " %#" PRIx64 "\n"), @@ -137,7 +138,7 @@ Signed-off-by: Ying Huang if (sh_flags != 0) ERROR (_("section [%2zu] '%s' contains unknown flag(s)" " %#" PRIx64 "\n"), -@@ -4059,6 +4074,7 @@ section [%2zu] '%s': merge flag set but +@@ -4060,6 +4075,7 @@ section [%2zu] '%s': merge flag set but switch (shdr->sh_type) { case SHT_PROGBITS: @@ -145,7 +146,7 @@ Signed-off-by: Ying Huang break; case SHT_NOBITS: -@@ -4716,7 +4732,7 @@ program header offset in ELF header and +@@ -4717,7 +4733,7 @@ program header offset in ELF header and if (shdr != NULL && ((is_debuginfo && shdr->sh_type == SHT_NOBITS) || (! is_debuginfo diff --git a/tools/elfutils/patches/014-backport-mips-support-stack.patch b/tools/elfutils/patches/014-backport-mips-support-stack.patch deleted file mode 100644 index 9907a30264..0000000000 --- a/tools/elfutils/patches/014-backport-mips-support-stack.patch +++ /dev/null @@ -1,273 +0,0 @@ -From f2acb06970522a9563d82490f2f1b8fc0bb5b720 Mon Sep 17 00:00:00 2001 -From: Ying Huang -Date: Tue, 5 Mar 2024 17:51:21 +0800 -Subject: [PATCH] stack: Fix stack unwind failure on mips - -Add abi_cfi, set_initial_registers_tid, unwind on mips. - - * backends/Makefile.am (mips_SRCS): Add mips_initreg.c, - mips_cfi.c and mips_unwind.c. - * backends/mips_init.c (mips_init): HOOK abi_cfi, unwind and - set_initial_registers_tid. Set frame_nregs to 71. - * backends/mips_cfi.c: New file. - * backends/mips_initreg.c: Likewise. - * backends/mips_unwind.c: Likewise. - -Signed-off-by: Ying Huang ---- - backends/Makefile.am | 3 +- - backends/mips_cfi.c | 68 +++++++++++++++++++++++++++++++++ - backends/mips_init.c | 4 ++ - backends/mips_initreg.c | 61 ++++++++++++++++++++++++++++++ - backends/mips_unwind.c | 84 +++++++++++++++++++++++++++++++++++++++++ - 5 files changed, 219 insertions(+), 1 deletion(-) - create mode 100644 backends/mips_cfi.c - create mode 100644 backends/mips_initreg.c - create mode 100644 backends/mips_unwind.c - ---- a/backends/Makefile.am -+++ b/backends/Makefile.am -@@ -102,7 +102,8 @@ loongarch_SRCS = loongarch_init.c loonga - - arc_SRCS = arc_init.c arc_symbol.c - --mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c -+mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ -+ mips_cfi.c mips_unwind.c - - libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ - $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ ---- /dev/null -+++ b/backends/mips_cfi.c -@@ -0,0 +1,68 @@ -+/* MIPS ABI-specified defaults for DWARF CFI. -+ Copyright (C) 2009 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+int -+mips_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info) -+{ -+ static const uint8_t abi_cfi[] = -+ { -+ DW_CFA_def_cfa, ULEB128_7 (31), ULEB128_7 (0), -+ /* Callee-saved regs. */ -+ DW_CFA_same_value, ULEB128_7 (16), /* s0 */ -+ DW_CFA_same_value, ULEB128_7 (17), /* s1 */ -+ DW_CFA_same_value, ULEB128_7 (18), /* s2 */ -+ DW_CFA_same_value, ULEB128_7 (19), /* s3 */ -+ DW_CFA_same_value, ULEB128_7 (20), /* s4 */ -+ DW_CFA_same_value, ULEB128_7 (21), /* s5 */ -+ DW_CFA_same_value, ULEB128_7 (22), /* s6 */ -+ DW_CFA_same_value, ULEB128_7 (23), /* s7 */ -+ DW_CFA_same_value, ULEB128_7 (28), /* gp */ -+ DW_CFA_same_value, ULEB128_7 (29), /* sp */ -+ DW_CFA_same_value, ULEB128_7 (30), /* fp */ -+ -+ DW_CFA_val_offset, ULEB128_7 (29), ULEB128_7 (0), -+ }; -+ -+ abi_info->initial_instructions = abi_cfi; -+ abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi]; -+ abi_info->data_alignment_factor = 8; -+ -+ abi_info->return_address_register = 31; /* %ra */ -+ -+ return 0; -+} ---- a/backends/mips_init.c -+++ b/backends/mips_init.c -@@ -58,5 +58,9 @@ mips_init (Elf *elf __attribute__ ((unus - HOOK (eh, check_object_attribute); - HOOK (eh, check_special_symbol); - HOOK (eh, check_reloc_target_type); -+ HOOK (eh, set_initial_registers_tid); -+ HOOK (eh, abi_cfi); -+ HOOK (eh, unwind); -+ eh->frame_nregs = 71; - return eh; - } ---- /dev/null -+++ b/backends/mips_initreg.c -@@ -0,0 +1,61 @@ -+/* Fetch live process registers from TID. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#if (defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)) && defined(__linux__) -+# include -+# include -+#include -+#endif -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+ -+bool -+mips_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), -+ ebl_tid_registers_t *setfunc __attribute__ ((unused)), -+ void *arg __attribute__ ((unused))) -+{ -+#if (!defined(mips) && !defined(__mips) && !defined(__mips__) && !defined(MIPS) && !defined(__MIPS__)) || !defined(__linux__) -+ return false; -+#else /* __mips__ */ -+/* For PTRACE_GETREGS */ -+ -+ struct pt_regs gregs; -+ if (ptrace (PTRACE_GETREGS, tid, 0, &gregs) != 0) -+ return false; -+ if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.cp0_epc, arg)) -+ return false; -+ return setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg); -+#endif /* __mips__ */ -+} ---- /dev/null -+++ b/backends/mips_unwind.c -@@ -0,0 +1,84 @@ -+/* Get previous frame state for an existing frame state. -+ Copyright (C) 2016 The Qt Company Ltd. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#define BACKEND mips_ -+#define SP_REG 29 -+#define FP_REG 30 -+#define LR_REG 31 -+#define FP_OFFSET 0 -+#define LR_OFFSET 8 -+#define SP_OFFSET 16 -+ -+#include "libebl_CPU.h" -+ -+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that? */ -+ -+bool -+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)), -+ ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc, -+ ebl_pid_memory_read_t *readfunc, void *arg, -+ bool *signal_framep __attribute__ ((unused))) -+{ -+ Dwarf_Word fp, lr, sp; -+ -+ if (!getfunc(LR_REG, 1, &lr, arg)) -+ return false; -+ -+ if (lr == 0 || !setfunc(-1, 1, &lr, arg)) -+ return false; -+ -+ if (!getfunc(FP_REG, 1, &fp, arg)) -+ fp = 0; -+ -+ if (!getfunc(SP_REG, 1, &sp, arg)) -+ sp = 0; -+ -+ Dwarf_Word newLr, newFp, newSp; -+ -+ if (!readfunc(fp + LR_OFFSET, &newLr, arg)) -+ newLr = 0; -+ -+ if (!readfunc(fp + FP_OFFSET, &newFp, arg)) -+ newFp = 0; -+ -+ newSp = fp + SP_OFFSET; -+ -+ // These are not fatal if they don't work. They will just prevent unwinding at the next frame. -+ setfunc(LR_REG, 1, &newLr, arg); -+ setfunc(FP_REG, 1, &newFp, arg); -+ setfunc(SP_REG, 1, &newSp, arg); -+ -+ // If the fp is invalid, we might still have a valid lr. -+ // But if the fp is valid, then the stack should be moving in the right direction. -+ return fp == 0 || newSp > sp; -+} diff --git a/tools/elfutils/patches/015-backport-mips-support-regs.patch b/tools/elfutils/patches/015-backport-mips-support-regs.patch deleted file mode 100644 index 7547a12140..0000000000 --- a/tools/elfutils/patches/015-backport-mips-support-regs.patch +++ /dev/null @@ -1,475 +0,0 @@ -From db33cb0cac3253c34881c0377ada51d9803eaae0 Mon Sep 17 00:00:00 2001 -From: Ying Huang -Date: Tue, 5 Mar 2024 17:51:22 +0800 -Subject: [PATCH] backends: Add register_info, return_value_location, core_note - on mips - - * backends/Makefile.am (mips_SRCS): Add mips_regs.c, - mips_retval.c and mips_corenote.c. - * backends/mips_init.c (mips_init): HOOK register_info, - return_value_location and core_note. - * backends/mips_corenote.c: New file. - * backends/mips_regs.c: Likewise. - * backends/mips_retval.c: Likewise. - -Signed-off-by: Ying Huang ---- - backends/Makefile.am | 3 +- - backends/mips_corenote.c | 85 +++++++++++++++++ - backends/mips_init.c | 3 + - backends/mips_regs.c | 135 +++++++++++++++++++++++++++ - backends/mips_retval.c | 196 +++++++++++++++++++++++++++++++++++++++ - 5 files changed, 421 insertions(+), 1 deletion(-) - create mode 100644 backends/mips_corenote.c - create mode 100644 backends/mips_regs.c - create mode 100644 backends/mips_retval.c - ---- a/backends/Makefile.am -+++ b/backends/Makefile.am -@@ -103,7 +103,8 @@ loongarch_SRCS = loongarch_init.c loonga - arc_SRCS = arc_init.c arc_symbol.c - - mips_SRCS = mips_init.c mips_symbol.c mips_attrs.c mips_initreg.c \ -- mips_cfi.c mips_unwind.c -+ mips_cfi.c mips_unwind.c mips_regs.c mips_retval.c \ -+ mips_corenote.c - - libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \ - $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \ ---- /dev/null -+++ b/backends/mips_corenote.c -@@ -0,0 +1,85 @@ -+/* MIPS specific core note handling. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+ -+#define BITS 64 -+#ifndef BITS -+# define BITS 32 -+#else -+# define BITS 64 -+#endif -+ -+#define PRSTATUS_REGS_SIZE (45 * (BITS / 8)) -+static const Ebl_Register_Location prstatus_regs[] = -+ { -+ { .offset = 0, .regno = 0, .count = (BITS == 32 ? 40 : 34), .bits = BITS }, -+ { .offset = BITS/8 * (BITS == 32 ? 41 : 35), .regno = (BITS == 32 ? 41 : 35), .count = (BITS == 32 ? 4 : 10), .bits = BITS }, -+ }; -+ -+#define PRSTATUS_REGSET_ITEMS \ -+ { \ -+ .name = "pc", .type = ELF_T_ADDR, .format = 'x', \ -+ .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + ((BITS/8) * (BITS == 32 ? 40 : 34)), \ -+ .group = "register", \ -+ .pc_register = true \ -+ } -+ -+#if BITS == 32 -+# define ULONG uint32_t -+# define ALIGN_ULONG 4 -+# define TYPE_ULONG ELF_T_WORD -+#define TYPE_LONG ELF_T_SWORD -+#else -+#define ULONG uint64_t -+#define ALIGN_ULONG 8 -+#define TYPE_ULONG ELF_T_XWORD -+#define TYPE_LONG ELF_T_SXWORD -+#endif -+#define PID_T int32_t -+#define UID_T uint32_t -+#define GID_T uint32_t -+#define ALIGN_PID_T 4 -+#define ALIGN_UID_T 4 -+#define ALIGN_GID_T 4 -+#define TYPE_PID_T ELF_T_SWORD -+#define TYPE_UID_T ELF_T_WORD -+#define TYPE_GID_T ELF_T_WORD -+ -+#include "linux-core-note.c" ---- a/backends/mips_init.c -+++ b/backends/mips_init.c -@@ -61,6 +61,9 @@ mips_init (Elf *elf __attribute__ ((unus - HOOK (eh, set_initial_registers_tid); - HOOK (eh, abi_cfi); - HOOK (eh, unwind); -+ HOOK (eh, register_info); -+ HOOK (eh, return_value_location); -+ HOOK (eh, core_note); - eh->frame_nregs = 71; - return eh; - } ---- /dev/null -+++ b/backends/mips_regs.c -@@ -0,0 +1,135 @@ -+/* Register names and numbers for mips DWARF. -+ Copyright (C) 2006 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+#include -+ssize_t -+mips_register_info (Ebl *ebl __attribute__ ((unused)), -+ int regno, char *name, size_t namelen, -+ const char **prefix, const char **setname, -+ int *bits, int *type) -+{ -+ if (name == NULL) -+ return 72; -+ -+ if (regno < 0 || regno > 71 || namelen < 4) -+ return -1; -+ -+ *prefix = "$"; -+ if (regno < 38) -+ { -+ *setname = "integer"; -+ *type = DW_ATE_signed; -+ *bits = 32; -+ } -+ else -+ { -+ *setname = "FPU"; -+ *type = DW_ATE_float; -+ *bits = 64; -+ } -+ -+ if (regno < 32) -+ { -+ if (regno < 10) -+ { -+ name[0] = regno + '0'; -+ namelen = 1; -+ } -+ else -+ { -+ name[0] = (regno / 10) + '0'; -+ name[1] = (regno % 10) + '0'; -+ namelen = 2; -+ } -+ if (regno == 28 || regno == 29 || regno == 31) -+ *type = DW_ATE_address; -+ } -+ else if (regno == 32) -+ { -+ return stpcpy (name, "lo") + 1 - name; -+ } -+ else if (regno == 33) -+ { -+ return stpcpy (name, "hi") + 1 - name; -+ } -+ else if (regno == 34) -+ { -+ return stpcpy (name, "pc") + 1 - name; -+ } -+ else if (regno == 35) -+ { -+ *type = DW_ATE_address; -+ return stpcpy (name, "bad") + 1 - name; -+ } -+ else if (regno == 36) -+ { -+ return stpcpy (name, "sr") + 1 - name; -+ } -+ else if (regno == 37) -+ { -+ *type = DW_ATE_address; -+ return stpcpy (name, "cause") + 1 - name; -+ } -+ else if (regno < 70) -+ { -+ name[0] = 'f'; -+ if (regno < 38 + 10) -+ { -+ name[1] = (regno - 38) + '0'; -+ namelen = 2; -+ } -+ else -+ { -+ name[1] = (regno - 38) / 10 + '0'; -+ name[2] = (regno - 38) % 10 + '0'; -+ namelen = 3; -+ } -+ } -+ else if (regno == 70) -+ { -+ return stpcpy (name, "fsr") + 1 - name; -+ } -+ else if (regno == 71) -+ { -+ return stpcpy (name, "fir") + 1 - name; -+ } -+ -+ name[namelen++] = '\0'; -+ return namelen; -+} ---- /dev/null -+++ b/backends/mips_retval.c -@@ -0,0 +1,196 @@ -+/* Function return value location for Linux/mips ABI. -+ Copyright (C) 2005 Red Hat, Inc. -+ Copyright (C) 2024 CIP United Inc. -+ This file is part of elfutils. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define BACKEND mips_ -+#include "libebl_CPU.h" -+#include "libdwP.h" -+#include -+ -+/* $v0 or pair $v0, $v1 */ -+static const Dwarf_Op loc_intreg_o32[] = -+ { -+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 }, -+ }; -+ -+static const Dwarf_Op loc_intreg[] = -+ { -+ { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 8 }, -+ { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 8 }, -+ }; -+#define nloc_intreg 1 -+#define nloc_intregpair 4 -+ -+/* $f0 (float), or pair $f0, $f1 (double). -+ * f2/f3 are used for COMPLEX (= 2 doubles) returns in Fortran */ -+static const Dwarf_Op loc_fpreg_o32[] = -+ { -+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 }, -+ { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 }, -+ }; -+ -+/* $f0, or pair $f0, $f2. */ -+static const Dwarf_Op loc_fpreg[] = -+ { -+ { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 8 }, -+ { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 }, -+ }; -+#define nloc_fpreg 1 -+#define nloc_fpregpair 4 -+#define nloc_fpregquad 8 -+ -+/* The return value is a structure and is actually stored in stack space -+ passed in a hidden argument by the caller. But, the compiler -+ helpfully returns the address of that space in $v0. */ -+static const Dwarf_Op loc_aggregate[] = -+ { -+ { .atom = DW_OP_breg2, .number = 0 } -+ }; -+#define nloc_aggregate 1 -+ -+int -+mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) -+{ -+ unsigned int regsize = (gelf_getclass (functypedie->cu->dbg->elf) == ELFCLASS32 ) ? 4 : 8; -+ if (!regsize) -+ return -2; -+ -+ /* Start with the function's type, and get the DW_AT_type attribute, -+ which is the type of the return value. */ -+ -+ Dwarf_Attribute attr_mem; -+ Dwarf_Attribute *attr = dwarf_attr_integrate (functypedie, DW_AT_type, &attr_mem); -+ if (attr == NULL) -+ /* The function has no return value, like a `void' function in C. */ -+ return 0; -+ -+ Dwarf_Die die_mem; -+ Dwarf_Die *typedie = dwarf_formref_die (attr, &die_mem); -+ int tag = dwarf_tag (typedie); -+ -+ /* Follow typedefs and qualifiers to get to the actual type. */ -+ while (tag == DW_TAG_typedef -+ || tag == DW_TAG_const_type || tag == DW_TAG_volatile_type -+ || tag == DW_TAG_restrict_type) -+ { -+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); -+ typedie = dwarf_formref_die (attr, &die_mem); -+ tag = dwarf_tag (typedie); -+ } -+ -+ switch (tag) -+ { -+ case -1: -+ return -1; -+ -+ case DW_TAG_subrange_type: -+ if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size)) -+ { -+ attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem); -+ typedie = dwarf_formref_die (attr, &die_mem); -+ tag = dwarf_tag (typedie); -+ } -+ /* Fall through. */ -+ FALLTHROUGH; -+ -+ case DW_TAG_base_type: -+ case DW_TAG_enumeration_type: -+ CASE_POINTER: -+ { -+ Dwarf_Word size; -+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, -+ &attr_mem), &size) != 0) -+ { -+ if (dwarf_is_pointer (tag)) -+ size = regsize; -+ else -+ return -1; -+ } -+ if (tag == DW_TAG_base_type) -+ { -+ Dwarf_Word encoding; -+ if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, -+ &attr_mem), &encoding) != 0) -+ return -1; -+ -+#define ARCH_LOC(loc, regsize) ((regsize) == 4 ? (loc ## _o32) : (loc)) -+ -+ if (encoding == DW_ATE_float) -+ { -+ *locp = ARCH_LOC(loc_fpreg, regsize); -+ if (size <= regsize) -+ return nloc_fpreg; -+ -+ if (size <= 2*regsize) -+ return nloc_fpregpair; -+ -+ if (size <= 4*regsize) -+ return nloc_fpregquad; -+ -+ goto aggregate; -+ } -+ } -+ *locp = ARCH_LOC(loc_intreg, regsize); -+ if (size <= regsize) -+ return nloc_intreg; -+ if (size <= 2*regsize) -+ return nloc_intregpair; -+ -+ /* Else fall through. Shouldn't happen though (at least with gcc) */ -+ } -+ FALLTHROUGH; -+ -+ case DW_TAG_structure_type: -+ case DW_TAG_class_type: -+ case DW_TAG_union_type: -+ case DW_TAG_array_type: -+ aggregate: -+ *locp = loc_aggregate; -+ return nloc_aggregate; -+ case DW_TAG_unspecified_type: -+ return 0; -+ } -+ -+ /* XXX We don't have a good way to return specific errors from ebl calls. -+ This value means we do not understand the type, but it is well-formed -+ DWARF and might be valid. */ -+ return -2; -+} diff --git a/tools/elfutils/patches/095-src-unused-variable.patch b/tools/elfutils/patches/095-src-unused-variable.patch deleted file mode 100644 index be5d285574..0000000000 --- a/tools/elfutils/patches/095-src-unused-variable.patch +++ /dev/null @@ -1,29 +0,0 @@ -From ef8a4b841aaf26326b8961a651dbe915d54d23e7 Mon Sep 17 00:00:00 2001 -From: Jose Quaresma -Date: Tue, 19 Mar 2024 10:34:33 +0000 -Subject: [PATCH] srcfiles: fix unused variable BUFFER_SIZE - -The const variable BUFFER_SIZE is used only on the zip_files -function witch is only available with LIBARCHIVE. - -| ../../elfutils-0.191/src/srcfiles.cxx:81:18: error: unused variable 'BUFFER_SIZE' [-Werror,-Wunused-const-variable] -| 81 | constexpr size_t BUFFER_SIZE = 8192; -| | ^~~~~~~~~~~ - -Signed-off-by: Jose Quaresma ---- - src/srcfiles.cxx | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/src/srcfiles.cxx -+++ b/src/srcfiles.cxx -@@ -78,7 +78,9 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_ve - /* Bug report address. */ - ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; - -+#ifdef HAVE_LIBARCHIVE - constexpr size_t BUFFER_SIZE = 8192; -+#endif - - /* Definitions of arguments for argp functions. */ - static const struct argp_option options[] = diff --git a/tools/elfutils/patches/096-lib-config_h.patch b/tools/elfutils/patches/096-lib-config_h.patch deleted file mode 100644 index cc31fcfff2..0000000000 --- a/tools/elfutils/patches/096-lib-config_h.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c981e61aa301d389f18df5fd279c1ca4d39d38a0 Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Thu, 10 Oct 2024 10:26:54 +0000 -Subject: [PATCH] lib: Add missing config.h include to next_prime.c - -This is the last remaining C source file as of this commit -without the standard conditional inclusion of config.h -as the very first header. - - * lib/next_prime.c: add missing config.h header. - -Signed-off-by: Michael Pratt ---- - lib/next_prime.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/lib/next_prime.c -+++ b/lib/next_prime.c -@@ -27,6 +27,10 @@ - the GNU Lesser General Public License along with this program. If - not, see . */ - -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ - #include - - diff --git a/tools/elfutils/patches/097-libcpu-config_h.patch b/tools/elfutils/patches/097-libcpu-config_h.patch deleted file mode 100644 index 7bcd858696..0000000000 --- a/tools/elfutils/patches/097-libcpu-config_h.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 7f06ac2b3fc0077f29bcc68064ca8e91fa7cd080 Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Thu, 10 Oct 2024 10:27:02 +0000 -Subject: [PATCH] libcpu: Include config.h before standard headers in lexer - source - -As part of the processing of flex, definitions and headers -are added to output source before any literal text or generated code. - -This causes standard headers to come before config.h -unless config.h is included in a %top block instead -as specified in the flex manual, section 5.1 "Format of the Definitions". - -The %top block is non-POSIX, so using it reinforces -the requirement of "flex" over a standardized "lex" even more. - - * libcpu/i386_lex.l (%top): add flex %top block - and move config.h header inclusion to it. - -Signed-off-by: Michael Pratt ---- - libcpu/i386_lex.l | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - ---- a/libcpu/i386_lex.l -+++ b/libcpu/i386_lex.l -@@ -1,3 +1,9 @@ -+%top{ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+} -+ - %{ - /* Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc. - Written by Ulrich Drepper , 2004. -@@ -26,10 +32,6 @@ - the GNU Lesser General Public License along with this program. If - not, see . */ - --#ifdef HAVE_CONFIG_H --# include --#endif -- - #include - - #include diff --git a/tools/elfutils/patches/098-libdw-maintainer-clean.patch b/tools/elfutils/patches/098-libdw-maintainer-clean.patch deleted file mode 100644 index f502af226f..0000000000 --- a/tools/elfutils/patches/098-libdw-maintainer-clean.patch +++ /dev/null @@ -1,43 +0,0 @@ -From b68f34725229b08380a1612899b0537f8f597dad Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Thu, 10 Oct 2024 10:27:09 +0000 -Subject: [PATCH] libdw: Let clean targets be unconditional - -The automake rule "maintainer-clean-generic" -is always available and never conditional, -so let the variable that uses it be define -non-conditionally. - -If one actually wants conditional cleaning -they should write a custom rule and set it -as a dependency of a "*clean-local" automake rule. - -There is no need to do conditional cleaning here, -so move the MAINTAINERCLEANFILES variable definition -to the end of the Makefile.am file as it is -in the rest of the project. - - * libdw/Makefile.am: move MAINTAINERCLEANFILES - variable to the end of the file - as a non-conditional definition. - -Signed-off-by: Michael Pratt ---- - libdw/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/libdw/Makefile.am -+++ b/libdw/Makefile.am -@@ -97,7 +97,6 @@ libdw_a_SOURCES = dwarf_begin.c dwarf_be - - if MAINTAINER_MODE - BUILT_SOURCES = $(srcdir)/known-dwarf.h --MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h - $(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h - gawk -f $^ > $@.new - mv -f $@.new $@ -@@ -154,3 +153,4 @@ noinst_HEADERS = libdwP.h memory-access. - EXTRA_DIST = libdw.map - - MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so libdw.so.$(VERSION) -+MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h diff --git a/tools/elfutils/patches/099-remove-unlocked-stdio.patch b/tools/elfutils/patches/099-remove-unlocked-stdio.patch deleted file mode 100644 index a0089a3a4c..0000000000 --- a/tools/elfutils/patches/099-remove-unlocked-stdio.patch +++ /dev/null @@ -1,687 +0,0 @@ -From 12d58cf3e30dee91ed7aadb6475a15c6e74cc88b Mon Sep 17 00:00:00 2001 -From: Michael Pratt -Date: Wed, 16 Oct 2024 19:53:52 +0000 -Subject: [PATCH] Remove usage of "unlocked" variant of stdio print functions - -These "unlocked" Linux Standard Base variants of standard functions -are not available on some systems that are still capable -of building Linux and ELFs. - -The difference is negligible for simple printing to stdout. - -POSIX also states for the similar putc_unlocked(): - - These functions can safely be used in a multi-threaded program - if and only if they are called while the invoking thread owns - the (FILE *) object, as is the case after a successful call - to the flockfile() or ftrylockfile() functions. - -... - - These unlocked versions can be safely used - only within explicitly locked program regions, - using exported locking primitives. - -and these precautions were never done. - -Use the standard forms of these print functions. - -There is inconsistent use of fputc_unlocked() with putc_unlocked(), -so consistently use the safer fputc() instead. - -Signed-off-by: Michael Pratt ---- - libasm/asm_align.c | 4 +- - libcpu/i386_parse.y | 4 +- - libebl/eblobjnote.c | 4 +- - src/nm.c | 20 +++++----- - src/objdump.c | 24 ++++++------ - src/readelf.c | 90 ++++++++++++++++++++++----------------------- - src/size.c | 8 ++-- - src/strings.c | 20 +++++----- - tests/showptable.c | 8 ++-- - 9 files changed, 91 insertions(+), 91 deletions(-) - ---- a/libasm/asm_align.c -+++ b/libasm/asm_align.c -@@ -60,13 +60,13 @@ asm_align (AsmScn_t *asmscn, GElf_Word v - fprintf (asmscn->ctx->out.file, "%02hhx\n", asmscn->pattern->bytes[0]); - else - { -- fputc_unlocked ('"', asmscn->ctx->out.file); -+ fputc ('"', asmscn->ctx->out.file); - - for (size_t cnt = 0; cnt < asmscn->pattern->len; ++cnt) - fprintf (asmscn->ctx->out.file, "\\x%02hhx", - asmscn->pattern->bytes[cnt]); - -- fputs_unlocked ("\"\n", asmscn->ctx->out.file); -+ fputs ("\"\n", asmscn->ctx->out.file); - } - return 0; - } ---- a/libcpu/i386_parse.y -+++ b/libcpu/i386_parse.y -@@ -1158,7 +1158,7 @@ instrtable_out (void) - EMIT_SUFFIX (w1); - EMIT_SUFFIX (W1); - -- fputc_unlocked ('\n', outfile); -+ fputc ('\n', outfile); - - for (int i = 0; i < 3; ++i) - { -@@ -1333,7 +1333,7 @@ instrtable_out (void) - b = b->next; - } - -- fputc_unlocked ('\n', outfile); -+ fputc ('\n', outfile); - } - fputs ("};\n", outfile); - } ---- a/libebl/eblobjnote.c -+++ b/libebl/eblobjnote.c -@@ -643,10 +643,10 @@ ebl_object_note (Ebl *ebl, uint32_t name - for (size_t cnt = 1; cnt < descsz / 4; ++cnt) - { - if (cnt > 1) -- putchar_unlocked ('.'); -+ putchar ('.'); - printf ("%" PRIu32, buf[cnt]); - } -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - if (descsz / 4 > FIXED_TAG_BYTES) - free (buf); ---- a/src/nm.c -+++ b/src/nm.c -@@ -439,7 +439,7 @@ handle_ar (int fd, Elf *elf, const char - Elf_Arhdr *arhdr = NULL; - size_t arhdr_off = 0; /* Note: 0 is no valid offset. */ - -- fputs_unlocked (_("\nArchive index:\n"), stdout); -+ fputs (_("\nArchive index:\n"), stdout); - - while (arsym->as_off != 0) - { -@@ -825,8 +825,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word s - /* If we have to precede the line with the file name. */ - if (print_file_name) - { -- fputs_unlocked (fullname, stdout); -- putchar_unlocked (':'); -+ fputs (fullname, stdout); -+ putchar (':'); - } - - /* Convert the address. */ -@@ -972,8 +972,8 @@ show_symbols_bsd (Elf *elf, const GElf_E - /* If we have to precede the line with the file name. */ - if (print_file_name) - { -- fputs_unlocked (fullname, stdout); -- putchar_unlocked (':'); -+ fputs (fullname, stdout); -+ putchar (':'); - } - - bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS; -@@ -1046,8 +1046,8 @@ show_symbols_bsd (Elf *elf, const GElf_E - } - - if (color_mode) -- fputs_unlocked (color_off, stdout); -- putchar_unlocked ('\n'); -+ fputs (color_off, stdout); -+ putchar ('\n'); - } - - #ifdef USE_DEMANGLE -@@ -1104,9 +1104,9 @@ show_symbols_posix (Elf *elf, const GElf - /* If we have to precede the line with the file name. */ - if (print_file_name) - { -- fputs_unlocked (fullname, stdout); -- putchar_unlocked (':'); -- putchar_unlocked (' '); -+ fputs (fullname, stdout); -+ putchar (':'); -+ putchar (' '); - } - - printf ("%s %c%s", symstr, ---- a/src/objdump.c -+++ b/src/objdump.c -@@ -580,12 +580,12 @@ show_full_content (Ebl *ebl, const char - printf ("%02hhx%02hhx%02hhx%02hhx ", - cp[inner], cp[inner + 1], cp[inner + 2], - cp[inner + 3]); -- fputc_unlocked (' ', stdout); -+ fputc (' ', stdout); - - for (size_t inner = 0; inner < 16; ++inner) -- fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) -+ fputc (isascii (cp[inner]) && isprint (cp[inner]) - ? cp[inner] : '.', stdout); -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - } - - printf (" %04zx ", cnt); -@@ -601,14 +601,14 @@ show_full_content (Ebl *ebl, const char - - for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0; - --inner) -- fputc_unlocked (' ', stdout); -+ fputc (' ', stdout); - - for (inner = 0; inner < remaining; ++inner) -- fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner]) -+ fputc (isascii (cp[inner]) && isprint (cp[inner]) - ? cp[inner] : '.', stdout); -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - } - } - -@@ -640,12 +640,12 @@ disasm_output (char *buf, size_t buflen, - printf ("%8" PRIx64 ": ", (uint64_t) info->addr); - - if (info->bytes_color != NULL) -- fputs_unlocked (info->bytes_color, stdout); -+ fputs (info->bytes_color, stdout); - size_t cnt; - for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt) - printf (" %02" PRIx8, info->last_end[cnt]); - if (info->bytes_color != NULL) -- fputs_unlocked (color_off, stdout); -+ fputs (color_off, stdout); - - printf ("%*s %.*s\n", - (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf); -@@ -663,12 +663,12 @@ disasm_output (char *buf, size_t buflen, - printf ("%8" PRIx64 ": ", (uint64_t) info->addr); - - if (info->bytes_color != NULL) -- fputs_unlocked (info->bytes_color, stdout); -+ fputs (info->bytes_color, stdout); - for (; cnt < (size_t) (info->cur - info->last_end); ++cnt) - printf (" %02" PRIx8, info->last_end[cnt]); - if (info->bytes_color != NULL) -- fputs_unlocked (color_off, stdout); -- putchar_unlocked ('\n'); -+ fputs (color_off, stdout); -+ putchar ('\n'); - info->addr += info->cur - info->last_end - 8; - } - ---- a/src/readelf.c -+++ b/src/readelf.c -@@ -1127,7 +1127,7 @@ print_file_type (unsigned short int e_ty - static void - print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) - { -- fputs_unlocked (_("ELF Header:\n Magic: "), stdout); -+ fputs (_("ELF Header:\n Magic: "), stdout); - for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt) - printf (" %02hhx", ehdr->e_ident[cnt]); - -@@ -1154,7 +1154,7 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) - printf (_(" ABI Version: %hhd\n"), - ehdr->e_ident[EI_ABIVERSION]); - -- fputs_unlocked (_(" Type: "), stdout); -+ fputs (_(" Type: "), stdout); - print_file_type (ehdr->e_type); - - const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine); -@@ -1196,9 +1196,9 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) - printf (_(" (%" PRIu32 " in [0].sh_info)"), - (uint32_t) shdr->sh_info); - else -- fputs_unlocked (_(" ([0] not available)"), stdout); -+ fputs (_(" ([0] not available)"), stdout); - } -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - - printf (_(" Size of section header entries: %" PRId16 " %s\n"), - ehdr->e_shentsize, _("(bytes)")); -@@ -1213,9 +1213,9 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr) - printf (_(" (%" PRIu32 " in [0].sh_size)"), - (uint32_t) shdr->sh_size); - else -- fputs_unlocked (_(" ([0] not available)"), stdout); -+ fputs (_(" ([0] not available)"), stdout); - } -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - - if (unlikely (ehdr->e_shstrndx == SHN_XINDEX)) - { -@@ -1406,7 +1406,7 @@ There are %zd section headers, starting - } - } - -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - } - - -@@ -1552,22 +1552,22 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) - && shdr->sh_addr >= relro_from - && shdr->sh_addr + shdr->sh_size <= relro_to) - { -- fputs_unlocked (" [RELRO:", stdout); -+ fputs (" [RELRO:", stdout); - in_relro = true; - } - else if (has_relro && in_relro && shdr->sh_addr >= relro_to) - { -- fputs_unlocked ("]", stdout); -+ fputs ("]", stdout); - in_relro = false; - } - else if (has_relro && in_relro - && shdr->sh_addr + shdr->sh_size > relro_to) -- fputs_unlocked ("] p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0) - { - if (!in_ro) - { -- fputs_unlocked (" [RO:", stdout); -+ fputs (" [RO:", stdout); - in_ro = true; - } - } -@@ -1592,12 +1592,12 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) - { - if ((phdr2->p_flags & PF_W) == 0 && !in_ro) - { -- fputs_unlocked (" [RO:", stdout); -+ fputs (" [RO:", stdout); - in_ro = true; - } - else if ((phdr2->p_flags & PF_W) != 0 && in_ro) - { -- fputs_unlocked ("]", stdout); -+ fputs ("]", stdout); - in_ro = false; - } - } -@@ -1610,16 +1610,16 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) - if (has_relro && in_relro - && shdr->sh_addr + shdr->sh_size > relro_to) - { -- fputs_unlocked (">", stdout); -+ fputs (">", stdout); - in_relro = false; - } - } - } - if (in_relro || in_ro) -- fputs_unlocked ("]", stdout); -+ fputs ("]", stdout); - - /* Finish the line. */ -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - } - } - -@@ -1788,8 +1788,8 @@ print_flags (int class, GElf_Xword d_val - if (d_val & flags[cnt].mask) - { - if (!first) -- putchar_unlocked (' '); -- fputs_unlocked (flags[cnt].str, stdout); -+ putchar (' '); -+ fputs (flags[cnt].str, stdout); - d_val &= ~flags[cnt].mask; - first = false; - } -@@ -1797,11 +1797,11 @@ print_flags (int class, GElf_Xword d_val - if (d_val != 0) - { - if (!first) -- putchar_unlocked (' '); -+ putchar (' '); - printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val); - } - -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - - -@@ -1909,7 +1909,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, - phdr->p_offset); - } - -- fputs_unlocked (_(" Type Value\n"), stdout); -+ fputs (_(" Type Value\n"), stdout); - - /* if --use-dynamic option is enabled, - use the string table to get the related library info. */ -@@ -1953,7 +1953,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, - case DT_BIND_NOW: - case DT_TEXTREL: - /* No further output. */ -- fputc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - break; - - case DT_NEEDED: -@@ -2147,7 +2147,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr * - elf_strptr (ebl->elf, shstrndx, shdr->sh_name), - shdr->sh_offset, - nentries); -- fputs_unlocked (class == ELFCLASS32 -+ fputs (class == ELFCLASS32 - ? _("\ - Offset Type Value Name\n") - : _("\ -@@ -2384,7 +2384,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr - elf_strptr (ebl->elf, shstrndx, shdr->sh_name), - shdr->sh_offset, - nentries); -- fputs_unlocked (class == ELFCLASS32 -+ fputs (class == ELFCLASS32 - ? _("\ - Offset Type Value Addend Name\n") - : _("\ -@@ -2891,7 +2891,7 @@ process_symtab (Ebl *ebl, unsigned int n - } - } - -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - } - -@@ -2973,7 +2973,7 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, G - (unsigned int) shdr->sh_link, - elf_strptr (ebl->elf, shstrndx, glink->sh_name)); - -- fputs_unlocked (class == ELFCLASS32 -+ fputs (class == ELFCLASS32 - ? _("\ - Num: Value Size Type Bind Vis Ndx Name\n") - : _("\ -@@ -3649,12 +3649,12 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, G - { - ssize_t n; - case 0: -- fputs_unlocked (_(" 0 *local* "), -+ fputs (_(" 0 *local* "), - stdout); - break; - - case 1: -- fputs_unlocked (_(" 1 *global* "), -+ fputs (_(" 1 *global* "), - stdout); - break; - -@@ -3671,7 +3671,7 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, G - break; - } - } -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - - -@@ -3718,7 +3718,7 @@ print_hash_info (Ebl *ebl, Elf_Scn *scn, - uint64_t success = 0; - - /* xgettext:no-c-format */ -- fputs_unlocked (_("\ -+ fputs (_("\ - Length Number % of total Coverage\n"), stdout); - printf (_(" 0 %6" PRIu32 " %5.1f%%\n"), - counts[0], (counts[0] * 100.0) / nbucket); -@@ -4140,7 +4140,7 @@ print_attributes (Ebl *ebl, const GElf_E - if (unlikely (*p++ != 'A')) - return; - -- fputs_unlocked (_(" Owner Size\n"), stdout); -+ fputs (_(" Owner Size\n"), stdout); - - /* Loop over the sections. */ - while (left (data, p) >= 4) -@@ -7233,7 +7233,7 @@ print_encoding_base (const char *pfx, un - if (w & 0x70) - { - if (w != fde_encoding) -- fputc_unlocked (' ', stdout); -+ fputc (' ', stdout); - - w = print_relinfo (w); - } -@@ -9772,7 +9772,7 @@ print_debug_line_section (Dwfl_Module *d - { - get_uleb128 (u128, linep, lineendp); - if (n != standard_opcode_lengths[opcode]) -- putc_unlocked (',', stdout); -+ fputc (',', stdout); - printf (" %u", u128); - } - -@@ -10525,7 +10525,7 @@ print_debug_macinfo_section (Dwfl_Module - \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), section_name (ebl, shdr), - (uint64_t) shdr->sh_offset); -- putc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - - /* There is no function in libdw to iterate over the raw content of - the section but it is easy enough to do. */ -@@ -10687,7 +10687,7 @@ print_debug_macro_section (Dwfl_Module * - \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), - elf_ndxscn (scn), section_name (ebl, shdr), - (uint64_t) shdr->sh_offset); -- putc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - - /* Get the source file information for all CUs. Uses same - datastructure as macinfo. But uses offset field to directly -@@ -10840,15 +10840,15 @@ print_debug_macro_section (Dwfl_Module * - goto invalid_data; - args--; - if (args > 0) -- putchar_unlocked (','); -+ putchar (','); - } - } - else - printf (_(" no arguments.")); -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - } -- putchar_unlocked ('\n'); -+ putchar ('\n'); - - int level = 1; - if (readp + 1 > readendp) -@@ -11025,14 +11025,14 @@ print_debug_macro_section (Dwfl_Module * - if (args > 0) - printf (", "); - } -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - - if (readp + 1 > readendp) - goto invalid_data; - opcode = *readp++; - if (opcode == 0) -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - } - } -@@ -11368,7 +11368,7 @@ print_debug_frame_hdr_section (Dwfl_Modu - /* +4 because of the 4 byte header of the section. */ - (uint64_t) shdr->sh_offset + 4 + eh_frame_ptr); - -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - - uint64_t fde_count = 0; -@@ -11546,7 +11546,7 @@ print_debug_exception_table (Dwfl_Module - else if (ar_disp != 0) - puts (" -> ???"); - else -- putchar_unlocked ('\n'); -+ putchar ('\n'); - ++u; - } - while (readp < action_table_end); -@@ -13200,19 +13200,19 @@ handle_core_note (Ebl *ebl, const GElf_N - nregloc == 0 ? nhdr->n_descsz : 0, - items, nitems); - if (colno != 0) -- putchar_unlocked ('\n'); -+ putchar ('\n'); - - colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset, - reglocs, nregloc); - if (colno != 0) -- putchar_unlocked ('\n'); -+ putchar ('\n'); - } - - static void - handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr, - GElf_Off start, Elf_Data *data) - { -- fputs_unlocked (_(" Owner Data size Type\n"), stdout); -+ fputs (_(" Owner Data size Type\n"), stdout); - - if (data == NULL) - goto bad_note; ---- a/src/size.c -+++ b/src/size.c -@@ -411,7 +411,7 @@ show_sysv (Elf *elf, const char *prefix, - maxlen = MAX (maxlen, (int) strlen (name)); - } - -- fputs_unlocked (fname, stdout); -+ fputs (fname, stdout); - if (prefix != NULL) - printf (_(" (ex %s)"), prefix); - printf (":\n%-*s %*s %*s\n", -@@ -483,7 +483,7 @@ show_sysv_one_line (Elf *elf) - continue; - - if (! first) -- fputs_unlocked (" + ", stdout); -+ fputs (" + ", stdout); - first = false; - - printf ((radix == radix_hex ? "%" PRIx64 "(%s)" -@@ -555,7 +555,7 @@ show_bsd (Elf *elf, const char *prefix, - fname); - if (prefix != NULL) - printf (_(" (ex %s)"), prefix); -- fputs_unlocked ("\n", stdout); -+ fputs ("\n", stdout); - - total_textsize += textsize; - total_datasize += datasize; -@@ -607,7 +607,7 @@ show_segments (Elf *elf, const char *ful - continue; - - if (! first) -- fputs_unlocked (" + ", stdout); -+ fputs (" + ", stdout); - first = false; - - printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)" ---- a/src/strings.c -+++ b/src/strings.c -@@ -345,8 +345,8 @@ process_chunk_mb (const char *fname, con - /* We found a match. */ - if (unlikely (fname != NULL)) - { -- fputs_unlocked (fname, stdout); -- fputs_unlocked (": ", stdout); -+ fputs (fname, stdout); -+ fputs (": ", stdout); - } - - if (unlikely (radix != radix_none)) -@@ -357,7 +357,7 @@ process_chunk_mb (const char *fname, con - - if (unlikely (*unprinted != NULL)) - { -- fputs_unlocked (*unprinted, stdout); -+ fputs (*unprinted, stdout); - free (*unprinted); - *unprinted = NULL; - } -@@ -366,8 +366,8 @@ process_chunk_mb (const char *fname, con - assume the file data is encoded in UCS-2/UTF-16 or - UCS-4/UTF-32 respectively we could convert the string. - But there is no such guarantee. */ -- fwrite_unlocked (start, 1, buf - start, stdout); -- putc_unlocked ('\n', stdout); -+ fwrite (start, 1, buf - start, stdout); -+ fputc ('\n', stdout); - } - - start = ++buf; -@@ -413,8 +413,8 @@ process_chunk (const char *fname, const - /* We found a match. */ - if (likely (fname != NULL)) - { -- fputs_unlocked (fname, stdout); -- fputs_unlocked (": ", stdout); -+ fputs (fname, stdout); -+ fputs (": ", stdout); - } - - if (likely (radix != radix_none)) -@@ -425,12 +425,12 @@ process_chunk (const char *fname, const - - if (unlikely (*unprinted != NULL)) - { -- fputs_unlocked (*unprinted, stdout); -+ fputs (*unprinted, stdout); - free (*unprinted); - *unprinted = NULL; - } -- fwrite_unlocked (start, 1, buf - start, stdout); -- putc_unlocked ('\n', stdout); -+ fwrite (start, 1, buf - start, stdout); -+ fputc ('\n', stdout); - } - - start = ++buf; ---- a/tests/showptable.c -+++ b/tests/showptable.c -@@ -111,11 +111,11 @@ main (int argc, char *argv[]) - (unsigned long long int) phdr->p_memsz, - (unsigned long long int) phdr->p_align); - -- putc_unlocked ((phdr->p_flags & PF_X) ? 'X' : ' ', stdout); -- putc_unlocked ((phdr->p_flags & PF_W) ? 'W' : ' ', stdout); -- putc_unlocked ((phdr->p_flags & PF_R) ? 'R' : ' ', stdout); -+ fputc ((phdr->p_flags & PF_X) ? 'X' : ' ', stdout); -+ fputc ((phdr->p_flags & PF_W) ? 'W' : ' ', stdout); -+ fputc ((phdr->p_flags & PF_R) ? 'R' : ' ', stdout); - -- putc_unlocked ('\n', stdout); -+ fputc ('\n', stdout); - - if (phdr->p_type == PT_INTERP) - { diff --git a/tools/elfutils/patches/100-portability.patch b/tools/elfutils/patches/100-portability.patch index c2d14e575f..a82cd69ba2 100644 --- a/tools/elfutils/patches/100-portability.patch +++ b/tools/elfutils/patches/100-portability.patch @@ -23,7 +23,7 @@ # Only available since automake 1.12 m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_CHECK_TOOL([READELF], [readelf]) -@@ -635,6 +639,8 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([])], +@@ -646,6 +650,8 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([])], CFLAGS="$old_CFLAGS"]) AS_IF([test "x$ac_cv_fno_addrsig" = "xyes"], CFLAGS="$CFLAGS -fno-addrsig") @@ -34,9 +34,9 @@ LIBS="$saved_LIBS" --- a/lib/eu-config.h +++ b/lib/eu-config.h -@@ -59,14 +59,19 @@ - # define once(once_control, init_routine) init_routine() - #endif /* USE_LOCKS */ +@@ -31,14 +31,19 @@ + + #include "locks.h" -#include +#include @@ -55,7 +55,7 @@ #ifdef __i386__ # define internal_function __attribute__ ((regparm (3), stdcall)) -@@ -77,7 +82,7 @@ +@@ -49,7 +54,7 @@ #define internal_strong_alias(name, aliasname) \ extern __typeof (name) aliasname __attribute__ ((alias (#name))) internal_function; @@ -64,7 +64,7 @@ #define attribute_hidden \ __attribute__ ((visibility ("hidden"))) #else -@@ -166,7 +171,7 @@ asm (".section predict_data, \"aw\"; .pr +@@ -138,7 +143,7 @@ asm (".section predict_data, \"aw\"; .pr #endif /* Avoid PLT entries. */ @@ -203,7 +203,7 @@ +#include #include #include - + #include "eu-search.h" --- a/config/libdebuginfod.pc.in +++ b/config/libdebuginfod.pc.in @@ -8,5 +8,5 @@ Description: elfutils library to query d @@ -237,7 +237,7 @@ Requires.private: zlib @LIBZSTD@ --- a/libebl/eblopenbackend.c +++ b/libebl/eblopenbackend.c -@@ -200,8 +200,6 @@ static bool default_object_note (const c +@@ -202,8 +202,6 @@ static bool default_object_note (const c uint32_t descsz, const char *desc); static bool default_debugscn_p (const char *name); static bool default_copy_reloc_p (int reloc); @@ -246,7 +246,7 @@ static bool default_check_special_symbol (Elf *elf, const GElf_Sym *sym, const char *name, -@@ -253,8 +251,8 @@ fill_defaults (Ebl *result) +@@ -255,8 +253,8 @@ fill_defaults (Ebl *result) result->object_note = default_object_note; result->debugscn_p = default_debugscn_p; result->copy_reloc_p = default_copy_reloc_p; @@ -257,7 +257,7 @@ result->check_special_symbol = default_check_special_symbol; result->data_marker_symbol = default_data_marker_symbol; result->check_st_other_bits = default_check_st_other_bits; -@@ -636,8 +634,6 @@ default_copy_reloc_p (int reloc __attrib +@@ -638,8 +636,6 @@ default_copy_reloc_p (int reloc __attrib { return false; } diff --git a/tools/elfutils/patches/101-shared-conditional.patch b/tools/elfutils/patches/101-shared-conditional.patch index 800aa079a1..4eeee6a682 100644 --- a/tools/elfutils/patches/101-shared-conditional.patch +++ b/tools/elfutils/patches/101-shared-conditional.patch @@ -9,7 +9,7 @@ AC_CACHE_CHECK([whether gcc supports __attribute__((visibility()))], ac_cv_visibility, [dnl save_CFLAGS="$CFLAGS" -@@ -419,7 +421,10 @@ AS_HELP_STRING([--enable-install-elfh],[ +@@ -423,7 +425,10 @@ AS_HELP_STRING([--enable-install-elfh],[ AM_CONDITIONAL(INSTALL_ELFH, test "$install_elfh" = yes) AM_CONDITIONAL(BUILD_STATIC, [dnl @@ -132,7 +132,7 @@ libdebuginfod_a_SOURCES = debuginfod-client.c libdebuginfod_pic_a_SOURCES = debuginfod-client.c -@@ -111,12 +113,16 @@ $(LIBDEBUGINFOD_SONAME): $(srcdir)/libde +@@ -111,12 +113,17 @@ $(LIBDEBUGINFOD_SONAME): $(srcdir)/libde libdebuginfod.so: $(LIBDEBUGINFOD_SONAME) ln -fs $< $@ @@ -146,9 +146,10 @@ +else +libdebuginfod_a_LIBADD = $(foreach dep,$(wildcard $(libdebuginfod_so_LDLIBS:.so=.a)) $(LIBS:.so=.a),$(if $(findstring a,$(suffix $(dep))),$(addprefix $(dir $(dep)),$(shell cat $(basename $(dep)).manifest)),$(dep))) +endif - ++ uninstall: uninstall-am rm -f $(DESTDIR)$(libdir)/libdebuginfod-$(PACKAGE_VERSION).so + rm -f $(DESTDIR)$(libdir)/$(LIBDEBUGINFOD_SONAME) --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,7 @@ check_PROGRAMS = arextract arsymtest new @@ -158,9 +159,9 @@ - buildid deleted deleted-lib.so aggregate_size peel_type \ + buildid aggregate_size peel_type \ vdsosyms \ - getsrc_die strptr newdata elfstrtab dwfl-proc-attach \ - elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \ -@@ -180,7 +180,7 @@ TESTS = run-arextract.sh run-arsymtest.s + getsrc_die strptr newdata newzdata \ + elfstrtab dwfl-proc-attach \ +@@ -181,7 +181,7 @@ TESTS = run-arextract.sh run-arsymtest.s run-readelf-addr.sh run-readelf-str.sh \ run-readelf-multi-noline.sh \ run-readelf-types.sh \ @@ -168,10 +169,10 @@ + run-readelf-dwz-multi.sh run-allfcts-multi.sh \ run-linkmap-cut.sh run-aggregate-size.sh run-peel-type.sh \ vdsosyms run-readelf-A.sh \ - run-getsrc-die.sh run-strptr.sh newdata elfstrtab dwfl-proc-attach \ -@@ -284,6 +284,11 @@ funcretval_test__11_SOURCES = funcretval - TESTS += run-funcretval++11.sh - endif + run-getsrc-die.sh run-strptr.sh newdata newzdata \ +@@ -298,6 +298,11 @@ check_PROGRAMS += funcretval_test_struct + funcretval_test_struct_SOURCES = funcretval_test_struct.c + TESTS += run-funcretval-struct-native.sh +if BUILD_SHARED +check_PROGRAMS += deleted deleted-lib.so diff --git a/tools/elfutils/patches/110-objects-manifest.patch b/tools/elfutils/patches/110-objects-manifest.patch index 983331dfa7..35ef131190 100644 --- a/tools/elfutils/patches/110-objects-manifest.patch +++ b/tools/elfutils/patches/110-objects-manifest.patch @@ -39,7 +39,7 @@ MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h --- a/libdwfl/Makefile.am +++ b/libdwfl/Makefile.am -@@ -93,4 +93,10 @@ am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_S +@@ -94,4 +94,10 @@ am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_S noinst_HEADERS = libdwflP.h @@ -78,7 +78,7 @@ +MOSTLYCLEANFILES = $(am_libebl_pic_a_OBJECTS) $(EXTRA_libebl_a_DEPENDENCIES) --- a/backends/Makefile.am +++ b/backends/Makefile.am -@@ -119,4 +119,9 @@ am_libebl_backends_pic_a_OBJECTS = $(lib +@@ -122,4 +122,9 @@ am_libebl_backends_pic_a_OBJECTS = $(lib noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c EXTRA_DIST = $(modules:=_reloc.def) @@ -119,9 +119,9 @@ CLEANFILES += $(am_libelf_pic_a_OBJECTS) libelf.so libelf.so.$(VERSION) --- a/lib/Makefile.am +++ b/lib/Makefile.am -@@ -41,3 +41,10 @@ noinst_HEADERS = fixedsizehash.h libeu.h - eu-config.h color.h printversion.h bpf.h \ - atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h +@@ -42,3 +42,10 @@ noinst_HEADERS = fixedsizehash.h libeu.h + atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h \ + eu-search.h locks.h EXTRA_DIST = dynamicsizehash.c dynamicsizehash_concurrent.c + +EXTRA_libeu_a_DEPENDENCIES = libeu.manifest From 0b4ebe5dd3f87bcc60d29706a4f500cd7607b21e Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 25 Sep 2024 04:28:41 -0400 Subject: [PATCH 35/51] tools/elfutils: enable parallel building There are multiple subdirectories for elfutils and more than one is not dependent on another, so enabling parallel building can save time if multiple cores are available. The change in build time for the package is as much as 20% when cores are not in use by other jobs. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/elfutils/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/elfutils/Makefile b/tools/elfutils/Makefile index ce711ac66c..294947df10 100644 --- a/tools/elfutils/Makefile +++ b/tools/elfutils/Makefile @@ -48,6 +48,8 @@ PKG_GNULIB_MODS = \ strchrnul \ tsearch +HOST_BUILD_PARALLEL:=1 + include $(INCLUDE_DIR)/host-build.mk export $(PKG_GNULIB_BASE)=$(HOST_BUILD_DIR)/$(PKG_GNULIB_BASE)/.libs/$(PKG_GNULIB_BASE).a From 92d10e2cdf8dca65d5851cb49126a2308f514e29 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 16 May 2025 18:37:01 -0400 Subject: [PATCH 36/51] nftables: remove usage of autoreconf The usage of automake is left over after the patch which required it was removed since the new configure option "--without-cli" was added to upstream. Remove the usage of autotools to save build time. Ref: 72e6e0b85 ("nftables: introduce experimental nftables") Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- package/network/utils/nftables/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/package/network/utils/nftables/Makefile b/package/network/utils/nftables/Makefile index f2f7e5f12f..86ab2b7ab9 100644 --- a/package/network/utils/nftables/Makefile +++ b/package/network/utils/nftables/Makefile @@ -17,7 +17,6 @@ PKG_MAINTAINER:= PKG_LICENSE:=GPL-2.0 PKG_LICENSE_FILES:=COPYING -PKG_FIXUP:=autoreconf PKG_INSTALL:=1 PKG_BUILD_FLAGS:=lto From d19f8bc199b821dc60f0c64f4b96f5cd470deffc Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 7 Jun 2025 00:48:20 -0400 Subject: [PATCH 37/51] tools/gnulib: update to branch stable-202501 Move to the June 2025 update of the first 2025 stable branch in order to better support updating gettext to the latest versions. More instances of blocking the defining of functions that use reallocarray() is needed for portability with macOS as more similar functions have been added. And one instance is removed as the function was removed. Refer to a previous commit to explain the need for this. Manually adjusted patch: - 150-portable-tdestroy.patch - 160-flag-reallocarray.patch - 200-force-disable-after-configure.patch Removed upstreamed patch: - 500-acl-function-name.patch All other patches are automatically refreshed. Ref: 5ade7ee60 ("tools/gnulib: add macros to skip reallocarray() functions") Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/gnulib/Makefile | 6 +- tools/gnulib/patches/000-bootstrap.patch | 2 +- .../gnulib/patches/010-autoconf-version.patch | 4 +- .../patches/150-portable-tdestroy.patch | 16 +-- .../patches/160-flag-reallocarray.patch | 122 +++++++++++++++--- .../200-force-disable-after-configure.patch | 9 +- .../patches/320-modules-fallocate-posix.patch | 10 +- .../patches/500-acl-function-name.patch | 120 ----------------- 8 files changed, 125 insertions(+), 164 deletions(-) delete mode 100644 tools/gnulib/patches/500-acl-function-name.patch diff --git a/tools/gnulib/Makefile b/tools/gnulib/Makefile index 33e6aba1cc..1237fad46e 100644 --- a/tools/gnulib/Makefile +++ b/tools/gnulib/Makefile @@ -4,9 +4,9 @@ PKG_NAME:=gnulib PKG_CPE_ID:=cpe:/a:gnu:$(PKG_NAME) PKG_SOURCE_URL=git://git.git.savannah.gnu.org/$(PKG_NAME).git -PKG_SOURCE_DATE:=2025-05-03 -PKG_SOURCE_VERSION:=320db6ee7a3cd44ee77f09d30c8a9002159beb4b# # stable-202407 -PKG_MIRROR_HASH:=0c3d39a0d26381b042ac8e95d22b88bda99bc8cc3974b151b1de184c0f4ac1bf +PKG_SOURCE_DATE:=2025-07-01 +PKG_SOURCE_VERSION:=a3151d456d6919c9066b54dc6f680452168165cf# # stable-202501 +PKG_MIRROR_HASH:=b695d96e915ecd6c4551436f417cb2c0879aef4ef6318721c8d5cc86cb44ba9d include $(INCLUDE_DIR)/host-build.mk diff --git a/tools/gnulib/patches/000-bootstrap.patch b/tools/gnulib/patches/000-bootstrap.patch index 30a62e9bdb..8d032ac080 100644 --- a/tools/gnulib/patches/000-bootstrap.patch +++ b/tools/gnulib/patches/000-bootstrap.patch @@ -43,7 +43,7 @@ if [ ! "$inst_ver" ]; then warn_ "Error: '$app' not found" ret=1 -@@ -1178,7 +1178,7 @@ autogen() +@@ -1205,7 +1205,7 @@ autogen() # two just-pre-run programs. # Import from gettext. diff --git a/tools/gnulib/patches/010-autoconf-version.patch b/tools/gnulib/patches/010-autoconf-version.patch index 7726cc47a1..ff0d795a61 100644 --- a/tools/gnulib/patches/010-autoconf-version.patch +++ b/tools/gnulib/patches/010-autoconf-version.patch @@ -1,6 +1,6 @@ --- a/gnulib-tool.sh +++ b/gnulib-tool.sh -@@ -343,6 +343,34 @@ Options for --import, --add/remove-impor +@@ -344,6 +344,34 @@ Options for --import, --add/remove-impor Report bugs to ." } @@ -35,7 +35,7 @@ # func_version # outputs to stdout the --version message. func_version () -@@ -1665,6 +1693,9 @@ func_determine_path_separator +@@ -1666,6 +1694,9 @@ func_determine_path_separator fi case "$autoconf_minversion" in 1.* | 2.[0-5]* | 2.6[0-3]*) diff --git a/tools/gnulib/patches/150-portable-tdestroy.patch b/tools/gnulib/patches/150-portable-tdestroy.patch index ae08d4c303..8cae7504c9 100644 --- a/tools/gnulib/patches/150-portable-tdestroy.patch +++ b/tools/gnulib/patches/150-portable-tdestroy.patch @@ -107,7 +107,7 @@ +#endif /* defined(_LIBC) || GNULIB_defined_tdestroy */ --- a/m4/search_h.m4 +++ b/m4/search_h.m4 -@@ -40,7 +40,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], +@@ -41,7 +41,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], dnl Check for declarations of anything we want to poison if the dnl corresponding gnulib module is not in use. gl_WARN_ON_USE_PREPARE([[#include @@ -116,7 +116,7 @@ AC_REQUIRE([AC_C_RESTRICT]) ]) -@@ -76,8 +76,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], +@@ -77,8 +77,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LFIND], [1]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LSEARCH], [1]) dnl Assume proper GNU behavior unless another module says otherwise. @@ -133,7 +133,7 @@ ]) --- a/m4/tsearch.m4 +++ b/m4/tsearch.m4 -@@ -10,6 +10,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], +@@ -11,6 +11,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], AC_REQUIRE([gl_SEARCH_H_DEFAULTS]) gl_CHECK_FUNCS_ANDROID([tsearch], [[#include ]]) gl_CHECK_FUNCS_ANDROID([twalk], [[#include ]]) @@ -141,7 +141,7 @@ if test $ac_cv_func_tsearch = yes; then dnl On OpenBSD 4.0, the return value of tdelete() is incorrect. AC_REQUIRE([AC_PROG_CC]) -@@ -51,6 +52,7 @@ main () +@@ -52,6 +53,7 @@ main () *no) REPLACE_TSEARCH=1 REPLACE_TWALK=1 @@ -149,7 +149,7 @@ ;; esac else -@@ -65,6 +67,12 @@ main () +@@ -66,6 +68,12 @@ main () future*) REPLACE_TWALK=1 ;; esac fi @@ -162,8 +162,8 @@ ]) # Prerequisites of lib/tsearch.c. ---- a/modules/search -+++ b/modules/search +--- a/modules/search-h ++++ b/modules/search-h @@ -37,8 +37,10 @@ search.h: search.in.h $(top_builddir)/co -e 's/@''GNULIB_MDA_LSEARCH''@/$(GNULIB_MDA_LSEARCH)/g' \ -e 's|@''HAVE_TSEARCH''@|$(HAVE_TSEARCH)|g' \ @@ -177,7 +177,7 @@ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ --- a/modules/tsearch +++ b/modules/tsearch -@@ -11,7 +11,12 @@ search +@@ -11,7 +11,12 @@ search-h configure.ac: gl_FUNC_TSEARCH gl_CONDITIONAL([GL_COND_OBJ_TSEARCH], diff --git a/tools/gnulib/patches/160-flag-reallocarray.patch b/tools/gnulib/patches/160-flag-reallocarray.patch index f758b86e70..7c88c0de37 100644 --- a/tools/gnulib/patches/160-flag-reallocarray.patch +++ b/tools/gnulib/patches/160-flag-reallocarray.patch @@ -1,6 +1,6 @@ --- a/lib/ialloc.h +++ b/lib/ialloc.h -@@ -106,6 +106,8 @@ icalloc (idx_t n, idx_t s) +@@ -91,6 +91,8 @@ icalloc (idx_t n, idx_t s) return calloc (n, s); } @@ -9,8 +9,8 @@ /* ireallocarray (ptr, num, size) is like reallocarray (ptr, num, size). It returns a non-NULL pointer to num * size bytes of memory. Upon failure, it returns NULL with errno set. */ -@@ -131,6 +133,8 @@ ireallocarray (void *p, idx_t n, idx_t s - return _gl_alloc_nomem (); +@@ -102,6 +104,8 @@ ireallocarray (void *p, idx_t n, idx_t s + : _gl_alloc_nomem ()); } +#endif /* GNULIB_REALLOCARRAY */ @@ -57,7 +57,24 @@ new size. The new array will contain at least N_INCR_MIN more --- a/lib/xalloc.h +++ b/lib/xalloc.h -@@ -129,6 +129,7 @@ char *xstrdup (char const *str) +@@ -81,10 +81,16 @@ void *xrealloc (void *p, size_t s) + _GL_ATTRIBUTE_ALLOC_SIZE ((2)); + void *xirealloc (void *p, idx_t s) + _GL_ATTRIBUTE_ALLOC_SIZE ((2)) _GL_ATTRIBUTE_RETURNS_NONNULL; ++ ++# if GNULIB_REALLOCARRAY ++ + void *xreallocarray (void *p, size_t n, size_t s) + _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3)); + void *xireallocarray (void *p, idx_t n, idx_t s) + _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3)) _GL_ATTRIBUTE_RETURNS_NONNULL; ++ ++# endif /* GNULIB_REALLOCARRAY */ ++ + void *x2realloc (void *p, size_t *ps) /* superseded by xpalloc */ + _GL_ATTRIBUTE_RETURNS_NONNULL; + void *x2nrealloc (void *p, size_t *pn, size_t s) /* superseded by xpalloc */ +@@ -129,6 +135,7 @@ char *xstrdup (char const *str) # define XCALLOC(n, t) \ ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) @@ -65,7 +82,7 @@ /* Allocate an array of N objects, each with S bytes of memory, dynamically, with error checking. S must be nonzero. */ -@@ -156,6 +157,8 @@ char *xcharalloc (size_t n) +@@ -156,6 +163,8 @@ char *xcharalloc (size_t n) _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_ALLOC_SIZE ((1)) _GL_ATTRIBUTE_RETURNS_NONNULL; @@ -76,25 +93,15 @@ --- a/lib/safe-alloc.h +++ b/lib/safe-alloc.h -@@ -40,6 +40,7 @@ _GL_INLINE_HEADER_BEGIN +@@ -37,7 +37,6 @@ _GL_INLINE_HEADER_BEGIN extern "C" { #endif -+#if GNULIB_REALLOCARRAY - - /* Don't call these directly - use the macros below. */ - SAFE_ALLOC_INLINE void * -@@ -56,6 +57,9 @@ safe_alloc_realloc_n (void *ptr, size_t - #endif - return ptr; - } -+ -+#endif /* GNULIB_REALLOCARRAY */ -+ +- + /* Don't call this directly - use the macros below. */ _GL_ATTRIBUTE_NODISCARD SAFE_ALLOC_INLINE int safe_alloc_check (void *ptr) - { -@@ -89,6 +93,8 @@ safe_alloc_check (void *ptr) +@@ -72,6 +71,8 @@ safe_alloc_check (void *ptr) #define ALLOC_N(ptr, count) \ safe_alloc_check ((ptr) = calloc (count, sizeof *(ptr))) @@ -103,12 +110,85 @@ /** * ALLOC_N_UNINITIALIZED: * @ptr: pointer to allocated memory -@@ -117,6 +123,8 @@ safe_alloc_check (void *ptr) +@@ -100,6 +101,8 @@ safe_alloc_check (void *ptr) #define REALLOC_N(ptr, count) \ - safe_alloc_check ((ptr) = safe_alloc_realloc_n (ptr, count, sizeof *(ptr))) + safe_alloc_check ((ptr) = reallocarray (ptr, count, sizeof *(ptr))) +#endif /* GNULIB_REALLOCARRAY */ + /** * FREE: * @ptr: pointer holding address to be freed +--- a/lib/dfa.c ++++ b/lib/dfa.c +@@ -1620,6 +1620,8 @@ lex (struct dfa *dfa) + } + } + ++#if GNULIB_REALLOCARRAY ++ + static void + addtok_mb (struct dfa *dfa, token t, char mbprop) + { +@@ -1674,6 +1676,8 @@ addtok_mb (struct dfa *dfa, token t, cha + } + } + ++#endif /* GNULIB_REALLOCARRAY */ ++ + static void addtok_wc (struct dfa *dfa, wint_t wc); + + /* Add the given token to the parse tree, maintaining the depth count and +@@ -2934,6 +2938,8 @@ dfaanalyze (struct dfa *d, bool searchfl + free (tmp.elems); + } + ++#if GNULIB_REALLOCARRAY ++ + /* Make sure D's state arrays are large enough to hold NEW_STATE. */ + static void + realloc_trans_if_necessary (struct dfa *d) +@@ -2969,6 +2975,8 @@ realloc_trans_if_necessary (struct dfa * + } + } + ++#endif /* GNULIB_REALLOCARRAY */ ++ + /* + Calculate the transition table for a new state derived from state s + for a compiled dfa d after input character uc, and return the new +@@ -4010,6 +4018,8 @@ freelist (char **cpp) + free (*cpp++); + } + ++#if GNULIB_REALLOCARRAY ++ + static char ** + enlistnew (char **cpp, char *new) + { +@@ -4046,6 +4056,8 @@ enlist (char **cpp, char const *str, idx + return enlistnew (cpp, ximemdup0 (str, len)); + } + ++#endif /* GNULIB_REALLOCARRAY */ ++ + /* Given pointers to two strings, return a pointer to an allocated + list of their distinct common substrings. */ + static char ** +--- a/lib/readtokens.c ++++ b/lib/readtokens.c +@@ -128,6 +128,8 @@ readtoken (FILE *stream, + return i; + } + ++#if GNULIB_REALLOCARRAY ++ + /* Build a NULL-terminated array of pointers to tokens + read from STREAM. Return the number of tokens read. + All storage is obtained through calls to xmalloc-like functions. +@@ -190,3 +192,5 @@ readtokens (FILE *stream, + free (lengths); + return n_tokens; + } ++ ++#endif /* GNULIB_REALLOCARRAY */ diff --git a/tools/gnulib/patches/200-force-disable-after-configure.patch b/tools/gnulib/patches/200-force-disable-after-configure.patch index 34ca77610a..082820a344 100644 --- a/tools/gnulib/patches/200-force-disable-after-configure.patch +++ b/tools/gnulib/patches/200-force-disable-after-configure.patch @@ -20,8 +20,8 @@ { --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h -@@ -1508,10 +1508,16 @@ _GL_FUNCDECL_RPL (reallocarray, void *, - (void *ptr, size_t nmemb, size_t size)); +@@ -1549,11 +1549,17 @@ _GL_FUNCDECL_RPL (reallocarray, void *, + _GL_ATTRIBUTE_NODISCARD); _GL_CXXALIAS_RPL (reallocarray, void *, (void *ptr, size_t nmemb, size_t size)); +# if !GNULIB_defined_rpl_reallocarray @@ -30,7 +30,8 @@ # else # if ! @HAVE_REALLOCARRAY@ _GL_FUNCDECL_SYS (reallocarray, void *, - (void *ptr, size_t nmemb, size_t size)); + (void *ptr, size_t nmemb, size_t size), + _GL_ATTRIBUTE_NODISCARD); +# if !GNULIB_defined_reallocarray +# define GNULIB_defined_reallocarray 1 +# endif @@ -49,7 +50,7 @@ reallocarray (void *ptr, size_t nmemb, size_t size) { @@ -36,3 +38,5 @@ reallocarray (void *ptr, size_t nmemb, s - /* Rely on the semantics of GNU realloc. */ + /* Call realloc, setting errno to ENOMEM on failure. */ return realloc (ptr, nbytes); } + diff --git a/tools/gnulib/patches/320-modules-fallocate-posix.patch b/tools/gnulib/patches/320-modules-fallocate-posix.patch index d6f614eaa7..4cfd5bdcd6 100644 --- a/tools/gnulib/patches/320-modules-fallocate-posix.patch +++ b/tools/gnulib/patches/320-modules-fallocate-posix.patch @@ -69,7 +69,7 @@ +AC_DEFUN([gl_PREREQ_POSIX_FALLOCATE], [:]) --- a/m4/fcntl_h.m4 +++ b/m4/fcntl_h.m4 -@@ -25,7 +25,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H], +@@ -26,7 +26,7 @@ AC_DEFUN_ONCE([gl_FCNTL_H], dnl corresponding gnulib module is not in use, if it is not common dnl enough to be declared everywhere. gl_WARN_ON_USE_PREPARE([[#include @@ -78,7 +78,7 @@ ]) # gl_FCNTL_MODULE_INDICATOR([modulename]) -@@ -52,6 +52,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], +@@ -53,6 +53,7 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_NONBLOCKING]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPEN]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OPENAT]) @@ -86,7 +86,7 @@ dnl Support Microsoft deprecated alias function names by default. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_CREAT], [1]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_OPEN], [1]) -@@ -63,10 +64,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], +@@ -64,10 +65,12 @@ AC_DEFUN([gl_FCNTL_H_REQUIRE_DEFAULTS], AC_DEFUN([gl_FCNTL_H_DEFAULTS], [ dnl Assume proper GNU behavior unless another module says otherwise. @@ -127,7 +127,7 @@ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ --- a/lib/fcntl.in.h +++ b/lib/fcntl.in.h -@@ -239,6 +239,33 @@ _GL_WARN_ON_USE (openat, "openat is not +@@ -241,6 +241,33 @@ _GL_WARN_ON_USE (openat, "openat is not # endif #endif @@ -316,7 +316,7 @@ +} --- a/MODULES.html.sh +++ b/MODULES.html.sh -@@ -2552,6 +2552,7 @@ func_all_modules () +@@ -2555,6 +2555,7 @@ func_all_modules () func_module execve func_module execvp func_module execvpe diff --git a/tools/gnulib/patches/500-acl-function-name.patch b/tools/gnulib/patches/500-acl-function-name.patch deleted file mode 100644 index 372a80d10d..0000000000 --- a/tools/gnulib/patches/500-acl-function-name.patch +++ /dev/null @@ -1,120 +0,0 @@ -From 8a71833114c376212ecdd56495604905f6aa218d Mon Sep 17 00:00:00 2001 -From: Bruno Haible -Date: Sat, 24 Aug 2024 17:58:48 +0200 -Subject: acl: First step towards more consistent function names. - -* lib/acl.h (xset_acl): New declaration. -(set_acl): Mark deprecated. -(xcopy_acl): New declaration. -(copy_acl): Mark deprecated. -* lib/set-acl.c (xset_acl): Renamed from set_acl. -(set_acl): New function. -* lib/copy-acl.c (xcopy_acl): Renamed from copy_acl. -(copy_acl): New function. -* tests/test-set-mode-acl.c (main): Test xset_acl instead of set_acl. -* tests/test-copy-acl.c (main): Test xcopy_acl instead of copy_acl. ---- - lib/acl.h | 14 +++++++++++--- - lib/copy-acl.c | 11 +++++++++-- - lib/set-acl.c | 8 +++++++- - tests/test-copy-acl.c | 2 +- - tests/test-set-mode-acl.c | 2 +- - ---- a/lib/acl.h -+++ b/lib/acl.h -@@ -20,7 +20,7 @@ - #ifndef _GL_ACL_H - #define _GL_ACL_H 1 - --/* This file uses _GL_ATTRIBUTE_CONST. */ -+/* This file uses _GL_ATTRIBUTE_CONST, _GL_ATTRIBUTE_DEPRECATED. */ - #if !_GL_CONFIG_H_INCLUDED - #error "Please include config.h first." - #endif -@@ -35,10 +35,18 @@ extern "C" { - - bool acl_errno_valid (int) _GL_ATTRIBUTE_CONST; - int file_has_acl (char const *, struct stat const *); -+ - int qset_acl (char const *, int, mode_t); --int set_acl (char const *, int, mode_t); -+int xset_acl (char const *, int, mode_t); -+/* Old name of xset_acl. */ -+_GL_ATTRIBUTE_DEPRECATED int set_acl (char const *, int, mode_t); -+ - int qcopy_acl (char const *, int, char const *, int, mode_t); --int copy_acl (char const *, int, char const *, int, mode_t); -+int xcopy_acl (char const *, int, char const *, int, mode_t); -+/* Old name of xcopy_acl. */ -+_GL_ATTRIBUTE_DEPRECATED int copy_acl (char const *, int, char const *, int, -+ mode_t); -+ - int chmod_or_fchmod (char const *, int, mode_t); - - ---- a/lib/copy-acl.c -+++ b/lib/copy-acl.c -@@ -40,8 +40,8 @@ - negative error code. */ - - int --copy_acl (const char *src_name, int source_desc, const char *dst_name, -- int dest_desc, mode_t mode) -+xcopy_acl (const char *src_name, int source_desc, const char *dst_name, -+ int dest_desc, mode_t mode) - { - int ret = qcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); - switch (ret) -@@ -59,3 +59,10 @@ copy_acl (const char *src_name, int sour - } - return ret; - } -+ -+int -+copy_acl (const char *src_name, int source_desc, const char *dst_name, -+ int dest_desc, mode_t mode) -+{ -+ return xcopy_acl (src_name, source_desc, dst_name, dest_desc, mode); -+} ---- a/lib/set-acl.c -+++ b/lib/set-acl.c -@@ -39,10 +39,16 @@ - return -1. */ - - int --set_acl (char const *name, int desc, mode_t mode) -+xset_acl (char const *name, int desc, mode_t mode) - { - int ret = qset_acl (name, desc, mode); - if (ret != 0) - error (0, errno, _("setting permissions for %s"), quote (name)); - return ret; - } -+ -+int -+set_acl (char const *name, int desc, mode_t mode) -+{ -+ return xset_acl (name, desc, mode); -+} ---- a/tests/test-copy-acl.c -+++ b/tests/test-copy-acl.c -@@ -60,7 +60,7 @@ main (int argc, char *argv[]) - } - - #if USE_ACL -- if (copy_acl (file1, fd1, file2, fd2, mode)) -+ if (xcopy_acl (file1, fd1, file2, fd2, mode)) - exit (EXIT_FAILURE); - #else - chmod (file2, mode); ---- a/tests/test-set-mode-acl.c -+++ b/tests/test-set-mode-acl.c -@@ -35,7 +35,7 @@ main (int argc, char *argv[]) - file = argv[1]; - mode = strtol (argv[2], NULL, 8); - -- set_acl (file, -1, mode); -+ xset_acl (file, -1, mode); - - return test_exit_status; - } From 1a253a2bb5874f8ed33983216c098b474eda5bca Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 31 May 2025 02:47:11 -0400 Subject: [PATCH 38/51] tools/gnulib: backport patches for gettext The latest versions of gettext rely on several changes to gnulib including both changes to modules and new modules and some previously gettext specific code being moved to gnulib. Backport these changes in order to allow updating gettext while using the local gnulib copy of sources. Add patch: - 640-mem-hash-map.patch - 645-next-prime.patch - 646-hashcode-string.patch - 647-hashkey-string.patch - 650-package-version.patch - 651-package-version-simplify.patch - 652-package-version-simplify-further.patch - 653-package-version-warning.patch - 660-version-stamp.patch - 689-vc-mtime.patch - 755-clean-temp-hashkey.patch - 795-string-desc-rename-functions.patch - 796-vc-mtime-less-read.patch - 797-vc-mtime-add-api.patch - 798-vc-mtime-add-api.patch - 799-vc-mtime-old-git.patch - 900-str_startswith-module.patch - 901-str_endswith-module.patch Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/gnulib/patches/640-mem-hash-map.patch | 494 +++++++ tools/gnulib/patches/645-next-prime.patch | 218 ++++ .../gnulib/patches/646-hashcode-string.patch | 294 +++++ tools/gnulib/patches/647-hashkey-string.patch | 215 ++++ .../gnulib/patches/650-package-version.patch | 176 +++ .../651-package-version-simplify.patch | 66 + ...652-package-version-simplify-further.patch | 89 ++ .../patches/653-package-version-warning.patch | 32 + tools/gnulib/patches/660-version-stamp.patch | 75 ++ tools/gnulib/patches/689-vc-mtime.patch | 366 ++++++ .../patches/755-clean-temp-hashkey.patch | 64 + .../795-string-desc-rename-functions.patch | 1137 +++++++++++++++++ .../patches/796-vc-mtime-less-read.patch | 44 + .../gnulib/patches/797-vc-mtime-add-api.patch | 968 ++++++++++++++ .../gnulib/patches/798-vc-mtime-add-api.patch | 91 ++ .../gnulib/patches/799-vc-mtime-old-git.patch | 125 ++ .../patches/900-str_startswith-module.patch | 117 ++ .../patches/901-str_endswith-module.patch | 119 ++ 18 files changed, 4690 insertions(+) create mode 100644 tools/gnulib/patches/640-mem-hash-map.patch create mode 100644 tools/gnulib/patches/645-next-prime.patch create mode 100644 tools/gnulib/patches/646-hashcode-string.patch create mode 100644 tools/gnulib/patches/647-hashkey-string.patch create mode 100644 tools/gnulib/patches/650-package-version.patch create mode 100644 tools/gnulib/patches/651-package-version-simplify.patch create mode 100644 tools/gnulib/patches/652-package-version-simplify-further.patch create mode 100644 tools/gnulib/patches/653-package-version-warning.patch create mode 100644 tools/gnulib/patches/660-version-stamp.patch create mode 100644 tools/gnulib/patches/689-vc-mtime.patch create mode 100644 tools/gnulib/patches/755-clean-temp-hashkey.patch create mode 100644 tools/gnulib/patches/795-string-desc-rename-functions.patch create mode 100644 tools/gnulib/patches/796-vc-mtime-less-read.patch create mode 100644 tools/gnulib/patches/797-vc-mtime-add-api.patch create mode 100644 tools/gnulib/patches/798-vc-mtime-add-api.patch create mode 100644 tools/gnulib/patches/799-vc-mtime-old-git.patch create mode 100644 tools/gnulib/patches/900-str_startswith-module.patch create mode 100644 tools/gnulib/patches/901-str_endswith-module.patch diff --git a/tools/gnulib/patches/640-mem-hash-map.patch b/tools/gnulib/patches/640-mem-hash-map.patch new file mode 100644 index 0000000000..aaebe545fa --- /dev/null +++ b/tools/gnulib/patches/640-mem-hash-map.patch @@ -0,0 +1,494 @@ +From 5a842672e79a7a5f6be837c483be4f9901a4ecc0 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 30 Apr 2025 03:19:10 +0200 +Subject: [PATCH] New module mem-hash-map. + +* lib/mem-hash-map.h: New file, from GNU gettext. +* lib/mem-hash-map.c: New file, from GNU gettext. +* modules/mem-hash-map: New file, from GNU gettext. +--- + ChangeLog | 7 + + lib/mem-hash-map.c | 352 +++++++++++++++++++++++++++++++++++++++++++ + lib/mem-hash-map.h | 90 +++++++++++ + modules/mem-hash-map | 25 +++ + 4 files changed, 474 insertions(+) + create mode 100644 lib/mem-hash-map.c + create mode 100644 lib/mem-hash-map.h + create mode 100644 modules/mem-hash-map + +--- /dev/null ++++ b/lib/mem-hash-map.c +@@ -0,0 +1,352 @@ ++/* Simple hash table (no removals) where the keys are memory blocks. ++ Copyright (C) 1994-2025 Free Software Foundation, Inc. ++ Written by Ulrich Drepper , October 1994. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation, either version 3 of the License, ++ or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++/* Specification. */ ++#include "mem-hash-map.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "next-prime.h" ++ ++/* Since this simple implementation of hash tables allows only insertion, no ++ removal of entries, the right data structure for the memory holding all keys ++ is an obstack. */ ++#include "obstack.h" ++ ++/* Use checked memory allocation. */ ++#include "xalloc.h" ++ ++#define obstack_chunk_alloc xmalloc ++#define obstack_chunk_free free ++ ++ ++typedef struct hash_entry ++{ ++ size_t used; /* Hash code of the key, or 0 for an unused entry. */ ++ const void *key; /* Key. */ ++ size_t keylen; ++ void *data; /* Value. */ ++ struct hash_entry *next; ++} ++hash_entry; ++ ++ ++/* Initialize a hash table. INIT_SIZE > 1 is the initial number of available ++ entries. ++ Return 0 always. */ ++int ++hash_init (hash_table *htab, size_t init_size) ++{ ++ /* We need the size to be a prime. */ ++ init_size = next_prime (init_size); ++ ++ /* Initialize the data structure. */ ++ htab->size = init_size; ++ htab->filled = 0; ++ htab->first = NULL; ++ htab->table = XCALLOC (init_size + 1, hash_entry); ++ ++ obstack_init (&htab->mem_pool); ++ ++ return 0; ++} ++ ++ ++/* Delete a hash table's contents. ++ Return 0 always. */ ++int ++hash_destroy (hash_table *htab) ++{ ++ free (htab->table); ++ obstack_free (&htab->mem_pool, NULL); ++ return 0; ++} ++ ++ ++/* Compute a hash code for a key consisting of KEYLEN bytes starting at KEY ++ in memory. */ ++static size_t ++compute_hashval (const void *key, size_t keylen) ++{ ++ size_t cnt; ++ size_t hval; ++ ++ /* Compute the hash value for the given string. The algorithm ++ is taken from [Aho,Sethi,Ullman], fixed according to ++ https://haible.de/bruno/hashfunc.html. */ ++ cnt = 0; ++ hval = keylen; ++ while (cnt < keylen) ++ { ++ hval = (hval << 9) | (hval >> (sizeof (size_t) * CHAR_BIT - 9)); ++ hval += (size_t) *(((const char *) key) + cnt++); ++ } ++ return hval != 0 ? hval : ~((size_t) 0); ++} ++ ++ ++/* References: ++ [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 ++ [Knuth] The Art of Computer Programming, part3 (6.4) */ ++ ++/* Look up a given key in the hash table. ++ Return the index of the entry, if present, or otherwise the index a free ++ entry where it could be inserted. */ ++static size_t ++lookup (const hash_table *htab, ++ const void *key, size_t keylen, ++ size_t hval) ++{ ++ size_t hash; ++ size_t idx; ++ hash_entry *table = htab->table; ++ ++ /* First hash function: simply take the modul but prevent zero. */ ++ hash = 1 + hval % htab->size; ++ ++ idx = hash; ++ ++ if (table[idx].used) ++ { ++ if (table[idx].used == hval && table[idx].keylen == keylen ++ && memcmp (table[idx].key, key, keylen) == 0) ++ return idx; ++ ++ /* Second hash function as suggested in [Knuth]. */ ++ hash = 1 + hval % (htab->size - 2); ++ ++ do ++ { ++ if (idx <= hash) ++ idx = htab->size + idx - hash; ++ else ++ idx -= hash; ++ ++ /* If entry is found use it. */ ++ if (table[idx].used == hval && table[idx].keylen == keylen ++ && memcmp (table[idx].key, key, keylen) == 0) ++ return idx; ++ } ++ while (table[idx].used); ++ } ++ return idx; ++} ++ ++ ++/* Look up the value of a key in the given table. ++ If found, return 0 and set *RESULT to it. Otherwise return -1. */ ++int ++hash_find_entry (const hash_table *htab, const void *key, size_t keylen, ++ void **result) ++{ ++ hash_entry *table = htab->table; ++ size_t idx = lookup (htab, key, keylen, compute_hashval (key, keylen)); ++ ++ if (table[idx].used == 0) ++ return -1; ++ ++ *result = table[idx].data; ++ return 0; ++} ++ ++ ++/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table at index IDX. ++ HVAL is the key's hash code. IDX depends on it. The table entry at index ++ IDX is known to be unused. */ ++static void ++insert_entry_2 (hash_table *htab, ++ const void *key, size_t keylen, ++ size_t hval, size_t idx, void *data) ++{ ++ hash_entry *table = htab->table; ++ ++ table[idx].used = hval; ++ table[idx].key = key; ++ table[idx].keylen = keylen; ++ table[idx].data = data; ++ ++ /* List the new value in the list. */ ++ if (htab->first == NULL) ++ { ++ table[idx].next = &table[idx]; ++ htab->first = &table[idx]; ++ } ++ else ++ { ++ table[idx].next = htab->first->next; ++ htab->first->next = &table[idx]; ++ htab->first = &table[idx]; ++ } ++ ++ ++htab->filled; ++} ++ ++ ++/* Grow the hash table. */ ++static void ++resize (hash_table *htab) ++{ ++ size_t old_size = htab->size; ++ hash_entry *table = htab->table; ++ size_t idx; ++ ++ htab->size = next_prime (htab->size * 2); ++ htab->filled = 0; ++ htab->first = NULL; ++ htab->table = XCALLOC (1 + htab->size, hash_entry); ++ ++ for (idx = 1; idx <= old_size; ++idx) ++ if (table[idx].used) ++ insert_entry_2 (htab, table[idx].key, table[idx].keylen, ++ table[idx].used, ++ lookup (htab, table[idx].key, table[idx].keylen, ++ table[idx].used), ++ table[idx].data); ++ ++ free (table); ++} ++ ++ ++/* Try to insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. ++ Return non-NULL (more precisely, the address of the KEY inside the table's ++ memory pool) if successful, or NULL if there is already an entry with the ++ given key. */ ++const void * ++hash_insert_entry (hash_table *htab, ++ const void *key, size_t keylen, ++ void *data) ++{ ++ size_t hval = compute_hashval (key, keylen); ++ hash_entry *table = htab->table; ++ size_t idx = lookup (htab, key, keylen, hval); ++ ++ if (table[idx].used) ++ /* We don't want to overwrite the old value. */ ++ return NULL; ++ else ++ { ++ /* An empty bucket has been found. */ ++ void *keycopy = obstack_copy (&htab->mem_pool, key, keylen); ++ insert_entry_2 (htab, keycopy, keylen, hval, idx, data); ++ if (100 * htab->filled > 75 * htab->size) ++ /* Table is filled more than 75%. Resize the table. */ ++ resize (htab); ++ return keycopy; ++ } ++} ++ ++ ++/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. ++ Return 0. */ ++int ++hash_set_value (hash_table *htab, ++ const void *key, size_t keylen, ++ void *data) ++{ ++ size_t hval = compute_hashval (key, keylen); ++ hash_entry *table = htab->table; ++ size_t idx = lookup (htab, key, keylen, hval); ++ ++ if (table[idx].used) ++ { ++ /* Overwrite the old value. */ ++ table[idx].data = data; ++ return 0; ++ } ++ else ++ { ++ /* An empty bucket has been found. */ ++ void *keycopy = obstack_copy (&htab->mem_pool, key, keylen); ++ insert_entry_2 (htab, keycopy, keylen, hval, idx, data); ++ if (100 * htab->filled > 75 * htab->size) ++ /* Table is filled more than 75%. Resize the table. */ ++ resize (htab); ++ return 0; ++ } ++} ++ ++ ++/* Steps *PTR forward to the next used entry in the given hash table. *PTR ++ should be initially set to NULL. Store information about the next entry ++ in *KEY, *KEYLEN, *DATA. ++ Return 0 normally, -1 when the whole hash table has been traversed. */ ++int ++hash_iterate (hash_table *htab, void **ptr, const void **key, size_t *keylen, ++ void **data) ++{ ++ hash_entry *curr; ++ ++ if (*ptr == NULL) ++ { ++ if (htab->first == NULL) ++ return -1; ++ curr = htab->first; ++ } ++ else ++ { ++ if (*ptr == htab->first) ++ return -1; ++ curr = (hash_entry *) *ptr; ++ } ++ curr = curr->next; ++ *ptr = (void *) curr; ++ ++ *key = curr->key; ++ *keylen = curr->keylen; ++ *data = curr->data; ++ return 0; ++} ++ ++ ++/* Steps *PTR forward to the next used entry in the given hash table. *PTR ++ should be initially set to NULL. Store information about the next entry ++ in *KEY, *KEYLEN, *DATAP. *DATAP is set to point to the storage of the ++ value; modifying **DATAP will modify the value of the entry. ++ Return 0 normally, -1 when the whole hash table has been traversed. */ ++int ++hash_iterate_modify (hash_table *htab, void **ptr, ++ const void **key, size_t *keylen, ++ void ***datap) ++{ ++ hash_entry *curr; ++ ++ if (*ptr == NULL) ++ { ++ if (htab->first == NULL) ++ return -1; ++ curr = htab->first; ++ } ++ else ++ { ++ if (*ptr == htab->first) ++ return -1; ++ curr = (hash_entry *) *ptr; ++ } ++ curr = curr->next; ++ *ptr = (void *) curr; ++ ++ *key = curr->key; ++ *keylen = curr->keylen; ++ *datap = &curr->data; ++ return 0; ++} +--- /dev/null ++++ b/lib/mem-hash-map.h +@@ -0,0 +1,90 @@ ++/* Simple hash table (no removals) where the keys are memory blocks. ++ Copyright (C) 1995-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation, either version 3 of the License, ++ or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#ifndef _GL_MEM_HASH_MAP_H ++#define _GL_MEM_HASH_MAP_H ++ ++#include ++ ++#include "obstack.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct hash_entry; ++ ++typedef struct hash_table ++{ ++ size_t size; /* Number of allocated entries. */ ++ size_t filled; /* Number of used entries. */ ++ struct hash_entry *first; /* Pointer to head of list of entries. */ ++ struct hash_entry *table; /* Pointer to array of entries. */ ++ struct obstack mem_pool; /* Memory pool holding the keys. */ ++} ++hash_table; ++ ++/* Initialize a hash table. INIT_SIZE > 1 is the initial number of available ++ entries. ++ Return 0 always. */ ++extern int hash_init (hash_table *htab, size_t init_size); ++ ++/* Delete a hash table's contents. ++ Return 0 always. */ ++extern int hash_destroy (hash_table *htab); ++ ++/* Look up the value of a key in the given table. ++ If found, return 0 and set *RESULT to it. Otherwise return -1. */ ++extern int hash_find_entry (const hash_table *htab, ++ const void *key, size_t keylen, ++ void **result); ++ ++/* Try to insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. ++ Return non-NULL (more precisely, the address of the KEY inside the table's ++ memory pool) if successful, or NULL if there is already an entry with the ++ given key. */ ++extern const void * hash_insert_entry (hash_table *htab, ++ const void *key, size_t keylen, ++ void *data); ++ ++/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table. ++ Return 0. */ ++extern int hash_set_value (hash_table *htab, ++ const void *key, size_t keylen, ++ void *data); ++ ++/* Steps *PTR forward to the next used entry in the given hash table. *PTR ++ should be initially set to NULL. Store information about the next entry ++ in *KEY, *KEYLEN, *DATA. ++ Return 0 normally, -1 when the whole hash table has been traversed. */ ++extern int hash_iterate (hash_table *htab, void **ptr, ++ const void **key, size_t *keylen, ++ void **data); ++ ++/* Steps *PTR forward to the next used entry in the given hash table. *PTR ++ should be initially set to NULL. Store information about the next entry ++ in *KEY, *KEYLEN, *DATAP. *DATAP is set to point to the storage of the ++ value; modifying **DATAP will modify the value of the entry. ++ Return 0 normally, -1 when the whole hash table has been traversed. */ ++extern int hash_iterate_modify (hash_table *htab, void **ptr, ++ const void **key, size_t *keylen, ++ void ***datap); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* not _GL_MEM_HASH_MAP_H */ +--- /dev/null ++++ b/modules/mem-hash-map +@@ -0,0 +1,25 @@ ++Description: ++Simple hash table (no removals) where the keys are memory blocks. ++ ++Files: ++lib/mem-hash-map.h ++lib/mem-hash-map.c ++ ++Depends-on: ++next-prime ++obstack ++xalloc ++ ++configure.ac: ++ ++Makefile.am: ++lib_SOURCES += mem-hash-map.h mem-hash-map.c ++ ++Include: ++"mem-hash-map.h" ++ ++License: ++GPL ++ ++Maintainer: ++Bruno Haible diff --git a/tools/gnulib/patches/645-next-prime.patch b/tools/gnulib/patches/645-next-prime.patch new file mode 100644 index 0000000000..66f482f5ec --- /dev/null +++ b/tools/gnulib/patches/645-next-prime.patch @@ -0,0 +1,218 @@ +From 0b953ba82830f51ce9b939700705d238f9b0c0ba Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 30 Apr 2025 01:52:17 +0200 +Subject: [PATCH] New module next-prime. + +* lib/next-prime.h: New file, based on lib/hash.c. +* lib/next-prime.c: New file, based on lib/hash.c. +* modules/next-prime: New file. +* lib/hash.c: Include next-prime.h. +(is_prime, next_prime): Remove functions. +* modules/hash (Depends-on): Add next-prime. +--- + ChangeLog | 10 +++++++++ + lib/hash.c | 39 +------------------------------- + lib/next-prime.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ + lib/next-prime.h | 41 +++++++++++++++++++++++++++++++++ + modules/hash | 1 + + modules/next-prime | 24 ++++++++++++++++++++ + 6 files changed, 133 insertions(+), 38 deletions(-) + create mode 100644 lib/next-prime.c + create mode 100644 lib/next-prime.h + create mode 100644 modules/next-prime + +--- a/lib/hash.c ++++ b/lib/hash.c +@@ -27,6 +27,7 @@ + #include "hash.h" + + #include "bitrotate.h" ++#include "next-prime.h" + #include "xalloc-oversized.h" + + #include +@@ -390,44 +391,6 @@ hash_string (const char *string, size_t + + #endif /* not USE_DIFF_HASH */ + +-/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd +- number at least equal to 11. */ +- +-static bool _GL_ATTRIBUTE_CONST +-is_prime (size_t candidate) +-{ +- size_t divisor = 3; +- size_t square = divisor * divisor; +- +- while (square < candidate && (candidate % divisor)) +- { +- divisor++; +- square += 4 * divisor; +- divisor++; +- } +- +- return (candidate % divisor ? true : false); +-} +- +-/* Round a given CANDIDATE number up to the nearest prime, and return that +- prime. Primes lower than 10 are merely skipped. */ +- +-static size_t _GL_ATTRIBUTE_CONST +-next_prime (size_t candidate) +-{ +- /* Skip small primes. */ +- if (candidate < 10) +- candidate = 10; +- +- /* Make it definitely odd. */ +- candidate |= 1; +- +- while (SIZE_MAX != candidate && !is_prime (candidate)) +- candidate += 2; +- +- return candidate; +-} +- + void + hash_reset_tuning (Hash_tuning *tuning) + { +--- /dev/null ++++ b/lib/next-prime.c +@@ -0,0 +1,56 @@ ++/* Finding the next prime >= a given small integer. ++ Copyright (C) 1995-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++/* Specification. */ ++#include "next-prime.h" ++ ++#include /* for SIZE_MAX */ ++ ++/* Return true if CANDIDATE is a prime number. CANDIDATE should be an odd ++ number at least equal to 11. */ ++static bool _GL_ATTRIBUTE_CONST ++is_prime (size_t candidate) ++{ ++ size_t divisor = 3; ++ size_t square = divisor * divisor; ++ ++ while (square < candidate && (candidate % divisor)) ++ { ++ divisor++; ++ square += 4 * divisor; ++ divisor++; ++ } ++ ++ return (candidate % divisor ? true : false); ++} ++ ++size_t _GL_ATTRIBUTE_CONST ++next_prime (size_t candidate) ++{ ++ /* Skip small primes. */ ++ if (candidate < 10) ++ candidate = 10; ++ ++ /* Make it definitely odd. */ ++ candidate |= 1; ++ ++ while (SIZE_MAX != candidate && !is_prime (candidate)) ++ candidate += 2; ++ ++ return candidate; ++} +--- /dev/null ++++ b/lib/next-prime.h +@@ -0,0 +1,41 @@ ++/* Finding the next prime >= a given small integer. ++ Copyright (C) 1995-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#ifndef _GL_NEXT_PRIME_H ++#define _GL_NEXT_PRIME_H ++ ++/* This file uses _GL_ATTRIBUTE_CONST. */ ++#if !_GL_CONFIG_H_INCLUDED ++ #error "Please include config.h first." ++#endif ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++/* Round a given CANDIDATE number up to the nearest prime, and return that ++ prime. Primes lower than 10 are merely skipped. */ ++extern size_t _GL_ATTRIBUTE_CONST next_prime (size_t candidate); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _GL_NEXT_PRIME_H */ +--- a/modules/hash ++++ b/modules/hash +@@ -10,6 +10,7 @@ bitrotate + calloc-posix + free-posix + malloc-posix ++next-prime + bool + stdint-h + xalloc-oversized +--- /dev/null ++++ b/modules/next-prime +@@ -0,0 +1,24 @@ ++Description: ++Finding the next prime >= a given small integer. ++ ++Files: ++lib/next-prime.h ++lib/next-prime.c ++ ++Depends-on: ++bool ++stdint-h ++ ++configure.ac: ++ ++Makefile.am: ++lib_SOURCES += next-prime.h next-prime.c ++ ++Include: ++"next-prime.h" ++ ++License: ++LGPLv2+ ++ ++Maintainer: ++all diff --git a/tools/gnulib/patches/646-hashcode-string.patch b/tools/gnulib/patches/646-hashcode-string.patch new file mode 100644 index 0000000000..ee2ebd237f --- /dev/null +++ b/tools/gnulib/patches/646-hashcode-string.patch @@ -0,0 +1,294 @@ +From 64042bb91aea5f854ca8a8938e2b3f7d1935e4f1 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 30 Apr 2025 12:47:37 +0200 +Subject: [PATCH] New module hashcode-string1. + +* lib/hashcode-string1.h: New file. +* lib/hashcode-string1.c: New file, based on lib/hash.c. +* modules/hashcode-string1: New file. +* lib/hash.h: Include hashcode-string1.h. +(hash_string): Remove declaration. +* lib/hash.c (hash_string): Remove function. +* modules/hash (Depends-on): Add hashcode-string1. +* lib/exclude.c: Include hashcode-string1.h. +* modules/exclude (Depends-on): Add hashcode-string1. +--- + ChangeLog | 13 +++++++++ + lib/exclude.c | 1 + + lib/hash.c | 59 ++++++-------------------------------- + lib/hash.h | 11 +++---- + lib/hashcode-string1.c | 62 ++++++++++++++++++++++++++++++++++++++++ + lib/hashcode-string1.h | 38 ++++++++++++++++++++++++ + modules/exclude | 1 + + modules/hash | 1 + + modules/hashcode-string1 | 24 ++++++++++++++++ + 9 files changed, 154 insertions(+), 56 deletions(-) + create mode 100644 lib/hashcode-string1.c + create mode 100644 lib/hashcode-string1.h + create mode 100644 modules/hashcode-string1 + +--- a/lib/exclude.c ++++ b/lib/exclude.c +@@ -36,6 +36,7 @@ + #include "filename.h" + #include + #include "hash.h" ++#include "hashcode-string1.h" + #if GNULIB_MCEL_PREFER + # include "mcel.h" + #else +--- a/lib/hash.c ++++ b/lib/hash.c +@@ -345,57 +345,6 @@ hash_do_for_each (const Hash_table *tabl + return counter; + } + +-/* Allocation and clean-up. */ +- +-#if USE_DIFF_HASH +- +-/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see +- B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm, +- Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash +- algorithms tend to be domain-specific, so what's good for [diffutils'] io.c +- may not be good for your application." */ +- +-size_t +-hash_string (const char *string, size_t n_buckets) +-{ +-# define HASH_ONE_CHAR(Value, Byte) \ +- ((Byte) + rotl_sz (Value, 7)) +- +- size_t value = 0; +- unsigned char ch; +- +- for (; (ch = *string); string++) +- value = HASH_ONE_CHAR (value, ch); +- return value % n_buckets; +- +-# undef HASH_ONE_CHAR +-} +- +-#else /* not USE_DIFF_HASH */ +- +-/* This one comes from 'recode', and performs a bit better than the above as +- per a few experiments. It is inspired from a hashing routine found in the +- very old Cyber 'snoop', itself written in typical Greg Mansfield style. +- (By the way, what happened to this excellent man? Is he still alive?) */ +- +-size_t +-hash_string (const char *string, size_t n_buckets) +-{ +- size_t value = 0; +- unsigned char ch; +- +- for (; (ch = *string); string++) +- value = (value * 31 + ch) % n_buckets; +- return value; +-} +- +-#endif /* not USE_DIFF_HASH */ +- +-void +-hash_reset_tuning (Hash_tuning *tuning) +-{ +- *tuning = default_tuning; +-} + + /* If the user passes a NULL hasher, we hash the raw pointer. */ + static size_t +@@ -418,6 +367,14 @@ raw_comparator (const void *a, const voi + } + + ++/* Allocation and clean-up. */ ++ ++void ++hash_reset_tuning (Hash_tuning *tuning) ++{ ++ *tuning = default_tuning; ++} ++ + /* For the given hash TABLE, check the user supplied tuning structure for + reasonable values, and return true if there is no gross error with it. + Otherwise, definitively reset the TUNING field to some acceptable default +--- a/lib/hash.h ++++ b/lib/hash.h +@@ -134,11 +134,6 @@ extern size_t hash_do_for_each (const Ha + * Allocation and clean-up. + */ + +-/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1. +- This is a convenience routine for constructing other hashing functions. */ +-extern size_t hash_string (const char *string, size_t n_buckets) +- _GL_ATTRIBUTE_PURE; +- + extern void hash_reset_tuning (Hash_tuning *tuning); + + typedef size_t (*Hash_hasher) (const void *entry, size_t table_size); +@@ -266,6 +261,12 @@ extern void *hash_remove (Hash_table *ta + _GL_ATTRIBUTE_DEPRECATED + extern void *hash_delete (Hash_table *table, const void *entry); + ++ ++# if GNULIB_HASHCODE_STRING1 ++/* Include declarations of module 'hashcode-string1'. */ ++# include "hashcode-string1.h" ++# endif ++ + # ifdef __cplusplus + } + # endif +--- /dev/null ++++ b/lib/hashcode-string1.c +@@ -0,0 +1,62 @@ ++/* hashcode-string1.c -- compute a hash value from a NUL-terminated string. ++ ++ Copyright (C) 1998-2004, 2006-2007, 2009-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++/* Specification. */ ++#include "hashcode-string1.h" ++ ++#if USE_DIFF_HASH ++ ++# include "bitrotate.h" ++ ++/* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see ++ B. J. McKenzie, R. Harries & T. Bell, Selecting a hashing algorithm, ++ Software--practice & experience 20, 2 (Feb 1990), 209-224. Good hash ++ algorithms tend to be domain-specific, so what's good for [diffutils'] io.c ++ may not be good for your application." */ ++ ++size_t ++hash_string (const char *string, size_t tablesize) ++{ ++ size_t value = 0; ++ unsigned char ch; ++ ++ for (; (ch = *string); string++) ++ value = ch + rotl_sz (value, 7); ++ return value % tablesize; ++} ++ ++#else /* not USE_DIFF_HASH */ ++ ++/* This one comes from 'recode', and performs a bit better than the above as ++ per a few experiments. It is inspired from a hashing routine found in the ++ very old Cyber 'snoop', itself written in typical Greg Mansfield style. ++ (By the way, what happened to this excellent man? Is he still alive?) */ ++ ++size_t ++hash_string (const char *string, size_t tablesize) ++{ ++ size_t value = 0; ++ unsigned char ch; ++ ++ for (; (ch = *string); string++) ++ value = (value * 31 + ch) % tablesize; ++ return value; ++} ++ ++#endif /* not USE_DIFF_HASH */ +--- /dev/null ++++ b/lib/hashcode-string1.h +@@ -0,0 +1,38 @@ ++/* hashcode-string1.h -- declaration for a simple hash function ++ Copyright (C) 1998-2004, 2006-2007, 2009-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* This file uses _GL_ATTRIBUTE_PURE. */ ++#if !_GL_CONFIG_H_INCLUDED ++ #error "Please include config.h first." ++#endif ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++/* Compute a hash code for a NUL-terminated string S, ++ and return the hash code modulo TABLESIZE. ++ The result is platform dependent: it depends on the size of the 'size_t' ++ type. */ ++extern size_t hash_string (char const *s, size_t tablesize) _GL_ATTRIBUTE_PURE; ++ ++ ++#ifdef __cplusplus ++} ++#endif +--- a/modules/exclude ++++ b/modules/exclude +@@ -12,6 +12,7 @@ filename + fnmatch + fopen-gnu + hash ++hashcode-string1 + mbscasecmp + mbuiter [test "$GNULIB_MCEL_PREFER" != yes] + nullptr +--- a/modules/hash ++++ b/modules/hash +@@ -14,6 +14,7 @@ next-prime + bool + stdint-h + xalloc-oversized ++hashcode-string1 + + configure.ac: + +--- /dev/null ++++ b/modules/hashcode-string1 +@@ -0,0 +1,24 @@ ++Description: ++Compute a hash value for a NUL-terminated string. ++ ++Files: ++lib/hashcode-string1.h ++lib/hashcode-string1.c ++ ++Depends-on: ++bitrotate ++ ++configure.ac: ++gl_MODULE_INDICATOR([hashcode-string1]) ++ ++Makefile.am: ++lib_SOURCES += hashcode-string1.h hashcode-string1.c ++ ++Include: ++"hashcode-string1.h" ++ ++License: ++LGPLv2+ ++ ++Maintainer: ++Jim Meyering diff --git a/tools/gnulib/patches/647-hashkey-string.patch b/tools/gnulib/patches/647-hashkey-string.patch new file mode 100644 index 0000000000..d0cd0a6311 --- /dev/null +++ b/tools/gnulib/patches/647-hashkey-string.patch @@ -0,0 +1,215 @@ +From 52738dcd0f522b16653cc8b21adfcb758702f2ab Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 30 Apr 2025 01:20:17 +0200 +Subject: [PATCH] New module hashkey-string. + +* lib/hashkey-string.h: New file. +* lib/hashkey-string.c: New file, based on lib/clean-temp-simple.c. +* modules/hashkey-string: New file. +* lib/clean-temp-simple.c: Include hashkey-string.h. Don't include +. +(clean_temp_string_equals, clean_temp_string_hash): Remove functions. +(SIZE_BITS): Remove macro. +(register_temporary_file): Use hashkey_string_equals and +hashkey_string_hash. +* modules/clean-temp-simple (Depends-on): Add hashkey-string. +--- + ChangeLog | 14 ++++++++++++ + lib/clean-temp-simple.c | 33 +++------------------------ + lib/hashkey-string.c | 48 +++++++++++++++++++++++++++++++++++++++ + lib/hashkey-string.h | 35 ++++++++++++++++++++++++++++ + modules/clean-temp-simple | 1 + + modules/hashkey-string | 23 +++++++++++++++++++ + 6 files changed, 124 insertions(+), 30 deletions(-) + create mode 100644 lib/hashkey-string.c + create mode 100644 lib/hashkey-string.h + create mode 100644 modules/hashkey-string + +--- a/lib/clean-temp-simple.c ++++ b/lib/clean-temp-simple.c +@@ -22,7 +22,6 @@ + #include "clean-temp-private.h" + + #include +-#include + #include + #include + #include +@@ -36,6 +35,7 @@ + #include "thread-optim.h" + #include "gl_list.h" + #include "gl_linkedhash_list.h" ++#include "hashkey-string.h" + #include "gettext.h" + + #define _(msgid) dgettext ("gnulib", msgid) +@@ -106,33 +106,6 @@ gl_list_t /* */ volatil + asynchronous signal. + */ + +-/* String equality and hash code functions used by the lists. */ +- +-bool +-clean_temp_string_equals (const void *x1, const void *x2) +-{ +- const char *s1 = (const char *) x1; +- const char *s2 = (const char *) x2; +- return strcmp (s1, s2) == 0; +-} +- +-#define SIZE_BITS (sizeof (size_t) * CHAR_BIT) +- +-/* A hash function for NUL-terminated char* strings using +- the method described by Bruno Haible. +- See https://www.haible.de/bruno/hashfunc.html. */ +-size_t +-clean_temp_string_hash (const void *x) +-{ +- const char *s = (const char *) x; +- size_t h = 0; +- +- for (; *s; s++) +- h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); +- +- return h; +-} +- + + /* The set of fatal signal handlers. + Cached here because we are not allowed to call get_fatal_signal_set () +@@ -326,8 +299,8 @@ register_temporary_file (const char *abs + } + file_cleanup_list = + gl_list_nx_create_empty (GL_LINKEDHASH_LIST, +- clean_temp_string_equals, +- clean_temp_string_hash, ++ hashkey_string_equals, ++ hashkey_string_hash, + NULL, false); + if (file_cleanup_list == NULL) + { +--- /dev/null ++++ b/lib/hashkey-string.c +@@ -0,0 +1,48 @@ ++/* Support for using a string as a hash key. ++ Copyright (C) 2006-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#include ++ ++/* Specification. */ ++#include "hashkey-string.h" ++ ++#include ++#include ++ ++bool ++hashkey_string_equals (const void *x1, const void *x2) ++{ ++ const char *s1 = (const char *) x1; ++ const char *s2 = (const char *) x2; ++ return strcmp (s1, s2) == 0; ++} ++ ++#define SIZE_BITS (sizeof (size_t) * CHAR_BIT) ++ ++/* A hash function for NUL-terminated 'const char *' strings using ++ the method described by Bruno Haible. ++ See https://www.haible.de/bruno/hashfunc.html. */ ++size_t ++hashkey_string_hash (const void *x) ++{ ++ const char *s = (const char *) x; ++ size_t h = 0; ++ ++ for (; *s; s++) ++ h = *s + ((h << 9) | (h >> (SIZE_BITS - 9))); ++ ++ return h; ++} +--- /dev/null ++++ b/lib/hashkey-string.h +@@ -0,0 +1,35 @@ ++/* Support for using a string as a hash key. ++ Copyright (C) 2006-2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation; either version 2.1 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++#ifndef _GL_HASHKEY_STRING_H ++#define _GL_HASHKEY_STRING_H ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* String equality and hash code functions that operate on plain C strings ++ ('const char *'). */ ++extern bool hashkey_string_equals (const void *x1, const void *x2); ++extern size_t hashkey_string_hash (const void *x); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _GL_HASHKEY_STRING_H */ +--- a/modules/clean-temp-simple ++++ b/modules/clean-temp-simple +@@ -19,6 +19,7 @@ error + fatal-signal + rmdir + linkedhash-list ++hashkey-string + gettext-h + gnulib-i18n + +--- /dev/null ++++ b/modules/hashkey-string +@@ -0,0 +1,23 @@ ++Description: ++Support for using a string as a hash key in the hash-set and hash-map modules. ++ ++Files: ++lib/hashkey-string.h ++lib/hashkey-string.c ++ ++Depends-on: ++bool ++ ++configure.ac: ++ ++Makefile.am: ++lib_SOURCES += hashkey-string.h hashkey-string.c ++ ++Include: ++"hashkey-string.h" ++ ++License: ++LGPLv2+ ++ ++Maintainer: ++all diff --git a/tools/gnulib/patches/650-package-version.patch b/tools/gnulib/patches/650-package-version.patch new file mode 100644 index 0000000000..2e3e046736 --- /dev/null +++ b/tools/gnulib/patches/650-package-version.patch @@ -0,0 +1,176 @@ +From e518788ad085e02b046e42889039a1f671e4619a Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 22 Jan 2025 21:21:59 +0100 +Subject: New module 'package-version'. + +* m4/init-package-version.m4: New file, from GNU libunistring. +* modules/package-version: New file. +* modules/git-version-gen (Depends-on): Add it. +--- + ChangeLog | 7 +++ + m4/init-package-version.m4 | 124 +++++++++++++++++++++++++++++++++++++++++++++ + modules/git-version-gen | 1 + + modules/package-version | 19 +++++++ + 4 files changed, 151 insertions(+) + create mode 100644 m4/init-package-version.m4 + create mode 100644 modules/package-version + +--- /dev/null ++++ b/m4/init-package-version.m4 +@@ -0,0 +1,124 @@ ++# init-package-version.m4 ++# serial 3 ++dnl Copyright (C) 1992-2025 Free Software Foundation, Inc. ++dnl This file is free software, distributed under the terms of the GNU ++dnl General Public License. As a special exception to the GNU General ++dnl Public License, this file may be distributed as part of a program ++dnl that contains a configuration script generated by Autoconf, under ++dnl the same distribution terms as the rest of that program. ++ ++# Make it possible to pass version numbers extracted from a file in ++# $(srcdir) to autoconf. ++# ++# Autoconf insists on passing the package name and version number to ++# every generated .h file and every Makefile. This was a reasonable ++# design at times when a version number was changed only once a month. ++# Nowadays, people often assign a new version number once a week, or ++# even change it each time a 'git' commit is made. Regenerating all ++# the files that depend on configure.ac (aclocal.m4, configure, ++# config.status, config.h, all Makefiles) may take 15 minutes. These ++# delays can severely hamper development. ++# ++# An alternative is to store the version number in a file in $(srcdir) ++# that is separate from configure.ac. It can be a data file, a shell ++# script, a .m4 file, or other. The essential point is that the maintainer ++# is responsible for creating Makefile dependencies to this version file ++# for every file that needs to be rebuilt when the version changes. This ++# typically includes ++# - distributable documentation files that carry the version number, ++# but does not include ++# - aclocal.m4, configure, config.status, config.h, all Makefiles, ++# - executables. ++# ++# autoconf and automake make it hard to follow this approach: ++# ++# - If AC_INIT is used with arguments, there is a chicken-and-egg problem: ++# The arguments need to be read from a file in $(srcdir). The location ++# of $(srcdir) is only determined by AC_CONFIG_SRCDIR. AC_CONFIG_SRCDIR ++# can only appear after AC_INIT (otherwise aclocal gives an error: ++# "error: m4_defn: undefined macro: _m4_divert_diversion"). ++# Furthermore, the arguments passed to AC_INIT must be literals; for ++# example, the assignment to PACKAGE_VERSION looks like this: ++# [PACKAGE_VERSION=']AC_PACKAGE_VERSION['] ++# ++# - If AC_INIT is used without arguments: ++# Automake provides its own variables, PACKAGE and VERSION, and uses them ++# instead of PACKAGE_NAME and PACKAGE_VERSION that come from Autoconf. ++# - If AM_INIT_AUTOMAKE is used with two arguments, automake options ++# like 'silent-rules' cannot be specified. ++# - If AM_INIT_AUTOMAKE is used in its one-argument form or without ++# arguments at all, it triggers an error ++# "error: AC_INIT should be called with package and version arguments". ++# - If AM_INIT_AUTOMAKE is used in its one-argument form or without ++# arguments at all, and _AC_INIT_PACKAGE is used before it, with ++# the package and version number from the file as arguments, we get ++# a warning: "warning: AC_INIT: not a literal: $VERSION_NUMBER". ++# The arguments passed to _AC_INIT_PACKAGE must be literals. ++# ++# With the macro defined in this file, the approach can be coded like this: ++# ++# AC_INIT ++# AC_CONFIG_SRCDIR(WITNESS) ++# . $srcdir/../version.sh ++# gl_INIT_PACKAGE(PACKAGE, $VERSION_NUMBER) ++# AM_INIT_AUTOMAKE([OPTIONS]) ++# ++# and after changing version.sh, the developer can directly configure and build: ++# ++# make distclean ++# ./configure ++# make ++# ++# Some other packages use another approach: ++# ++# AC_INIT(PACKAGE, ++# m4_normalize(m4_esyscmd([. ./version.sh; echo $VERSION_NUMBER]))) ++# AC_CONFIG_SRCDIR(WITNESS) ++# AM_INIT_AUTOMAKE([OPTIONS]) ++# ++# but here, after changing version.sh, the developer must first regenerate the ++# configure file: ++# ++# make distclean ++# ./autogen.sh --skip-gnulib ++# ./configure ++# make ++# ++ ++# gl_INIT_PACKAGE(PACKAGE-NAME, VERSION) ++# -------------------------------------- ++# followed by an AM_INIT_AUTOMAKE invocation, ++# is like calling AM_INIT_AUTOMAKE(PACKAGE-NAME, VERSION) ++# except that it can use computed non-literal arguments. ++AC_DEFUN([gl_INIT_PACKAGE], ++[ ++ AC_BEFORE([$0], [AM_INIT_AUTOMAKE]) ++ dnl Redefine AM_INIT_AUTOMAKE. ++ m4_define([gl_AM_INIT_AUTOMAKE], ++ m4_bpatsubst(m4_dquote( ++ m4_bpatsubst(m4_dquote( ++ m4_bpatsubst(m4_dquote( ++ m4_defn([AM_INIT_AUTOMAKE])), ++ [AC_PACKAGE_NAME], [gl_INIT_DUMMY])), ++ [AC_PACKAGE_TARNAME], [gl_INIT_EMPTY])), ++ [AC_PACKAGE_VERSION], [gl_INIT_DUMMY]) ++ [AC_SUBST([PACKAGE], [$1]) ++ AC_SUBST([VERSION], [$2]) ++ ]) ++ m4_define([AM_INIT_AUTOMAKE], ++ m4_defn([gl_RPL_INIT_AUTOMAKE])) ++]) ++m4_define([gl_INIT_EMPTY], []) ++dnl Automake 1.16.4 no longer accepts an empty value for gl_INIT_DUMMY. ++dnl But a macro that later expands to empty works. ++m4_define([gl_INIT_DUMMY], [gl_INIT_DUMMY2]) ++m4_define([gl_INIT_DUMMY2], []) ++AC_DEFUN([gl_RPL_INIT_AUTOMAKE], [ ++ m4_ifval([$2], ++ [m4_fatal([After gl_INIT_PACKAGE, the two-argument form of AM_INIT_AUTOMAKE cannot be used.])]) ++ gl_AM_INIT_AUTOMAKE([$1 no-define]) ++ m4_if(m4_index([ $1 ], [ no-define ]), [-1], ++ [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) ++ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]) ++ ]) ++]) +--- a/modules/git-version-gen ++++ b/modules/git-version-gen +@@ -5,6 +5,7 @@ Files: + build-aux/git-version-gen + + Depends-on: ++package-version + + configure.ac: + +--- /dev/null ++++ b/modules/package-version +@@ -0,0 +1,19 @@ ++Description: ++Support for a computed version string. ++ ++Files: ++m4/init-package-version.m4 ++ ++Depends-on: ++ ++configure.ac: ++ ++Makefile.am: ++ ++Include: ++ ++License: ++GPLed build tool ++ ++Maintainer: ++Bruno Haible diff --git a/tools/gnulib/patches/651-package-version-simplify.patch b/tools/gnulib/patches/651-package-version-simplify.patch new file mode 100644 index 0000000000..bed3e65c41 --- /dev/null +++ b/tools/gnulib/patches/651-package-version-simplify.patch @@ -0,0 +1,66 @@ +From bb0f82be83d43db9cd77049be32ffd0b92ab5bb7 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Fri, 24 Jan 2025 22:03:29 +0100 +Subject: package-version: Simplify its use. + +Reported by Basil L. Contovounesios in +. + +* doc/package-version.texi (Propagating the package version): Recommend +to pass the usual arguments to AC_INIT. +* m4/init-package-version.m4: Likewise. +(gl_INIT_PACKAGE): Define PACKAGE_VERSION and PACKAGE_STRING as needed. +(gl_RPL_INIT_AUTOMAKE): Improve quoting. +--- + ChangeLog | 11 +++++++++++ + doc/package-version.texi | 2 +- + m4/init-package-version.m4 | 20 ++++++++++++++------ + 3 files changed, 26 insertions(+), 7 deletions(-) + +--- a/m4/init-package-version.m4 ++++ b/m4/init-package-version.m4 +@@ -1,5 +1,5 @@ + # init-package-version.m4 +-# serial 3 ++# serial 4 + dnl Copyright (C) 1992-2025 Free Software Foundation, Inc. + dnl This file is free software, distributed under the terms of the GNU + dnl General Public License. As a special exception to the GNU General +@@ -57,7 +57,7 @@ dnl the same distribution terms as the r + # + # With the macro defined in this file, the approach can be coded like this: + # +-# AC_INIT ++# AC_INIT(PACKAGE, [dummy], [MORE OPTIONS]) + # AC_CONFIG_SRCDIR(WITNESS) + # . $srcdir/../version.sh + # gl_INIT_PACKAGE(PACKAGE, $VERSION_NUMBER) +@@ -102,8 +102,16 @@ AC_DEFUN([gl_INIT_PACKAGE], + [AC_PACKAGE_NAME], [gl_INIT_DUMMY])), + [AC_PACKAGE_TARNAME], [gl_INIT_EMPTY])), + [AC_PACKAGE_VERSION], [gl_INIT_DUMMY]) +- [AC_SUBST([PACKAGE], [$1]) +- AC_SUBST([VERSION], [$2]) ++ [dnl Set variables documented in Automake. ++ AC_SUBST([PACKAGE], [$1]) ++ AC_SUBST([VERSION], ["$2"]) ++ dnl Set variables documented in Autoconf. ++ AC_SUBST([PACKAGE_VERSION], ["$2"]) ++ AC_SUBST([PACKAGE_STRING], ["$1 $2"]) ++ AC_DEFINE_UNQUOTED([PACKAGE_VERSION], ["$2"], ++ [Define to the version of this package.]) ++ AC_DEFINE_UNQUOTED([PACKAGE_STRING], ["$1 $2"], ++ [Define to the full name and version of this package.]) + ]) + m4_define([AM_INIT_AUTOMAKE], + m4_defn([gl_RPL_INIT_AUTOMAKE])) +@@ -118,7 +126,7 @@ AC_DEFUN([gl_RPL_INIT_AUTOMAKE], [ + [m4_fatal([After gl_INIT_PACKAGE, the two-argument form of AM_INIT_AUTOMAKE cannot be used.])]) + gl_AM_INIT_AUTOMAKE([$1 no-define]) + m4_if(m4_index([ $1 ], [ no-define ]), [-1], +- [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) +- AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]) ++ [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) ++ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package]) + ]) + ]) diff --git a/tools/gnulib/patches/652-package-version-simplify-further.patch b/tools/gnulib/patches/652-package-version-simplify-further.patch new file mode 100644 index 0000000000..5458918246 --- /dev/null +++ b/tools/gnulib/patches/652-package-version-simplify-further.patch @@ -0,0 +1,89 @@ +From 48648b4b9b3fd79a5c68913deb28678bd9d8eb34 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Sat, 25 Jan 2025 04:07:32 +0100 +Subject: package-version: Simplify further. + +* doc/package-version.texi (Propagating the package version): Recommend +use of gl_INIT_PACKAGE_VERSION instead of gl_INIT_PACKAGE. +* build-aux/git-version-gen: Likewise. +* m4/init-package-version.m4: Likewise. +(gl_INIT_PACKAGE_VERSION): Renamed from gl_INIT_PACKAGE. Take only one +argument. Don't fiddle with AC_PACKAGE_NAME, AC_PACKAGE_TARNAME, +PACKAGE. +(gl_RPL_INIT_AUTOMAKE): Update. +--- + ChangeLog | 10 ++++++++++ + build-aux/git-version-gen | 4 ++-- + doc/package-version.texi | 4 ++-- + m4/init-package-version.m4 | 30 ++++++++++++------------------ + 4 files changed, 26 insertions(+), 22 deletions(-) + +--- a/m4/init-package-version.m4 ++++ b/m4/init-package-version.m4 +@@ -1,5 +1,5 @@ + # init-package-version.m4 +-# serial 4 ++# serial 5 + dnl Copyright (C) 1992-2025 Free Software Foundation, Inc. + dnl This file is free software, distributed under the terms of the GNU + dnl General Public License. As a special exception to the GNU General +@@ -60,7 +60,7 @@ dnl the same distribution terms as the r + # AC_INIT(PACKAGE, [dummy], [MORE OPTIONS]) + # AC_CONFIG_SRCDIR(WITNESS) + # . $srcdir/../version.sh +-# gl_INIT_PACKAGE(PACKAGE, $VERSION_NUMBER) ++# gl_INIT_PACKAGE_VERSION($VERSION_NUMBER) + # AM_INIT_AUTOMAKE([OPTIONS]) + # + # and after changing version.sh, the developer can directly configure and build: +@@ -85,32 +85,26 @@ dnl the same distribution terms as the r + # make + # + +-# gl_INIT_PACKAGE(PACKAGE-NAME, VERSION) +-# -------------------------------------- ++# gl_INIT_PACKAGE_VERSION(VERSION) ++# -------------------------------- + # followed by an AM_INIT_AUTOMAKE invocation, + # is like calling AM_INIT_AUTOMAKE(PACKAGE-NAME, VERSION) + # except that it can use computed non-literal arguments. +-AC_DEFUN([gl_INIT_PACKAGE], ++AC_DEFUN([gl_INIT_PACKAGE_VERSION], + [ + AC_BEFORE([$0], [AM_INIT_AUTOMAKE]) + dnl Redefine AM_INIT_AUTOMAKE. + m4_define([gl_AM_INIT_AUTOMAKE], +- m4_bpatsubst(m4_dquote( +- m4_bpatsubst(m4_dquote( +- m4_bpatsubst(m4_dquote( +- m4_defn([AM_INIT_AUTOMAKE])), +- [AC_PACKAGE_NAME], [gl_INIT_DUMMY])), +- [AC_PACKAGE_TARNAME], [gl_INIT_EMPTY])), ++ m4_bpatsubst(m4_dquote(m4_defn([AM_INIT_AUTOMAKE])), + [AC_PACKAGE_VERSION], [gl_INIT_DUMMY]) + [dnl Set variables documented in Automake. +- AC_SUBST([PACKAGE], [$1]) +- AC_SUBST([VERSION], ["$2"]) ++ AC_SUBST([VERSION], ["$1"]) + dnl Set variables documented in Autoconf. +- AC_SUBST([PACKAGE_VERSION], ["$2"]) +- AC_SUBST([PACKAGE_STRING], ["$1 $2"]) +- AC_DEFINE_UNQUOTED([PACKAGE_VERSION], ["$2"], ++ AC_SUBST([PACKAGE_VERSION], ["$1"]) ++ AC_SUBST([PACKAGE_STRING], ["AC_PACKAGE_NAME $1"]) ++ AC_DEFINE_UNQUOTED([PACKAGE_VERSION], ["$1"], + [Define to the version of this package.]) +- AC_DEFINE_UNQUOTED([PACKAGE_STRING], ["$1 $2"], ++ AC_DEFINE_UNQUOTED([PACKAGE_STRING], ["AC_PACKAGE_NAME $1"], + [Define to the full name and version of this package.]) + ]) + m4_define([AM_INIT_AUTOMAKE], +@@ -123,7 +117,7 @@ m4_define([gl_INIT_DUMMY], [gl_INIT_DUMM + m4_define([gl_INIT_DUMMY2], []) + AC_DEFUN([gl_RPL_INIT_AUTOMAKE], [ + m4_ifval([$2], +- [m4_fatal([After gl_INIT_PACKAGE, the two-argument form of AM_INIT_AUTOMAKE cannot be used.])]) ++ [m4_fatal([After gl_INIT_PACKAGE_VERSION, the two-argument form of AM_INIT_AUTOMAKE cannot be used.])]) + gl_AM_INIT_AUTOMAKE([$1 no-define]) + m4_if(m4_index([ $1 ], [ no-define ]), [-1], + [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) diff --git a/tools/gnulib/patches/653-package-version-warning.patch b/tools/gnulib/patches/653-package-version-warning.patch new file mode 100644 index 0000000000..4baa21ce65 --- /dev/null +++ b/tools/gnulib/patches/653-package-version-warning.patch @@ -0,0 +1,32 @@ +From 2e46209809f751087ca27523283bd5c3e9071d31 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Sun, 26 Jan 2025 13:26:35 +0100 +Subject: package-version: Avoid compiler warnings in config.log. + +* m4/init-package-version.m4 (gl_INIT_PACKAGE_VERSION): Undefine +PACKAGE_VERSION and PACKAGE_STRING before redefining them. +--- + ChangeLog | 6 ++++++ + m4/init-package-version.m4 | 4 +++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/m4/init-package-version.m4 ++++ b/m4/init-package-version.m4 +@@ -1,5 +1,5 @@ + # init-package-version.m4 +-# serial 5 ++# serial 6 + dnl Copyright (C) 1992-2025 Free Software Foundation, Inc. + dnl This file is free software, distributed under the terms of the GNU + dnl General Public License. As a special exception to the GNU General +@@ -102,8 +102,10 @@ AC_DEFUN([gl_INIT_PACKAGE_VERSION], + dnl Set variables documented in Autoconf. + AC_SUBST([PACKAGE_VERSION], ["$1"]) + AC_SUBST([PACKAGE_STRING], ["AC_PACKAGE_NAME $1"]) ++ _AC_DEFINE([#undef PACKAGE_VERSION]) + AC_DEFINE_UNQUOTED([PACKAGE_VERSION], ["$1"], + [Define to the version of this package.]) ++ _AC_DEFINE([#undef PACKAGE_STRING]) + AC_DEFINE_UNQUOTED([PACKAGE_STRING], ["AC_PACKAGE_NAME $1"], + [Define to the full name and version of this package.]) + ]) diff --git a/tools/gnulib/patches/660-version-stamp.patch b/tools/gnulib/patches/660-version-stamp.patch new file mode 100644 index 0000000000..d85c0455cf --- /dev/null +++ b/tools/gnulib/patches/660-version-stamp.patch @@ -0,0 +1,75 @@ +From 85599643e2fbf70f7f0bd58831993132ef335705 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 22 Jan 2025 21:25:27 +0100 +Subject: New module 'version-stamp'. + +* m4/version-stamp.m4: New file. +* modules/version-stamp: New file. +--- + ChangeLog | 6 ++++++ + m4/version-stamp.m4 | 35 +++++++++++++++++++++++++++++++++++ + modules/version-stamp | 19 +++++++++++++++++++ + 3 files changed, 60 insertions(+) + create mode 100644 m4/version-stamp.m4 + create mode 100644 modules/version-stamp + +--- /dev/null ++++ b/m4/version-stamp.m4 +@@ -0,0 +1,35 @@ ++# version-stamp.m4 ++# serial 1 ++dnl Copyright (C) 2025 Free Software Foundation, Inc. ++dnl This file is free software, distributed under the terms of the GNU ++dnl General Public License. As a special exception to the GNU General ++dnl Public License, this file may be distributed as part of a program ++dnl that contains a configuration script generated by Autoconf, under ++dnl the same distribution terms as the rest of that program. ++ ++# Manages a stamp file, that keeps track when $(VERSION) was last changed. ++# ++# gl_CONFIG_VERSION_STAMP ++# needs to be invoked near the end of the package's top-level configure.ac, ++# before AC_OUTPUT. ++# It makes sure that during the build, ++# - $(top_srcdir)/.version exists, and ++# - when $(VERSION) is changed, $(top_srcdir)/.version gets modified. ++# ++# $(top_srcdir)/.version is a stamp file. Its contents wouldn't matter, ++# except that for detecting the change, we store the value of $(VERSION) ++# in it (but we could just as well store it in a different file). ++AC_DEFUN([gl_CONFIG_VERSION_STAMP], ++[ ++ AC_CONFIG_COMMANDS([version-timestamp], ++ [if test -f "$ac_top_srcdir/.version" \ ++ && test `cat "$ac_top_srcdir/.version"` = "$gl_version"; then ++ # The value of $(VERSION) is the same as last time. ++ : ++ else ++ # The value of $(VERSION) has changed. Update the stamp. ++ echo "$gl_version" > "$ac_top_srcdir/.version" ++ fi ++ ], ++ [gl_version="$VERSION"]) ++]) +--- /dev/null ++++ b/modules/version-stamp +@@ -0,0 +1,19 @@ ++Description: ++Optimized rebuilding of artifacts that depend on $(VERSION). ++ ++Files: ++m4/version-stamp.m4 ++ ++Depends-on: ++ ++configure.ac: ++ ++Makefile.am: ++ ++Include: ++ ++License: ++GPLed build tool ++ ++Maintainer: ++Bruno Haible diff --git a/tools/gnulib/patches/689-vc-mtime.patch b/tools/gnulib/patches/689-vc-mtime.patch new file mode 100644 index 0000000000..62638d7ff4 --- /dev/null +++ b/tools/gnulib/patches/689-vc-mtime.patch @@ -0,0 +1,366 @@ +From 701d20aaf579bb71f35209dd63a272c3d9d21096 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Mon, 24 Feb 2025 19:03:17 +0100 +Subject: [PATCH] vc-mtime: New module. + +* lib/vc-mtime.h: New file. +* lib/vc-mtime.c: New file. +* modules/vc-mtime: New file. +--- + ChangeLog | 7 ++ + lib/vc-mtime.c | 208 +++++++++++++++++++++++++++++++++++++++++++++++ + lib/vc-mtime.h | 97 ++++++++++++++++++++++ + modules/vc-mtime | 34 ++++++++ + 4 files changed, 346 insertions(+) + create mode 100644 lib/vc-mtime.c + create mode 100644 lib/vc-mtime.h + create mode 100644 modules/vc-mtime + +--- /dev/null ++++ b/lib/vc-mtime.c +@@ -0,0 +1,208 @@ ++/* Return the version-control based modification time of a file. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Bruno Haible , 2025. */ ++ ++#include ++ ++/* Specification. */ ++#include "vc-mtime.h" ++ ++#include ++#include ++ ++#include ++#include "spawn-pipe.h" ++#include "wait-process.h" ++#include "execute.h" ++#include "safe-read.h" ++#include "xstrtol.h" ++#include "stat-time.h" ++#include "gettext.h" ++ ++#define _(msgid) dgettext ("gnulib", msgid) ++ ++ ++/* Determines whether the specified file is under version control. */ ++static bool ++git_vc_controlled (const char *filename) ++{ ++ /* Run "git ls-files FILENAME" and return true if the exit code is 0 ++ and the output is non-empty. */ ++ const char *argv[4]; ++ pid_t child; ++ int fd[1]; ++ ++ argv[0] = "git"; ++ argv[1] = "ls-files"; ++ argv[2] = filename; ++ argv[3] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ return false; ++ ++ /* Read the subprocess output, and test whether it is non-empty. */ ++ size_t count = 0; ++ char c; ++ ++ while (safe_read (fd[0], &c, 1) > 0) ++ count++; ++ ++ close (fd[0]); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ int exitstatus = ++ wait_subprocess (child, "git", false, true, true, false, NULL); ++ return (exitstatus == 0 && count > 0); ++} ++ ++/* Determines whether the specified file is unmodified, compared to the ++ last version in version control. */ ++static bool ++git_unmodified (const char *filename) ++{ ++ /* Run "git diff --quiet -- HEAD FILENAME" ++ (or "git diff --quiet HEAD FILENAME") ++ and return true if the exit code is 0. ++ The '--' option is for the case that the specified file was removed. */ ++ const char *argv[7]; ++ int exitstatus; ++ ++ argv[0] = "git"; ++ argv[1] = "diff"; ++ argv[2] = "--quiet"; ++ argv[3] = "--"; ++ argv[4] = "HEAD"; ++ argv[5] = filename; ++ argv[6] = NULL; ++ exitstatus = execute ("git", "git", argv, NULL, NULL, ++ false, false, true, true, ++ true, false, NULL); ++ return (exitstatus == 0); ++} ++ ++/* Stores in *MTIME the time of last modification in version control of the ++ specified file, and returns 0. ++ Upon failure, it returns -1. */ ++static int ++git_mtime (struct timespec *mtime, const char *filename) ++{ ++ /* Run "git log -1 --format=%ct -- FILENAME". It prints the time of last ++ modification, as the number of seconds since the Epoch. ++ The '--' option is for the case that the specified file was removed. */ ++ const char *argv[7]; ++ pid_t child; ++ int fd[1]; ++ ++ argv[0] = "git"; ++ argv[1] = "log"; ++ argv[2] = "-1"; ++ argv[3] = "--format=%ct"; ++ argv[4] = "--"; ++ argv[5] = filename; ++ argv[6] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ return -1; ++ ++ /* Retrieve its result. */ ++ FILE *fp; ++ char *line; ++ size_t linesize; ++ size_t linelen; ++ ++ fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ line = NULL; linesize = 0; ++ linelen = getline (&line, &linesize, fp); ++ if (linelen == (size_t)(-1)) ++ { ++ error (0, 0, _("%s subprocess I/O error"), "git"); ++ fclose (fp); ++ wait_subprocess (child, "git", true, false, true, false, NULL); ++ } ++ else ++ { ++ int exitstatus; ++ ++ if (linelen > 0 && line[linelen - 1] == '\n') ++ line[linelen - 1] = '\0'; ++ ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ exitstatus = ++ wait_subprocess (child, "git", true, false, true, false, NULL); ++ if (exitstatus == 0) ++ { ++ char *endptr; ++ unsigned long git_log_time; ++ if (xstrtoul (line, &endptr, 10, &git_log_time, NULL) == LONGINT_OK ++ && endptr == line + strlen (line)) ++ { ++ mtime->tv_sec = git_log_time; ++ mtime->tv_nsec = 0; ++ free (line); ++ return 0; ++ } ++ } ++ } ++ free (line); ++ return -1; ++} ++ ++int ++vc_mtime (struct timespec *mtime, const char *filename) ++{ ++ static bool git_tested; ++ static bool git_present; ++ ++ if (!git_tested) ++ { ++ /* Test for presence of git: ++ "git --version >/dev/null 2>/dev/null" */ ++ const char *argv[3]; ++ int exitstatus; ++ ++ argv[0] = "git"; ++ argv[1] = "--version"; ++ argv[2] = NULL; ++ exitstatus = execute ("git", "git", argv, NULL, NULL, ++ false, false, true, true, ++ true, false, NULL); ++ git_present = (exitstatus == 0); ++ git_tested = true; ++ } ++ ++ if (git_present ++ && git_vc_controlled (filename) ++ && git_unmodified (filename)) ++ { ++ if (git_mtime (mtime, filename) == 0) ++ return 0; ++ } ++ struct stat statbuf; ++ if (stat (filename, &statbuf) == 0) ++ { ++ *mtime = get_stat_mtime (&statbuf); ++ return 0; ++ } ++ return -1; ++} +--- /dev/null ++++ b/lib/vc-mtime.h +@@ -0,0 +1,97 @@ ++/* Return the version-control based modification time of a file. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ ++ This program is free software: you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation, either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Bruno Haible , 2025. */ ++ ++#ifndef _VC_MTIME_H ++#define _VC_MTIME_H ++ ++/* Get struct timespec. */ ++#include ++ ++/* The "version-controlled modification time" vc_mtime(F) of a file F ++ is defined as: ++ - If F is under version control and not modified locally: ++ the time of the last change of F in the version control system. ++ - Otherwise: The modification time of F on disk. ++ ++ For now, the only VCS supported by this module is git. (hg and svn are ++ hardly in use any more.) ++ ++ This has the properties that: ++ - Different users who have checked out the same git repo on different ++ machines, at different times, and not done local modifications, ++ get the same vc_mtime(F). ++ - If a user has modified F locally, the modification time of that file ++ counts. ++ - If that user then reverts the modification, they then again get the ++ same vc_mtime(F) as everyone else. ++ - Different users who have unpacked the same tarball (without .git ++ directory) on different machines, at different times, also get the same ++ vc_mtime(F) [but possibly a different one than when the .git directory ++ was present]. (Assuming a POSIX compliant file system.) ++ - When a user commits local modifications into git, this only increases ++ (not decreases) the vc_mtime(F). ++ ++ The purpose of the version-controlled modification time is to produce a ++ reproducible timestamp(Z) of a file Z that depends on files X1, ..., Xn, ++ in such a way that ++ - timestamp(Z) is reproducible, that is, different users on different ++ machines get the same value. ++ - timestamp(Z) is related to reality. It's not just a dummy, like what ++ is suggested in . ++ - One can arrange for timestamp(Z) to respect the modification time ++ relations of a build system. ++ ++ There are two uses of such a timestamp: ++ - It can be set as the modification time of file Z in a file system, or ++ - It can be embedded in Z, with the purpose of telling a user how old ++ the file Z is. For example, in PDF files or in generated documentation, ++ such a time is embedded in a special place. ++ ++ The simplest example is a file Z that depends on files X1, ..., Xn. ++ Generally one will define ++ timestamp(Z) = max (vc_mtime(X1), ..., vc_mtime(Xn)) ++ for an embedded timestamp, or ++ timestamp(Z) = max (vc_mtime(X1), ..., vc_mtime(Xn)) + 1 second ++ for a time stamp in a file system. The added second ++ 1. accounts for fractional seconds in mtime(X1), ..., mtime(Xn), ++ 2. allows for 'make' implementation that attempt to rebuild Z ++ if mtime(Z) == mtime(Xi). ++ ++ A more complicated example is when there are intermediate built files, not ++ under version control. For example, if the build process produces ++ X1, X2 -> Y1 ++ X3, X4 -> Y2 ++ Y1, Y2, X5 -> Z ++ where Y1 and Y2 are intermediate built files, you should ignore the ++ mtime(Y1), mtime(Y2), and consider only the vc_mtime(X1), ..., vc_mtime(X5). ++ */ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Determines the version-controlled modification time of FILENAME, stores it ++ in *MTIME, and returns 0. ++ Upon failure, it returns -1. */ ++extern int vc_mtime (struct timespec *mtime, const char *filename); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _VC_MTIME_H */ +--- /dev/null ++++ b/modules/vc-mtime +@@ -0,0 +1,34 @@ ++Description: ++Returns the version-control based modification time of a file. ++ ++Files: ++lib/vc-mtime.h ++lib/vc-mtime.c ++ ++Depends-on: ++time-h ++bool ++spawn-pipe ++wait-process ++execute ++safe-read ++error ++getline ++xstrtol ++stat-time ++gettext-h ++gnulib-i18n ++ ++configure.ac: ++ ++Makefile.am: ++lib_SOURCES += vc-mtime.c ++ ++Include: ++"vm-mtime.h" ++ ++License: ++GPL ++ ++Maintainer: ++Bruno Haible diff --git a/tools/gnulib/patches/755-clean-temp-hashkey.patch b/tools/gnulib/patches/755-clean-temp-hashkey.patch new file mode 100644 index 0000000000..7a4774c9b3 --- /dev/null +++ b/tools/gnulib/patches/755-clean-temp-hashkey.patch @@ -0,0 +1,64 @@ +From f47c5f2e21d0ccedb271b406e35b6963b23a64c4 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Wed, 30 Apr 2025 13:11:01 +0200 +Subject: [PATCH] clean-temp: Fix link error (regression yesterday). + +* lib/clean-temp.c: Include hashkey-string.h. +(create_temp_dir): Use hashkey_string_* functions instead of +clean_temp_string_*. +* lib/clean-temp-private.h (clean_temp_string_equals, +clean_temp_string_hash): Remove declarations. +* modules/clean-temp (Depends-on): Add hashkey-string. +--- + ChangeLog | 10 ++++++++++ + lib/clean-temp-private.h | 3 --- + lib/clean-temp.c | 5 +++-- + modules/clean-temp | 1 + + 4 files changed, 14 insertions(+), 5 deletions(-) + +--- a/lib/clean-temp-private.h ++++ b/lib/clean-temp-private.h +@@ -68,9 +68,6 @@ struct closeable_fd + #define descriptors clean_temp_descriptors + extern gl_list_t /* */ volatile descriptors; + +-extern bool clean_temp_string_equals (const void *x1, const void *x2); +-extern size_t clean_temp_string_hash (const void *x); +- + extern _GL_ASYNC_SAFE int clean_temp_asyncsafe_close (struct closeable_fd *element); + extern void clean_temp_init_asyncsafe_close (void); + +--- a/lib/clean-temp.c ++++ b/lib/clean-temp.c +@@ -45,6 +45,7 @@ + #include "xmalloca.h" + #include "glthread/lock.h" + #include "thread-optim.h" ++#include "hashkey-string.h" + #include "gl_xlist.h" + #include "gl_linkedhash_list.h" + #include "gl_linked_list.h" +@@ -221,11 +222,11 @@ create_temp_dir (const char *prefix, con + tmpdir->cleanup_verbose = cleanup_verbose; + tmpdir->subdirs = + gl_list_create_empty (GL_LINKEDHASH_LIST, +- clean_temp_string_equals, clean_temp_string_hash, ++ hashkey_string_equals, hashkey_string_hash, + NULL, false); + tmpdir->files = + gl_list_create_empty (GL_LINKEDHASH_LIST, +- clean_temp_string_equals, clean_temp_string_hash, ++ hashkey_string_equals, hashkey_string_hash, + NULL, false); + + /* Create the temporary directory. */ +--- a/modules/clean-temp ++++ b/modules/clean-temp +@@ -24,6 +24,7 @@ rmdir + xalloc + xalloc-die + xmalloca ++hashkey-string + linkedhash-list + linked-list + xlist diff --git a/tools/gnulib/patches/795-string-desc-rename-functions.patch b/tools/gnulib/patches/795-string-desc-rename-functions.patch new file mode 100644 index 0000000000..032545b063 --- /dev/null +++ b/tools/gnulib/patches/795-string-desc-rename-functions.patch @@ -0,0 +1,1137 @@ +From 9a26e7043fa95b4c9ee4576ce8c0ac15668e695e Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Thu, 2 Jan 2025 13:54:54 +0100 +Subject: [PATCH] string-desc, xstring-desc, string-desc-quotearg: Rename + functions. + +* lib/string-desc.h (sd_equals): Renamed from string_desc_equals. +(sd_startswith): Renamed from string_desc_startswith. +(sd_endswith): Renamed from string_desc_endswith. +(sd_cmp): Renamed from string_desc_cmp. +(sd_c_casecmp): Renamed from string_desc_c_casecmp. +(sd_index): Renamed from string_desc_index. +(sd_last_index): Renamed from string_desc_last_index. +(sd_contains): Renamed from string_desc_contains. +(sd_new_empty): Renamed from string_desc_new_empty. +(sd_new_addr): Renamed from string_desc_new_addr. +(sd_from_c): Renamed from string_desc_from_c. +(sd_substring): Renamed from string_desc_substring. +(sd_write): Renamed from string_desc_write. +(sd_fwrite): Renamed from string_desc_fwrite. +(sd_new): Renamed from string_desc_new. +(sd_new_filled): Renamed from string_desc_new_filled. +(sd_copy): Renamed from string_desc_copy. +(sd_concat): Renamed from string_desc_concat. +(sd_c): Renamed from string_desc_c. +(sd_set_char_at): Renamed from string_desc_set_char_at. +(sd_fill): Renamed from string_desc_fill. +(sd_overwrite): Renamed from string_desc_overwrite. +(sd_free): Renamed from string_desc_free. +(sd_length): Renamed from string_desc_length. +(sd_char_at): Renamed from string_desc_char_at. +(sd_data): Renamed from string_desc_data. +(sd_is_empty): Renamed from string_desc_is_empty. +* lib/string-desc.c (sd_equals): Renamed from string_desc_equals. +(sd_startswith): Renamed from string_desc_startswith. +(sd_endswith): Renamed from string_desc_endswith. +(sd_cmp): Renamed from string_desc_cmp. +(sd_c_casecmp): Renamed from string_desc_c_casecmp. +(sd_index): Renamed from string_desc_index. +(sd_last_index): Renamed from string_desc_last_index. +(sd_new_empty): Renamed from string_desc_new_empty. +(sd_new_addr): Renamed from string_desc_new_addr. +(sd_from_c): Renamed from string_desc_from_c. +(sd_substring): Renamed from string_desc_substring. +(sd_write): Renamed from string_desc_write. +(sd_fwrite): Renamed from string_desc_fwrite. +(sd_new): Renamed from string_desc_new. +(sd_new_filled): Renamed from string_desc_new_filled. +(sd_copy): Renamed from string_desc_copy. +(sd_concat): Renamed from string_desc_concat. +(sd_c): Renamed from string_desc_c. +(sd_set_char_at): Renamed from string_desc_set_char_at. +(sd_fill): Renamed from string_desc_fill. +(sd_overwrite): Renamed from string_desc_overwrite. +(sd_free): Renamed from string_desc_free. +* lib/xstring-desc.h (xsd_concat): Renamed from xstring_desc_concat. +(xsd_new): Renamed from xstring_desc_new. +(xsd_new_filled): Renamed from xstring_desc_new_filled. +(xsd_copy): Renamed from xstring_desc_copy. +(xsd_c): Renamed from xstring_desc_c. +* lib/xstring-desc.c (xsd_concat): Renamed from xstring_desc_concat. +* lib/string-desc-quotearg.h (sd_quotearg_buffer): Renamed from +string_desc_quotearg_buffer. +(sd_quotearg_alloc): Renamed from string_desc_quotearg_alloc. +(sd_quotearg_n): Renamed from string_desc_quotearg_n. +(sd_quotearg): Renamed from string_desc_quotearg. +(sd_quotearg_n_style): Renamed from string_desc_quotearg_n_style. +(sd_quotearg_style): Renamed from string_desc_quotearg_style. +(sd_quotearg_char): Renamed from string_desc_quotearg_char. +(sd_quotearg_colon): Renamed from string_desc_quotearg_colon. +(sd_quotearg_n_custom): Renamed from string_desc_quotearg_n_custom. +(sd_quotearg_custom): Renamed from sd_quotearg_n_custom. +* lib/string-desc-contains.c (sd_contains): Renamed from +string_desc_contains. +* lib/string-buffer.h: Update. +* lib/string-buffer.c (sb_append_desc, sb_contents, sb_dupfree): Update. +* lib/xstring-buffer.c (sb_xdupfree): Update. +* lib/sf-istream.c (sf_istream_init_from_string_desc): Update. +* tests/test-string-desc.c (main): Update. +* tests/test-string-desc.sh: Update. +* tests/test-xstring-desc.c (main): Update. +* tests/test-string-desc-quotearg.c (main): Update. +* tests/test-string-buffer.c (main): Update. +* tests/test-sf-istream.c (main): Update. +* tests/test-sfl-istream.c (main): Update. +* doc/string-desc.texi: Update. +* doc/strings.texi: Update. +* NEWS: Mention the change. +--- + ChangeLog | 86 +++++++++ + NEWS | 4 + + doc/string-desc.texi | 4 +- + doc/strings.texi | 18 +- + lib/sf-istream.c | 4 +- + lib/string-buffer.c | 12 +- + lib/string-buffer.h | 4 +- + lib/string-desc-contains.c | 2 +- + lib/string-desc-quotearg.h | 114 ++++++------ + lib/string-desc.c | 52 +++--- + lib/string-desc.h | 62 +++---- + lib/xstring-buffer.c | 4 +- + lib/xstring-desc.c | 2 +- + lib/xstring-desc.h | 26 +-- + tests/test-sf-istream.c | 4 +- + tests/test-sfl-istream.c | 4 +- + tests/test-string-buffer.c | 18 +- + tests/test-string-desc-quotearg.c | 44 ++--- + tests/test-string-desc.c | 296 +++++++++++++++--------------- + tests/test-string-desc.sh | 4 +- + tests/test-xstring-desc.c | 68 +++---- + 21 files changed, 461 insertions(+), 371 deletions(-) + +--- a/lib/sf-istream.c ++++ b/lib/sf-istream.c +@@ -46,8 +46,8 @@ sf_istream_init_from_string_desc (sf_ist + string_desc_t input) + { + stream->fp = NULL; +- stream->input = string_desc_data (input); +- stream->input_end = stream->input + string_desc_length (input); ++ stream->input = sd_data (input); ++ stream->input_end = stream->input + sd_length (input); + } + + int +--- a/lib/string-buffer.c ++++ b/lib/string-buffer.c +@@ -101,13 +101,13 @@ sb_append1 (struct string_buffer *buffer + int + sb_append_desc (struct string_buffer *buffer, string_desc_t s) + { +- size_t len = string_desc_length (s); ++ size_t len = sd_length (s); + if (sb_ensure_more_bytes (buffer, len) < 0) + { + buffer->error = true; + return -1; + } +- memcpy (buffer->data + buffer->length, string_desc_data (s), len); ++ memcpy (buffer->data + buffer->length, sd_data (s), len); + buffer->length += len; + return 0; + } +@@ -136,7 +136,7 @@ sb_free (struct string_buffer *buffer) + string_desc_t + sb_contents (struct string_buffer *buffer) + { +- return string_desc_new_addr (buffer->length, buffer->data); ++ return sd_new_addr (buffer->length, buffer->data); + } + + const char * +@@ -162,7 +162,7 @@ sb_dupfree (struct string_buffer *buffer + if (copy == NULL) + goto fail; + memcpy (copy, buffer->data, length); +- return string_desc_new_addr (length, copy); ++ return sd_new_addr (length, copy); + } + else + { +@@ -174,12 +174,12 @@ sb_dupfree (struct string_buffer *buffer + if (contents == NULL) + goto fail; + } +- return string_desc_new_addr (length, contents); ++ return sd_new_addr (length, contents); + } + + fail: + sb_free (buffer); +- return string_desc_new_addr (0, NULL); ++ return sd_new_addr (0, NULL); + } + + char * +--- a/lib/string-buffer.h ++++ b/lib/string-buffer.h +@@ -115,7 +115,7 @@ extern const char * sb_contents_c (struc + + /* Returns the contents of BUFFER and frees all other memory held by BUFFER. + Returns NULL upon failure or if there was an error earlier. +- It is the responsibility of the caller to string_desc_free() the result. */ ++ It is the responsibility of the caller to sd_free() the result. */ + extern string_desc_t sb_dupfree (struct string_buffer *buffer) + _GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data); + +@@ -182,7 +182,7 @@ extern const char * sb_xcontents_c (stru + + /* Returns the contents of BUFFER and frees all other memory held by BUFFER. + Returns (0, NULL) if there was an error earlier. +- It is the responsibility of the caller to string_desc_free() the result. */ ++ It is the responsibility of the caller to sd_free() the result. */ + extern string_desc_t sb_xdupfree (struct string_buffer *buffer) + _GL_ATTRIBUTE_RELEASE_CAPABILITY (buffer->data); + +--- a/lib/string-desc-contains.c ++++ b/lib/string-desc-contains.c +@@ -31,7 +31,7 @@ + which — depending on platforms — costs up to 2 KB of binary code. */ + + ptrdiff_t +-string_desc_contains (string_desc_t haystack, string_desc_t needle) ++sd_contains (string_desc_t haystack, string_desc_t needle) + { + if (needle._nbytes == 0) + return 0; +--- a/lib/string-desc-quotearg.h ++++ b/lib/string-desc-quotearg.h +@@ -50,22 +50,22 @@ extern "C" { + does not use backslash escapes and the flags of O do not request + elision of null bytes. */ + #if 0 +-extern size_t string_desc_quotearg_buffer (char *restrict buffer, +- size_t buffersize, +- string_desc_t arg, +- struct quoting_options const *o); ++extern size_t sd_quotearg_buffer (char *restrict buffer, ++ size_t buffersize, ++ string_desc_t arg, ++ struct quoting_options const *o); + #endif + +-/* Like string_desc_quotearg_buffer, except return the result in a newly ++/* Like sd_quotearg_buffer, except return the result in a newly + allocated buffer and store its length, excluding the terminating null + byte, in *SIZE. It is the caller's responsibility to free the result. + The result might contain embedded null bytes if the style of O does + not use backslash escapes and the flags of O do not request elision + of null bytes. */ + #if 0 +-extern char *string_desc_quotearg_alloc (string_desc_t arg, +- size_t *size, +- struct quoting_options const *o) ++extern char *sd_quotearg_alloc (string_desc_t arg, ++ size_t *size, ++ struct quoting_options const *o) + _GL_ATTRIBUTE_NONNULL ((2)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE + _GL_ATTRIBUTE_RETURNS_NONNULL; +@@ -77,68 +77,68 @@ extern char *string_desc_quotearg_alloc + reused by the next call to this function with the same value of N. + N must be nonnegative. */ + #if 0 +-extern char *string_desc_quotearg_n (int n, string_desc_t arg); ++extern char *sd_quotearg_n (int n, string_desc_t arg); + #endif + +-/* Equivalent to string_desc_quotearg_n (0, ARG). */ ++/* Equivalent to sd_quotearg_n (0, ARG). */ + #if 0 +-extern char *string_desc_quotearg (string_desc_t arg); ++extern char *sd_quotearg (string_desc_t arg); + #endif + + /* Use style S and storage slot N to return a quoted version of the string ARG. +- This is like string_desc_quotearg_n (N, ARG), except that it uses S ++ This is like sd_quotearg_n (N, ARG), except that it uses S + with no other options to specify the quoting method. */ + #if 0 +-extern char *string_desc_quotearg_n_style (int n, enum quoting_style s, +- string_desc_t arg); ++extern char *sd_quotearg_n_style (int n, enum quoting_style s, ++ string_desc_t arg); + #endif + +-/* Equivalent to string_desc_quotearg_n_style (0, S, ARG). */ ++/* Equivalent to sd_quotearg_n_style (0, S, ARG). */ + #if 0 +-extern char *string_desc_quotearg_style (enum quoting_style s, +- string_desc_t arg); ++extern char *sd_quotearg_style (enum quoting_style s, ++ string_desc_t arg); + #endif + +-/* Like string_desc_quotearg (ARG), except also quote any instances of CH. ++/* Like sd_quotearg (ARG), except also quote any instances of CH. + See set_char_quoting for a description of acceptable CH values. */ + #if 0 +-extern char *string_desc_quotearg_char (string_desc_t arg, char ch); ++extern char *sd_quotearg_char (string_desc_t arg, char ch); + #endif + +-/* Equivalent to string_desc_quotearg_char (ARG, ':'). */ ++/* Equivalent to sd_quotearg_char (ARG, ':'). */ + #if 0 +-extern char *string_desc_quotearg_colon (string_desc_t arg); ++extern char *sd_quotearg_colon (string_desc_t arg); + #endif + +-/* Like string_desc_quotearg_n_style (N, S, ARG) but with S as ++/* Like sd_quotearg_n_style (N, S, ARG) but with S as + custom_quoting_style with left quote as LEFT_QUOTE and right quote + as RIGHT_QUOTE. See set_custom_quoting for a description of acceptable + LEFT_QUOTE and RIGHT_QUOTE values. */ + #if 0 +-extern char *string_desc_quotearg_n_custom (int n, +- char const *left_quote, +- char const *right_quote, +- string_desc_t arg); ++extern char *sd_quotearg_n_custom (int n, ++ char const *left_quote, ++ char const *right_quote, ++ string_desc_t arg); + #endif + + /* Equivalent to +- string_desc_quotearg_n_custom (0, LEFT_QUOTE, RIGHT_QUOTE, ARG). */ ++ sd_quotearg_n_custom (0, LEFT_QUOTE, RIGHT_QUOTE, ARG). */ + #if 0 +-extern char *string_desc_quotearg_custom (char const *left_quote, +- char const *right_quote, +- string_desc_t arg); ++extern char *sd_quotearg_custom (char const *left_quote, ++ char const *right_quote, ++ string_desc_t arg); + #endif + + + /* ==== Inline function definitions ==== */ + + GL_STRING_DESC_QUOTEARG_INLINE size_t +-string_desc_quotearg_buffer (char *restrict buffer, size_t buffersize, +- string_desc_t arg, +- struct quoting_options const *o) ++sd_quotearg_buffer (char *restrict buffer, size_t buffersize, ++ string_desc_t arg, ++ struct quoting_options const *o) + { + return quotearg_buffer (buffer, buffersize, +- string_desc_data (arg), string_desc_length (arg), ++ sd_data (arg), sd_length (arg), + o); + } + +@@ -147,69 +147,69 @@ _GL_ATTRIBUTE_NONNULL ((2)) + _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE + _GL_ATTRIBUTE_RETURNS_NONNULL + char * +-string_desc_quotearg_alloc (string_desc_t arg, +- size_t *size, +- struct quoting_options const *o) ++sd_quotearg_alloc (string_desc_t arg, ++ size_t *size, ++ struct quoting_options const *o) + { +- return quotearg_alloc_mem (string_desc_data (arg), string_desc_length (arg), ++ return quotearg_alloc_mem (sd_data (arg), sd_length (arg), + size, + o); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_n (int n, string_desc_t arg) ++sd_quotearg_n (int n, string_desc_t arg) + { +- return quotearg_n_mem (n, string_desc_data (arg), string_desc_length (arg)); ++ return quotearg_n_mem (n, sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg (string_desc_t arg) ++sd_quotearg (string_desc_t arg) + { +- return quotearg_mem (string_desc_data (arg), string_desc_length (arg)); ++ return quotearg_mem (sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_n_style (int n, enum quoting_style s, string_desc_t arg) ++sd_quotearg_n_style (int n, enum quoting_style s, string_desc_t arg) + { + return quotearg_n_style_mem (n, s, +- string_desc_data (arg), string_desc_length (arg)); ++ sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_style (enum quoting_style s, string_desc_t arg) ++sd_quotearg_style (enum quoting_style s, string_desc_t arg) + { + return quotearg_style_mem (s, +- string_desc_data (arg), string_desc_length (arg)); ++ sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_char (string_desc_t arg, char ch) ++sd_quotearg_char (string_desc_t arg, char ch) + { +- return quotearg_char_mem (string_desc_data (arg), string_desc_length (arg), ++ return quotearg_char_mem (sd_data (arg), sd_length (arg), + ch); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_colon (string_desc_t arg) ++sd_quotearg_colon (string_desc_t arg) + { +- return quotearg_colon_mem (string_desc_data (arg), string_desc_length (arg)); ++ return quotearg_colon_mem (sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_n_custom (int n, +- char const *left_quote, char const *right_quote, +- string_desc_t arg) ++sd_quotearg_n_custom (int n, ++ char const *left_quote, char const *right_quote, ++ string_desc_t arg) + { + return quotearg_n_custom_mem (n, left_quote, right_quote, +- string_desc_data (arg), string_desc_length (arg)); ++ sd_data (arg), sd_length (arg)); + } + + GL_STRING_DESC_QUOTEARG_INLINE char * +-string_desc_quotearg_custom (char const *left_quote, char const *right_quote, +- string_desc_t arg) ++sd_quotearg_custom (char const *left_quote, char const *right_quote, ++ string_desc_t arg) + { + return quotearg_custom_mem (left_quote, right_quote, +- string_desc_data (arg), string_desc_length (arg)); ++ sd_data (arg), sd_length (arg)); + } + + +--- a/lib/string-desc.c ++++ b/lib/string-desc.c +@@ -39,14 +39,14 @@ + + /* Return true if A and B are equal. */ + bool +-string_desc_equals (string_desc_t a, string_desc_t b) ++sd_equals (string_desc_t a, string_desc_t b) + { + return (a._nbytes == b._nbytes + && (a._nbytes == 0 || memcmp (a._data, b._data, a._nbytes) == 0)); + } + + bool +-string_desc_startswith (string_desc_t s, string_desc_t prefix) ++sd_startswith (string_desc_t s, string_desc_t prefix) + { + return (s._nbytes >= prefix._nbytes + && (prefix._nbytes == 0 +@@ -54,7 +54,7 @@ string_desc_startswith (string_desc_t s, + } + + bool +-string_desc_endswith (string_desc_t s, string_desc_t suffix) ++sd_endswith (string_desc_t s, string_desc_t suffix) + { + return (s._nbytes >= suffix._nbytes + && (suffix._nbytes == 0 +@@ -63,7 +63,7 @@ string_desc_endswith (string_desc_t s, s + } + + int +-string_desc_cmp (string_desc_t a, string_desc_t b) ++sd_cmp (string_desc_t a, string_desc_t b) + { + if (a._nbytes > b._nbytes) + { +@@ -86,14 +86,14 @@ string_desc_cmp (string_desc_t a, string + } + + int +-string_desc_c_casecmp (string_desc_t a, string_desc_t b) ++sd_c_casecmp (string_desc_t a, string_desc_t b) + { + /* Don't use memcasecmp here, since it uses the current locale, not the + "C" locale. */ +- idx_t an = string_desc_length (a); +- idx_t bn = string_desc_length (b); +- const char *ap = string_desc_data (a); +- const char *bp = string_desc_data (b); ++ idx_t an = sd_length (a); ++ idx_t bn = sd_length (b); ++ const char *ap = sd_data (a); ++ const char *bp = sd_data (b); + idx_t n = (an < bn ? an : bn); + idx_t i; + for (i = 0; i < n; i++) +@@ -108,7 +108,7 @@ string_desc_c_casecmp (string_desc_t a, + } + + ptrdiff_t +-string_desc_index (string_desc_t s, char c) ++sd_index (string_desc_t s, char c) + { + if (s._nbytes > 0) + { +@@ -120,7 +120,7 @@ string_desc_index (string_desc_t s, char + } + + ptrdiff_t +-string_desc_last_index (string_desc_t s, char c) ++sd_last_index (string_desc_t s, char c) + { + if (s._nbytes > 0) + { +@@ -132,7 +132,7 @@ string_desc_last_index (string_desc_t s, + } + + string_desc_t +-string_desc_new_empty (void) ++sd_new_empty (void) + { + string_desc_t result; + +@@ -144,7 +144,7 @@ string_desc_new_empty (void) + } + + string_desc_t +-string_desc_new_addr (idx_t n, char *addr) ++sd_new_addr (idx_t n, char *addr) + { + string_desc_t result; + +@@ -158,7 +158,7 @@ string_desc_new_addr (idx_t n, char *add + } + + string_desc_t +-string_desc_from_c (const char *s) ++sd_from_c (const char *s) + { + string_desc_t result; + +@@ -169,7 +169,7 @@ string_desc_from_c (const char *s) + } + + string_desc_t +-string_desc_substring (string_desc_t s, idx_t start, idx_t end) ++sd_substring (string_desc_t s, idx_t start, idx_t end) + { + string_desc_t result; + +@@ -184,7 +184,7 @@ string_desc_substring (string_desc_t s, + } + + int +-string_desc_write (int fd, string_desc_t s) ++sd_write (int fd, string_desc_t s) + { + if (s._nbytes > 0) + if (full_write (fd, s._data, s._nbytes) != s._nbytes) +@@ -194,7 +194,7 @@ string_desc_write (int fd, string_desc_t + } + + int +-string_desc_fwrite (FILE *fp, string_desc_t s) ++sd_fwrite (FILE *fp, string_desc_t s) + { + if (s._nbytes > 0) + if (fwrite (s._data, 1, s._nbytes, fp) != s._nbytes) +@@ -206,7 +206,7 @@ string_desc_fwrite (FILE *fp, string_des + /* ==== Memory-allocating operations on string descriptors ==== */ + + int +-string_desc_new (string_desc_t *resultp, idx_t n) ++sd_new (string_desc_t *resultp, idx_t n) + { + string_desc_t result; + +@@ -230,7 +230,7 @@ string_desc_new (string_desc_t *resultp, + } + + int +-string_desc_new_filled (string_desc_t *resultp, idx_t n, char c) ++sd_new_filled (string_desc_t *resultp, idx_t n, char c) + { + string_desc_t result; + +@@ -251,7 +251,7 @@ string_desc_new_filled (string_desc_t *r + } + + int +-string_desc_copy (string_desc_t *resultp, string_desc_t s) ++sd_copy (string_desc_t *resultp, string_desc_t s) + { + string_desc_t result; + idx_t n = s._nbytes; +@@ -273,7 +273,7 @@ string_desc_copy (string_desc_t *resultp + } + + int +-string_desc_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...) ++sd_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...) + { + if (n <= 0) + /* Invalid argument. */ +@@ -327,7 +327,7 @@ string_desc_concat (string_desc_t *resul + } + + char * +-string_desc_c (string_desc_t s) ++sd_c (string_desc_t s) + { + idx_t n = s._nbytes; + char *result = (char *) imalloc (n + 1); +@@ -345,7 +345,7 @@ string_desc_c (string_desc_t s) + /* ==== Operations with side effects on string descriptors ==== */ + + void +-string_desc_set_char_at (string_desc_t s, idx_t i, char c) ++sd_set_char_at (string_desc_t s, idx_t i, char c) + { + if (!(i >= 0 && i < s._nbytes)) + /* Invalid argument. */ +@@ -354,7 +354,7 @@ string_desc_set_char_at (string_desc_t s + } + + void +-string_desc_fill (string_desc_t s, idx_t start, idx_t end, char c) ++sd_fill (string_desc_t s, idx_t start, idx_t end, char c) + { + if (!(start >= 0 && start <= end)) + /* Invalid arguments. */ +@@ -365,7 +365,7 @@ string_desc_fill (string_desc_t s, idx_t + } + + void +-string_desc_overwrite (string_desc_t s, idx_t start, string_desc_t t) ++sd_overwrite (string_desc_t s, idx_t start, string_desc_t t) + { + if (!(start >= 0 && start + t._nbytes <= s._nbytes)) + /* Invalid arguments. */ +@@ -376,7 +376,7 @@ string_desc_overwrite (string_desc_t s, + } + + void +-string_desc_free (string_desc_t s) ++sd_free (string_desc_t s) + { + free (s._data); + } +--- a/lib/string-desc.h ++++ b/lib/string-desc.h +@@ -69,82 +69,82 @@ struct string_desc_t + + /* Return the length of the string S. */ + #if 0 /* Defined inline below. */ +-extern idx_t string_desc_length (string_desc_t s); ++extern idx_t sd_length (string_desc_t s); + #endif + + /* Return the byte at index I of string S. + I must be < length(S). */ + #if 0 /* Defined inline below. */ +-extern char string_desc_char_at (string_desc_t s, idx_t i); ++extern char sd_char_at (string_desc_t s, idx_t i); + #endif + + /* Return a read-only view of the bytes of S. */ + #if 0 /* Defined inline below. */ +-extern const char * string_desc_data (string_desc_t s); ++extern const char * sd_data (string_desc_t s); + #endif + + /* Return true if S is the empty string. */ + #if 0 /* Defined inline below. */ +-extern bool string_desc_is_empty (string_desc_t s); ++extern bool sd_is_empty (string_desc_t s); + #endif + + /* Return true if A and B are equal. */ +-extern bool string_desc_equals (string_desc_t a, string_desc_t b); ++extern bool sd_equals (string_desc_t a, string_desc_t b); + + /* Return true if S starts with PREFIX. */ +-extern bool string_desc_startswith (string_desc_t s, string_desc_t prefix); ++extern bool sd_startswith (string_desc_t s, string_desc_t prefix); + + /* Return true if S ends with SUFFIX. */ +-extern bool string_desc_endswith (string_desc_t s, string_desc_t suffix); ++extern bool sd_endswith (string_desc_t s, string_desc_t suffix); + + /* Return > 0, == 0, or < 0 if A > B, A == B, A < B. + This uses a lexicographic ordering, where the bytes are compared as + 'unsigned char'. */ +-extern int string_desc_cmp (string_desc_t a, string_desc_t b); ++extern int sd_cmp (string_desc_t a, string_desc_t b); + + /* Return > 0, == 0, or < 0 if A > B, A == B, A < B. + Either A or B must be entirely ASCII. + This uses a lexicographic ordering, where the bytes are compared as + 'unsigned char', ignoring case, in the "C" locale. */ +-extern int string_desc_c_casecmp (string_desc_t a, string_desc_t b); ++extern int sd_c_casecmp (string_desc_t a, string_desc_t b); + + /* Return the index of the first occurrence of C in S, + or -1 if there is none. */ +-extern ptrdiff_t string_desc_index (string_desc_t s, char c); ++extern ptrdiff_t sd_index (string_desc_t s, char c); + + /* Return the index of the last occurrence of C in S, + or -1 if there is none. */ +-extern ptrdiff_t string_desc_last_index (string_desc_t s, char c); ++extern ptrdiff_t sd_last_index (string_desc_t s, char c); + + /* Return the index of the first occurrence of NEEDLE in HAYSTACK, + or -1 if there is none. */ +-extern ptrdiff_t string_desc_contains (string_desc_t haystack, string_desc_t needle); ++extern ptrdiff_t sd_contains (string_desc_t haystack, string_desc_t needle); + + /* Return an empty string. */ +-extern string_desc_t string_desc_new_empty (void); ++extern string_desc_t sd_new_empty (void); + + /* Construct and return a string of length N, at the given memory address. */ +-extern string_desc_t string_desc_new_addr (idx_t n, char *addr); ++extern string_desc_t sd_new_addr (idx_t n, char *addr); + + /* Return a string that represents the C string S, of length strlen (S). */ +-extern string_desc_t string_desc_from_c (const char *s); ++extern string_desc_t sd_from_c (const char *s); + + /* Return the substring of S, starting at offset START and ending at offset END. + START must be <= END. + The result is of length END - START. + The result must not be freed (since its storage is part of the storage + of S). */ +-extern string_desc_t string_desc_substring (string_desc_t s, idx_t start, idx_t end); ++extern string_desc_t sd_substring (string_desc_t s, idx_t start, idx_t end); + + /* Output S to the file descriptor FD. + Return 0 if successful. + Upon error, return -1 with errno set. */ +-extern int string_desc_write (int fd, string_desc_t s); ++extern int sd_write (int fd, string_desc_t s); + + /* Output S to the FILE stream FP. + Return 0 if successful. + Upon error, return -1. */ +-extern int string_desc_fwrite (FILE *fp, string_desc_t s); ++extern int sd_fwrite (FILE *fp, string_desc_t s); + + + /* ==== Memory-allocating operations on string descriptors ==== */ +@@ -153,61 +153,61 @@ extern int string_desc_fwrite (FILE *fp, + Return 0 if successful. + Upon error, return -1 with errno set. */ + _GL_ATTRIBUTE_NODISCARD +-extern int string_desc_new (string_desc_t *resultp, idx_t n); ++extern int sd_new (string_desc_t *resultp, idx_t n); + + /* Construct a string of length N, filled with C. + Return 0 if successful. + Upon error, return -1 with errno set. */ + _GL_ATTRIBUTE_NODISCARD +-extern int string_desc_new_filled (string_desc_t *resultp, idx_t n, char c); ++extern int sd_new_filled (string_desc_t *resultp, idx_t n, char c); + + /* Construct a copy of string S. + Return 0 if successful. + Upon error, return -1 with errno set. */ + _GL_ATTRIBUTE_NODISCARD +-extern int string_desc_copy (string_desc_t *resultp, string_desc_t s); ++extern int sd_copy (string_desc_t *resultp, string_desc_t s); + + /* Construct the concatenation of N strings. N must be > 0. + Return 0 if successful. + Upon error, return -1 with errno set. */ + _GL_ATTRIBUTE_NODISCARD +-extern int string_desc_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...); ++extern int sd_concat (string_desc_t *resultp, idx_t n, string_desc_t string1, ...); + + /* Construct a copy of string S, as a NUL-terminated C string. + Return it is successful. + Upon error, return NULL with errno set. */ +-extern char * string_desc_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE; ++extern char * sd_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE; + + + /* ==== Operations with side effects on string descriptors ==== */ + + /* Overwrite the byte at index I of string S with C. + I must be < length(S). */ +-extern void string_desc_set_char_at (string_desc_t s, idx_t i, char c); ++extern void sd_set_char_at (string_desc_t s, idx_t i, char c); + + /* Fill part of S, starting at offset START and ending at offset END, + with copies of C. + START must be <= END. */ +-extern void string_desc_fill (string_desc_t s, idx_t start, idx_t end, char c); ++extern void sd_fill (string_desc_t s, idx_t start, idx_t end, char c); + + /* Overwrite part of S with T, starting at offset START. + START + length(T) must be <= length (S). */ +-extern void string_desc_overwrite (string_desc_t s, idx_t start, string_desc_t t); ++extern void sd_overwrite (string_desc_t s, idx_t start, string_desc_t t); + + /* Free S. */ +-extern void string_desc_free (string_desc_t s); ++extern void sd_free (string_desc_t s); + + + /* ==== Inline function definitions ==== */ + + GL_STRING_DESC_INLINE idx_t +-string_desc_length (string_desc_t s) ++sd_length (string_desc_t s) + { + return s._nbytes; + } + + GL_STRING_DESC_INLINE char +-string_desc_char_at (string_desc_t s, idx_t i) ++sd_char_at (string_desc_t s, idx_t i) + { + if (!(i >= 0 && i < s._nbytes)) + /* Invalid argument. */ +@@ -216,13 +216,13 @@ string_desc_char_at (string_desc_t s, id + } + + GL_STRING_DESC_INLINE const char * +-string_desc_data (string_desc_t s) ++sd_data (string_desc_t s) + { + return s._data; + } + + GL_STRING_DESC_INLINE bool +-string_desc_is_empty (string_desc_t s) ++sd_is_empty (string_desc_t s) + { + return s._nbytes == 0; + } +--- a/lib/xstring-buffer.c ++++ b/lib/xstring-buffer.c +@@ -59,10 +59,10 @@ sb_xdupfree (struct string_buffer *buffe + if (buffer->error) + { + sb_free (buffer); +- return string_desc_new_addr (0, NULL); ++ return sd_new_addr (0, NULL); + } + string_desc_t contents = sb_dupfree (buffer); +- if (string_desc_data (contents) == NULL) ++ if (sd_data (contents) == NULL) + xalloc_die (); + return contents; + } +--- a/lib/xstring-desc.c ++++ b/lib/xstring-desc.c +@@ -22,7 +22,7 @@ + #include "ialloc.h" + + string_desc_t +-xstring_desc_concat (idx_t n, string_desc_t string1, ...) ++xsd_concat (idx_t n, string_desc_t string1, ...) + { + if (n <= 0) + /* Invalid argument. */ +--- a/lib/xstring-desc.h ++++ b/lib/xstring-desc.h +@@ -43,53 +43,53 @@ extern "C" { + + /* Return a string of length N, with uninitialized contents. */ + #if 0 /* Defined inline below. */ +-extern string_desc_t xstring_desc_new (idx_t n); ++extern string_desc_t xsd_new (idx_t n); + #endif + + /* Return a string of length N, filled with C. */ + #if 0 /* Defined inline below. */ +-extern string_desc_t xstring_desc_new_filled (idx_t n, char c); ++extern string_desc_t xsd_new_filled (idx_t n, char c); + #endif + + /* Return a copy of string S. */ + #if 0 /* Defined inline below. */ +-extern string_desc_t xstring_desc_copy (string_desc_t s); ++extern string_desc_t xsd_copy (string_desc_t s); + #endif + + /* Return the concatenation of N strings. N must be > 0. */ +-extern string_desc_t xstring_desc_concat (idx_t n, string_desc_t string1, ...); ++extern string_desc_t xsd_concat (idx_t n, string_desc_t string1, ...); + + /* Construct and return a copy of string S, as a NUL-terminated C string. */ + #if 0 /* Defined inline below. */ +-extern char * xstring_desc_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE; ++extern char * xsd_c (string_desc_t s) _GL_ATTRIBUTE_DEALLOC_FREE; + #endif + + + /* ==== Inline function definitions ==== */ + + GL_XSTRING_DESC_INLINE string_desc_t +-xstring_desc_new (idx_t n) ++xsd_new (idx_t n) + { + string_desc_t result; +- if (string_desc_new (&result, n) < 0) ++ if (sd_new (&result, n) < 0) + xalloc_die (); + return result; + } + + GL_XSTRING_DESC_INLINE string_desc_t +-xstring_desc_new_filled (idx_t n, char c) ++xsd_new_filled (idx_t n, char c) + { + string_desc_t result; +- if (string_desc_new_filled (&result, n, c) < 0) ++ if (sd_new_filled (&result, n, c) < 0) + xalloc_die (); + return result; + } + + GL_XSTRING_DESC_INLINE string_desc_t +-xstring_desc_copy (string_desc_t s) ++xsd_copy (string_desc_t s) + { + string_desc_t result; +- if (string_desc_copy (&result, s) < 0) ++ if (sd_copy (&result, s) < 0) + xalloc_die (); + return result; + } +@@ -97,9 +97,9 @@ xstring_desc_copy (string_desc_t s) + GL_XSTRING_DESC_INLINE + _GL_ATTRIBUTE_DEALLOC_FREE + char * +-xstring_desc_c (string_desc_t s) ++xsd_c (string_desc_t s) + { +- char *result = string_desc_c (s); ++ char *result = sd_c (s); + if (result == NULL) + xalloc_die (); + return result; +--- a/tests/test-string-desc-quotearg.c ++++ b/tests/test-string-desc-quotearg.c +@@ -28,75 +28,75 @@ + int + main (void) + { +- string_desc_t s1 = string_desc_from_c ("Hello world!"); +- string_desc_t s2 = string_desc_new_addr (21, "The\0quick\0brown\0\0fox"); ++ string_desc_t s1 = sd_from_c ("Hello world!"); ++ string_desc_t s2 = sd_new_addr (21, "The\0quick\0brown\0\0fox"); + +- /* Test string_desc_quotearg_buffer. */ ++ /* Test sd_quotearg_buffer. */ + { + char buf[80]; +- size_t n = string_desc_quotearg_buffer (buf, sizeof (buf), s2, NULL); ++ size_t n = sd_quotearg_buffer (buf, sizeof (buf), s2, NULL); + ASSERT (n == 21); + ASSERT (memcmp (buf, "The\0quick\0brown\0\0fox", n) == 0); + } + +- /* Test string_desc_quotearg_alloc. */ ++ /* Test sd_quotearg_alloc. */ + { + size_t n; +- char *ret = string_desc_quotearg_alloc (s2, &n, NULL); ++ char *ret = sd_quotearg_alloc (s2, &n, NULL); + ASSERT (n == 21); + ASSERT (memcmp (ret, "The\0quick\0brown\0\0fox", n) == 0); + free (ret); + } + +- /* Test string_desc_quotearg_n. */ ++ /* Test sd_quotearg_n. */ + { +- char *ret = string_desc_quotearg_n (1, s2); ++ char *ret = sd_quotearg_n (1, s2); + ASSERT (memcmp (ret, "Thequickbrownfox", 16 + 1) == 0); + } + +- /* Test string_desc_quotearg. */ ++ /* Test sd_quotearg. */ + { +- char *ret = string_desc_quotearg (s2); ++ char *ret = sd_quotearg (s2); + ASSERT (memcmp (ret, "Thequickbrownfox", 16 + 1) == 0); + } + +- /* Test string_desc_quotearg_n_style. */ ++ /* Test sd_quotearg_n_style. */ + { +- char *ret = string_desc_quotearg_n_style (1, clocale_quoting_style, s2); ++ char *ret = sd_quotearg_n_style (1, clocale_quoting_style, s2); + ASSERT (memcmp (ret, "\"The\\0quick\\0brown\\0\\0fox\\0\"", 28 + 1) == 0 + || /* if the locale has UTF-8 encoding */ + memcmp (ret, "\342\200\230The\\0quick\\0brown\\0\\0fox\\0\342\200\231", 32 + 1) == 0); + } + +- /* Test string_desc_quotearg_style. */ ++ /* Test sd_quotearg_style. */ + { +- char *ret = string_desc_quotearg_style (clocale_quoting_style, s2); ++ char *ret = sd_quotearg_style (clocale_quoting_style, s2); + ASSERT (memcmp (ret, "\"The\\0quick\\0brown\\0\\0fox\\0\"", 28 + 1) == 0 + || /* if the locale has UTF-8 encoding */ + memcmp (ret, "\342\200\230The\\0quick\\0brown\\0\\0fox\\0\342\200\231", 32 + 1) == 0); + } + +- /* Test string_desc_quotearg_char. */ ++ /* Test sd_quotearg_char. */ + { +- char *ret = string_desc_quotearg_char (s1, ' '); ++ char *ret = sd_quotearg_char (s1, ' '); + ASSERT (memcmp (ret, "Hello world!", 12 + 1) == 0); /* ' ' not quoted?! */ + } + +- /* Test string_desc_quotearg_colon. */ ++ /* Test sd_quotearg_colon. */ + { +- char *ret = string_desc_quotearg_colon (string_desc_from_c ("a:b")); ++ char *ret = sd_quotearg_colon (sd_from_c ("a:b")); + ASSERT (memcmp (ret, "a:b", 3 + 1) == 0); /* ':' not quoted?! */ + } + +- /* Test string_desc_quotearg_n_custom. */ ++ /* Test sd_quotearg_n_custom. */ + { +- char *ret = string_desc_quotearg_n_custom (2, "<", ">", s1); ++ char *ret = sd_quotearg_n_custom (2, "<", ">", s1); + ASSERT (memcmp (ret, "", 14 + 1) == 0); + } + +- /* Test string_desc_quotearg_n_custom. */ ++ /* Test sd_quotearg_n_custom. */ + { +- char *ret = string_desc_quotearg_custom ("[[", "]]", s1); ++ char *ret = sd_quotearg_custom ("[[", "]]", s1); + ASSERT (memcmp (ret, "[[Hello world!]]", 16 + 1) == 0); + } + +--- a/tests/test-string-desc.sh ++++ b/tests/test-string-desc.sh +@@ -6,7 +6,7 @@ ${CHECKER} test-string-desc${EXEEXT} tes + printf 'Hello world!The\0quick\0brown\0\0fox\0' > test-string-desc.ok + + : "${DIFF=diff}" +-${DIFF} test-string-desc.ok test-string-desc-1.tmp || { echo "string_desc_fwrite KO" 1>&2; Exit 1; } +-${DIFF} test-string-desc.ok test-string-desc-3.tmp || { echo "string_desc_write KO" 1>&2; Exit 1; } ++${DIFF} test-string-desc.ok test-string-desc-1.tmp || { echo "sd_fwrite KO" 1>&2; Exit 1; } ++${DIFF} test-string-desc.ok test-string-desc-3.tmp || { echo "sd_write KO" 1>&2; Exit 1; } + + Exit 0 +--- a/tests/test-xstring-desc.c ++++ b/tests/test-xstring-desc.c +@@ -28,53 +28,53 @@ + int + main (void) + { +- string_desc_t s0 = string_desc_new_empty (); +- string_desc_t s1 = string_desc_from_c ("Hello world!"); +- string_desc_t s2 = string_desc_new_addr (21, "The\0quick\0brown\0\0fox"); ++ string_desc_t s0 = sd_new_empty (); ++ string_desc_t s1 = sd_from_c ("Hello world!"); ++ string_desc_t s2 = sd_new_addr (21, "The\0quick\0brown\0\0fox"); + +- /* Test xstring_desc_new. */ +- string_desc_t s4 = xstring_desc_new (5); +- string_desc_set_char_at (s4, 0, 'H'); +- string_desc_set_char_at (s4, 4, 'o'); +- string_desc_set_char_at (s4, 1, 'e'); +- string_desc_fill (s4, 2, 4, 'l'); +- ASSERT (string_desc_length (s4) == 5); +- ASSERT (string_desc_startswith (s1, s4)); ++ /* Test xsd_new. */ ++ string_desc_t s4 = xsd_new (5); ++ sd_set_char_at (s4, 0, 'H'); ++ sd_set_char_at (s4, 4, 'o'); ++ sd_set_char_at (s4, 1, 'e'); ++ sd_fill (s4, 2, 4, 'l'); ++ ASSERT (sd_length (s4) == 5); ++ ASSERT (sd_startswith (s1, s4)); + +- /* Test xstring_desc_new_filled. */ +- string_desc_t s5 = xstring_desc_new_filled (5, 'l'); +- string_desc_set_char_at (s5, 0, 'H'); +- string_desc_set_char_at (s5, 4, 'o'); +- string_desc_set_char_at (s5, 1, 'e'); +- ASSERT (string_desc_length (s5) == 5); +- ASSERT (string_desc_startswith (s1, s5)); ++ /* Test xsd_new_filled. */ ++ string_desc_t s5 = xsd_new_filled (5, 'l'); ++ sd_set_char_at (s5, 0, 'H'); ++ sd_set_char_at (s5, 4, 'o'); ++ sd_set_char_at (s5, 1, 'e'); ++ ASSERT (sd_length (s5) == 5); ++ ASSERT (sd_startswith (s1, s5)); + +- /* Test xstring_desc_copy. */ ++ /* Test xsd_copy. */ + { +- string_desc_t s6 = xstring_desc_copy (s0); +- ASSERT (string_desc_is_empty (s6)); +- string_desc_free (s6); ++ string_desc_t s6 = xsd_copy (s0); ++ ASSERT (sd_is_empty (s6)); ++ sd_free (s6); + } + { +- string_desc_t s6 = xstring_desc_copy (s2); +- ASSERT (string_desc_equals (s6, s2)); +- string_desc_free (s6); ++ string_desc_t s6 = xsd_copy (s2); ++ ASSERT (sd_equals (s6, s2)); ++ sd_free (s6); + } + +- /* Test xstring_desc_concat. */ ++ /* Test xsd_concat. */ + { + string_desc_t s8 = +- xstring_desc_concat (3, string_desc_new_addr (10, "The\0quick"), +- string_desc_new_addr (7, "brown\0"), +- string_desc_new_addr (4, "fox"), +- string_desc_new_addr (7, "unused")); +- ASSERT (string_desc_equals (s8, s2)); +- string_desc_free (s8); ++ xsd_concat (3, sd_new_addr (10, "The\0quick"), ++ sd_new_addr (7, "brown\0"), ++ sd_new_addr (4, "fox"), ++ sd_new_addr (7, "unused")); ++ ASSERT (sd_equals (s8, s2)); ++ sd_free (s8); + } + +- /* Test xstring_desc_c. */ ++ /* Test xsd_c. */ + { +- char *ptr = xstring_desc_c (s2); ++ char *ptr = xsd_c (s2); + ASSERT (ptr != NULL); + ASSERT (memcmp (ptr, "The\0quick\0brown\0\0fox\0", 22) == 0); + free (ptr); diff --git a/tools/gnulib/patches/796-vc-mtime-less-read.patch b/tools/gnulib/patches/796-vc-mtime-less-read.patch new file mode 100644 index 0000000000..3fabe10369 --- /dev/null +++ b/tools/gnulib/patches/796-vc-mtime-less-read.patch @@ -0,0 +1,44 @@ +From 60cd34886c2c9f509974239fcf64a61f9a507d14 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Tue, 25 Feb 2025 09:04:28 +0100 +Subject: [PATCH] vc-mtime: Reduce number of read() system calls. + +* lib/vc-mtime.c: Include . +(git_vc_controlled): Read bytes into a buffer, not one-by-one. +--- + ChangeLog | 6 ++++++ + lib/vc-mtime.c | 15 +++++++++++---- + 2 files changed, 17 insertions(+), 4 deletions(-) + +--- a/lib/vc-mtime.c ++++ b/lib/vc-mtime.c +@@ -21,6 +21,7 @@ + /* Specification. */ + #include "vc-mtime.h" + ++#include + #include + #include + +@@ -56,11 +57,17 @@ git_vc_controlled (const char *filename) + return false; + + /* Read the subprocess output, and test whether it is non-empty. */ +- size_t count = 0; +- char c; ++ ptrdiff_t count = 0; + +- while (safe_read (fd[0], &c, 1) > 0) +- count++; ++ for (;;) ++ { ++ char buf[1024]; ++ ptrdiff_t n = safe_read (fd[0], buf, sizeof (buf)); ++ if (n > 0) ++ count += n; ++ else ++ break; ++ } + + close (fd[0]); + diff --git a/tools/gnulib/patches/797-vc-mtime-add-api.patch b/tools/gnulib/patches/797-vc-mtime-add-api.patch new file mode 100644 index 0000000000..eeb6636e67 --- /dev/null +++ b/tools/gnulib/patches/797-vc-mtime-add-api.patch @@ -0,0 +1,968 @@ +From 78269749030dde23182c29376d1410592436eb5d Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Thu, 1 May 2025 17:26:27 +0200 +Subject: [PATCH] vc-mtime: Add API for more efficient use of git. + +Reported by Serhii Tereshchenko, Arthur, Adam YS, Foucauld Degeorges +at . + +* lib/vc-mtime.h (max_vc_mtime): New declaration. +* lib/vc-mtime.c: Include , , , filename.h, +xalloc.h, xgetcwd.h, xvasprintf.h, gl_map.h, gl_xmap.h, gl_hash_map.h, +hashkey-string.h, unlocked-io.h. +(is_git_present): New function, extracted from vc_mtime. +(vc_mtime): Invoke it. +(MAX_COMMAND_LENGTH, MAX_CMD_LEN): New macros. +(abs_git_checkout): New function, based on execute_and_read_line in +lib/javacomp.c. +(ancestor_level, relativize): New functions. +(struct accumulator): New type. +(accumulate): New function. +(max_vc_mtime): New function. +(test_ancestor_level, test_relativize, main) [TEST]: New functions. +* modules/vc-mtime (Depends-on): Add filename, xalloc, xgetcwd, +canonicalize-lgpl, xvasprintf, str_startswith, map, xmap, hash-map, +hashkey-string, getdelim. +--- + ChangeLog | 23 ++ + lib/vc-mtime.c | 866 +++++++++++++++++++++++++++++++++++++++++++++-- + lib/vc-mtime.h | 7 + + modules/vc-mtime | 11 + + 4 files changed, 886 insertions(+), 21 deletions(-) + +--- a/lib/vc-mtime.c ++++ b/lib/vc-mtime.c +@@ -21,8 +21,11 @@ + /* Specification. */ + #include "vc-mtime.h" + ++#include + #include ++#include + #include ++#include + #include + + #include +@@ -32,11 +35,51 @@ + #include "safe-read.h" + #include "xstrtol.h" + #include "stat-time.h" ++#include "filename.h" ++#include "xalloc.h" ++#include "xgetcwd.h" ++#include "xvasprintf.h" ++#include "gl_map.h" ++#include "gl_xmap.h" ++#include "gl_hash_map.h" ++#include "hashkey-string.h" ++#if USE_UNLOCKED_IO ++# include "unlocked-io.h" ++#endif + #include "gettext.h" + + #define _(msgid) dgettext ("gnulib", msgid) + + ++/* ========================================================================== */ ++ ++/* Determines whether git is present. */ ++static bool ++is_git_present (void) ++{ ++ static bool git_tested; ++ static bool git_present; ++ ++ if (!git_tested) ++ { ++ /* Test for presence of git: ++ "git --version >/dev/null 2>/dev/null" */ ++ const char *argv[3]; ++ int exitstatus; ++ ++ argv[0] = "git"; ++ argv[1] = "--version"; ++ argv[2] = NULL; ++ exitstatus = execute ("git", "git", argv, NULL, NULL, ++ false, false, true, true, ++ true, false, NULL); ++ git_present = (exitstatus == 0); ++ git_tested = true; ++ } ++ ++ return git_present; ++} ++ + /* Determines whether the specified file is under version control. */ + static bool + git_vc_controlled (const char *filename) +@@ -178,27 +221,7 @@ git_mtime (struct timespec *mtime, const + int + vc_mtime (struct timespec *mtime, const char *filename) + { +- static bool git_tested; +- static bool git_present; +- +- if (!git_tested) +- { +- /* Test for presence of git: +- "git --version >/dev/null 2>/dev/null" */ +- const char *argv[3]; +- int exitstatus; +- +- argv[0] = "git"; +- argv[1] = "--version"; +- argv[2] = NULL; +- exitstatus = execute ("git", "git", argv, NULL, NULL, +- false, false, true, true, +- true, false, NULL); +- git_present = (exitstatus == 0); +- git_tested = true; +- } +- +- if (git_present ++ if (is_git_present () + && git_vc_controlled (filename) + && git_unmodified (filename)) + { +@@ -213,3 +236,804 @@ vc_mtime (struct timespec *mtime, const + } + return -1; + } ++ ++/* ========================================================================== */ ++ ++/* Maximum length of a command that is guaranteed to work. */ ++#if defined _WIN32 || defined __CYGWIN__ ++/* Windows */ ++# define MAX_COMMAND_LENGTH 8192 ++#else ++/* Unix platforms */ ++# define MAX_COMMAND_LENGTH 32768 ++#endif ++/* Keep some safe distance to this maximum. */ ++#define MAX_CMD_LEN ((int) (MAX_COMMAND_LENGTH * 0.8)) ++ ++/* Returns the directory name of the git checkout that contains tha current ++ directory, as an absolute file name, or NULL if the current directory is ++ not in a git checkout. */ ++static char * ++abs_git_checkout (void) ++{ ++ /* Run "git rev-parse --show-toplevel 2>/dev/null" and return its output, ++ without the trailing newline. */ ++ const char *argv[4]; ++ pid_t child; ++ int fd[1]; ++ ++ argv[0] = "git"; ++ argv[1] = "rev-parse"; ++ argv[2] = "--show-toplevel"; ++ argv[3] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ ++ if (child == -1) ++ return NULL; ++ ++ /* Retrieve its result. */ ++ FILE *fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ char *line = NULL; ++ size_t linesize = 0; ++ size_t linelen = getline (&line, &linesize, fp); ++ if (linelen == (size_t)(-1)) ++ { ++ fclose (fp); ++ wait_subprocess (child, "git", true, true, true, false, NULL); ++ return NULL; ++ } ++ else ++ { ++ int exitstatus; ++ ++ if (linelen > 0 && line[linelen - 1] == '\n') ++ line[linelen - 1] = '\0'; ++ ++ /* Read until EOF (otherwise the child process may get a SIGPIPE signal). */ ++ while (getc (fp) != EOF) ++ ; ++ ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ exitstatus = ++ wait_subprocess (child, "git", true, true, true, false, NULL); ++ if (exitstatus == 0) ++ return line; ++ } ++ free (line); ++ return NULL; ++} ++ ++/* Given an absolute canonicalized directory DIR1 and an absolute canonicalized ++ directory DIR2, returns N where DIR1 = DIR2 "/.." ... "/.." with N times ++ "/..", or -1 if DIR1 is not an ancestor directory of DIR2. */ ++static long ++ancestor_level (const char *dir1, const char *dir2) ++{ ++ if (strcmp (dir1, "/") == 0) ++ dir1 = ""; ++ if (strcmp (dir2, "/") == 0) ++ dir2 = ""; ++ size_t dir1_len = strlen (dir1); ++ if (strncmp (dir1, dir2, dir1_len) == 0) ++ { ++ /* DIR2 starts with DIR1. */ ++ const char *p = dir2 + dir1_len; ++ if (*p == '\0') ++ /* DIR2 and DIR1 are the same. */ ++ return 0; ++ if (ISSLASH (*p)) ++ { ++ /* Return the number of slashes in the tail of DIR2 that starts ++ at P. */ ++ long n = 1; ++ p++; ++ for (; *p != '\0'; p++) ++ if (ISSLASH (*p)) ++ n++; ++ return n; ++ } ++ } ++ return -1; ++} ++ ++/* Given an absolute canolicalized FILENAME that starts with DIR1, returns the ++ same file name relative to DIR2, where DIR1 = DIR2 "/.." ... "/.." with ++ N times "/..", as a freshly allocated string. */ ++static char * ++relativize (const char *filename, ++ unsigned long n, const char *dir1, const char *dir2) ++{ ++ if (strcmp (dir1, "/") == 0) ++ dir1 = ""; ++ size_t dir1_len = strlen (dir1); ++ if (!(strncmp (filename, dir1, dir1_len) == 0 ++ && (filename[dir1_len] == '\0' || ISSLASH (filename[dir1_len])))) ++ /* Invalid argument. */ ++ abort (); ++ if (strcmp (dir2, "/") == 0) ++ dir2 = ""; ++ ++ dir2 += dir1_len; ++ filename += dir1_len; ++ for (;;) ++ { ++ /* Invariant: The result will be N times "../" followed by FILENAME. */ ++ if (*filename == '\0') ++ break; ++ if (!ISSLASH (*filename)) ++ abort (); ++ filename++; ++ if (*dir2 == '\0') ++ break; ++ if (!ISSLASH (*dir2)) ++ abort (); ++ dir2++; ++ /* Skip one component in DIR2. */ ++ const char *dir2_s; ++ for (dir2_s = dir2; *dir2_s != '\0'; dir2_s++) ++ if (ISSLASH (*dir2_s)) ++ break; ++ /* Skip one component in FILENAME, at P. */ ++ const char *filename_s; ++ for (filename_s = filename; *filename_s != '\0'; filename_s++) ++ if (ISSLASH (*filename_s)) ++ break; ++ /* Did the components match? */ ++ if (!(filename_s - filename == dir2_s - dir2 ++ && memcmp (filename, dir2, dir2_s - dir2) == 0)) ++ break; ++ dir2 = dir2_s; ++ filename = filename_s; ++ n--; ++ } ++ ++ if (n == 0 && *filename == '\0') ++ return xstrdup ("."); ++ ++ char *result = (char *) xmalloc (3 * n + strlen (filename) + 1); ++ { ++ char *q = result; ++ for (; n > 0; n--) ++ { ++ q[0] = '.'; q[1] = '.'; q[2] = '/'; q += 3; ++ } ++ strcpy (q, filename); ++ } ++ return result; ++} ++ ++/* Accumulating mtimes. */ ++struct accumulator ++{ ++ bool has_some_mtimes; ++ struct timespec max_of_mtimes; ++}; ++ ++static void ++accumulate (struct accumulator *accu, struct timespec mtime) ++{ ++ if (accu->has_some_mtimes) ++ { ++ /* Compute the maximum of accu->max_of_mtimes and mtime. */ ++ if (accu->max_of_mtimes.tv_sec < mtime.tv_sec ++ || (accu->max_of_mtimes.tv_sec == mtime.tv_sec ++ && accu->max_of_mtimes.tv_nsec < mtime.tv_nsec)) ++ accu->max_of_mtimes = mtime; ++ } ++ else ++ { ++ accu->max_of_mtimes = mtime; ++ accu->has_some_mtimes = true; ++ } ++} ++ ++int ++max_vc_mtime (struct timespec *max_of_mtimes, ++ size_t nfiles, const char * const *filenames) ++{ ++ if (nfiles == 0) ++ /* Invalid argument. */ ++ abort (); ++ ++ struct accumulator accu = { false }; ++ ++ /* Determine which of the specified files are under version control, ++ and which are duplicates. (The case of duplicates is rare, but it needs ++ special attention, because 'git ls-files' eliminates duplicates.) ++ vc_controlled[n] = 1 means that filenames[n] is under version control. ++ vc_controlled[n] = 0 means that filenames[n] is not under version control. ++ vc_controlled[n] = -1 means that filenames[n] is a duplicate. */ ++ signed char *vc_controlled = XNMALLOC (nfiles, signed char); ++ for (size_t n = 0; n < nfiles; n++) ++ vc_controlled[n] = 0; ++ ++ if (is_git_present ()) ++ { ++ /* Since 'git ls-files' produces an error when at least one of the files ++ is outside the git checkout that contains tha current directory, we ++ need to filter out such files. This is most easily done by converting ++ each file name to a canonical file name first and then comparing with ++ the directory name of said git checkout. */ ++ char *git_checkout = abs_git_checkout (); ++ if (git_checkout != NULL) ++ { ++ char *currdir = xgetcwd (); ++ /* git_checkout is expected to be an ancestor directory of the ++ current directory. */ ++ long ancestor = ancestor_level (git_checkout, currdir); ++ if (ancestor >= 0) ++ { ++ char **canonical_filenames = XNMALLOC (nfiles, char *); ++ for (size_t n = 0; n < nfiles; n++) ++ { ++ char *canonical = canonicalize_file_name (filenames[n]); ++ if (canonical == NULL) ++ { ++ if (errno == ENOMEM) ++ xalloc_die (); ++ /* The file filenames[n] does not exist. */ ++ for (size_t k = n; k > 0; ) ++ free (canonical_filenames[--k]); ++ free (canonical_filenames); ++ free (currdir); ++ free (git_checkout); ++ free (vc_controlled); ++ return -1; ++ } ++ canonical_filenames[n] = canonical; ++ } ++ ++ /* Test which of these absolute file names are outside of the ++ git_checkout. */ ++ char *git_checkout_slash = ++ (strcmp (git_checkout, "/") == 0 ++ ? xstrdup (git_checkout) ++ : xasprintf ("%s/", git_checkout)); ++ ++ char **checkout_relative_filenames = XNMALLOC (nfiles, char *); ++ char **currdir_relative_filenames = XNMALLOC (nfiles, char *); ++ for (size_t n = 0; n < nfiles; n++) ++ { ++ if (str_startswith (canonical_filenames[n], git_checkout_slash)) ++ { ++ vc_controlled[n] = 1; ++ checkout_relative_filenames[n] = ++ relativize (canonical_filenames[n], ++ 0, git_checkout, git_checkout); ++ currdir_relative_filenames[n] = ++ relativize (canonical_filenames[n], ++ ancestor, git_checkout, currdir); ++ } ++ else ++ { ++ vc_controlled[n] = 0; ++ checkout_relative_filenames[n] = NULL; ++ currdir_relative_filenames[n] = NULL; ++ } ++ } ++ ++ /* Room for passing arguments to git commands. */ ++ const char **argv = XNMALLOC (6 + nfiles + 1, const char *); ++ ++ { ++ /* Put the relative file names into a hash table. This is needed ++ because 'git ls-files' returns the files in a different order ++ than the one we provide in the command. */ ++ gl_map_t relative_filenames_ht = ++ gl_map_create_empty (GL_HASH_MAP, ++ hashkey_string_equals, hashkey_string_hash, ++ NULL, NULL); ++ for (size_t n = 0; n < nfiles; n++) ++ if (currdir_relative_filenames[n] != NULL) ++ { ++ if (gl_map_get (relative_filenames_ht, currdir_relative_filenames[n]) != NULL) ++ { ++ /* It's already in the table. */ ++ vc_controlled[n] = -1; ++ } ++ else ++ gl_map_put (relative_filenames_ht, currdir_relative_filenames[n], &vc_controlled[n]); ++ } ++ ++ /* Run "git ls-files -c -o -t -z FILE1..." for as many files as ++ possible, and inspect the output. */ ++ size_t n0 = 0; ++ do ++ { ++ size_t i = 0; ++ argv[i++] = "git"; ++ argv[i++] = "ls-files"; ++ argv[i++] = "-c"; ++ argv[i++] = "-o"; ++ argv[i++] = "-t"; ++ argv[i++] = "-z"; ++ size_t i0 = i; ++ ++ size_t n = n0; ++ size_t cmd_len = 25; ++ for (; n < nfiles; n++) ++ { ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } ++ n++; ++ } ++ if (i > i0) ++ { ++ pid_t child; ++ int fd[1]; ++ ++ argv[i] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ break; ++ ++ /* Read the subprocess output. It is expected to be of the form ++ T1 NUL ++ T2 NUL ++ ... ++ where the relative filenames correspond to the given file ++ names (because we have already relativized them). */ ++ FILE *fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ char *fn = NULL; ++ size_t fn_size = 0; ++ for (;;) ++ { ++ int status = fgetc (fp); ++ if (status == EOF) ++ break; ++ /* status is a status tag, as documented in ++ "man git-ls-files". */ ++ ++ int space = fgetc (fp); ++ if (space != ' ') ++ { ++ fprintf (stderr, "vc-mtime: git ls-files output not as expected\n"); ++ break; ++ } ++ ++ if (getdelim (&fn, &fn_size, '\0', fp) == -1) ++ { ++ if (errno == ENOMEM) ++ xalloc_die (); ++ fprintf (stderr, "vc-mtime: failed to read git ls-files output\n"); ++ break; ++ } ++ signed char *vc_controlled_p = ++ (signed char *) gl_map_get (relative_filenames_ht, fn); ++ if (vc_controlled_p == NULL) ++ fprintf (stderr, "vc-mtime: git ls-files returned an unexpected file name: %s\n", fn); ++ else ++ *vc_controlled_p = (status == 'H' ? 1 : 0); ++ } ++ ++ free (fn); ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ int exitstatus = ++ wait_subprocess (child, "git", false, true, true, false, NULL); ++ if (exitstatus != 0) ++ fprintf (stderr, "vc-mtime: git ls-files failed with exit code %d\n", exitstatus); ++ } ++ n0 = n; ++ } ++ while (n0 < nfiles); ++ ++ gl_map_free (relative_filenames_ht); ++ } ++ ++ { ++ /* Put the relative file names into a hash table. This is needed ++ because 'git diff' returns the files in a different order ++ than the one we provide in the command. */ ++ gl_map_t relative_filenames_ht = ++ gl_map_create_empty (GL_HASH_MAP, ++ hashkey_string_equals, hashkey_string_hash, ++ NULL, NULL); ++ for (size_t n = 0; n < nfiles; n++) ++ if (vc_controlled[n] == 1) ++ { ++ /* No need to test for duplicates here. We have already set ++ vc_controlled[n] to -1 for duplicates, above. */ ++ gl_map_put (relative_filenames_ht, checkout_relative_filenames[n], &vc_controlled[n]); ++ } ++ ++ /* Run "git diff --name-only --no-relative -z HEAD -- FILE1..." for ++ as many files as possible, and inspect the output. */ ++ size_t n0 = 0; ++ do ++ { ++ size_t i = 0; ++ argv[i++] = "git"; ++ argv[i++] = "diff"; ++ argv[i++] = "--name-only"; ++ argv[i++] = "--no-relative"; ++ argv[i++] = "-z"; ++ argv[i++] = "HEAD"; ++ argv[i++] = "--"; ++ size_t i0 = i; ++ ++ size_t n = n0; ++ size_t cmd_len = 46; ++ for (; n < nfiles; n++) ++ { ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } ++ n++; ++ } ++ if (i > i0) ++ { ++ pid_t child; ++ int fd[1]; ++ ++ argv[i] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ break; ++ ++ /* Read the subprocess output. It is expected to be of the form ++ NUL ++ NUL ++ ... ++ where the relative filenames are relative to the git ++ checkout dir, not to currdir! */ ++ FILE *fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ char *fn = NULL; ++ size_t fn_size = 0; ++ for (;;) ++ { ++ /* Test for EOF. */ ++ int c = fgetc (fp); ++ if (c == EOF) ++ break; ++ ungetc (c, fp); ++ ++ if (getdelim (&fn, &fn_size, '\0', fp) == -1) ++ { ++ if (errno == ENOMEM) ++ xalloc_die (); ++ fprintf (stderr, "vc-mtime: failed to read git diff output\n"); ++ break; ++ } ++ signed char *vc_controlled_p = ++ (signed char *) gl_map_get (relative_filenames_ht, fn); ++ if (vc_controlled_p == NULL) ++ fprintf (stderr, "vc-mtime: git diff returned an unexpected file name: %s\n", fn); ++ else ++ /* filenames[n] is under version control but is modified. ++ Treat it like a file not under version control. */ ++ *vc_controlled_p = 0; ++ } ++ ++ free (fn); ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ int exitstatus = ++ wait_subprocess (child, "git", false, true, true, false, NULL); ++ if (exitstatus != 0) ++ fprintf (stderr, "vc-mtime: git diff failed with exit code %d\n", exitstatus); ++ } ++ n0 = n; ++ } ++ while (n0 < nfiles); ++ ++ gl_map_free (relative_filenames_ht); ++ } ++ ++ { ++ /* Run "git log -1 --format=%ct -- FILE1...". It prints the ++ time of last modification (the 'CommitDate', not the ++ 'AuthorDate' which merely represents the time at which the ++ author locally committed the first version of the change), ++ as the number of seconds since the Epoch. The '--' option ++ is for the case that the specified file was removed. */ ++ size_t n0 = 0; ++ do ++ { ++ size_t i = 0; ++ argv[i++] = "git"; ++ argv[i++] = "log"; ++ argv[i++] = "-1"; ++ argv[i++] = "--format=%ct"; ++ argv[i++] = "--"; ++ size_t i0 = i; ++ ++ size_t n = n0; ++ size_t cmd_len = 27; ++ for (; n < nfiles; n++) ++ { ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } ++ n++; ++ } ++ if (i > i0) ++ { ++ pid_t child; ++ int fd[1]; ++ ++ argv[i] = NULL; ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ break; ++ ++ /* Read the subprocess output. It is expected to be a ++ single line, containing a positive integer. */ ++ FILE *fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ char *line = NULL; ++ size_t linesize = 0; ++ size_t linelen = getline (&line, &linesize, fp); ++ if (linelen == (size_t)(-1)) ++ { ++ if (errno == ENOMEM) ++ xalloc_die (); ++ fprintf (stderr, "vc-mtime: failed to read git log output\n"); ++ git_log_fail1: ++ free (line); ++ fclose (fp); ++ wait_subprocess (child, "git", true, false, true, false, NULL); ++ git_log_fail2: ++ free (argv); ++ for (size_t k = nfiles; k > 0; ) ++ free (currdir_relative_filenames[--k]); ++ free (currdir_relative_filenames); ++ for (size_t k = nfiles; k > 0; ) ++ free (checkout_relative_filenames[--k]); ++ free (checkout_relative_filenames); ++ free (git_checkout_slash); ++ for (size_t k = nfiles; k > 0; ) ++ free (canonical_filenames[--k]); ++ free (canonical_filenames); ++ free (currdir); ++ free (git_checkout); ++ free (vc_controlled); ++ return -1; ++ } ++ if (linelen > 0 && line[linelen - 1] == '\n') ++ line[linelen - 1] = '\0'; ++ ++ char *endptr; ++ unsigned long git_log_time; ++ if (!(xstrtoul (line, &endptr, 10, &git_log_time, NULL) == LONGINT_OK ++ && endptr == line + strlen (line))) ++ { ++ fprintf (stderr, "vc-mtime: git log output not as expected\n"); ++ goto git_log_fail1; ++ } ++ ++ struct timespec mtime; ++ mtime.tv_sec = git_log_time; ++ mtime.tv_nsec = 0; ++ accumulate (&accu, mtime); ++ ++ free (line); ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit status. */ ++ int exitstatus = ++ wait_subprocess (child, "git", false, true, true, false, NULL); ++ if (exitstatus != 0) ++ { ++ fprintf (stderr, "vc-mtime: git log failed with exit code %d\n", exitstatus); ++ goto git_log_fail2; ++ } ++ } ++ n0 = n; ++ } ++ while (n0 < nfiles); ++ } ++ ++ free (argv); ++ for (size_t k = nfiles; k > 0; ) ++ free (currdir_relative_filenames[--k]); ++ free (currdir_relative_filenames); ++ for (size_t k = nfiles; k > 0; ) ++ free (checkout_relative_filenames[--k]); ++ free (checkout_relative_filenames); ++ free (git_checkout_slash); ++ for (size_t k = nfiles; k > 0; ) ++ free (canonical_filenames[--k]); ++ free (canonical_filenames); ++ } ++ free (currdir); ++ } ++ free (git_checkout); ++ } ++ ++ /* For the files that are not under version control, or that are modified ++ compared to HEAD, use the file's time stamp. */ ++ for (size_t n = 0; n < nfiles; n++) ++ if (vc_controlled[n] == 0) ++ { ++ struct stat statbuf; ++ if (stat (filenames[n], &statbuf) < 0) ++ { ++ free (vc_controlled); ++ return -1; ++ } ++ ++ struct timespec mtime = get_stat_mtime (&statbuf); ++ accumulate (&accu, mtime); ++ } ++ ++ free (vc_controlled); ++ ++ /* Since nfiles > 0, we must have accumulated at least one mtime. */ ++ if (!accu.has_some_mtimes) ++ abort (); ++ *max_of_mtimes = accu.max_of_mtimes; ++ return 0; ++} ++ ++/* ========================================================================== */ ++ ++#ifdef TEST ++ ++#include ++#include ++#include ++ ++/* Some unit tests for internal functions. */ ++ ++static void ++test_ancestor_level (void) ++{ ++ assert (ancestor_level ("/home/user/projects/gnulib", "/home/user/projects/gnulib") == 0); ++ assert (ancestor_level ("/", "/") == 0); ++ ++ assert (ancestor_level ("/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto") == 2); ++ assert (ancestor_level ("/", "/home/user") == 2); ++ ++ assert (ancestor_level ("/home/user/.local", "/home/user/projects/gnulib") == -1); ++ assert (ancestor_level ("/.local", "/home/user") == -1); ++ assert (ancestor_level ("/.local", "/") == -1); ++} ++ ++static void ++test_relativize (void) ++{ ++ assert (strcmp (relativize ("/home/user/projects/gnulib", ++ 0, "/home/user/projects/gnulib", "/home/user/projects/gnulib"), ++ ".") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/NEWS", ++ 0, "/home/user/projects/gnulib", "/home/user/projects/gnulib"), ++ "NEWS") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/doc/Makefile", ++ 0, "/home/user/projects/gnulib", "/home/user/projects/gnulib"), ++ "doc/Makefile") == 0); ++ ++ assert (strcmp (relativize ("/", ++ 0, "/", "/"), ++ ".") == 0); ++ assert (strcmp (relativize ("/swapfile", ++ 0, "/", "/"), ++ "swapfile") == 0); ++ assert (strcmp (relativize ("/etc/passwd", ++ 0, "/", "/"), ++ "etc/passwd") == 0); ++ ++ assert (strcmp (relativize ("/home/user/projects/gnulib", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../../") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/lib", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/lib/crypto", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ ".") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/lib/malloc", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../malloc") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/lib/cr", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../cr") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/lib/cryptography", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../cryptography") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/doc", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../../doc") == 0); ++ assert (strcmp (relativize ("/home/user/projects/gnulib/doc/Makefile", ++ 2, "/home/user/projects/gnulib", "/home/user/projects/gnulib/lib/crypto"), ++ "../../doc/Makefile") == 0); ++ ++ assert (strcmp (relativize ("/", ++ 2, "/", "/home/user"), ++ "../../") == 0); ++ assert (strcmp (relativize ("/home", ++ 2, "/", "/home/user"), ++ "../") == 0); ++ assert (strcmp (relativize ("/home/user", ++ 2, "/", "/home/user"), ++ ".") == 0); ++ assert (strcmp (relativize ("/home/root", ++ 2, "/", "/home/user"), ++ "../root") == 0); ++ assert (strcmp (relativize ("/home/us", ++ 2, "/", "/home/user"), ++ "../us") == 0); ++ assert (strcmp (relativize ("/home/users", ++ 2, "/", "/home/user"), ++ "../users") == 0); ++ assert (strcmp (relativize ("/etc", ++ 2, "/", "/home/user"), ++ "../../etc") == 0); ++ assert (strcmp (relativize ("/etc/passwd", ++ 2, "/", "/home/user"), ++ "../../etc/passwd") == 0); ++} ++ ++/* Usage: ./a.out FILE[...] ++ */ ++int ++main (int argc, char *argv[]) ++{ ++ test_ancestor_level (); ++ test_relativize (); ++ ++ if (argc == 1) ++ { ++ fprintf (stderr, "Usage: ./a.out FILE[...]\n"); ++ return 1; ++ } ++ struct timespec mtime; ++ int ret = max_vc_mtime (&mtime, argc - 1, (const char **) argv + 1); ++ if (ret == 0) ++ { ++ time_t t = mtime.tv_sec; ++ struct tm *gmt = gmtime (&t); ++ printf ("mtime = %04d-%02d-%02d %02d:%02d:%02d UTC\n", ++ gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, ++ gmt->tm_hour, gmt->tm_min, gmt->tm_sec); ++ return 0; ++ } ++ else ++ { ++ printf ("failed\n"); ++ return 1; ++ } ++} ++ ++/* ++ * Local Variables: ++ * compile-command: "gcc -ggdb -DTEST -Wall -I. -I.. vc-mtime.c libgnu.a" ++ * End: ++ */ ++ ++#endif +--- a/lib/vc-mtime.h ++++ b/lib/vc-mtime.h +@@ -90,6 +90,13 @@ extern "C" { + Upon failure, it returns -1. */ + extern int vc_mtime (struct timespec *mtime, const char *filename); + ++/* Determines the maximum of the version-controlled modification times of ++ FILENAMES[0..NFILES-1], and returns 0. ++ Upon failure, it returns -1. ++ NFILES must be > 0. */ ++extern int max_vc_mtime (struct timespec *max_of_mtimes, ++ size_t nfiles, const char * const *filenames); ++ + #ifdef __cplusplus + } + #endif +--- a/modules/vc-mtime ++++ b/modules/vc-mtime +@@ -16,6 +16,17 @@ error + getline + xstrtol + stat-time ++filename ++xalloc ++xgetcwd ++canonicalize-lgpl ++xvasprintf ++str_startswith ++map ++xmap ++hash-map ++hashkey-string ++getdelim + gettext-h + gnulib-i18n + diff --git a/tools/gnulib/patches/798-vc-mtime-add-api.patch b/tools/gnulib/patches/798-vc-mtime-add-api.patch new file mode 100644 index 0000000000..2cf7edab4e --- /dev/null +++ b/tools/gnulib/patches/798-vc-mtime-add-api.patch @@ -0,0 +1,91 @@ +From f4c40c2d6aabef8e587176bbf5226c8bc6649574 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Fri, 2 May 2025 02:43:23 +0200 +Subject: [PATCH] vc-mtime: Add API for more efficient use of git, part 2. + +* lib/vc-mtime.c (max_vc_mtime): Don't skip the odd-numbered arguments. +--- + ChangeLog | 5 +++++ + lib/vc-mtime.c | 57 +++++++++++++++++++++----------------------------- + 2 files changed, 29 insertions(+), 33 deletions(-) + +--- a/lib/vc-mtime.c ++++ b/lib/vc-mtime.c +@@ -558,17 +558,14 @@ max_vc_mtime (struct timespec *max_of_mt + size_t n = n0; + size_t cmd_len = 25; + for (; n < nfiles; n++) +- { +- if (vc_controlled[n] == 1) +- { +- if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN +- && i > i0) +- break; +- argv[i++] = currdir_relative_filenames[n]; +- cmd_len += 1 + strlen (currdir_relative_filenames[n]); +- } +- n++; +- } ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } + if (i > i0) + { + pid_t child; +@@ -672,17 +669,14 @@ max_vc_mtime (struct timespec *max_of_mt + size_t n = n0; + size_t cmd_len = 46; + for (; n < nfiles; n++) +- { +- if (vc_controlled[n] == 1) +- { +- if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN +- && i > i0) +- break; +- argv[i++] = currdir_relative_filenames[n]; +- cmd_len += 1 + strlen (currdir_relative_filenames[n]); +- } +- n++; +- } ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } + if (i > i0) + { + pid_t child; +@@ -768,17 +762,14 @@ max_vc_mtime (struct timespec *max_of_mt + size_t n = n0; + size_t cmd_len = 27; + for (; n < nfiles; n++) +- { +- if (vc_controlled[n] == 1) +- { +- if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN +- && i > i0) +- break; +- argv[i++] = currdir_relative_filenames[n]; +- cmd_len += 1 + strlen (currdir_relative_filenames[n]); +- } +- n++; +- } ++ if (vc_controlled[n] == 1) ++ { ++ if (cmd_len + strlen (currdir_relative_filenames[n]) >= MAX_CMD_LEN ++ && i > i0) ++ break; ++ argv[i++] = currdir_relative_filenames[n]; ++ cmd_len += 1 + strlen (currdir_relative_filenames[n]); ++ } + if (i > i0) + { + pid_t child; diff --git a/tools/gnulib/patches/799-vc-mtime-old-git.patch b/tools/gnulib/patches/799-vc-mtime-old-git.patch new file mode 100644 index 0000000000..4c2082504b --- /dev/null +++ b/tools/gnulib/patches/799-vc-mtime-old-git.patch @@ -0,0 +1,125 @@ +From 47548a77525a0f4489c9c420ccc2159079365da8 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Fri, 2 May 2025 12:09:40 +0200 +Subject: [PATCH] vc-mtime: Make it work with git versions < 2.28. + +* lib/vc-mtime.c (git_version): New variable. +(is_git_present): Read the output of "git --version", and set +git_version. +(max_vc_mtime): Don't pass option --no-relative if the git version +is < 2.28. +--- + ChangeLog | 9 ++++++ + lib/vc-mtime.c | 82 +++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 83 insertions(+), 8 deletions(-) + +--- a/lib/vc-mtime.c ++++ b/lib/vc-mtime.c +@@ -53,7 +53,9 @@ + + /* ========================================================================== */ + +-/* Determines whether git is present. */ ++static const char *git_version; ++ ++/* Determines whether git is present, and sets git_version if so. */ + static bool + is_git_present (void) + { +@@ -63,17 +65,67 @@ is_git_present (void) + if (!git_tested) + { + /* Test for presence of git: +- "git --version >/dev/null 2>/dev/null" */ ++ "git --version 2>/dev/null" */ + const char *argv[3]; +- int exitstatus; ++ pid_t child; ++ int fd[1]; + + argv[0] = "git"; + argv[1] = "--version"; + argv[2] = NULL; +- exitstatus = execute ("git", "git", argv, NULL, NULL, +- false, false, true, true, +- true, false, NULL); +- git_present = (exitstatus == 0); ++ child = create_pipe_in ("git", "git", argv, NULL, NULL, ++ DEV_NULL, true, true, false, fd); ++ if (child == -1) ++ git_present = false; ++ else ++ { ++ /* Retrieve its result. */ ++ FILE *fp = fdopen (fd[0], "r"); ++ if (fp == NULL) ++ error (EXIT_FAILURE, errno, _("fdopen() failed")); ++ ++ char *line = NULL; ++ size_t linesize = 0; ++ size_t linelen = getline (&line, &linesize, fp); ++ if (linelen == (size_t)(-1)) ++ { ++ fclose (fp); ++ wait_subprocess (child, "git", true, true, true, false, NULL); ++ git_present = false; ++ } ++ else ++ { ++ if (linelen > 0 && line[linelen - 1] == '\n') ++ line[linelen - 1] = '\0'; ++ ++ /* Read until EOF (otherwise the child process may get a SIGPIPE ++ signal). */ ++ while (getc (fp) != EOF) ++ ; ++ ++ fclose (fp); ++ ++ /* Remove zombie process from process list, and retrieve exit ++ status. */ ++ int exitstatus = ++ wait_subprocess (child, "git", true, true, true, false, NULL); ++ if (exitstatus != 0) ++ { ++ free (line); ++ git_present = false; ++ } ++ else ++ { ++ /* The version starts at the first digit in the line. */ ++ const char *p = line; ++ for (; *p != '0'; p++) ++ if (*p >= '0' && *p <= '9') ++ break; ++ git_version = p; ++ git_present = true; ++ } ++ } ++ } + git_tested = true; + } + +@@ -660,7 +712,21 @@ max_vc_mtime (struct timespec *max_of_mt + argv[i++] = "git"; + argv[i++] = "diff"; + argv[i++] = "--name-only"; +- argv[i++] = "--no-relative"; ++ /* With git versions >= 2.28, we pass option --no-relative, ++ in order to neutralize any possible customization of the ++ "diff.relative" property. With git versions < 2.28, this ++ is not needed, and the option --no-relative does not ++ exist. */ ++ if (!(git_version[0] <= '1' ++ || (git_version[0] == '2' && git_version[1] == '.' ++ && ((git_version[2] >= '0' && git_version[2] <= '9' ++ && !(git_version[3] >= '0' && git_version[3] <= '9')) ++ || (((git_version[2] == '1' ++ && git_version[3] >= '0' && git_version[3] <= '9') ++ || (git_version[2] == '2' ++ && git_version[3] >= '0' && git_version[3] <= '7')) ++ && !(git_version[4] >= '0' && git_version[4] <= '9')))))) ++ argv[i++] = "--no-relative"; + argv[i++] = "-z"; + argv[i++] = "HEAD"; + argv[i++] = "--"; diff --git a/tools/gnulib/patches/900-str_startswith-module.patch b/tools/gnulib/patches/900-str_startswith-module.patch new file mode 100644 index 0000000000..c9af62710a --- /dev/null +++ b/tools/gnulib/patches/900-str_startswith-module.patch @@ -0,0 +1,117 @@ +From 24010120fab36721caaf92be076655571e44da07 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Fri, 3 Jan 2025 09:26:14 +0100 +Subject: [PATCH] str_startswith: New module. + +* lib/string.in.h (str_startswith): New declaration. +* lib/str_startswith.c: New file. +* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize +GNULIB_STR_STARTSWITH. +* modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH. +* modules/str_startswith: New file. +--- + ChangeLog | 10 ++++++++++ + lib/str_startswith.c | 29 +++++++++++++++++++++++++++++ + lib/string.in.h | 8 ++++++++ + m4/string_h.m4 | 3 ++- + modules/str_startswith | 23 +++++++++++++++++++++++ + modules/string-h | 1 + + 6 files changed, 73 insertions(+), 1 deletion(-) + create mode 100644 lib/str_startswith.c + create mode 100644 modules/str_startswith + +--- /dev/null ++++ b/lib/str_startswith.c +@@ -0,0 +1,29 @@ ++/* str_startswith function. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation, either version 3 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Bruno Haible , 2025. */ ++ ++#include "config.h" ++ ++/* Specification. */ ++#include ++ ++ ++int ++str_startswith (const char *string, const char *prefix) ++{ ++ return strncmp (string, prefix, strlen (prefix)) == 0; ++} +--- a/lib/string.in.h ++++ b/lib/string.in.h +@@ -1079,6 +1079,14 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is + /* The following functions are not specified by POSIX. They are gnulib + extensions. */ + ++#if @GNULIB_STR_STARTSWITH@ ++/* Returns true if STRING starts with PREFIX. ++ Returns false otherwise. */ ++_GL_EXTERN_C int str_startswith (const char *string, const char *prefix) ++ _GL_ATTRIBUTE_PURE ++ _GL_ARG_NONNULL ((1, 2)); ++#endif ++ + #if @GNULIB_MBSLEN@ + /* Return the number of multibyte characters in the character string STRING. + This considers multibyte characters, unlike strlen, which counts bytes. */ +--- a/m4/string_h.m4 ++++ b/m4/string_h.m4 +@@ -70,6 +70,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS], + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRSTR]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R]) ++ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR]) +--- /dev/null ++++ b/modules/str_startswith +@@ -0,0 +1,23 @@ ++Description: ++str_startswith() function: test whether a string starts with a given prefix. ++ ++Files: ++lib/str_startswith.c ++ ++Depends-on: ++string-h ++ ++configure.ac: ++gl_STRING_MODULE_INDICATOR([str_startswith]) ++ ++Makefile.am: ++lib_SOURCES += str_startswith.c ++ ++Include: ++ ++ ++License: ++LGPLv2+ ++ ++Maintainer: ++all +--- a/modules/string-h ++++ b/modules/string-h +@@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/co + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ ++ -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ + -e 's/@''GNULIB_STRERRORNAME_NP''@/$(GNULIB_STRERRORNAME_NP)/g' \ diff --git a/tools/gnulib/patches/901-str_endswith-module.patch b/tools/gnulib/patches/901-str_endswith-module.patch new file mode 100644 index 0000000000..00db5cdce0 --- /dev/null +++ b/tools/gnulib/patches/901-str_endswith-module.patch @@ -0,0 +1,119 @@ +From d89ac9373d9748f7601babf52c9129fcbcf0c907 Mon Sep 17 00:00:00 2001 +From: Bruno Haible +Date: Fri, 3 Jan 2025 09:54:14 +0100 +Subject: [PATCH] str_endswith: New module. + +* lib/string.in.h (str_endswith): New declaration. +* lib/str_endswith.c: New file. +* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize +GNULIB_STR_ENDSWITH. +* modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH. +* modules/str_endswith: New file. +--- + ChangeLog | 10 ++++++++++ + lib/str_endswith.c | 31 +++++++++++++++++++++++++++++++ + lib/string.in.h | 8 ++++++++ + m4/string_h.m4 | 3 ++- + modules/str_endswith | 23 +++++++++++++++++++++++ + modules/string-h | 1 + + 6 files changed, 75 insertions(+), 1 deletion(-) + create mode 100644 lib/str_endswith.c + create mode 100644 modules/str_endswith + +--- /dev/null ++++ b/lib/str_endswith.c +@@ -0,0 +1,31 @@ ++/* str_endswith function. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ ++ This file is free software: you can redistribute it and/or modify ++ it under the terms of the GNU Lesser General Public License as ++ published by the Free Software Foundation, either version 3 of the ++ License, or (at your option) any later version. ++ ++ This file is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public License ++ along with this program. If not, see . */ ++ ++/* Written by Bruno Haible , 2025. */ ++ ++#include "config.h" ++ ++/* Specification. */ ++#include ++ ++ ++int ++str_endswith (const char *string, const char *suffix) ++{ ++ size_t len = strlen (string); ++ size_t n = strlen (suffix); ++ return len >= n && strcmp (string + len - n, suffix) == 0; ++} +--- a/lib/string.in.h ++++ b/lib/string.in.h +@@ -1087,6 +1087,14 @@ _GL_EXTERN_C int str_startswith (const c + _GL_ARG_NONNULL ((1, 2)); + #endif + ++#if @GNULIB_STR_ENDSWITH@ ++/* Returns true if STRING ends with SUFFIX. ++ Returns false otherwise. */ ++_GL_EXTERN_C int str_endswith (const char *string, const char *prefix) ++ _GL_ATTRIBUTE_PURE ++ _GL_ARG_NONNULL ((1, 2)); ++#endif ++ + #if @GNULIB_MBSLEN@ + /* Return the number of multibyte characters in the character string STRING. + This considers multibyte characters, unlike strlen, which counts bytes. */ +--- a/m4/string_h.m4 ++++ b/m4/string_h.m4 +@@ -71,6 +71,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS], + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH]) ++ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_ENDSWITH]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR]) +--- /dev/null ++++ b/modules/str_endswith +@@ -0,0 +1,23 @@ ++Description: ++str_endswith() function: test whether a string ends with a given suffix. ++ ++Files: ++lib/str_endswith.c ++ ++Depends-on: ++string-h ++ ++configure.ac: ++gl_STRING_MODULE_INDICATOR([str_endswith]) ++ ++Makefile.am: ++lib_SOURCES += str_endswith.c ++ ++Include: ++ ++ ++License: ++LGPLv2+ ++ ++Maintainer: ++all +--- a/modules/string-h ++++ b/modules/string-h +@@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/co + -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \ + -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \ + -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \ ++ -e 's/@''GNULIB_STR_ENDSWITH''@/$(GNULIB_STR_ENDSWITH)/g' \ + -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \ + -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \ + -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \ From 246eba7528434d39013f39fa74e981d999039ff5 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 31 May 2025 14:08:53 -0400 Subject: [PATCH 39/51] gnulib-l10n: add package This package is a supplement for part of gettext that uses gnulib sources, and includes the localizations for messages specifically in gnulib files. This is being added as a separate package instead of a build target of gnulib because that method of acquiring the localizations requires the use of gettext and would be a reverse dependency. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- package/libs/gnulib-l10n/Makefile | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 package/libs/gnulib-l10n/Makefile diff --git a/package/libs/gnulib-l10n/Makefile b/package/libs/gnulib-l10n/Makefile new file mode 100644 index 0000000000..ff02ffcb27 --- /dev/null +++ b/package/libs/gnulib-l10n/Makefile @@ -0,0 +1,37 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gnulib-l10n +PKG_CPE_ID:=cpe:/a:gnu:$(PKG_NAME) +PKG_VERSION:=20241231 + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz +PKG_SOURCE_URL:=@GNU/gnulib +PKG_HASH:=155752ba6796aa294cde87c2bf0e771a5891eeeacb131345be0e080a3ec0ceea + +include $(INCLUDE_DIR)/host-build.mk +include $(INCLUDE_DIR)/package.mk + +define Package/gnulib-l10n + SECTION:=libs + CATEGORY:=Libraries + TITLE:=GNU Gnulib localization translation files + URL:=http://www.gnu.org/software/gnulib/ +endef + +define Package/gnulib-l10n/description + Localizations (translations) of messages for GNU gnulib code. +endef + +HOST_CONFIGURE_ARGS += \ + --localedir=$(HOST_BUILD_PREFIX)/share/locale + +define Host/Uninstall + -$(call Host/Compile/Default,uninstall) +endef + +define Package/gnulib-l10n/install + $(call Build/Install/Default,install SUBDIRS='$(PKG_SUBDIRS)') +endef + +$(eval $(call HostBuild)) +$(eval $(call BuildPackage,gnulib-l10n)) From da541f7acd62bc33e7b0a891cf65a39d4bfe0b96 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sat, 31 May 2025 16:16:10 -0400 Subject: [PATCH 40/51] gettext-full: update to 0.24.1 Update to a newer bugfix release of gettext. Include gnulib-l10n as a new dependency. All patches are automatically refreshed. Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- package/libs/gettext-full/Makefile | 6 +++--- .../patches/200-libunistring-missing-link.patch | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package/libs/gettext-full/Makefile b/package/libs/gettext-full/Makefile index 0a7782c1f1..405243240f 100644 --- a/package/libs/gettext-full/Makefile +++ b/package/libs/gettext-full/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gettext-full -PKG_VERSION:=0.22.5 +PKG_VERSION:=0.24.1 PKG_RELEASE:=1 PKG_SOURCE:=gettext-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@GNU/gettext -PKG_HASH:=fe10c37353213d78a5b83d48af231e005c4da84db5ce88037d88355938259640 +PKG_HASH:=6164ec7aa61653ac9cdfb41d5c2344563b21f707da1562712e48715f1d2052a6 PKG_BUILD_DIR:=$(BUILD_DIR)/gettext-$(PKG_VERSION) HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/gettext-$(PKG_VERSION) @@ -27,7 +27,7 @@ PKG_BUILD_PARALLEL:=0 PKG_FIXUP:=autoreconf -HOST_BUILD_DEPENDS:=gperf/host libiconv-full/host libunistring/host libxml2/host +HOST_BUILD_DEPENDS:=gnulib-l10n/host gperf/host libiconv-full/host libunistring/host libxml2/host HOST_BUILD_PARALLEL:=0 PKG_SUBDIRS:= \ diff --git a/package/libs/gettext-full/patches/200-libunistring-missing-link.patch b/package/libs/gettext-full/patches/200-libunistring-missing-link.patch index 19a1ae177f..32c100519c 100644 --- a/package/libs/gettext-full/patches/200-libunistring-missing-link.patch +++ b/package/libs/gettext-full/patches/200-libunistring-missing-link.patch @@ -1,6 +1,6 @@ --- a/autogen.sh +++ b/autogen.sh -@@ -81,6 +81,7 @@ if ! $skip_gnulib; then +@@ -104,6 +104,7 @@ if ! $skip_gnulib; then getopt-gnu gettext-h havelib @@ -18,4 +18,4 @@ +LDADD = ../gnulib-lib/libgrt.a $(LTLIBUNISTRING) @LTLIBINTL@ @LTLIBICONV@ $(WOE32_LDADD) # Specify installation directory, for --enable-relocatable. - gettext_CFLAGS = -DINSTALLDIR=\"$(bindir)\" + gettext_CFLAGS = -DINSTALLDIR=$(bindir_c_make) From d7d02059407b5da875cb41f1717fe57385cfe753 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Sun, 1 Jun 2025 19:08:12 -0400 Subject: [PATCH 41/51] tools/automake: update to 1.18 Update to the latest stable release with the new API versions for binaries. The temporary patching of shebangs is no longer necessary since the whitespace check has been changed to a warning. Part of a patch was upstreamed and therefore removed. Manually adjusted patch: - 000-relocatable.patch - 101-do-not-require-files.patch All other patches are automatically refreshed. Link: https://lists.gnu.org/archive/html/autotools-announce/2025-05/msg00001.html Signed-off-by: Michael Pratt Link: https://github.com/openwrt/openwrt/pull/16522 Signed-off-by: Robert Marko --- tools/automake/Makefile | 6 ++-- tools/automake/patches/000-relocatable.patch | 28 ++++++------------- ...clocal-skip-not-existing-directories.patch | 2 +- .../patches/101-do-not-require-files.patch | 13 ++------- .../patches/300-output-TRUE-cond-first.patch | 4 +-- .../310-maintainer-clean-built_sources.patch | 2 +- 6 files changed, 17 insertions(+), 38 deletions(-) diff --git a/tools/automake/Makefile b/tools/automake/Makefile index f281583f05..d3da6d1921 100644 --- a/tools/automake/Makefile +++ b/tools/automake/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=automake PKG_CPE_ID:=cpe:/a:gnu:automake -PKG_VERSION:=1.17 +PKG_VERSION:=1.18 PKG_API_VERSION:=$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/automake -PKG_HASH:=397767d4db3018dd4440825b60c64258b636eaf6bf99ac8b0897f06c89310acd +PKG_HASH:=af6043a5d4b3beef0c48161f4a6936259321cd101a34c1ab0768328515626c8a include $(INCLUDE_DIR)/host-build.mk @@ -21,7 +21,7 @@ HOST_CONFIGURE_ARGS += \ --disable-silent-rules HOST_CONFIGURE_VARS += \ - # temporary patch alternative for PERL="/usr/bin/env perl" + PERL="/usr/bin/env perl" define Host/Configure (cd $(HOST_BUILD_DIR); $(AM_TOOL_PATHS) STAGING_DIR_HOST="" ./bootstrap) diff --git a/tools/automake/patches/000-relocatable.patch b/tools/automake/patches/000-relocatable.patch index d3a9e178e4..ec442ed3e3 100644 --- a/tools/automake/patches/000-relocatable.patch +++ b/tools/automake/patches/000-relocatable.patch @@ -1,6 +1,6 @@ --- a/lib/Automake/Config.in +++ b/lib/Automake/Config.in -@@ -34,7 +34,7 @@ our $PACKAGE = '@PACKAGE@'; +@@ -32,7 +32,7 @@ our $PACKAGE = '@PACKAGE@'; our $PACKAGE_BUGREPORT = '@PACKAGE_BUGREPORT@'; our $VERSION = '@VERSION@'; our $RELEASE_YEAR = '@RELEASE_YEAR@'; @@ -11,15 +11,9 @@ # We need at least this version for CLONE support. --- a/bin/aclocal.in +++ b/bin/aclocal.in -@@ -1,4 +1,4 @@ --#!@PERL@ -+#!/usr/bin/env perl - # aclocal - create aclocal.m4 by scanning configure.ac -*- perl -*- - # @configure_input@ - # Copyright (C) 1996-2024 Free Software Foundation, Inc. -@@ -23,9 +23,11 @@ use 5.006; - use strict; - use warnings FATAL => 'all'; +@@ -21,9 +21,11 @@ + + use 5.006; use strict; use warnings; +$^W = 1; + @@ -30,7 +24,7 @@ unless $ENV{AUTOMAKE_UNINSTALLED}; } -@@ -65,8 +67,8 @@ $perl_threads = 0; +@@ -63,8 +65,8 @@ $perl_threads = 0; # --aclocal-path option/ACLOCAL_PATH environment variable, and reset # with the '--system-acdir' option. my @user_includes = (); @@ -43,15 +37,9 @@ # Whether we should copy M4 file in $user_includes[0]. --- a/bin/automake.in +++ b/bin/automake.in -@@ -1,4 +1,4 @@ --#!@PERL@ -+#!/usr/bin/env perl - # automake - create Makefile.in from Makefile.am -*- perl -*- - # @configure_input@ - # Copyright (C) 1994-2024 Free Software Foundation, Inc. -@@ -26,9 +26,11 @@ use 5.006; - use strict; - use warnings FATAL => 'all'; +@@ -24,9 +24,11 @@ package Automake; + + use 5.006; use strict; use warnings; +$^W = 1; + diff --git a/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch index 6fa23c49e8..5ba02c0d85 100644 --- a/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch +++ b/tools/automake/patches/100-aclocal-skip-not-existing-directories.patch @@ -1,6 +1,6 @@ --- a/bin/aclocal.in +++ b/bin/aclocal.in -@@ -372,6 +372,12 @@ sub scan_m4_dirs ($$@) +@@ -370,6 +370,12 @@ sub scan_m4_dirs ($$@) foreach my $m4dir (@dirlist) { diff --git a/tools/automake/patches/101-do-not-require-files.patch b/tools/automake/patches/101-do-not-require-files.patch index 26847bc680..7fbc330975 100644 --- a/tools/automake/patches/101-do-not-require-files.patch +++ b/tools/automake/patches/101-do-not-require-files.patch @@ -1,15 +1,6 @@ --- a/bin/automake.in +++ b/bin/automake.in -@@ -4552,7 +4552,7 @@ sub handle_gettext () - && grep ($_ eq 'intl', @subdirs)); - } - -- require_file ($ac_gettext_location, GNU, 'ABOUT-NLS'); -+ require_file ($ac_gettext_location, GNITS, 'ABOUT-NLS'); - } - - # Emit makefile footer. -@@ -5677,7 +5677,7 @@ sub check_gnu_standards () +@@ -5700,7 +5700,7 @@ sub check_gnu_standards () # otherwise require non-.md. my $required = (! -f $file && -f "$file.md") ? "$file.md" : $file; @@ -18,7 +9,7 @@ } # Accept one of these three licenses; default to COPYING. -@@ -5691,7 +5691,7 @@ sub check_gnu_standards () +@@ -5714,7 +5714,7 @@ sub check_gnu_standards () last; } } diff --git a/tools/automake/patches/300-output-TRUE-cond-first.patch b/tools/automake/patches/300-output-TRUE-cond-first.patch index 1bfc0203dd..1ac655adff 100644 --- a/tools/automake/patches/300-output-TRUE-cond-first.patch +++ b/tools/automake/patches/300-output-TRUE-cond-first.patch @@ -1,6 +1,6 @@ --- a/lib/Automake/Variable.pm +++ b/lib/Automake/Variable.pm -@@ -1259,8 +1259,15 @@ sub output_variables () +@@ -1258,8 +1258,15 @@ sub output_variables () foreach my $var (@vars) { my $v = rvar $var; @@ -16,7 +16,7 @@ $res .= $v->output ($cond) if $v->rdef ($cond)->owner == VAR_AUTOMAKE; } -@@ -1270,8 +1277,15 @@ sub output_variables () +@@ -1269,8 +1276,15 @@ sub output_variables () foreach my $var (@vars) { my $v = rvar $var; diff --git a/tools/automake/patches/310-maintainer-clean-built_sources.patch b/tools/automake/patches/310-maintainer-clean-built_sources.patch index 5737a65023..679236bda0 100644 --- a/tools/automake/patches/310-maintainer-clean-built_sources.patch +++ b/tools/automake/patches/310-maintainer-clean-built_sources.patch @@ -1,6 +1,6 @@ --- a/bin/automake.in +++ b/bin/automake.in -@@ -4745,12 +4745,42 @@ sub handle_clean +@@ -4760,12 +4760,42 @@ sub handle_clean if var ('CLEANFILES'); $clean_files{'$(DISTCLEANFILES)'} = DIST_CLEAN if var ('DISTCLEANFILES'); From 6e8042ed97cef92e7217ab53c913aa0c2a35cbf0 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 26 Jul 2025 14:12:47 +0900 Subject: [PATCH 42/51] mediatek: add missing #address/size-cells for ELECOM WRC-X3000GS3 Add missing `#address-cells = <1>;` and `#size-cells = <0>;` properties to `ð` and `&wifi` nodes to resolve the following warnings. ``` ../dts/mt7981b-elecom-wrc-x3000gs3.dts:114.3-13: Warning (reg_format): /soc/ethernet@15100000/mac@0:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) ../dts/mt7981b-elecom-wrc-x3000gs3.dts:129.3-13: Warning (reg_format): /soc/ethernet@15100000/mac@1:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) ../dts/mt7981b-elecom-wrc-x3000gs3.dts:372.3-13: Warning (reg_format): /soc/wifi@18000000/band@0:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) ../dts/mt7981b-elecom-wrc-x3000gs3.dts:378.3-13: Warning (reg_format): /soc/wifi@18000000/band@1:reg: property has invalid length (4 bytes) (#address-cells == 2, #size-cells == 1) ../dts/mt7981b-elecom-wrc-x3000gs3.dts:112.15-125.4: Warning (avoid_default_addr_size): /soc/ethernet@15100000/mac@0: Relying on default #address-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:112.15-125.4: Warning (avoid_default_addr_size): /soc/ethernet@15100000/mac@0: Relying on default #size-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:127.15-136.4: Warning (avoid_default_addr_size): /soc/ethernet@15100000/mac@1: Relying on default #address-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:127.15-136.4: Warning (avoid_default_addr_size): /soc/ethernet@15100000/mac@1: Relying on default #size-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:371.9-375.4: Warning (avoid_default_addr_size): /soc/wifi@18000000/band@0: Relying on default #address-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:371.9-375.4: Warning (avoid_default_addr_size): /soc/wifi@18000000/band@0: Relying on default #size-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:377.9-381.4: Warning (avoid_default_addr_size): /soc/wifi@18000000/band@1: Relying on default #address-cells value ../dts/mt7981b-elecom-wrc-x3000gs3.dts:377.9-381.4: Warning (avoid_default_addr_size): /soc/wifi@18000000/band@1: Relying on default #size-cells value ``` Signed-off-by: INAGAKI Hiroshi Link: https://github.com/openwrt/openwrt/pull/19530 Signed-off-by: Hauke Mehrtens --- target/linux/mediatek/dts/mt7981b-elecom-wrc-x3000gs3.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/linux/mediatek/dts/mt7981b-elecom-wrc-x3000gs3.dts b/target/linux/mediatek/dts/mt7981b-elecom-wrc-x3000gs3.dts index 195f05c6fa..fbd83c6c8d 100644 --- a/target/linux/mediatek/dts/mt7981b-elecom-wrc-x3000gs3.dts +++ b/target/linux/mediatek/dts/mt7981b-elecom-wrc-x3000gs3.dts @@ -108,6 +108,8 @@ pinctrl-0 = <&mdio_pins>; pinctrl-names = "default"; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; gmac0: mac@0 { compatible = "mediatek,eth-mac"; @@ -367,6 +369,8 @@ nvmem-cells = <&eeprom_factory_0>; nvmem-cell-names = "eeprom"; status = "okay"; + #address-cells = <1>; + #size-cells = <0>; band@0 { reg = <0>; From a3bfb67072a70e8720326b7e1527d55f8439b54c Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Mon, 21 Jul 2025 08:34:54 -0400 Subject: [PATCH 43/51] realtek: mdio: RTL838x: move functions over to bus The mdio bus functions are still split between ethernet and dsa driver. Before moving everthing out to a separate mdio driver we decided to collect everything in the ethernet driver with the rtmdio prefix. Take over the remaining RTL838x functions. Remark: This is more or less a copy/paste with function renaming. As there are still some consumers in the DSA driver the definitions and inclusions must be flipped. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/19484 Signed-off-by: Hauke Mehrtens --- .../drivers/net/dsa/rtl83xx/common.c | 7 +- .../drivers/net/dsa/rtl83xx/rtl838x.c | 163 ---------------- .../drivers/net/ethernet/rtl838x_eth.c | 180 +++++++++++++++++- .../drivers/net/ethernet/rtl838x_eth.h | 3 + 4 files changed, 179 insertions(+), 174 deletions(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c index 411ee7f5e3..5c15824d00 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c @@ -29,6 +29,9 @@ extern const struct dsa_switch_ops rtl930x_switch_ops; extern const struct phylink_pcs_ops rtl83xx_pcs_ops; extern const struct phylink_pcs_ops rtl93xx_pcs_ops; +extern int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +extern int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val); + DEFINE_MUTEX(smi_lock); int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port) @@ -244,7 +247,7 @@ int read_phy(u32 port, u32 page, u32 reg, u32 *val) { switch (soc_info.family) { case RTL8380_FAMILY_ID: - return rtl838x_read_phy(port, page, reg, val); + return rtmdio_838x_read_phy(port, page, reg, val); case RTL8390_FAMILY_ID: return rtl839x_read_phy(port, page, reg, val); case RTL9300_FAMILY_ID: @@ -260,7 +263,7 @@ int write_phy(u32 port, u32 page, u32 reg, u32 val) { switch (soc_info.family) { case RTL8380_FAMILY_ID: - return rtl838x_write_phy(port, page, reg, val); + return rtmdio_838x_write_phy(port, page, reg, val); case RTL8390_FAMILY_ID: return rtl839x_write_phy(port, page, reg, val); case RTL9300_FAMILY_ID: diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c index fafdca6216..ac4b962318 100644 --- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c +++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c @@ -1768,169 +1768,6 @@ irqreturn_t rtl838x_switch_irq(int irq, void *dev_id) return IRQ_HANDLED; } -int rtl838x_smi_wait_op(int timeout) -{ - int ret = 0; - u32 val; - - ret = readx_poll_timeout(sw_r32, RTL838X_SMI_ACCESS_PHY_CTRL_1, - val, !(val & 0x1), 20, timeout); - if (ret) - pr_err("%s: timeout\n", __func__); - - return ret; -} - -/* Reads a register in a page from the PHY */ -int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val) -{ - u32 v, park_page = 0x1f << 15; - int err; - - if (port > 31) { - *val = 0xffff; - return 0; - } - - if (page > 4095 || reg > 31) - return -ENOTSUPP; - - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = reg << 20 | page << 3; - sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); - sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Write to a register in a page of the PHY */ -int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val) -{ - u32 v, park_page = 0x1f << 15; - int err; - - val &= 0xffff; - if (port > 31 || page > 4095 || reg > 31) - return -ENOTSUPP; - - mutex_lock(&smi_lock); - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = reg << 20 | page << 3 | 0x4; - sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); - sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Read an mmd register of a PHY */ -int rtl838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val) -{ - int err; - u32 v; - - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - v = addr << 16 | reg; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_3); - - /* mmd-access | read | cmd-start */ - v = 1 << 1 | 0 << 2 | 1; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - - return err; -} - -/* Write to an mmd register of a PHY */ -int rtl838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val) -{ - int err; - u32 v; - - pr_debug("MMD write: port %d, dev %d, reg %d, val %x\n", port, addr, reg, val); - val &= 0xffff; - mutex_lock(&smi_lock); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); - mdelay(10); - - sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); - - sw_w32_mask(0x1f << 16, addr << 16, RTL838X_SMI_ACCESS_PHY_CTRL_3); - sw_w32_mask(0xffff, reg, RTL838X_SMI_ACCESS_PHY_CTRL_3); - /* mmd-access | write | cmd-start */ - v = 1 << 1 | 1 << 2 | 1; - sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); - - err = rtl838x_smi_wait_op(100000); - if (err) - goto errout; - - err = 0; - -errout: - mutex_unlock(&smi_lock); - return err; -} - void rtl8380_get_version(struct rtl838x_switch_priv *priv) { u32 rw_save, info_save; diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c index 91577ac766..5c6d79d19b 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c @@ -27,11 +27,6 @@ extern struct rtl83xx_soc_info soc_info; extern int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data); -extern int rtl838x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); -extern int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); -extern int rtl838x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val); -extern int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val); - extern int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val); extern int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val); extern int rtl839x_read_sds_phy(int phy_addr, int phy_reg); @@ -1640,6 +1635,8 @@ static int rtl838x_set_link_ksettings(struct net_device *ndev, * reimplemented. For now it should be sufficient. */ +DEFINE_MUTEX(rtmdio_lock); + struct rtmdio_bus_priv { u16 id; u16 family_id; @@ -1769,6 +1766,171 @@ static int rtmdio_838x_write_sds(int addr, int regnum, u16 val) return 0; } +/* RTL838x specific MDIO functions */ + +static int rtmdio_838x_smi_wait_op(int timeout) +{ + int ret = 0; + u32 val; + + ret = readx_poll_timeout(sw_r32, RTL838X_SMI_ACCESS_PHY_CTRL_1, + val, !(val & 0x1), 20, timeout); + if (ret) + pr_err("%s: timeout\n", __func__); + + return ret; +} + +/* Reads a register in a page from the PHY */ +int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val) +{ + u32 v, park_page = 0x1f << 15; + int err; + + if (port > 31) { + *val = 0xffff; + return 0; + } + + if (page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = reg << 20 | page << 3; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Write to a register in a page of the PHY */ +int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val) +{ + u32 v, park_page = 0x1f << 15; + int err; + + val &= 0xffff; + if (port > 31 || page > 4095 || reg > 31) + return -ENOTSUPP; + + mutex_lock(&rtmdio_lock); + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(BIT(port), RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = reg << 20 | page << 3 | 0x4; + sw_w32(v | park_page, RTL838X_SMI_ACCESS_PHY_CTRL_1); + sw_w32_mask(0, 1, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Read an mmd register of a PHY */ +static int rtmdio_838x_read_mmd_phy(u32 port, u32 addr, u32 reg, u32 *val) +{ + int err; + u32 v; + + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, port << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + v = addr << 16 | reg; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_3); + + /* mmd-access | read | cmd-start */ + v = 1 << 1 | 0 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + *val = sw_r32(RTL838X_SMI_ACCESS_PHY_CTRL_2) & 0xffff; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + + return err; +} + +/* Write to an mmd register of a PHY */ +static int rtmdio_838x_write_mmd_phy(u32 port, u32 addr, u32 reg, u32 val) +{ + int err; + u32 v; + + pr_debug("MMD write: port %d, dev %d, reg %d, val %x\n", port, addr, reg, val); + val &= 0xffff; + mutex_lock(&rtmdio_lock); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + sw_w32(1 << port, RTL838X_SMI_ACCESS_PHY_CTRL_0); + mdelay(10); + + sw_w32_mask(0xffff0000, val << 16, RTL838X_SMI_ACCESS_PHY_CTRL_2); + + sw_w32_mask(0x1f << 16, addr << 16, RTL838X_SMI_ACCESS_PHY_CTRL_3); + sw_w32_mask(0xffff, reg, RTL838X_SMI_ACCESS_PHY_CTRL_3); + /* mmd-access | write | cmd-start */ + v = 1 << 1 | 1 << 2 | 1; + sw_w32(v, RTL838X_SMI_ACCESS_PHY_CTRL_1); + + err = rtmdio_838x_smi_wait_op(100000); + if (err) + goto errout; + + err = 0; + +errout: + mutex_unlock(&rtmdio_lock); + return err; +} + /* These are the core functions of our new Realtek SoC MDIO bus. */ static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum) @@ -2215,10 +2377,10 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv) priv->mii_bus->read = rtmdio_83xx_read; priv->mii_bus->write = rtmdio_83xx_write; priv->mii_bus->reset = rtmdio_838x_reset; - bus_priv->read_mmd_phy = rtl838x_read_mmd_phy; - bus_priv->write_mmd_phy = rtl838x_write_mmd_phy; - bus_priv->read_phy = rtl838x_read_phy; - bus_priv->write_phy = rtl838x_write_phy; + bus_priv->read_mmd_phy = rtmdio_838x_read_mmd_phy; + bus_priv->write_mmd_phy = rtmdio_838x_write_mmd_phy; + bus_priv->read_phy = rtmdio_838x_read_phy; + bus_priv->write_phy = rtmdio_838x_write_phy; bus_priv->cpu_port = RTL838X_CPU_PORT; bus_priv->rawpage = 0xfff; break; diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h index e899467d13..720c22fdd3 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h @@ -453,4 +453,7 @@ int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 int phy_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum); int phy_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val); +int rtmdio_838x_read_phy(u32 port, u32 page, u32 reg, u32 *val); +int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val); + #endif /* _RTL838X_ETH_H */ From 21d3722c4072e1888c2beea2ee7c058376193d5f Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Wed, 23 Jul 2025 01:37:02 -0400 Subject: [PATCH 44/51] realtek: don't disable MIPS counter on secondary VPEs After observation that timer interrupt 7 always fires on secondary VPEs the counter was disabled in the startup code. This is a bad idea when building the kernel with jitterentropy. To generate entropy it makes use of function random_get_entropy(). On MIPS architecture this simply reads the counter register on the current core. With a disabled counter it always returns the same value and the entropy initialization stalls the core if it runs on a secondary VPE. See backtrace [ 21.736246] rcu: INFO: rcu_sched self-detected stall on CPU [ 21.736246] rcu: INFO: rcu_sched self-detected stall on CPU [ 21.748594] rcu: 1-....: (2100 ticks this GP) idle=064c/1/0x40000002 softirq=7/7 fqs=1050 [ 21.748594] rcu: 1-....: (2100 ticks this GP) idle=064c/1/0x40000002 softirq=7/7 fqs=1050 [ 21.766871] rcu: (t=2102 jiffies g=-1187 q=25 ncpus=2) [ 21.766871] rcu: (t=2102 jiffies g=-1187 q=25 ncpus=2) [ 21.778429] CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.39 #482 [ 21.778429] CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.39 #482 [ 21.778461] Hardware name: Zyxel GS1900-48 [ 21.778461] Hardware name: Zyxel GS1900-48 ... [ 21.779757] [<8029b968>] jent_measure_jitter+0xc8/0x10c [ 21.779757] [<8029b968>] jent_measure_jitter+0xc8/0x10c [ 21.779779] [<8029b9e8>] jent_gen_entropy+0x3c/0xb0 [ 21.779779] [<8029b9e8>] jent_gen_entropy+0x3c/0xb0 [ 21.779800] [<8029bcc0>] jent_entropy_collector_alloc+0x104/0x118 [ 21.779800] [<8029bcc0>] jent_entropy_collector_alloc+0x104/0x118 [ 21.779822] [<8029bd6c>] jent_entropy_init+0x4c/0x2ec [ 21.779822] [<8029bd6c>] jent_entropy_init+0x4c/0x2ec [ 21.779844] [<8086f184>] jent_mod_init+0x58/0xac [ 21.779844] [<8086f184>] jent_mod_init+0x58/0xac [ 21.779865] [<80100200>] do_one_initcall+0x70/0x250 [ 21.779865] [<80100200>] do_one_initcall+0x70/0x250 [ 21.779883] [<8085c018>] kernel_init_freeable+0x1f0/0x280 [ 21.779883] [<8085c018>] kernel_init_freeable+0x1f0/0x280 [ 21.779905] [<8067cba4>] kernel_init+0x20/0xb0 [ 21.779905] [<8067cba4>] kernel_init+0x20/0xb0 [ 21.779926] [<80101158>] ret_from_kernel_thread+0x14/0x1c [ 21.779926] [<80101158>] ret_from_kernel_thread+0x14/0x1c This bit of entropy is helpful on these low end devices. Reenable the counter and simply disable the interrupt. Fixes: b7aab1958591e6290 ("realtek: SMP handling of R4K timer interrupts") Reported-by: Sebastian Gottschall Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/19499 Signed-off-by: Hauke Mehrtens --- .../linux/realtek/files-6.12/arch/mips/rtl838x/prom.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target/linux/realtek/files-6.12/arch/mips/rtl838x/prom.c b/target/linux/realtek/files-6.12/arch/mips/rtl838x/prom.c index c2c4b09d1d..68b4e5c144 100644 --- a/target/linux/realtek/files-6.12/arch/mips/rtl838x/prom.c +++ b/target/linux/realtek/files-6.12/arch/mips/rtl838x/prom.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -41,13 +42,13 @@ static void rtlsmp_finish(void) { /* These devices are low on resources. There might be the chance that CEVT_R4K is * not enabled in kernel build. Nevertheless the timer and interrupt 7 might be - * active by default after startup of secondary VPE. With no registered handler - * that leads to continuous unhandeled interrupts. In this case disable counting - * (DC) in the core and confirm a pending interrupt. + * active by default after startup of secondary VPEs. With no registered handler + * that leads to continuous unhandeled interrupts. Disable it but keep the counter + * running so it can still be used as an entropy source. */ if (!IS_ENABLED(CONFIG_CEVT_R4K)) { - write_c0_cause(read_c0_cause() | CAUSEF_DC); - write_c0_compare(0); + write_c0_status(read_c0_status() & ~CAUSEF_IP7); + write_c0_compare(read_c0_count() - 1); } local_irq_enable(); From aeaa61517b5439bb58aa40e39cf9d7d340c2bee5 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 26 Jul 2025 17:06:16 +0200 Subject: [PATCH 45/51] tools: automake: update to 1.18.1 automake update to 1.18 broke buildbots as we dont have makeinfo host tool present, after investigation this was an automake regression that was fixed in 1.18.1[1]. So, since 1.18.1 contains small number of fixes, update to it instead of just backporting the single commit. [1] https://cgit.git.savannah.gnu.org/cgit/automake.git/commit/?id=9b92240af4a8f7a3050c13adec367cf48e9ce063 Fixes: d7d02059407b ("tools/automake: update to 1.18") Signed-off-by: Robert Marko --- tools/automake/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/automake/Makefile b/tools/automake/Makefile index d3da6d1921..01cd9941d2 100644 --- a/tools/automake/Makefile +++ b/tools/automake/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=automake PKG_CPE_ID:=cpe:/a:gnu:automake -PKG_VERSION:=1.18 +PKG_VERSION:=1.18.1 PKG_API_VERSION:=$(word 2,$(subst ., ,$(PKG_VERSION))) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=@GNU/automake -PKG_HASH:=af6043a5d4b3beef0c48161f4a6936259321cd101a34c1ab0768328515626c8a +PKG_HASH:=63e585246d0fc8772dffdee0724f2f988146d1a3f1c756a3dc5cfbefa3c01915 include $(INCLUDE_DIR)/host-build.mk From e805d8bac94d0d52221a3cf328ecc2078ca5cfbd Mon Sep 17 00:00:00 2001 From: Til Kaiser Date: Wed, 23 Jul 2025 10:08:38 +0200 Subject: [PATCH 46/51] image: also show GRUB options for EROFS f7fa414d3b4d967a7e40b162977f48e1be430c1c added support for EROFS image generation. Generating combined GRUB images for EROFS is possible, but currently hidden if neither ext4, jffs2, or squashfs is selected. This commit adds EROFS as a dependency to the GRUB options. Signed-off-by: Til Kaiser Link: https://github.com/openwrt/openwrt/pull/19501 Signed-off-by: Hauke Mehrtens --- config/Config-images.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/Config-images.in b/config/Config-images.in index 05476dac77..208c4838d1 100644 --- a/config/Config-images.in +++ b/config/Config-images.in @@ -231,7 +231,7 @@ menu "Target Images" config GRUB_IMAGES bool "Build GRUB images (Linux x86 or x86_64 host only)" depends on TARGET_x86 - depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS + depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS || TARGET_ROOTFS_EROFS select PACKAGE_grub2 select PACKAGE_grub2-bios-setup default y @@ -239,7 +239,7 @@ menu "Target Images" config GRUB_EFI_IMAGES bool "Build GRUB EFI images" depends on TARGET_x86 || TARGET_armsr || TARGET_loongarch64 - depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS + depends on TARGET_ROOTFS_EXT4FS || TARGET_ROOTFS_JFFS2 || TARGET_ROOTFS_SQUASHFS || TARGET_ROOTFS_EROFS select PACKAGE_grub2 if TARGET_x86 select PACKAGE_grub2-efi if TARGET_x86 select PACKAGE_grub2-bios-setup if TARGET_x86 From 5809bfaaacca1d10c2e77bd073065d1d3b77527e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Mon, 9 Jun 2025 15:44:44 +0000 Subject: [PATCH 47/51] busybox: fix login applet on selinux MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the system boots up, but is unusable because pressing enter does not provide login with error: login: can't get SID for root This is happenning, because login.c passes the Linux username directly to get_default_context(), while libselinux expects an SELinux user identity, causing the call to fail for users without a matching SELinux name (e.g., root) and aborting login on SELinux-enabled systems. Fixes: #19075 Upstream-Status: Submitted [https://lists.busybox.net/pipermail/busybox/2025-April/091407.html] Signed-off-by: Petr Štetiar Link: https://github.com/openwrt/openwrt/pull/19080 Signed-off-by: Hauke Mehrtens --- ....c-libselinux-get_default_context-ex.patch | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 package/utils/busybox/patches/600-loginutils-login.c-libselinux-get_default_context-ex.patch diff --git a/package/utils/busybox/patches/600-loginutils-login.c-libselinux-get_default_context-ex.patch b/package/utils/busybox/patches/600-loginutils-login.c-libselinux-get_default_context-ex.patch new file mode 100644 index 0000000000..8c26ee001b --- /dev/null +++ b/package/utils/busybox/patches/600-loginutils-login.c-libselinux-get_default_context-ex.patch @@ -0,0 +1,51 @@ +From 850a6d031039237b0b13d8fab9f10a7cd4752907 Mon Sep 17 00:00:00 2001 +From: Dominick Grift +Date: Sat, 5 Apr 2025 13:40:26 +0200 +Subject: [PATCH] loginutils/login.c: libselinux get_default_context() expects + seuser + +Use getseuserbyname() to get the seuser associated with username and use that +instead with get_default_context() + +>From get_default_context.3: +"These functions takes a SELinux user identity that must be defined in the SELinux policy as their input, not a Linux username." + +Fixes: #19075 +Upstream-Status: Submitted [https://lists.busybox.net/pipermail/busybox/2025-April/091407.html] +Signed-off-by: Dominick Grift +--- + loginutils/login.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/loginutils/login.c ++++ b/loginutils/login.c +@@ -183,12 +183,16 @@ static void die_if_nologin(void) + static void initselinux(char *username, char *full_tty, + security_context_t *user_sid) + { ++ char *seuser = NULL, *level = NULL; + security_context_t old_tty_sid, new_tty_sid; + + if (!is_selinux_enabled()) + return; + +- if (get_default_context(username, NULL, user_sid)) { ++ if (getseuserbyname(username, &seuser, &level)) { ++ bb_error_msg_and_die("can't get seuser for %s", username); ++ } ++ if (get_default_context(seuser, NULL, user_sid)) { + bb_error_msg_and_die("can't get SID for %s", username); + } + if (getfilecon(full_tty, &old_tty_sid) < 0) { +@@ -201,6 +205,11 @@ static void initselinux(char *username, + if (setfilecon(full_tty, new_tty_sid) != 0) { + bb_perror_msg_and_die("chsid(%s, %s) failed", full_tty, new_tty_sid); + } ++ ++ if (ENABLE_FEATURE_CLEAN_UP) { ++ free(seuser); ++ free(level); ++ } + } + #endif + From 098e98dd4df5381bde600cfbce3f40227f9632e7 Mon Sep 17 00:00:00 2001 From: Dominick Grift Date: Sun, 1 Jun 2025 13:12:38 +0200 Subject: [PATCH 48/51] selinux-policy: update version to v2.8.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes since v2.6: a3383be configgenerate 8d04a3b adds modemnodedev and deletes cdcserialtermdev 77b52c4 README 3b8e1dc README 356211b README: add note about possible regression since selinux 3.6 171a3cc iwinfo 16ae0c1 haproxy 78bcb69 dufsysagent fix 6d88ac5 dufs fixes filecon c9aa6cd adds dufs 5f15774 net: clean up 02c8e76 unneeded sys.moduleload calls 6334366 README: todo /usr/bin/fit_check_sign 12b659f README: add reminder on polvers 3e93844 related to bpi-r4 Linux 6.12 449cb74 sysagent: use logintermdev (no differences) 20ad31d unlabeled/invalid: these are relative to . 9c85622 iproute2sysagent: ss c2a7863 README 6d7ad1c adds swaptools swapfile 5b69b63 rpcd related to luci mount tab afeee67 hotplugcall: iwinfo 6ca7996 adds ttyGS0 tty login serial f8b2fba wget: read shouldnt be needed e2faf89 bmon adds ~/.bmonrc 5ede79b adds seccompconffile 3034b20 some comments 9b4b44e loginsysagent: loose end fe0973c README ea06908 loginsysagent 2405c46 loginsysagent 9413988 loginsysagent: adds skel for wrapper retry 22929cb Revert "login.cil: skel for login.sh wrapper" fbcccf4 login.cil: skel for login.sh wrapper 1addde4 Revert "iproute2 ip protocol not supported" f38fd20 iproute2 ip protocol not supported 5abde97 openssl for openssl s_client -connect ip:port 642ddd9 ttyd be00125 iproute2 ip 1fbba89 iproute2 ip 342c981 no cap_userns d241cfb iproute2 ip netns related 6778504 iproute2 ip netns related 491d3c4 iproute2 ip d2dce16 iproute ip 8b43b1c iproute2 ip basic netns support 107e63f iproute2 ip 1b39905 README: looks like this is a no-go b081dba acme note about expected removal of /tmp/run/acme/lock 4df51dd haproxy ee825c8 coreutils: these dont have busybox equivalent 46f4a8b Revert "ucode: needed for custom rules in /etc/nftables.d" 048337a ucode: needed for custom rules in /etc/nftables.d 76b5a69 haproxy pid file c90f840 openssl s_client -connect dbbe475 haproxy local logging 7f58831 haproxy /etc/haproxy for stuff like proxy maps 050afc7 acmesysagent 031e0f3 README 2acf047 haproxy and iproute2 c5d1ce4 README b9304a5 haproxy whitespace b07c524 adds haproxy and iproute2 ss rules 9bc53b1 acme 6031379 openssl 8d6aaba adds sysfsutils skel fc24d0c README 12cc1d4 openssl 79cf372 apk leaks memfd 9912075 adds socat dataexecfile 011bf9a adds wget (consolidate uclient-fetch) 0ba70c0 adds ftp reserved ports 5b35e96 README bd02d73 README 4f6895f netifd comment fix bd46c1f coreutils ad13688 dnsmasq: more robust filecon d5d6dd3 README 74f73d1 fwtool: do_stage2: online sysupgrade sdcard 8251117 README badfb57 iw/tmux socket creation is implied in macros 5663f89 iwsysagent and readme 6815a6c README bde5a56 README 6b89f0a hotplug and netif unconfined.exec.file underline "trusted" 862da9b unknown netifd protocols with netif.unconfined.exec.file Signed-off-by: Dominick Grift Signed-off-by: Petr Štetiar [package hash fix] Link: https://github.com/openwrt/openwrt/pull/19080 Signed-off-by: Hauke Mehrtens --- package/system/selinux-policy/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package/system/selinux-policy/Makefile b/package/system/selinux-policy/Makefile index b3a3165b49..e3ae80516b 100644 --- a/package/system/selinux-policy/Makefile +++ b/package/system/selinux-policy/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=selinux-policy PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://git.defensec.nl/selinux-policy.git -PKG_VERSION:=2.6 -PKG_MIRROR_HASH:=3604ce2d2874f58a7fc03998daa81628fca43aa8ac0a7436f07612365b6ce7ad +PKG_VERSION:=2.8.2 +PKG_MIRROR_HASH:=7e81e6e9e933e6409b7f7bf2d5639960c440c82589c99b199b3540676f88eb8a PKG_SOURCE_VERSION:=v$(PKG_VERSION) PKG_BUILD_DEPENDS:=secilc/host policycoreutils/host From e8a27c4196b3b4394c841a68f08f7d682594a6e3 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 26 Jul 2025 13:12:48 +0200 Subject: [PATCH 49/51] kernel: kmod-crypto-lib-aescfb: Remove package kmod-crypto-lib-aescfb is marked hidden and not selected by any other package, it can not be build. The Kconfig option in the kernel has no title, so it can not be selected, it is only selected by CONFIG_TCG_TPM2_HMAC in the kernel. Fixes: ef2310b031a9 ("kernel: modules: update dependency for kmod-tpm") Fixes: aa51a1c13a3a ("kernel: kmod-crypto-lib-aescfb: Mark hidden") Link: https://github.com/openwrt/openwrt/pull/19532 Signed-off-by: Hauke Mehrtens --- package/kernel/linux/modules/crypto.mk | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/package/kernel/linux/modules/crypto.mk b/package/kernel/linux/modules/crypto.mk index 21197baad4..3f6b20fbbb 100644 --- a/package/kernel/linux/modules/crypto.mk +++ b/package/kernel/linux/modules/crypto.mk @@ -559,18 +559,6 @@ endef $(eval $(call KernelPackage,crypto-kpp)) -define KernelPackage/crypto-lib-aescfb - TITLE:=AES cipher operations feedback mode library - DEPENDS:=@!LINUX_6_6 - HIDDEN:=1 - KCONFIG:=CONFIG_CRYPTO_LIB_AESCFB - FILES:=$(LINUX_DIR)/lib/crypto/libaescfb.ko - AUTOLOAD:=$(call AutoLoad,09,libaescfb) - $(call AddDepends/crypto) -endef - -$(eval $(call KernelPackage,crypto-lib-aescfb)) - define KernelPackage/crypto-lib-chacha20 TITLE:=ChaCha library interface KCONFIG:=CONFIG_CRYPTO_LIB_CHACHA From 4e497102117884c609b233f7df6cf0ba0dbb5c34 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 26 Jul 2025 13:17:23 +0200 Subject: [PATCH 50/51] kernel: kmod-drm-imx-hdmi: Fix kmod-drm-display-helper dependency Select the kmod-drm-display-helper package instead of depending on it. kmod-drm-display-helper is hidden now, so the user can not manually select it. This fixes the build of the imx target. Fixes: 8bcc6d1894eb ("kernel: kmod-drm-display-helper: Mark hidden") Link: https://github.com/openwrt/openwrt/pull/19532 Signed-off-by: Hauke Mehrtens --- package/kernel/linux/modules/video.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/linux/modules/video.mk b/package/kernel/linux/modules/video.mk index 6b4dc6a3b2..5519774a48 100644 --- a/package/kernel/linux/modules/video.mk +++ b/package/kernel/linux/modules/video.mk @@ -585,7 +585,7 @@ $(eval $(call KernelPackage,drm-imx)) define KernelPackage/drm-imx-hdmi SUBMENU:=$(VIDEO_MENU) TITLE:=Freescale i.MX HDMI DRM support - DEPENDS:=+kmod-sound-core kmod-drm-imx kmod-drm-display-helper + DEPENDS:=+kmod-sound-core kmod-drm-imx +kmod-drm-display-helper KCONFIG:=CONFIG_DRM_IMX_HDMI \ CONFIG_DRM_DW_HDMI_AHB_AUDIO \ CONFIG_DRM_DW_HDMI_I2S_AUDIO From c2066fcb95d48eb3d8cddb7076c71a4f763b0349 Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Sat, 26 Jul 2025 13:19:34 +0200 Subject: [PATCH 51/51] gemini: Remove kmod-md-multipath dependency kmod-md-multipath was removed in kernel 6.12, remove the dependency here too. This fixes the build of the gemini target. Fixes: d12a603de575 ("kernel: kmod-md-multipath: Depend on kernel 6.6") Link: https://github.com/openwrt/openwrt/pull/19532 Signed-off-by: Hauke Mehrtens --- target/linux/gemini/image/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/linux/gemini/image/Makefile b/target/linux/gemini/image/Makefile index d7b77acdb1..df0d86096e 100644 --- a/target/linux/gemini/image/Makefile +++ b/target/linux/gemini/image/Makefile @@ -135,7 +135,7 @@ endef # A reasonable set of default packages handling the NAS type # of devices out of the box (former NAS42x0 IcyBox defaults) GEMINI_NAS_PACKAGES := $(DEFAULT_PACKAGES.nas) \ - kmod-md-mod kmod-md-linear kmod-md-multipath \ + kmod-md-mod kmod-md-linear \ kmod-md-raid0 kmod-md-raid1 kmod-md-raid10 kmod-md-raid456 \ kmod-fs-btrfs kmod-fs-cifs kmod-fs-nfs \ kmod-fs-nfsd kmod-fs-ntfs3 kmod-fs-reiserfs kmod-fs-vfat \