diff --git a/config/Config-images.in b/config/Config-images.in index d63a5536e5..5a874203d2 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 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)) 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; \ 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 diff --git a/package/kernel/linux/modules/video.mk b/package/kernel/linux/modules/video.mk index c5c5f186e1..3a48c49e64 100644 --- a/package/kernel/linux/modules/video.mk +++ b/package/kernel/linux/modules/video.mk @@ -620,7 +620,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 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) 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)) 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 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 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 + diff --git a/scripts/download.pl b/scripts/download.pl index 2b82b4a065..4af7a4a2e6 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 { @@ -325,14 +330,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; 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 \ 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>; 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(); 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/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, }; 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 */ diff --git a/tools/Makefile b/tools/Makefile index 9fadf65ee9..752a56158c 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -98,9 +98,10 @@ $(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 +$(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 @@ -138,10 +139,17 @@ $(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)/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) tools-y += bash else diff --git a/tools/automake/Makefile b/tools/automake/Makefile index 7f129c1d83..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.16.5 +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:=07bd24ad08a64bc17250ce09ec56e921d6343903943e99ccf63bbf0705e34605 +PKG_HASH:=63e585246d0fc8772dffdee0724f2f988146d1a3f1c756a3dc5cfbefa3c01915 include $(INCLUDE_DIR)/host-build.mk @@ -21,8 +21,7 @@ HOST_CONFIGURE_ARGS += \ --disable-silent-rules HOST_CONFIGURE_VARS += \ - PERL="/usr/bin/env perl" \ - am_cv_prog_PERL_ithreads=no + 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..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,9 +11,9 @@ # We need at least this version for CLONE support. --- a/bin/aclocal.in +++ b/bin/aclocal.in -@@ -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; + @@ -24,22 +24,22 @@ unless $ENV{AUTOMAKE_UNINSTALLED}; } -@@ -65,8 +67,8 @@ $perl_threads = 0; - # ACLOCAL_PATH environment variable, and reset with the '--system-acdir' - # option. +@@ -63,8 +65,8 @@ $perl_threads = 0; + # --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 -@@ -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 a0d04e21e5..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 -@@ -371,6 +371,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 3a8c9fcb47..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 -@@ -4513,7 +4513,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. -@@ -5641,7 +5641,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. -@@ -5655,7 +5655,7 @@ sub check_gnu_standards () +@@ -5714,7 +5714,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)' 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..1ac655adff --- /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 +@@ -1258,8 +1258,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; + } +@@ -1269,8 +1276,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..679236bda0 --- /dev/null +++ b/tools/automake/patches/310-maintainer-clean-built_sources.patch @@ -0,0 +1,49 @@ +--- a/bin/automake.in ++++ b/bin/automake.in +@@ -4760,12 +4760,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, [], diff --git a/tools/automake/patches/999-clean-am.patch b/tools/automake/patches/999-clean-am.patch new file mode 100644 index 0000000000..a9642d1c79 --- /dev/null +++ b/tools/automake/patches/999-clean-am.patch @@ -0,0 +1,28 @@ +--- 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 +--- 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 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/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, 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 - 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 diff --git a/tools/coreutils/Makefile b/tools/coreutils/Makefile index 73b95912ee..a0443b214c 100644 --- a/tools/coreutils/Makefile +++ b/tools/coreutils/Makefile @@ -8,38 +8,42 @@ 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 -PKG_PROGRAMS:=date readlink touch ln chown ginstall +PKG_PROGRAMS:=chown cp date ginstall ln readlink realpath rmdir seq stat touch include $(INCLUDE_DIR)/host-build.mk export GNULIB_SRCDIR:=$(HOST_GNULIB_SRCDIR) HOST_GNULIB_SKIP := \ - lib/nstrftime.c \ - lib/fprintftime.c \ - lib/fcntl.in.h \ - lib/locale.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))) HOST_MAKE_FLAGS += \ - $(AM_TOOL_PATHS_FAKE) \ + $(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=. define Host/Bootstrap ( \ cd $(HOST_BUILD_DIR); \ - $(AM_TOOL_PATHS_FAKE) \ + $(AM_TOOL_PATHS) AUTOPOINT="$(TRUE)" GTKDOCIZE="$(TRUE)" \ ./bootstrap \ --bootstrap-sync \ --force \ @@ -58,17 +62,21 @@ 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 $(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 - rm -f $(STAGING_DIR_HOST)/bin/install - -$(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 $(eval $(call HostBuild)) diff --git a/tools/coreutils/patches/000-bootstrap.patch b/tools/coreutils/patches/000-bootstrap.patch index 68db19084f..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. @@ -43,3 +43,17 @@ grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \ with_gettext=no +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -354,11 +354,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 diff --git a/tools/elfutils/Makefile b/tools/elfutils/Makefile index ae829cd340..294947df10 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 @@ -43,24 +43,49 @@ PKG_GNULIB_MODS = \ fallocate-posix \ fnmatch-gnu \ fts \ - obstack \ + obstack-printf-posix \ progname \ 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 + +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 += \ - DEFAULT_INCLUDES='-I. -I$$$$(top_builddir) -I$$$$(top_srcdir)/$(PKG_GNULIB_BASE)' \ + 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 +97,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 +122,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)) 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/010-backport-mips-support-reloc.patch b/tools/elfutils/patches/010-backport-mips-support-reloc.patch deleted file mode 100644 index 8a65e4e464..0000000000 --- a/tools/elfutils/patches/010-backport-mips-support-reloc.patch +++ /dev/null @@ -1,2525 +0,0 @@ -From 8d3bb7db9d6f07decfc59d83988cda54e5a8b0cd 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 - - * 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,16 @@ 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 -+ - 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,74 @@ -+/* 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" -+ -+extern __typeof (EBLHOOK (core_note)) mips64_core_note attribute_hidden; -+ -+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); -+ 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 -+++ 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,671 @@ -+/* 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; -+ } -+} -+ -+/* 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 * - 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,8 @@ 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..3a61acde6e --- /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_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 + +--- /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,6 +48,13 @@ 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); + 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 + 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 +@@ -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) ++#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"); ++ } ++ } + } + } + } +@@ -12037,7 +12133,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); +@@ -12067,7 +12163,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 +@@ -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-sysroot.sh + + if !BIARCH +@@ -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-define-file.bz2 \ ++ run-readelf-reloc.sh testfile-define-file.bz2 \ + testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh + + +--- /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..2ef9304bd1 --- /dev/null +++ b/tools/elfutils/patches/013-backport-mips-support-elflint.patch @@ -0,0 +1,157 @@ +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,10 +51,13 @@ 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); + 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, + 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); +@@ -3829,6 +3831,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 +@@ -3989,12 +3995,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"), +@@ -4060,6 +4075,7 @@ section [%2zu] '%s': merge flag set but + switch (shdr->sh_type) + { + case SHT_PROGBITS: ++ case SHT_MIPS_DWARF: + break; + + case SHT_NOBITS: +@@ -4717,7 +4733,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/100-portability.patch b/tools/elfutils/patches/100-portability.patch index 2cc8a4c56e..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 @@ -235,19 +235,9 @@ 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 +@@ -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); @@ -256,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; @@ -267,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; } @@ -276,25 +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[] = ---- 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 diff --git a/tools/elfutils/patches/101-shared-conditional.patch b/tools/elfutils/patches/101-shared-conditional.patch index 17d8cc72a1..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 @@ -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)) @@ -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 1f5b5d2138..35ef131190 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,9 +36,10 @@ + 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 +@@ -94,4 +94,10 @@ am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_S noinst_HEADERS = libdwflP.h @@ -77,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) @@ -118,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 diff --git a/tools/gnulib/Makefile b/tools/gnulib/Makefile index 5119355522..1237fad46e 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_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz -PKG_SOURCE_URL:=https://git.savannah.gnu.org/cgit/$(PKG_NAME).git/snapshot -PKG_HASH:=8e6f4a907d9677b55fd452e1340a3e030a6f530b138d420c11975da33f086b1e +PKG_SOURCE_URL=git://git.git.savannah.gnu.org/$(PKG_NAME).git +PKG_SOURCE_DATE:=2025-07-01 +PKG_SOURCE_VERSION:=a3151d456d6919c9066b54dc6f680452168165cf# # stable-202501 +PKG_MIRROR_HASH:=b695d96e915ecd6c4551436f417cb2c0879aef4ef6318721c8d5cc86cb44ba9d include $(INCLUDE_DIR)/host-build.mk @@ -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/000-bootstrap.patch b/tools/gnulib/patches/000-bootstrap.patch index 120586694e..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 -@@ -1157,7 +1157,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 a091bb2e1d..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 -+++ b/gnulib-tool -@@ -346,6 +346,34 @@ Options for --import, --add/remove-impor +--- a/gnulib-tool.sh ++++ b/gnulib-tool.sh +@@ -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 () -@@ -1620,6 +1648,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/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/150-portable-tdestroy.patch b/tools/gnulib/patches/150-portable-tdestroy.patch index 39c291f196..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 -@@ -39,7 +39,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]) ]) -@@ -75,8 +75,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 -@@ -9,6 +9,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]) -@@ -50,6 +51,7 @@ main () +@@ -52,6 +53,7 @@ main () *no) REPLACE_TSEARCH=1 REPLACE_TWALK=1 @@ -149,7 +149,7 @@ ;; esac else -@@ -64,6 +66,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 8ffe273e11..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 */ @@ -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 @@ -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,26 +93,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 +@@ -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 * - safe_alloc_realloc_n (void *ptr, size_t count, size_t size) -@@ -51,6 +53,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) - { -@@ -84,6 +89,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))) @@ -104,12 +110,85 @@ /** * ALLOC_N_UNINITIALIZED: * @ptr: pointer to allocated memory -@@ -112,6 +119,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 55335b27d2..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 -@@ -1447,10 +1447,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 e30a7172aa..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 -@@ -23,7 +23,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]) -@@ -50,6 +50,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]) -@@ -61,10 +62,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 -@@ -238,6 +238,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/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' \ diff --git a/tools/libtool/Makefile b/tools/libtool/Makefile index 761f7dc06b..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) @@ -23,6 +21,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 +47,7 @@ endef define Host/Configure $(if $(QUILT),$(call Host/Bootstrap)) $(call Host/Configure/Default) + $(call Host/Uninstall) endef define Host/Install @@ -54,6 +57,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 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