From 73e1a9d6d87ac1e3049a732cb3fd6889cf77a23a Mon Sep 17 00:00:00 2001 From: Ryan Burns Date: Thu, 11 Dec 2025 23:57:29 -0800 Subject: [PATCH 01/74] libcamera: 0.5.2 -> 0.6.0 Changelog: https://git.libcamera.org/libcamera/libcamera.git/tag/?h=v0.6.0 (cherry picked from commit b8bc22382c9a1d298d6cda468f39a917d0874621) --- pkgs/by-name/li/libcamera/package.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/li/libcamera/package.nix b/pkgs/by-name/li/libcamera/package.nix index 5633a74ec866c..97d3893925eb2 100644 --- a/pkgs/by-name/li/libcamera/package.nix +++ b/pkgs/by-name/li/libcamera/package.nix @@ -27,12 +27,12 @@ stdenv.mkDerivation rec { pname = "libcamera"; - version = "0.5.2"; + version = "0.6.0"; src = fetchgit { url = "https://git.libcamera.org/libcamera/libcamera.git"; rev = "v${version}"; - hash = "sha256-nr1LmnedZMGBWLf2i5uw4E/OMeXObEKgjuO+PUx/GDY="; + hash = "sha256-zGcbzL1Q2hUaj/s9NjBlp7hVjmSFb0GF8CnCoDS82Tw="; }; outputs = [ @@ -112,6 +112,7 @@ stdenv.mkDerivation rec { "-Dv4l2=true" (lib.mesonEnable "tracing" withTracing) (lib.mesonEnable "qcam" withQcam) + "-Dlibunwind=disabled" "-Dlc-compliance=disabled" # tries unconditionally to download gtest when enabled # Avoid blanket -Werror to evade build failures on less # tested compilers. From fb77441cce3c34534c42c12669111b278c2bb4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Thu, 18 Dec 2025 12:50:53 -0800 Subject: [PATCH 02/74] imagemagick: 7.1.2-10 -> 7.1.2-11 Diff: https://github.com/ImageMagick/ImageMagick/compare/7.1.2-10...7.1.2-11 Changelog: https://github.com/ImageMagick/Website/blob/main/ChangeLog.md (cherry picked from commit 8688a2923322a5e994ce706640ff5228d254fc06) --- pkgs/applications/graphics/ImageMagick/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/applications/graphics/ImageMagick/default.nix b/pkgs/applications/graphics/ImageMagick/default.nix index 05c4735524daa..774b76f89fe05 100644 --- a/pkgs/applications/graphics/ImageMagick/default.nix +++ b/pkgs/applications/graphics/ImageMagick/default.nix @@ -85,13 +85,13 @@ in stdenv.mkDerivation (finalAttrs: { pname = "imagemagick"; - version = "7.1.2-10"; + version = "7.1.2-11"; src = fetchFromGitHub { owner = "ImageMagick"; repo = "ImageMagick"; tag = finalAttrs.version; - hash = "sha256-96lhd0B4yV2s/zVazKrqAcDZvn+yIiXxp8fqyKSfxLc="; + hash = "sha256-RFiE23VW8AbVb7iglxjQMT6njDw+P7vLW6+nSKqN0p8="; }; outputs = [ From bd688bfbcdc0439824d9fb255cacf811260b5eb0 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sat, 13 Dec 2025 17:18:32 +0100 Subject: [PATCH 03/74] wolfssl: 5.8.2 -> 5.8.4 Fixes CVE-2025-12888, CVE-2025-11936, CVE-2025-11935, CVE-2025-11934, CVE-2025-11933, CVE-2025-11931, CVE-2025-11932 and CVE-2025-12889. Fixes #470470 Fixes #470471 Changes: https://github.com/wolfSSL/wolfssl/releases/tag/v5.8.4-stable (cherry picked from commit b4bdc1b3773e487a577b57b4daaf91157fa47026) --- pkgs/by-name/wo/wolfssl/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/wo/wolfssl/package.nix b/pkgs/by-name/wo/wolfssl/package.nix index b85e2c2016e06..e904c4dfefcca 100644 --- a/pkgs/by-name/wo/wolfssl/package.nix +++ b/pkgs/by-name/wo/wolfssl/package.nix @@ -17,13 +17,13 @@ }: stdenv.mkDerivation (finalAttrs: { pname = "wolfssl-${variant}"; - version = "5.8.2"; + version = "5.8.4"; src = fetchFromGitHub { owner = "wolfSSL"; repo = "wolfssl"; tag = "v${finalAttrs.version}-stable"; - hash = "sha256-rWBfpI6tdpKvQA/XdazBvU5hzyai5PtKRBpM4iplZDU="; + hash = "sha256-vfJKmDdM0r591t5GnuSS7NyiUYXCQOTKbWLVydB3N9s="; }; postPatch = '' From 2b76e8b4af7f66723110149e8992902bd3c817a7 Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Thu, 18 Dec 2025 22:26:21 +0100 Subject: [PATCH 04/74] systemd: 258.2 -> 258.3 (cherry picked from commit 32119d46c05d77e689607aa95890e6d5995f8383) --- pkgs/os-specific/linux/systemd/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/os-specific/linux/systemd/default.nix b/pkgs/os-specific/linux/systemd/default.nix index 49710f5123c56..4de92454d3b50 100644 --- a/pkgs/os-specific/linux/systemd/default.nix +++ b/pkgs/os-specific/linux/systemd/default.nix @@ -207,13 +207,13 @@ let in stdenv.mkDerivation (finalAttrs: { inherit pname; - version = "258.2"; + version = "258.3"; src = fetchFromGitHub { owner = "systemd"; repo = "systemd"; rev = "v${finalAttrs.version}"; - hash = "sha256-1iWeuNefDOIEUSTzxzvt+jfcs6sSMPhxQfdwp0mqUjQ="; + hash = "sha256-wpg/0z7xrB8ysPaa/zNp1mz+yYRCGyXz0ODZcKapovM="; }; # On major changes, or when otherwise required, you *must* : From 01eefe711a4acc0163d006f6b960af9177c719fd Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Thu, 25 Dec 2025 13:04:31 +0100 Subject: [PATCH 05/74] systemd: remove systemd-initrd-luks-unl0kr from passthru IDK what unl0kr is. The tests have been broken on aarch64 since the beginning and it's not part of systemd. The maintainer of unl0kr can be responsible for maintaining the unl0kr tests (cherry picked from commit 58f613d99619698ade40e90a32927fe7732ea27c) --- pkgs/os-specific/linux/systemd/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/os-specific/linux/systemd/default.nix b/pkgs/os-specific/linux/systemd/default.nix index 4de92454d3b50..c1dac94276505 100644 --- a/pkgs/os-specific/linux/systemd/default.nix +++ b/pkgs/os-specific/linux/systemd/default.nix @@ -956,7 +956,6 @@ stdenv.mkDerivation (finalAttrs: { systemd-initrd-luks-empty-passphrase systemd-initrd-luks-password systemd-initrd-luks-tpm2 - systemd-initrd-luks-unl0kr systemd-initrd-modprobe systemd-initrd-shutdown systemd-initrd-simple From e2fd562499e065e0ea24fa614c0cc33d769d329b Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Thu, 25 Dec 2025 13:06:51 +0100 Subject: [PATCH 06/74] nixos/tests/systemd-boot: only run tests on x86_64-linux They're all broken on aarch64-linux and makes it impossible for me to test systemd bumps by building the passthru tests Disable them on the platforms in question. We can fix them later. (cherry picked from commit 19c82da75a3c89664e4e53f7c4016e5aefa2f4c7) --- nixos/tests/systemd-boot.nix | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nixos/tests/systemd-boot.nix b/nixos/tests/systemd-boot.nix index fe0bde3176462..53f8db7a808c1 100644 --- a/nixos/tests/systemd-boot.nix +++ b/nixos/tests/systemd-boot.nix @@ -158,7 +158,8 @@ in } ); - basicXbootldr = runTest ( + # TODO: Fix on aarch64-linux + basicXbootldr = runTestOn [ "x86_64-linux" ] ( { lib, ... }: { name = "systemd-boot-xbootldr"; @@ -282,7 +283,8 @@ in } ); - update = runTest ( + # TODO: Fix on aarch64-linux + update = runTestOn [ "x86_64-linux" ] ( { lib, ... }: { name = "systemd-boot-update"; @@ -457,7 +459,8 @@ in } ); - entryFilenameXbootldr = runTest ( + # TODO: Fix on aarch64-linux + entryFilenameXbootldr = runTestOn [ "x86_64-linux" ] ( { lib, ... }: { name = "systemd-boot-entry-filename-xbootldr"; From 27dcf5b416231dae7ab7abc5872b23ff06771ceb Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sun, 21 Dec 2025 07:01:44 +0000 Subject: [PATCH 07/74] mpg123: 1.33.3 -> 1.33.4 Changes: https://www.mpg123.de/#2025-12-20 (cherry picked from commit e70fb322aa2663fba12452f5841ce52447602952) --- pkgs/applications/audio/mpg123/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/applications/audio/mpg123/default.nix b/pkgs/applications/audio/mpg123/default.nix index fb95111cbfe5f..e526288734e1b 100644 --- a/pkgs/applications/audio/mpg123/default.nix +++ b/pkgs/applications/audio/mpg123/default.nix @@ -21,11 +21,11 @@ assert withConplay -> !libOnly; stdenv.mkDerivation rec { pname = "${lib.optionalString libOnly "lib"}mpg123"; - version = "1.33.3"; + version = "1.33.4"; src = fetchurl { url = "mirror://sourceforge/mpg123/mpg123-${version}.tar.bz2"; - hash = "sha256-agxkct0VbiE8IGj0ARXru3OXjC2HPma64qJQ4tIZjSY="; + hash = "sha256-OujJ/4Cpe/wOIuifvNdGh+yk/B2zFbEmB/J/ActaR9k="; }; outputs = [ From d37e76e3e8615ee1348d48d85a46ac74582d3ceb Mon Sep 17 00:00:00 2001 From: ajs124 Date: Thu, 11 Dec 2025 15:24:04 +0100 Subject: [PATCH 08/74] tzdata: 2025b -> 2025c https://lists.iana.org/hyperkitty/list/tz-announce@iana.org/message/TAGXKYLMAQRZRFTERQ33CEKOW7KRJVAK/ (cherry picked from commit c44a597a9148d9e6ef790c1c063dace82c0ce368) --- pkgs/by-name/tz/tzdata/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/tz/tzdata/package.nix b/pkgs/by-name/tz/tzdata/package.nix index 773419da35cbb..146b46dc230d2 100644 --- a/pkgs/by-name/tz/tzdata/package.nix +++ b/pkgs/by-name/tz/tzdata/package.nix @@ -8,16 +8,16 @@ stdenv.mkDerivation (finalAttrs: { pname = "tzdata"; - version = "2025b"; + version = "2025c"; srcs = [ (fetchurl { url = "https://data.iana.org/time-zones/releases/tzdata${finalAttrs.version}.tar.gz"; - hash = "sha256-EYEEEzRfx4BQF+J+qfpIhf10zWGykRcRrQOPXSjXFHQ="; + hash = "sha256-SqeeTv/uU/xAKf/l9uvpeTcoLrzfOG1dLakc6EFC+Vc="; }) (fetchurl { url = "https://data.iana.org/time-zones/releases/tzcode${finalAttrs.version}.tar.gz"; - hash = "sha256-Bfj+2zUl7nDUnIfT+ueKig265P6HqlZcZc2plIrhNew="; + hash = "sha256-aX6+ZiVESu9QgPWOSdA0JLu1Lgi/SD0921rPEMvRV0A="; }) ]; From 1b856e376037a7b2cb66078dee86fa99acd102a4 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Sun, 16 Nov 2025 05:23:48 +0000 Subject: [PATCH 09/74] publicsuffix-list: 0-unstable-2025-10-08 -> 0-unstable-2025-11-14 (cherry picked from commit 6292cb6a988baf293317935e352d39431e62bbfd) --- pkgs/by-name/pu/publicsuffix-list/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/pu/publicsuffix-list/package.nix b/pkgs/by-name/pu/publicsuffix-list/package.nix index 09df1b471010c..a54b70e96ead6 100644 --- a/pkgs/by-name/pu/publicsuffix-list/package.nix +++ b/pkgs/by-name/pu/publicsuffix-list/package.nix @@ -7,13 +7,13 @@ stdenvNoCC.mkDerivation { pname = "publicsuffix-list"; - version = "0-unstable-2025-10-08"; + version = "0-unstable-2025-11-14"; src = fetchFromGitHub { owner = "publicsuffix"; repo = "list"; - rev = "ee7dec4a99602baaf51879dd8469b6642881a494"; - hash = "sha256-IlR3dICad9EZeizI3V0A1YCQZiV/xg2GxtmTLG4EASU="; + rev = "64ba165cf391818a086139239c8fa223264eebcc"; + hash = "sha256-Ugou4SzYx9EtzcBtocCqhCZZaU1Sngvk1IEVAIJZ4KY="; }; dontBuild = true; From 787c83a733d22bac18a529e40d6bc3a02d3ce437 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Wed, 31 Dec 2025 16:15:28 +0000 Subject: [PATCH 10/74] publicsuffix-list: 0-unstable-2025-11-14 -> 0-unstable-2025-12-28 (cherry picked from commit f8eed45c095774bd6d857a48f6f4cfd1c71351be) --- pkgs/by-name/pu/publicsuffix-list/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/pu/publicsuffix-list/package.nix b/pkgs/by-name/pu/publicsuffix-list/package.nix index a54b70e96ead6..4d53a001b9972 100644 --- a/pkgs/by-name/pu/publicsuffix-list/package.nix +++ b/pkgs/by-name/pu/publicsuffix-list/package.nix @@ -7,13 +7,13 @@ stdenvNoCC.mkDerivation { pname = "publicsuffix-list"; - version = "0-unstable-2025-11-14"; + version = "0-unstable-2025-12-28"; src = fetchFromGitHub { owner = "publicsuffix"; repo = "list"; - rev = "64ba165cf391818a086139239c8fa223264eebcc"; - hash = "sha256-Ugou4SzYx9EtzcBtocCqhCZZaU1Sngvk1IEVAIJZ4KY="; + rev = "1ef6d3bc102c85d12e92be54ec0dad8ee990dd5f"; + hash = "sha256-rQdum6XLgfXwzpKTneakFmC80tOmlPFrZ8C7dfEnlSo="; }; dontBuild = true; From 7c94d17d7797ff8d79604779611df56b31074985 Mon Sep 17 00:00:00 2001 From: Michael Daniels Date: Fri, 2 Jan 2026 08:58:48 -0500 Subject: [PATCH 11/74] libsodium: add mdaniels5757 as co-maintainer (cherry picked from commit 1534a22c766e15ca05262be88cff0a9016c7ef04) --- pkgs/by-name/li/libsodium/package.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/by-name/li/libsodium/package.nix b/pkgs/by-name/li/libsodium/package.nix index 734c84088d338..3de95adc0bfe2 100644 --- a/pkgs/by-name/li/libsodium/package.nix +++ b/pkgs/by-name/li/libsodium/package.nix @@ -43,7 +43,10 @@ stdenv.mkDerivation (finalAttrs: { description = "Modern and easy-to-use crypto library"; homepage = "https://doc.libsodium.org/"; license = lib.licenses.isc; - maintainers = with lib.maintainers; [ raskin ]; + maintainers = with lib.maintainers; [ + mdaniels5757 + raskin + ]; pkgConfigModules = [ "libsodium" ]; platforms = lib.platforms.all; }; From f8afb5c32be88ddb87d7d1309080a67bce241e66 Mon Sep 17 00:00:00 2001 From: Michael Daniels Date: Fri, 2 Jan 2026 16:56:20 -0500 Subject: [PATCH 12/74] libsodium: 1.0.20 -> 1.0.20-unstable-2025-12-31; use GitHub for releases; set updateScript (cherry picked from commit d9a76d1105b837b8ed6f07870d79e2bea5f534ba) --- pkgs/by-name/li/libsodium/package.nix | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/pkgs/by-name/li/libsodium/package.nix b/pkgs/by-name/li/libsodium/package.nix index 3de95adc0bfe2..383ee5a05a084 100644 --- a/pkgs/by-name/li/libsodium/package.nix +++ b/pkgs/by-name/li/libsodium/package.nix @@ -1,18 +1,21 @@ { lib, stdenv, - fetchurl, autoreconfHook, + fetchFromGitHub, testers, + unstableGitUpdater, }: stdenv.mkDerivation (finalAttrs: { pname = "libsodium"; - version = "1.0.20"; + version = "1.0.20-unstable-2025-12-31"; - src = fetchurl { - url = "https://download.libsodium.org/libsodium/releases/libsodium-${finalAttrs.version}.tar.gz"; - hash = "sha256-67Ze9spDkzPCu0GgwZkFhyiNoH9sf9B8s6GMwY0wzhk="; + src = fetchFromGitHub { + owner = "jedisct1"; + repo = "libsodium"; + rev = "d44593f1a5b7d31b5122689605b489577356f7e8"; + hash = "sha256-6DC9JJLUwAoZHrYdCIiqOtAlWOEczec2r2FmaBbsa/Q="; }; outputs = [ @@ -37,7 +40,13 @@ stdenv.mkDerivation (finalAttrs: { doCheck = true; - passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; + passthru = { + tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; + updateScript = unstableGitUpdater { + branch = "stable"; + tagConverter = "cut -d - -f 1"; + }; + }; meta = { description = "Modern and easy-to-use crypto library"; From 88ade8ca68f2b62fb5016694b86a2836556c1045 Mon Sep 17 00:00:00 2001 From: Michael Daniels Date: Fri, 2 Jan 2026 18:41:09 -0500 Subject: [PATCH 13/74] python3Packages.pynacl: 1.6.0 -> 1.6.2 (cherry picked from commit f426f342aef1b75cfaf66686e6084e7710b57809) --- pkgs/development/python-modules/pynacl/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pynacl/default.nix b/pkgs/development/python-modules/pynacl/default.nix index 11a60e232336a..1606ab44db30f 100644 --- a/pkgs/development/python-modules/pynacl/default.nix +++ b/pkgs/development/python-modules/pynacl/default.nix @@ -14,7 +14,7 @@ buildPythonPackage rec { pname = "pynacl"; - version = "1.6.0"; + version = "1.6.2"; outputs = [ "out" "doc" @@ -27,7 +27,7 @@ buildPythonPackage rec { owner = "pyca"; repo = "pynacl"; tag = version; - hash = "sha256-7SDJB2bXn0IGJQi597yehs9epdfmS7slbQ97vFVUkEA="; + hash = "sha256-EzzJVRDgYQO6T8YIQjad/Eb9O+BXT4IpOpa48fpBPnc="; }; build-system = [ From 1d0ab97623a8e7db120ed2784868ee52d1b490bf Mon Sep 17 00:00:00 2001 From: Audrey Dutcher Date: Tue, 30 Dec 2025 18:08:57 -0800 Subject: [PATCH 14/74] systemd: accept more symlink patterns for /etc/localtime (cherry picked from commit e8a805af1005ffeb98d4376dd2cbb9b9a809ab3b) --- .../0007-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/os-specific/linux/systemd/0007-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch b/pkgs/os-specific/linux/systemd/0007-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch index 21589efdd8494..254a63c1a1072 100644 --- a/pkgs/os-specific/linux/systemd/0007-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch +++ b/pkgs/os-specific/linux/systemd/0007-Change-usr-share-zoneinfo-to-etc-zoneinfo.patch @@ -70,7 +70,7 @@ index 55931a2546..2e00bd7539 100644 return r; /* Return EINVAL if not a symlink */ - const char *e = PATH_STARTSWITH_SET(t, "/usr/share/zoneinfo/", "../usr/share/zoneinfo/"); -+ const char *e = PATH_STARTSWITH_SET(t, "/etc/zoneinfo/", "../etc/zoneinfo/"); ++ const char *e = PATH_STARTSWITH_SET(t, "/etc/zoneinfo/", "../etc/zoneinfo/", "zoneinfo/"); if (!e) return -EINVAL; if (!timezone_is_valid(e, LOG_DEBUG)) @@ -112,7 +112,7 @@ index 480a9c55c6..02c9ae6608 100644 path, - "../usr/share/zoneinfo/", - "/usr/share/zoneinfo/"); -+ "../etc/zoneinfo/", ++ "../etc/zoneinfo/", "zoneinfo/", + "/etc/zoneinfo/"); } From 305af14e5b20786a36d7d3fe99fa64aec63ae101 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sun, 4 Jan 2026 22:22:44 +0100 Subject: [PATCH 15/74] xorg.xorgserver: 21.1.20 -> 21.1.21 Fixes some regressions https://lists.x.org/archives/xorg-announce/2025-November/003643.html Not-cherry-picked-because: package was refactored and renamed on unstable. PR on unstable: #471756 --- pkgs/servers/x11/xorg/default.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/servers/x11/xorg/default.nix b/pkgs/servers/x11/xorg/default.nix index c13e999194b3c..2d214e1dfb599 100644 --- a/pkgs/servers/x11/xorg/default.nix +++ b/pkgs/servers/x11/xorg/default.nix @@ -3051,11 +3051,11 @@ self: with self; { }: stdenv.mkDerivation (finalAttrs: { pname = "xorg-server"; - version = "21.1.20"; + version = "21.1.21"; builder = ./builder.sh; src = fetchurl { - url = "mirror://xorg/individual/xserver/xorg-server-21.1.20.tar.xz"; - sha256 = "sha256-dpW8YYJLOoG2utL3iwVADKAVAD3kAtGzIhFxBbcC6Tc="; + url = "mirror://xorg/individual/xserver/xorg-server-21.1.21.tar.xz"; + sha256 = "sha256-wMvlVFs/ZFuuYCS4MNHRFUqVY1BoOk5Ssv/1sPoatRk="; }; hardeningDisable = [ "bindnow" From a3b37e95a1e3dc2ab64d19882e65bc5981bf944a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lima?= Date: Sat, 3 Jan 2026 02:09:40 +0000 Subject: [PATCH 16/74] xdg-user-dirs: 0.18 -> 0.19 (cherry picked from commit 514ae4ea8e12028e44d1679aad11acc2cf5aa007) --- .../xd/xdg-user-dirs/gettext-0.25.patch | 20 ---------- pkgs/by-name/xd/xdg-user-dirs/package.nix | 40 ++++++++++--------- 2 files changed, 21 insertions(+), 39 deletions(-) delete mode 100644 pkgs/by-name/xd/xdg-user-dirs/gettext-0.25.patch diff --git a/pkgs/by-name/xd/xdg-user-dirs/gettext-0.25.patch b/pkgs/by-name/xd/xdg-user-dirs/gettext-0.25.patch deleted file mode 100644 index f292da934d593..0000000000000 --- a/pkgs/by-name/xd/xdg-user-dirs/gettext-0.25.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index dc389db..45a35df 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2,6 +2,7 @@ AC_INIT(xdg-user-dirs-update.c) - - AM_INIT_AUTOMAKE(xdg-user-dirs, 0.18) - AM_CONFIG_HEADER(config.h) -+AC_CONFIG_MACRO_DIRS([m4]) - - AM_SANITY_CHECK - AM_MAINTAINER_MODE -@@ -20,6 +21,7 @@ GETTEXT_PACKAGE=xdg-user-dirs - AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [The gettext domain name]) - AC_SUBST(GETTEXT_PACKAGE) - -+AM_GNU_GETTEXT_REQUIRE_VERSION([0.14.4]) - AM_GNU_GETTEXT([external]) - - dnl ========================================================================== diff --git a/pkgs/by-name/xd/xdg-user-dirs/package.nix b/pkgs/by-name/xd/xdg-user-dirs/package.nix index 1a77506ccf0a4..c0423a044442b 100644 --- a/pkgs/by-name/xd/xdg-user-dirs/package.nix +++ b/pkgs/by-name/xd/xdg-user-dirs/package.nix @@ -1,42 +1,41 @@ { lib, stdenv, - autoreconfHook, + meson, + ninja, fetchurl, libxslt, docbook_xsl, docbook_xml_dtd_43, gettext, - makeWrapper, + makeBinaryWrapper, + libiconv, + libintl, }: stdenv.mkDerivation (finalAttrs: { pname = "xdg-user-dirs"; - version = "0.18"; + version = "0.19"; src = fetchurl { - url = "https://user-dirs.freedesktop.org/releases/xdg-user-dirs-${finalAttrs.version}.tar.gz"; - hash = "sha256-7G8G10lc26N6cyA5+bXhV4vLKWV2/eDaQO2y9SIg3zw="; + url = "https://user-dirs.freedesktop.org/releases/xdg-user-dirs-${finalAttrs.version}.tar.xz"; + hash = "sha256-6S3rkpwQ1LKTKTl6+KJYUQEkf35hd6xvHSjoITDtjBk="; }; - patches = [ - # https://gitlab.freedesktop.org/xdg/xdg-user-dirs/-/merge_requests/16 - ./gettext-0.25.patch - ]; - - postPatch = '' - substituteInPlace Makefile.am \ - --replace-fail 'libraries = $(LIBINTL)' 'libraries = $(LIBICONV) $(LIBINTL)' - ''; - nativeBuildInputs = [ - autoreconfHook - makeWrapper + meson + ninja + makeBinaryWrapper libxslt docbook_xsl docbook_xml_dtd_43 - ] - ++ lib.optionals stdenv.hostPlatform.isDarwin [ gettext ]; + gettext + ]; + + buildInputs = [ + libiconv + libintl + ]; NIX_LDFLAGS = if stdenv.isDarwin then "-liconv" else null; @@ -44,6 +43,9 @@ stdenv.mkDerivation (finalAttrs: { # fallback values need to be last wrapProgram "$out/bin/xdg-user-dirs-update" \ --suffix XDG_CONFIG_DIRS : "$out/etc/xdg" + + substituteInPlace "$out/lib/systemd/user/xdg-user-dirs.service" \ + --replace-fail "/usr/bin/xdg-user-dirs-update" "$out/bin/xdg-user-dirs-update" ''; meta = { From 8c0288d9a8596ff1803f84438ebe4f1ceb565296 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Wed, 31 Dec 2025 12:58:22 +0000 Subject: [PATCH 17/74] libpcap: 1.10.5 -> 1.10.6 (cherry picked from commit 4ba51512654ebd116348b17eb106eb3b03fc6228) --- pkgs/by-name/li/libpcap/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/li/libpcap/package.nix b/pkgs/by-name/li/libpcap/package.nix index 57304a6e3951b..55573a77c7e2c 100644 --- a/pkgs/by-name/li/libpcap/package.nix +++ b/pkgs/by-name/li/libpcap/package.nix @@ -26,13 +26,13 @@ stdenv.mkDerivation rec { pname = "libpcap"; - version = "1.10.5"; + version = "1.10.6"; __structuredAttrs = true; src = fetchurl { url = "https://www.tcpdump.org/release/${pname}-${version}.tar.gz"; - hash = "sha256-N87ZChmjAqfzLkWCJKAMNlwReQXCzTWsVEtogKgUiPA="; + hash = "sha256-hy3REzf+GrAq2dT+4EfJ2iRNaVxt3zTi67cz79Ttiqk="; }; outputs = [ From 99b3cac74074002786e80156b7293b34a3d7fc3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lima?= Date: Sat, 3 Jan 2026 02:18:21 +0000 Subject: [PATCH 18/74] xdg-user-dirs-gtk: 0.14 -> 0.16 (cherry picked from commit 9e75aec4c536f2012366717dc7250690e1418585) --- pkgs/by-name/xd/xdg-user-dirs-gtk/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/xd/xdg-user-dirs-gtk/package.nix b/pkgs/by-name/xd/xdg-user-dirs-gtk/package.nix index 383b36d71b905..b13967cb78883 100644 --- a/pkgs/by-name/xd/xdg-user-dirs-gtk/package.nix +++ b/pkgs/by-name/xd/xdg-user-dirs-gtk/package.nix @@ -13,11 +13,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "xdg-user-dirs-gtk"; - version = "0.14"; + version = "0.16"; src = fetchurl { url = "mirror://gnome/sources/xdg-user-dirs-gtk/${lib.versions.majorMinor finalAttrs.version}/xdg-user-dirs-gtk-${finalAttrs.version}.tar.xz"; - hash = "sha256-U3++FCskc27XiU5KAfaf11jLbHpnejgoeVKdIX9KKHM="; + hash = "sha256-voJd5/iRddterQzTdE0nYRCccJQyUahwkiWRYwJVIKk="; }; nativeBuildInputs = [ From aa1adb73f503063d25162fb9a579a20190e2da7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Mon, 5 Jan 2026 02:22:36 -0800 Subject: [PATCH 19/74] python3Packages.aiohttp: 3.13.2 -> 3.13.3 Diff: https://github.com/aio-libs/aiohttp/compare/v3.13.2...v3.13.3 Changelog: https://docs.aiohttp.org/en/v3.13.3/changes.html (cherry picked from commit 28a7d239f858e22377c84b573d0bf192a4fa0286) --- pkgs/development/python-modules/aiohttp/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/aiohttp/default.nix b/pkgs/development/python-modules/aiohttp/default.nix index 2706b731c80a8..a3beffd1a863d 100644 --- a/pkgs/development/python-modules/aiohttp/default.nix +++ b/pkgs/development/python-modules/aiohttp/default.nix @@ -51,14 +51,14 @@ buildPythonPackage rec { pname = "aiohttp"; - version = "3.13.2"; + version = "3.13.3"; pyproject = true; src = fetchFromGitHub { owner = "aio-libs"; repo = "aiohttp"; tag = "v${version}"; - hash = "sha256-LqYGrrWgSZazk0hjQvTFwqtU/PtMEaPi+m1Ya8Ds+pU="; + hash = "sha256-V+digrfigdA3hwd2xW47BACh3r07j6pGE8WFAGivZnA="; }; postPatch = '' From 6ebc8443b43c37936ddb22ac278e9647af1bcdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Thu, 8 Jan 2026 02:48:42 -0800 Subject: [PATCH 20/74] python3Packages.brotlicffi: 1.1.0.0 -> 1.2.0.0 Diff: https://github.com/python-hyper/brotlicffi/compare/v1.1.0.0...v1.2.0.0 Changelog: https://github.com/python-hyper/brotlicffi/blob/v1.2.0.0/HISTORY.rst (cherry picked from commit b2e35ab78256222e9473013882d0791118794b11) --- pkgs/development/python-modules/brotlicffi/default.nix | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/development/python-modules/brotlicffi/default.nix b/pkgs/development/python-modules/brotlicffi/default.nix index 7f7171a6ebb99..618bffa999336 100644 --- a/pkgs/development/python-modules/brotlicffi/default.nix +++ b/pkgs/development/python-modules/brotlicffi/default.nix @@ -2,7 +2,6 @@ lib, fetchFromGitHub, buildPythonPackage, - pythonOlder, cffi, # overridden as pkgs.brotli brotli, @@ -13,15 +12,14 @@ buildPythonPackage rec { pname = "brotlicffi"; - version = "1.1.0.0"; + version = "1.2.0.0"; pyproject = true; - disabled = pythonOlder "3.7"; src = fetchFromGitHub { owner = "python-hyper"; repo = "brotlicffi"; - rev = "v${version}"; - sha256 = "sha256-oW4y1WBJ7+4XwNwwSSR0qUqN03cZYXUYQ6EAwce9dzI="; + tag = "v${version}"; + hash = "sha256-3/68qBfsFtH+7h3gPxUdkyHwG6qLbh+bVLrxzsb3bc4="; }; build-system = [ setuptools ]; @@ -49,6 +47,7 @@ buildPythonPackage rec { pythonImportsCheck = [ "brotlicffi" ]; meta = { + changelog = "https://github.com/python-hyper/brotlicffi/blob/${src.tag}/HISTORY.rst"; description = "Python CFFI bindings to the Brotli library"; homepage = "https://github.com/python-hyper/brotlicffi"; license = lib.licenses.mit; From fcea730152483cb0bb070bb45b2defd7a699666f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lima?= Date: Sun, 4 Jan 2026 15:37:38 +0000 Subject: [PATCH 21/74] nixos/gnome: install xdg-user-dirs{,-gtk} systemd units GNOME 49 has completely removed the built-in service manager, which allowed .desktop files to be used for launching services. This mechanism was used by xdg-user-dirs and xdg-user-dirs-gtk to update the xdg user directories. In recent versions of xdg-user-dirs and xdg-user-dirs-gtk, systemd units are included in the installation to work around that. This commit installs those units when gnome-shell is enabled. Link: https://gitlab.gnome.org/GNOME/gnome-session/-/blob/49.2/NEWS?ref_type=tags#L51-54 Link: https://gitlab.freedesktop.org/xdg/xdg-user-dirs/-/commit/2a63d3f0ffb76135790bb1168a3270a599904380 (cherry picked from commit a46c0676118a011612ff6ff2fca51c85734ce8b4) --- nixos/modules/services/desktop-managers/gnome.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nixos/modules/services/desktop-managers/gnome.nix b/nixos/modules/services/desktop-managers/gnome.nix index bfad0efc7f654..4fddcf9903cb8 100644 --- a/nixos/modules/services/desktop-managers/gnome.nix +++ b/nixos/modules/services/desktop-managers/gnome.nix @@ -390,6 +390,10 @@ in systemd.packages = [ pkgs.gnome-session pkgs.gnome-shell + ] + ++ removeExcluded [ + pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/ + pkgs.xdg-user-dirs-gtk # Used to create the default bookmarks ]; services.udev.packages = [ From b1bcdca82dd921362eeaa6293eeaa0e2176c4e18 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 8 Jan 2026 17:58:48 +0100 Subject: [PATCH 22/74] libtasn1: 4.20.0 -> 4.21.0 https://gitlab.com/gnutls/libtasn1/-/blob/v4.21.0/NEWS.md https://www.openwall.com/lists/oss-security/2026/01/08/5 Fixes: CVE-2025-13151 (cherry picked from commit 8b91f725c2e219f1631a775a415eaeb7bbdea771) --- pkgs/by-name/li/libtasn1/package.nix | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/by-name/li/libtasn1/package.nix b/pkgs/by-name/li/libtasn1/package.nix index c8e506d2bd532..7de5f9bc2b742 100644 --- a/pkgs/by-name/li/libtasn1/package.nix +++ b/pkgs/by-name/li/libtasn1/package.nix @@ -11,13 +11,13 @@ qemu, }: -stdenv.mkDerivation rec { +stdenv.mkDerivation (finalAttrs: { pname = "libtasn1"; - version = "4.20.0"; + version = "4.21.0"; src = fetchurl { - url = "mirror://gnu/libtasn1/libtasn1-${version}.tar.gz"; - sha256 = "sha256-kuDjvUwC1K7udgNrLd2D8McyukzaXLcdWDJysjWHp2w="; + url = "mirror://gnu/libtasn1/libtasn1-${finalAttrs.version}.tar.gz"; + hash = "sha256-HYpESiI8xUZCQHdzRuEl3lHY5qvwuLrHQqyEYJFn3Ic="; }; outputs = [ @@ -50,6 +50,6 @@ stdenv.mkDerivation rec { ''; license = lib.licenses.lgpl2Plus; platforms = lib.platforms.all; - changelog = "https://gitlab.com/gnutls/libtasn1/-/blob/v${version}/NEWS"; + changelog = "https://gitlab.com/gnutls/libtasn1/-/blob/v${finalAttrs.version}/NEWS.md"; }; -} +}) From 303a0262e91fbc8319a7a3141d4de8413a3a36ce Mon Sep 17 00:00:00 2001 From: Marcin Serwin Date: Sun, 11 Jan 2026 13:31:43 +0100 Subject: [PATCH 23/74] sdl3: fix dynamic loading of vulkan Vulkan support broke after https://github.com/NixOS/nixpkgs/pull/439652 due to https://github.com/libsdl-org/SDL/issues/14805. Fixes: https://github.com/NixOS/nixpkgs/issues/478908 Signed-off-by: Marcin Serwin (cherry picked from commit f91cf267f2f2a1d9a9bcdc1107a81485e76c745d) --- pkgs/by-name/sd/sdl3/package.nix | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkgs/by-name/sd/sdl3/package.nix b/pkgs/by-name/sd/sdl3/package.nix index 48ef594995ad4..67416de996919 100644 --- a/pkgs/by-name/sd/sdl3/package.nix +++ b/pkgs/by-name/sd/sdl3/package.nix @@ -88,6 +88,20 @@ stdenv.mkDerivation (finalAttrs: { --replace-fail '"zenity"' '"${lib.getExe zenity}"' substituteInPlace src/dialog/unix/SDL_zenitydialog.c \ --replace-fail '"zenity"' '"${lib.getExe zenity}"' + '' + # https://github.com/libsdl-org/SDL/issues/14805 + + '' + substituteInPlace src/video/x11/SDL_x11vulkan.c \ + src/video/wayland/SDL_waylandvulkan.c \ + src/video/offscreen/SDL_offscreenvulkan.c \ + src/video/kmsdrm/SDL_kmsdrmvulkan.c \ + src/video/vivante/SDL_vivantevulkan.c \ + src/video/android/SDL_androidvulkan.c \ + --replace-fail 'libvulkan.so' '${lib.getLib vulkan-loader}/lib/libvulkan.so' + '' + + lib.optionalString x11Support '' + substituteInPlace src/video/x11/SDL_x11vulkan.c \ + --replace-fail 'libX11-xcb.so' '${lib.getLib xorg.libX11}/lib/libX11-xcb.so' ''; strictDeps = true; From f644307e16cd8e7fa7a17d87c140453c2497473e Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sun, 11 Jan 2026 23:01:33 +0100 Subject: [PATCH 24/74] harfbuzz: apply patch for CVE-2026-22693 https://github.com/harfbuzz/harfbuzz/security/advisories/GHSA-xvjr-f2r9-c7ww (cherry picked from commit 16e7551ed4a37f9c53bee25e2009fbe74cef9644) --- pkgs/by-name/ha/harfbuzz/package.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkgs/by-name/ha/harfbuzz/package.nix b/pkgs/by-name/ha/harfbuzz/package.nix index d172d5922dd92..fa40f88b14fed 100644 --- a/pkgs/by-name/ha/harfbuzz/package.nix +++ b/pkgs/by-name/ha/harfbuzz/package.nix @@ -2,6 +2,7 @@ lib, stdenv, fetchurl, + fetchpatch, pkg-config, glib, freetype, @@ -41,6 +42,15 @@ stdenv.mkDerivation (finalAttrs: { hash = "sha256-5cgbf24LEC37AAz6QkU4uOiWq3ii9Lil7IyuYqtDNp4="; }; + patches = [ + (fetchpatch { + # https://github.com/harfbuzz/harfbuzz/security/advisories/GHSA-xvjr-f2r9-c7ww + name = "CVE-2026-22693.patch"; + url = "https://github.com/harfbuzz/harfbuzz/commit/1265ff8d990284f04d8768f35b0e20ae5f60daae.patch"; + hash = "sha256-mdgIhp1ndPSfzplBRB7s+BN2T5Z9dEYZ0bAmSDCUPSE="; + }) + ]; + postPatch = '' patchShebangs src/*.py test '' From e222eb9853bae03f396aeee0d2d0869be676fc18 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sat, 10 Jan 2026 11:46:36 +0100 Subject: [PATCH 25/74] fontforge: apply patches for CVE-2025-15279, CVE-2025-15275 and CVE-2025-15269 https://www.zerodayinitiative.com/advisories/ZDI-CAN-27517/ https://www.zerodayinitiative.com/advisories/ZDI-CAN-28543/ https://www.zerodayinitiative.com/advisories/ZDI-CAN-28564/ (cherry picked from commit 7a8c7944a666148937082e901f895edc2de4b195) --- pkgs/by-name/fo/fontforge/package.nix | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pkgs/by-name/fo/fontforge/package.nix b/pkgs/by-name/fo/fontforge/package.nix index d929d95d6ea4a..7b60bd47b28e9 100644 --- a/pkgs/by-name/fo/fontforge/package.nix +++ b/pkgs/by-name/fo/fontforge/package.nix @@ -1,6 +1,7 @@ { stdenv, fetchFromGitHub, + fetchpatch, lib, replaceVars, cmake, @@ -48,6 +49,26 @@ stdenv.mkDerivation (finalAttrs: { patches = [ # Provide a Nix-controlled location for the initial `sys.path` entry. (replaceVars ./set-python-sys-path.patch { python = "${py}/${py.sitePackages}"; }) + (fetchpatch { + name = "CVE-2025-15279_1.patch"; + url = "https://github.com/fontforge/fontforge/commit/7d67700cf8888e0bb37b453ad54ed932c8587073.patch"; + hash = "sha256-AqixWSgMc75qkgO30nWnI9NKLRtVwCDR+uSEiwMtFKg="; + }) + (fetchpatch { + name = "CVE-2025-15279_2.patch"; + url = "https://github.com/fontforge/fontforge/commit/720ea95020c964202928afd2e93b0f5fac11027e.patch"; + hash = "sha256-DsP2fDTZlTtg8MXcnsuGQ4PFPOVp56Jm95gq877PLlE="; + }) + (fetchpatch { + name = "CVE-2025-15275.patch"; + url = "https://github.com/fontforge/fontforge/commit/7195402701ace7783753ef9424153eff48c9af44.patch"; + hash = "sha256-NHgKUvHF389z7PRqaDj3IWLSLijlSw0F3UYcMjLxKvE="; + }) + (fetchpatch { + name = "CVE-2025-15269.patch"; + url = "https://github.com/fontforge/fontforge/commit/6aea6db5da332d8ac94e3501bb83c1b21f52074d.patch"; + hash = "sha256-3KsWSXVRpPJbytVmzjExCGw6IaCgcrKwqQGRKpQAOiY="; + }) ]; # use $SOURCE_DATE_EPOCH instead of non-deterministic timestamps From f05b9a4f298de3af84295bd12e82936886d8f94c Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Tue, 13 Jan 2026 15:19:53 +0100 Subject: [PATCH 26/74] nodejs_22: 22.21.1 -> 22.22.0 (cherry picked from commit f3dfef5ce7283255d11e2327b9fdf08c660dabe8) --- pkgs/development/web/nodejs/v22.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/web/nodejs/v22.nix b/pkgs/development/web/nodejs/v22.nix index a9be2fdad4b36..cfc4f014fa1df 100644 --- a/pkgs/development/web/nodejs/v22.nix +++ b/pkgs/development/web/nodejs/v22.nix @@ -23,8 +23,8 @@ let in buildNodejs { inherit enableNpm; - version = "22.21.1"; - sha256 = "487d73fd4db00dc2420d659a8221b181a7937fbc5bc73f31c30b1680ad6ded6a"; + version = "22.22.0"; + sha256 = "4c138012bb5352f49822a8f3e6d1db71e00639d0c36d5b6756f91e4c6f30b683"; patches = ( if (stdenv.hostPlatform.emulatorAvailable buildPackages) then From 902976cd8821a6e2fda94028d80cb5cb831aae27 Mon Sep 17 00:00:00 2001 From: Emily Date: Sat, 10 Jan 2026 18:55:51 +0000 Subject: [PATCH 27/74] llvmPackages.libllvm: clean up rebuild avoidance (cherry picked from commit 0ecdff6a06bbd30e40d3acc39f0fd4e98653222d) --- .../compilers/llvm/common/llvm/default.nix | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/pkgs/development/compilers/llvm/common/llvm/default.nix b/pkgs/development/compilers/llvm/common/llvm/default.nix index 1e22dbe246037..79bc113d414fd 100644 --- a/pkgs/development/compilers/llvm/common/llvm/default.nix +++ b/pkgs/development/compilers/llvm/common/llvm/default.nix @@ -299,17 +299,10 @@ stdenv.mkDerivation ( # This was fixed upstream in LLVM 21 with # 88f041f3e05e26617856cc096d2e2864dfaa1c7b, but it’s too # painful to backport all the way. - lib.optionalString - ( - lib.versionOlder release_version "21" - || - # Rebuild avoidance; TODO: clean up on `staging`. - stdenv.hostPlatform.isx86 - ) - '' - substituteInPlace unittests/TargetParser/Host.cpp \ - --replace-fail "getMacOSHostVersion" "DISABLED_getMacOSHostVersion" - '' + lib.optionalString (lib.versionOlder release_version "21") '' + substituteInPlace unittests/TargetParser/Host.cpp \ + --replace-fail "getMacOSHostVersion" "DISABLED_getMacOSHostVersion" + '' + # This test fails with a `dysmutil` crash; have not yet dug into what's # going on here (TODO(@rrbutani)). From 153d30f3c33389a6da4ebcbf69d9febbbe92d9bc Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Wed, 7 Jan 2026 20:26:42 +0100 Subject: [PATCH 28/74] curl: 8.17.0 -> 8.18.0 https://curl.se/ch/8.18.0.html https://github.com/curl/curl/releases/tag/curl-8_18_0 Signed-off-by: Sefa Eyeoglu (cherry picked from commit c81d7b2acdbd6ba81a7fcf92c743c143d0c93ac2) --- pkgs/by-name/cu/curlMinimal/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/cu/curlMinimal/package.nix b/pkgs/by-name/cu/curlMinimal/package.nix index f64a4c9de767f..48cd59798c61b 100644 --- a/pkgs/by-name/cu/curlMinimal/package.nix +++ b/pkgs/by-name/cu/curlMinimal/package.nix @@ -86,7 +86,7 @@ assert stdenv.mkDerivation (finalAttrs: { pname = "curl"; - version = "8.17.0"; + version = "8.18.0"; src = fetchurl { urls = [ @@ -95,7 +95,7 @@ stdenv.mkDerivation (finalAttrs: { builtins.replaceStrings [ "." ] [ "_" ] finalAttrs.version }/curl-${finalAttrs.version}.tar.xz" ]; - hash = "sha256-lV9ucprWs1ZiYOj+9oYg52ujwxrPChhSRBahhaz3eZI="; + hash = "sha256-QN95Fm50qiAUk2XhHuTHmKRq1Xw05PaP0TEA4smpGUY="; }; # this could be accomplished by updateAutotoolsGnuConfigScriptsHook, but that causes infinite recursion From 1fd45bc4279480e6838ab7fd12355473c31aa669 Mon Sep 17 00:00:00 2001 From: Tom Herbers Date: Thu, 15 Jan 2026 21:09:07 +0100 Subject: [PATCH 29/74] go_1_25: 1.25.5 -> 1.25.6 Changelog: https://go.dev/doc/devel/release#go1.25.minor (cherry picked from commit 841730db5ceb7fa28a050cf288b6f905ba2f3c1e) --- pkgs/development/compilers/go/1.25.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/compilers/go/1.25.nix b/pkgs/development/compilers/go/1.25.nix index acc8569de85c7..7e76017801425 100644 --- a/pkgs/development/compilers/go/1.25.nix +++ b/pkgs/development/compilers/go/1.25.nix @@ -25,11 +25,11 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "go"; - version = "1.25.5"; + version = "1.25.6"; src = fetchurl { url = "https://go.dev/dl/go${finalAttrs.version}.src.tar.gz"; - hash = "sha256-IqX9CpHvzSihsFNxBrmVmygEth9Zw3WLUejlQpwalU8="; + hash = "sha256-WMv3ceRNdt5vVtGeM7d9dFoeSJNAkih15GWFuXXCsFk="; }; strictDeps = true; From 3525256cc43598ebdb84efcc14e633ee57a28ba8 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Sat, 17 Jan 2026 09:50:49 +0100 Subject: [PATCH 30/74] glibc: 2.40-142 -> 2.40-217, fixes CVE-2026-0915, CVE-2026-0861 Note for the reviewers: I used `git 2.47.2` from 24.11 to generate the diff. Using a newer git created a slightly different format in other parts of the patch-file which would've lead to unnecessary confusion. Apparently we messed up one of the past glibc updates, we claim it's still 2.40-66, but the patchset goes up to -142. --- .../libraries/glibc/2.40-master.patch | 13707 ++++++++++++++++ pkgs/development/libraries/glibc/common.nix | 4 +- 2 files changed, 13709 insertions(+), 2 deletions(-) diff --git a/pkgs/development/libraries/glibc/2.40-master.patch b/pkgs/development/libraries/glibc/2.40-master.patch index 3384de16dc3b4..61b32239b03d0 100644 --- a/pkgs/development/libraries/glibc/2.40-master.patch +++ b/pkgs/development/libraries/glibc/2.40-master.patch @@ -43308,3 +43308,13710 @@ index 0000000000..3c091d8c44 +} + +#include + +commit 95c9b7351cc9e5dc8dafffd8ad9ffb968782410a +Author: Wilco Dijkstra +Date: Fri Jun 27 14:10:55 2025 +0000 + + AArch64: Avoid memset ifunc in cpu-features.c [BZ #33112] + + During early startup memcpy or memset must not be called since many targets + use ifuncs for them which won't be initialized yet. Security hardening may + use -ftrivial-auto-var-init=zero which inserts calls to memset. Redirect + memset to memset_generic by including dl-symbol-redir-ifunc.h in cpu-features.c. + This fixes BZ #33112. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 681a24ae4d0cb8ed92de98b4da660308840b09ba) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +index c0b047bc0d..0ad55a0c7f 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c ++++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #define DCZID_DZP_MASK (1 << 4) + #define DCZID_BS_MASK (0xf) + +commit 2f0c3a5287a79d363c4bc8b028c6136b0f8b14cb +Author: Pierre Blanchard +Date: Tue Mar 18 17:07:31 2025 +0000 + + AArch64: Optimize algorithm in users of SVE expf helper + + Polynomial order was unnecessarily high, unlocking multiple + optimizations. + Max error for new SVE expf is 0.88 +0.5ULP. + Max error for new SVE coshf is 2.56 +0.5ULP. + Performance improvement on Neoverse V1: expf (30%), coshf (26%). + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit cf56eb28fa277d9dbb301654682ca89f71c30a48) + +diff --git a/sysdeps/aarch64/fpu/coshf_sve.c b/sysdeps/aarch64/fpu/coshf_sve.c +index 7ad6efa0fc..508c0790ee 100644 +--- a/sysdeps/aarch64/fpu/coshf_sve.c ++++ b/sysdeps/aarch64/fpu/coshf_sve.c +@@ -39,9 +39,9 @@ special_case (svfloat32_t x, svfloat32_t half_e, svfloat32_t half_over_e, + } + + /* Single-precision vector cosh, using vector expf. +- Maximum error is 2.77 ULP: +- _ZGVsMxv_coshf(-0x1.5b38f4p+1) got 0x1.e45946p+2 +- want 0x1.e4594cp+2. */ ++ Maximum error is 2.56 +0.5 ULP: ++ _ZGVsMxv_coshf(-0x1.5b40f4p+1) got 0x1.e47748p+2 ++ want 0x1.e4774ep+2. */ + svfloat32_t SV_NAME_F1 (cosh) (svfloat32_t x, svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +diff --git a/sysdeps/aarch64/fpu/expf_sve.c b/sysdeps/aarch64/fpu/expf_sve.c +index da93e01b87..aee86a2033 100644 +--- a/sysdeps/aarch64/fpu/expf_sve.c ++++ b/sysdeps/aarch64/fpu/expf_sve.c +@@ -40,9 +40,9 @@ special_case (svfloat32_t x, svbool_t special, const struct sv_expf_data *d) + } + + /* Optimised single-precision SVE exp function. +- Worst-case error is 1.04 ulp: +- SV_NAME_F1 (exp)(0x1.a8eda4p+1) got 0x1.ba74bcp+4 +- want 0x1.ba74bap+4. */ ++ Worst-case error is 0.88 +0.50 ULP: ++ _ZGVsMxv_expf(-0x1.bba276p-6) got 0x1.f25288p-1 ++ want 0x1.f2528ap-1. */ + svfloat32_t SV_NAME_F1 (exp) (svfloat32_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +diff --git a/sysdeps/aarch64/fpu/sv_expf_inline.h b/sysdeps/aarch64/fpu/sv_expf_inline.h +index 75781fb4dd..01fbb4d4c0 100644 +--- a/sysdeps/aarch64/fpu/sv_expf_inline.h ++++ b/sysdeps/aarch64/fpu/sv_expf_inline.h +@@ -24,50 +24,40 @@ + + struct sv_expf_data + { +- float c1, c3, inv_ln2; +- float ln2_lo, c0, c2, c4; +- float ln2_hi, shift; ++ float ln2_hi, ln2_lo, c1, null; ++ float inv_ln2, shift; + }; + +-/* Coefficients copied from the polynomial in AdvSIMD variant, reversed for +- compatibility with polynomial helpers. Shift is 1.5*2^17 + 127. */ ++/* Shift is 1.5*2^17 + 127. */ + #define SV_EXPF_DATA \ + { \ +- /* Coefficients copied from the polynomial in AdvSIMD variant. */ \ +- .c0 = 0x1.ffffecp-1f, .c1 = 0x1.fffdb6p-2f, .c2 = 0x1.555e66p-3f, \ +- .c3 = 0x1.573e2ep-5f, .c4 = 0x1.0e4020p-7f, .inv_ln2 = 0x1.715476p+0f, \ +- .ln2_hi = 0x1.62e4p-1f, .ln2_lo = 0x1.7f7d1cp-20f, \ +- .shift = 0x1.803f8p17f, \ ++ .c1 = 0.5f, .inv_ln2 = 0x1.715476p+0f, .ln2_hi = 0x1.62e4p-1f, \ ++ .ln2_lo = 0x1.7f7d1cp-20f, .shift = 0x1.803f8p17f, \ + } + +-#define C(i) sv_f32 (d->poly[i]) +- + static inline svfloat32_t + expf_inline (svfloat32_t x, const svbool_t pg, const struct sv_expf_data *d) + { + /* exp(x) = 2^n (1 + poly(r)), with 1 + poly(r) in [1/sqrt(2),sqrt(2)] + x = ln2*n + r, with r in [-ln2/2, ln2/2]. */ + +- svfloat32_t lane_consts = svld1rq (svptrue_b32 (), &d->ln2_lo); ++ svfloat32_t lane_consts = svld1rq (svptrue_b32 (), &d->ln2_hi); + + /* n = round(x/(ln2/N)). */ + svfloat32_t z = svmad_x (pg, sv_f32 (d->inv_ln2), x, d->shift); + svfloat32_t n = svsub_x (pg, z, d->shift); + + /* r = x - n*ln2/N. */ +- svfloat32_t r = svmsb_x (pg, sv_f32 (d->ln2_hi), n, x); ++ svfloat32_t r = x; + r = svmls_lane (r, n, lane_consts, 0); ++ r = svmls_lane (r, n, lane_consts, 1); + + /* scale = 2^(n/N). */ + svfloat32_t scale = svexpa (svreinterpret_u32 (z)); + +- /* poly(r) = exp(r) - 1 ~= C0 r + C1 r^2 + C2 r^3 + C3 r^4 + C4 r^5. */ +- svfloat32_t p12 = svmla_lane (sv_f32 (d->c1), r, lane_consts, 2); +- svfloat32_t p34 = svmla_lane (sv_f32 (d->c3), r, lane_consts, 3); ++ /* poly(r) = exp(r) - 1 ~= r + 0.5 r^2. */ + svfloat32_t r2 = svmul_x (svptrue_b32 (), r, r); +- svfloat32_t p14 = svmla_x (pg, p12, p34, r2); +- svfloat32_t p0 = svmul_lane (r, lane_consts, 1); +- svfloat32_t poly = svmla_x (pg, p0, r2, p14); ++ svfloat32_t poly = svmla_lane (r, r2, lane_consts, 2); + + return svmla_x (pg, scale, scale, poly); + } + +commit bfd0490911b8abb3c43d90a169a5fe3ff8b66c5b +Author: Dylan Fleming +Date: Mon May 19 11:36:51 2025 +0000 + + AArch64: Optimize inverse trig functions + + Improve performance of Inverse trig functions by altering how coefficients are + loaded. + + Performance improvement on Neoverse V1: + SVE acos 14% + AdvSIMD acos 6% + + AdvSIMD asin 6% + SVE asin 5% + AdvSIMD asinf 2% + + AdvSIMD atanf 22% + SVE atanf 20% + SVE atan 11% + AdvSIMD atan 5% + + SVE atan2 7% + SVE atan2f 4% + AdvSIMD atan2f 3% + AdvSIMD atan2 2% + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 1e84509e0041c0a83997aba602a585bb3b8285f0) + +diff --git a/sysdeps/aarch64/fpu/acos_advsimd.c b/sysdeps/aarch64/fpu/acos_advsimd.c +index 0a86c9823a..aaf874f4ea 100644 +--- a/sysdeps/aarch64/fpu/acos_advsimd.c ++++ b/sysdeps/aarch64/fpu/acos_advsimd.c +@@ -18,24 +18,23 @@ + . */ + + #include "v_math.h" +-#include "poly_advsimd_f64.h" + + static const struct data + { +- float64x2_t poly[12]; +- float64x2_t pi, pi_over_2; ++ double c1, c3, c5, c7, c9, c11; ++ float64x2_t c0, c2, c4, c6, c8, c10; + uint64x2_t abs_mask; ++ float64x2_t pi, pi_over_2; + } data = { + /* Polynomial approximation of (asin(sqrt(x)) - sqrt(x)) / (x * sqrt(x)) + on [ 0x1p-106, 0x1p-2 ], relative error: 0x1.c3d8e169p-57. */ +- .poly = { V2 (0x1.555555555554ep-3), V2 (0x1.3333333337233p-4), +- V2 (0x1.6db6db67f6d9fp-5), V2 (0x1.f1c71fbd29fbbp-6), +- V2 (0x1.6e8b264d467d6p-6), V2 (0x1.1c5997c357e9dp-6), +- V2 (0x1.c86a22cd9389dp-7), V2 (0x1.856073c22ebbep-7), +- V2 (0x1.fd1151acb6bedp-8), V2 (0x1.087182f799c1dp-6), +- V2 (-0x1.6602748120927p-7), V2 (0x1.cfa0dd1f9478p-6), }, +- .pi = V2 (0x1.921fb54442d18p+1), +- .pi_over_2 = V2 (0x1.921fb54442d18p+0), ++ .c0 = V2 (0x1.555555555554ep-3), .c1 = 0x1.3333333337233p-4, ++ .c2 = V2 (0x1.6db6db67f6d9fp-5), .c3 = 0x1.f1c71fbd29fbbp-6, ++ .c4 = V2 (0x1.6e8b264d467d6p-6), .c5 = 0x1.1c5997c357e9dp-6, ++ .c6 = V2 (0x1.c86a22cd9389dp-7), .c7 = 0x1.856073c22ebbep-7, ++ .c8 = V2 (0x1.fd1151acb6bedp-8), .c9 = 0x1.087182f799c1dp-6, ++ .c10 = V2 (-0x1.6602748120927p-7), .c11 = 0x1.cfa0dd1f9478p-6, ++ .pi = V2 (0x1.921fb54442d18p+1), .pi_over_2 = V2 (0x1.921fb54442d18p+0), + .abs_mask = V2 (0x7fffffffffffffff), + }; + +@@ -63,7 +62,7 @@ special_case (float64x2_t x, float64x2_t y, uint64x2_t special) + + acos(x) ~ pi/2 - (x + x^3 P(x^2)). + +- The largest observed error in this region is 1.18 ulps, ++ The largest observed error in this region is 1.18 ulp: + _ZGVnN2v_acos (0x1.fbab0a7c460f6p-2) got 0x1.0d54d1985c068p+0 + want 0x1.0d54d1985c069p+0. + +@@ -71,9 +70,9 @@ special_case (float64x2_t x, float64x2_t y, uint64x2_t special) + + acos(x) = y + y * z * P(z), with z = (1-x)/2 and y = sqrt(z). + +- The largest observed error in this region is 1.52 ulps, +- _ZGVnN2v_acos (0x1.23d362722f591p-1) got 0x1.edbbedf8a7d6ep-1 +- want 0x1.edbbedf8a7d6cp-1. */ ++ The largest observed error in this region is 1.50 ulp: ++ _ZGVnN2v_acos (0x1.252a2cf3fb9acp-1) got 0x1.ec1a46aa82901p-1 ++ want 0x1.ec1a46aa829p-1. */ + float64x2_t VPCS_ATTR V_NAME_D1 (acos) (float64x2_t x) + { + const struct data *d = ptr_barrier (&data); +@@ -99,13 +98,32 @@ float64x2_t VPCS_ATTR V_NAME_D1 (acos) (float64x2_t x) + float64x2_t z = vbslq_f64 (a_le_half, ax, vsqrtq_f64 (z2)); + + /* Use a single polynomial approximation P for both intervals. */ ++ float64x2_t z3 = vmulq_f64 (z2, z); + float64x2_t z4 = vmulq_f64 (z2, z2); + float64x2_t z8 = vmulq_f64 (z4, z4); +- float64x2_t z16 = vmulq_f64 (z8, z8); +- float64x2_t p = v_estrin_11_f64 (z2, z4, z8, z16, d->poly); + +- /* Finalize polynomial: z + z * z2 * P(z2). */ +- p = vfmaq_f64 (z, vmulq_f64 (z, z2), p); ++ /* Order-11 Estrin. */ ++ float64x2_t c13 = vld1q_f64 (&d->c1); ++ float64x2_t c57 = vld1q_f64 (&d->c5); ++ float64x2_t c911 = vld1q_f64 (&d->c9); ++ ++ float64x2_t p01 = vfmaq_laneq_f64 (d->c0, z2, c13, 0); ++ float64x2_t p23 = vfmaq_laneq_f64 (d->c2, z2, c13, 1); ++ float64x2_t p03 = vfmaq_f64 (p01, z4, p23); ++ ++ float64x2_t p45 = vfmaq_laneq_f64 (d->c4, z2, c57, 0); ++ float64x2_t p67 = vfmaq_laneq_f64 (d->c6, z2, c57, 1); ++ float64x2_t p47 = vfmaq_f64 (p45, z4, p67); ++ ++ float64x2_t p89 = vfmaq_laneq_f64 (d->c8, z2, c911, 0); ++ float64x2_t p1011 = vfmaq_laneq_f64 (d->c10, z2, c911, 1); ++ float64x2_t p811 = vfmaq_f64 (p89, z4, p1011); ++ ++ float64x2_t p411 = vfmaq_f64 (p47, z8, p811); ++ float64x2_t p = vfmaq_f64 (p03, z8, p411); ++ ++ /* Finalize polynomial: z + z3 * P(z2). */ ++ p = vfmaq_f64 (z, z3, p); + + /* acos(|x|) = pi/2 - sign(x) * Q(|x|), for |x| < 0.5 + = 2 Q(|x|) , for 0.5 < x < 1.0 +diff --git a/sysdeps/aarch64/fpu/acos_sve.c b/sysdeps/aarch64/fpu/acos_sve.c +index 99dbfac3e6..870d8062cf 100644 +--- a/sysdeps/aarch64/fpu/acos_sve.c ++++ b/sysdeps/aarch64/fpu/acos_sve.c +@@ -18,20 +18,21 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[12]; +- float64_t pi, pi_over_2; ++ float64_t c1, c3, c5, c7, c9, c11; ++ float64_t c0, c2, c4, c6, c8, c10; ++ float64_t pi_over_2; + } data = { + /* Polynomial approximation of (asin(sqrt(x)) - sqrt(x)) / (x * sqrt(x)) + on [ 0x1p-106, 0x1p-2 ], relative error: 0x1.c3d8e169p-57. */ +- .poly = { 0x1.555555555554ep-3, 0x1.3333333337233p-4, 0x1.6db6db67f6d9fp-5, +- 0x1.f1c71fbd29fbbp-6, 0x1.6e8b264d467d6p-6, 0x1.1c5997c357e9dp-6, +- 0x1.c86a22cd9389dp-7, 0x1.856073c22ebbep-7, 0x1.fd1151acb6bedp-8, +- 0x1.087182f799c1dp-6, -0x1.6602748120927p-7, 0x1.cfa0dd1f9478p-6, }, +- .pi = 0x1.921fb54442d18p+1, ++ .c0 = 0x1.555555555554ep-3, .c1 = 0x1.3333333337233p-4, ++ .c2 = 0x1.6db6db67f6d9fp-5, .c3 = 0x1.f1c71fbd29fbbp-6, ++ .c4 = 0x1.6e8b264d467d6p-6, .c5 = 0x1.1c5997c357e9dp-6, ++ .c6 = 0x1.c86a22cd9389dp-7, .c7 = 0x1.856073c22ebbep-7, ++ .c8 = 0x1.fd1151acb6bedp-8, .c9 = 0x1.087182f799c1dp-6, ++ .c10 = -0x1.6602748120927p-7, .c11 = 0x1.cfa0dd1f9478p-6, + .pi_over_2 = 0x1.921fb54442d18p+0, + }; + +@@ -42,20 +43,21 @@ static const struct data + + acos(x) ~ pi/2 - (x + x^3 P(x^2)). + +- The largest observed error in this region is 1.18 ulps, +- _ZGVsMxv_acos (0x1.fbc5fe28ee9e3p-2) got 0x1.0d4d0f55667f6p+0 +- want 0x1.0d4d0f55667f7p+0. ++ The largest observed error in this region is 1.18 ulp: ++ _ZGVsMxv_acos (0x1.fbb7c9079b429p-2) got 0x1.0d51266607582p+0 ++ want 0x1.0d51266607583p+0. + + For |x| in [0.5, 1.0], use same approximation with a change of variable + + acos(x) = y + y * z * P(z), with z = (1-x)/2 and y = sqrt(z). + +- The largest observed error in this region is 1.52 ulps, +- _ZGVsMxv_acos (0x1.24024271a500ap-1) got 0x1.ed82df4243f0dp-1 +- want 0x1.ed82df4243f0bp-1. */ ++ The largest observed error in this region is 1.50 ulp: ++ _ZGVsMxv_acos (0x1.252a2cf3fb9acp-1) got 0x1.ec1a46aa82901p-1 ++ want 0x1.ec1a46aa829p-1. */ + svfloat64_t SV_NAME_D1 (acos) (svfloat64_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); ++ svbool_t ptrue = svptrue_b64 (); + + svuint64_t sign = svand_x (pg, svreinterpret_u64 (x), 0x8000000000000000); + svfloat64_t ax = svabs_x (pg, x); +@@ -70,24 +72,41 @@ svfloat64_t SV_NAME_D1 (acos) (svfloat64_t x, const svbool_t pg) + svfloat64_t z = svsqrt_m (ax, a_gt_half, z2); + + /* Use a single polynomial approximation P for both intervals. */ +- svfloat64_t z4 = svmul_x (pg, z2, z2); +- svfloat64_t z8 = svmul_x (pg, z4, z4); +- svfloat64_t z16 = svmul_x (pg, z8, z8); +- svfloat64_t p = sv_estrin_11_f64_x (pg, z2, z4, z8, z16, d->poly); ++ svfloat64_t z3 = svmul_x (ptrue, z2, z); ++ svfloat64_t z4 = svmul_x (ptrue, z2, z2); ++ svfloat64_t z8 = svmul_x (ptrue, z4, z4); ++ ++ svfloat64_t c13 = svld1rq (ptrue, &d->c1); ++ svfloat64_t c57 = svld1rq (ptrue, &d->c5); ++ svfloat64_t c911 = svld1rq (ptrue, &d->c9); ++ ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), z2, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), z2, c13, 1); ++ svfloat64_t p03 = svmla_x (pg, p01, z4, p23); ++ ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), z2, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), z2, c57, 1); ++ svfloat64_t p47 = svmla_x (pg, p45, z4, p67); ++ ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), z2, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), z2, c911, 1); ++ svfloat64_t p811 = svmla_x (pg, p89, z4, p1011); ++ ++ svfloat64_t p411 = svmla_x (pg, p47, z8, p811); ++ svfloat64_t p = svmad_x (pg, p411, z8, p03); + + /* Finalize polynomial: z + z * z2 * P(z2). */ +- p = svmla_x (pg, z, svmul_x (pg, z, z2), p); ++ p = svmad_x (pg, p, z3, z); + + /* acos(|x|) = pi/2 - sign(x) * Q(|x|), for |x| < 0.5 + = 2 Q(|x|) , for 0.5 < x < 1.0 + = pi - 2 Q(|x|) , for -1.0 < x < -0.5. */ +- svfloat64_t y +- = svreinterpret_f64 (svorr_x (pg, svreinterpret_u64 (p), sign)); +- +- svbool_t is_neg = svcmplt (pg, x, 0.0); +- svfloat64_t off = svdup_f64_z (is_neg, d->pi); +- svfloat64_t mul = svsel (a_gt_half, sv_f64 (2.0), sv_f64 (-1.0)); +- svfloat64_t add = svsel (a_gt_half, off, sv_f64 (d->pi_over_2)); +- +- return svmla_x (pg, add, mul, y); ++ svfloat64_t mul = svreinterpret_f64 ( ++ svlsl_m (a_gt_half, svreinterpret_u64 (sv_f64 (1.0)), 10)); ++ mul = svreinterpret_f64 (sveor_x (ptrue, svreinterpret_u64 (mul), sign)); ++ svfloat64_t add = svreinterpret_f64 ( ++ svorr_x (ptrue, sign, svreinterpret_u64 (sv_f64 (d->pi_over_2)))); ++ add = svsub_m (a_gt_half, sv_f64 (d->pi_over_2), add); ++ ++ return svmsb_x (pg, p, mul, add); + } +diff --git a/sysdeps/aarch64/fpu/asin_advsimd.c b/sysdeps/aarch64/fpu/asin_advsimd.c +index 2de6eff407..f4884227a5 100644 +--- a/sysdeps/aarch64/fpu/asin_advsimd.c ++++ b/sysdeps/aarch64/fpu/asin_advsimd.c +@@ -18,24 +18,23 @@ + . */ + + #include "v_math.h" +-#include "poly_advsimd_f64.h" + + static const struct data + { +- float64x2_t poly[12]; ++ float64x2_t c0, c2, c4, c6, c8, c10; + float64x2_t pi_over_2; + uint64x2_t abs_mask; ++ double c1, c3, c5, c7, c9, c11; + } data = { + /* Polynomial approximation of (asin(sqrt(x)) - sqrt(x)) / (x * sqrt(x)) + on [ 0x1p-106, 0x1p-2 ], relative error: 0x1.c3d8e169p-57. */ +- .poly = { V2 (0x1.555555555554ep-3), V2 (0x1.3333333337233p-4), +- V2 (0x1.6db6db67f6d9fp-5), V2 (0x1.f1c71fbd29fbbp-6), +- V2 (0x1.6e8b264d467d6p-6), V2 (0x1.1c5997c357e9dp-6), +- V2 (0x1.c86a22cd9389dp-7), V2 (0x1.856073c22ebbep-7), +- V2 (0x1.fd1151acb6bedp-8), V2 (0x1.087182f799c1dp-6), +- V2 (-0x1.6602748120927p-7), V2 (0x1.cfa0dd1f9478p-6), }, +- .pi_over_2 = V2 (0x1.921fb54442d18p+0), +- .abs_mask = V2 (0x7fffffffffffffff), ++ .c0 = V2 (0x1.555555555554ep-3), .c1 = 0x1.3333333337233p-4, ++ .c2 = V2 (0x1.6db6db67f6d9fp-5), .c3 = 0x1.f1c71fbd29fbbp-6, ++ .c4 = V2 (0x1.6e8b264d467d6p-6), .c5 = 0x1.1c5997c357e9dp-6, ++ .c6 = V2 (0x1.c86a22cd9389dp-7), .c7 = 0x1.856073c22ebbep-7, ++ .c8 = V2 (0x1.fd1151acb6bedp-8), .c9 = 0x1.087182f799c1dp-6, ++ .c10 = V2 (-0x1.6602748120927p-7), .c11 = 0x1.cfa0dd1f9478p-6, ++ .pi_over_2 = V2 (0x1.921fb54442d18p+0), .abs_mask = V2 (0x7fffffffffffffff), + }; + + #define AllMask v_u64 (0xffffffffffffffff) +@@ -68,8 +67,8 @@ special_case (float64x2_t x, float64x2_t y, uint64x2_t special) + asin(x) = pi/2 - (y + y * z * P(z)), with z = (1-x)/2 and y = sqrt(z). + + The largest observed error in this region is 2.69 ulps, +- _ZGVnN2v_asin (0x1.044ac9819f573p-1) got 0x1.110d7e85fdd5p-1 +- want 0x1.110d7e85fdd53p-1. */ ++ _ZGVnN2v_asin (0x1.044e8cefee301p-1) got 0x1.1111dd54ddf96p-1 ++ want 0x1.1111dd54ddf99p-1. */ + float64x2_t VPCS_ATTR V_NAME_D1 (asin) (float64x2_t x) + { + const struct data *d = ptr_barrier (&data); +@@ -86,7 +85,7 @@ float64x2_t VPCS_ATTR V_NAME_D1 (asin) (float64x2_t x) + return special_case (x, x, AllMask); + #endif + +- uint64x2_t a_lt_half = vcltq_f64 (ax, v_f64 (0.5)); ++ uint64x2_t a_lt_half = vcaltq_f64 (x, v_f64 (0.5)); + + /* Evaluate polynomial Q(x) = y + y * z * P(z) with + z = x ^ 2 and y = |x| , if |x| < 0.5 +@@ -99,7 +98,26 @@ float64x2_t VPCS_ATTR V_NAME_D1 (asin) (float64x2_t x) + float64x2_t z4 = vmulq_f64 (z2, z2); + float64x2_t z8 = vmulq_f64 (z4, z4); + float64x2_t z16 = vmulq_f64 (z8, z8); +- float64x2_t p = v_estrin_11_f64 (z2, z4, z8, z16, d->poly); ++ ++ /* order-11 estrin. */ ++ float64x2_t c13 = vld1q_f64 (&d->c1); ++ float64x2_t c57 = vld1q_f64 (&d->c5); ++ float64x2_t c911 = vld1q_f64 (&d->c9); ++ ++ float64x2_t p01 = vfmaq_laneq_f64 (d->c0, z2, c13, 0); ++ float64x2_t p23 = vfmaq_laneq_f64 (d->c2, z2, c13, 1); ++ float64x2_t p03 = vfmaq_f64 (p01, z4, p23); ++ ++ float64x2_t p45 = vfmaq_laneq_f64 (d->c4, z2, c57, 0); ++ float64x2_t p67 = vfmaq_laneq_f64 (d->c6, z2, c57, 1); ++ float64x2_t p47 = vfmaq_f64 (p45, z4, p67); ++ ++ float64x2_t p89 = vfmaq_laneq_f64 (d->c8, z2, c911, 0); ++ float64x2_t p1011 = vfmaq_laneq_f64 (d->c10, z2, c911, 1); ++ float64x2_t p811 = vfmaq_f64 (p89, z4, p1011); ++ ++ float64x2_t p07 = vfmaq_f64 (p03, z8, p47); ++ float64x2_t p = vfmaq_f64 (p07, z16, p811); + + /* Finalize polynomial: z + z * z2 * P(z2). */ + p = vfmaq_f64 (z, vmulq_f64 (z, z2), p); +diff --git a/sysdeps/aarch64/fpu/asin_sve.c b/sysdeps/aarch64/fpu/asin_sve.c +index 9daa382e34..acbf1b3bdd 100644 +--- a/sysdeps/aarch64/fpu/asin_sve.c ++++ b/sysdeps/aarch64/fpu/asin_sve.c +@@ -18,45 +18,43 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[12]; +- float64_t pi_over_2f; ++ float64_t c1, c3, c5, c7, c9, c11; ++ float64_t c0, c2, c4, c6, c8, c10; ++ float64_t pi_over_2; + } data = { + /* Polynomial approximation of (asin(sqrt(x)) - sqrt(x)) / (x * sqrt(x)) + on [ 0x1p-106, 0x1p-2 ], relative error: 0x1.c3d8e169p-57. */ +- .poly = { 0x1.555555555554ep-3, 0x1.3333333337233p-4, +- 0x1.6db6db67f6d9fp-5, 0x1.f1c71fbd29fbbp-6, +- 0x1.6e8b264d467d6p-6, 0x1.1c5997c357e9dp-6, +- 0x1.c86a22cd9389dp-7, 0x1.856073c22ebbep-7, +- 0x1.fd1151acb6bedp-8, 0x1.087182f799c1dp-6, +- -0x1.6602748120927p-7, 0x1.cfa0dd1f9478p-6, }, +- .pi_over_2f = 0x1.921fb54442d18p+0, ++ .c0 = 0x1.555555555554ep-3, .c1 = 0x1.3333333337233p-4, ++ .c2 = 0x1.6db6db67f6d9fp-5, .c3 = 0x1.f1c71fbd29fbbp-6, ++ .c4 = 0x1.6e8b264d467d6p-6, .c5 = 0x1.1c5997c357e9dp-6, ++ .c6 = 0x1.c86a22cd9389dp-7, .c7 = 0x1.856073c22ebbep-7, ++ .c8 = 0x1.fd1151acb6bedp-8, .c9 = 0x1.087182f799c1dp-6, ++ .c10 = -0x1.6602748120927p-7, .c11 = 0x1.cfa0dd1f9478p-6, ++ .pi_over_2 = 0x1.921fb54442d18p+0, + }; + +-#define P(i) sv_f64 (d->poly[i]) +- + /* Double-precision SVE implementation of vector asin(x). + + For |x| in [0, 0.5], use an order 11 polynomial P such that the final + approximation is an odd polynomial: asin(x) ~ x + x^3 P(x^2). + +- The largest observed error in this region is 0.52 ulps, +- _ZGVsMxv_asin(0x1.d95ae04998b6cp-2) got 0x1.ec13757305f27p-2 +- want 0x1.ec13757305f26p-2. +- +- For |x| in [0.5, 1.0], use same approximation with a change of variable ++ The largest observed error in this region is 0.98 ulp: ++ _ZGVsMxv_asin (0x1.d98f6a748ed8ap-2) got 0x1.ec4eb661a73d3p-2 ++ want 0x1.ec4eb661a73d2p-2. + +- asin(x) = pi/2 - (y + y * z * P(z)), with z = (1-x)/2 and y = sqrt(z). ++ For |x| in [0.5, 1.0], use same approximation with a change of variable: ++ asin(x) = pi/2 - (y + y * z * P(z)), with z = (1-x)/2 and y = sqrt(z). + +- The largest observed error in this region is 2.69 ulps, +- _ZGVsMxv_asin(0x1.044ac9819f573p-1) got 0x1.110d7e85fdd5p-1 +- want 0x1.110d7e85fdd53p-1. */ ++ The largest observed error in this region is 2.66 ulp: ++ _ZGVsMxv_asin (0x1.04024f6e2a2fbp-1) got 0x1.10b9586f087a8p-1 ++ want 0x1.10b9586f087abp-1. */ + svfloat64_t SV_NAME_D1 (asin) (svfloat64_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); ++ svbool_t ptrue = svptrue_b64 (); + + svuint64_t sign = svand_x (pg, svreinterpret_u64 (x), 0x8000000000000000); + svfloat64_t ax = svabs_x (pg, x); +@@ -70,17 +68,37 @@ svfloat64_t SV_NAME_D1 (asin) (svfloat64_t x, const svbool_t pg) + svfloat64_t z = svsqrt_m (ax, a_ge_half, z2); + + /* Use a single polynomial approximation P for both intervals. */ ++ svfloat64_t z3 = svmul_x (pg, z2, z); + svfloat64_t z4 = svmul_x (pg, z2, z2); + svfloat64_t z8 = svmul_x (pg, z4, z4); +- svfloat64_t z16 = svmul_x (pg, z8, z8); +- svfloat64_t p = sv_estrin_11_f64_x (pg, z2, z4, z8, z16, d->poly); ++ ++ svfloat64_t c13 = svld1rq (ptrue, &d->c1); ++ svfloat64_t c57 = svld1rq (ptrue, &d->c5); ++ svfloat64_t c911 = svld1rq (ptrue, &d->c9); ++ ++ /* Order-11 Estrin scheme. */ ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), z2, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), z2, c13, 1); ++ svfloat64_t p03 = svmla_x (pg, p01, z4, p23); ++ ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), z2, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), z2, c57, 1); ++ svfloat64_t p47 = svmla_x (pg, p45, z4, p67); ++ ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), z2, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), z2, c911, 1); ++ svfloat64_t p811 = svmla_x (pg, p89, z4, p1011); ++ ++ svfloat64_t p411 = svmla_x (pg, p47, z8, p811); ++ svfloat64_t p = svmla_x (pg, p03, z8, p411); ++ + /* Finalize polynomial: z + z * z2 * P(z2). */ +- p = svmla_x (pg, z, svmul_x (pg, z, z2), p); ++ p = svmla_x (pg, z, z3, p); + +- /* asin(|x|) = Q(|x|) , for |x| < 0.5 +- = pi/2 - 2 Q(|x|), for |x| >= 0.5. */ +- svfloat64_t y = svmad_m (a_ge_half, p, sv_f64 (-2.0), d->pi_over_2f); ++ /* asin(|x|) = Q(|x|), for |x| < 0.5 ++ = pi/2 - 2 Q(|x|), for |x| >= 0.5. */ ++ svfloat64_t y = svmad_m (a_ge_half, p, sv_f64 (-2.0), d->pi_over_2); + +- /* Copy sign. */ ++ /* Reinsert the sign from the argument. */ + return svreinterpret_f64 (svorr_x (pg, svreinterpret_u64 (y), sign)); + } +diff --git a/sysdeps/aarch64/fpu/asinf_advsimd.c b/sysdeps/aarch64/fpu/asinf_advsimd.c +index 59d870ca36..88437f85ab 100644 +--- a/sysdeps/aarch64/fpu/asinf_advsimd.c ++++ b/sysdeps/aarch64/fpu/asinf_advsimd.c +@@ -18,22 +18,21 @@ + . */ + + #include "v_math.h" +-#include "poly_advsimd_f32.h" + + static const struct data + { +- float32x4_t poly[5]; ++ float32x4_t c0, c2, c4; ++ float c1, c3; + float32x4_t pi_over_2f; + } data = { + /* Polynomial approximation of (asin(sqrt(x)) - sqrt(x)) / (x * sqrt(x)) on + [ 0x1p-24 0x1p-2 ] order = 4 rel error: 0x1.00a23bbp-29 . */ +- .poly = { V4 (0x1.55555ep-3), V4 (0x1.33261ap-4), V4 (0x1.70d7dcp-5), +- V4 (0x1.b059dp-6), V4 (0x1.3af7d8p-5) }, +- .pi_over_2f = V4 (0x1.921fb6p+0f), ++ .c0 = V4 (0x1.55555ep-3f), .c1 = 0x1.33261ap-4f, ++ .c2 = V4 (0x1.70d7dcp-5f), .c3 = 0x1.b059dp-6f, ++ .c4 = V4 (0x1.3af7d8p-5f), .pi_over_2f = V4 (0x1.921fb6p+0f), + }; + + #define AbsMask 0x7fffffff +-#define Half 0x3f000000 + #define One 0x3f800000 + #define Small 0x39800000 /* 2^-12. */ + +@@ -47,11 +46,8 @@ special_case (float32x4_t x, float32x4_t y, uint32x4_t special) + + /* Single-precision implementation of vector asin(x). + +- For |x| < Small, approximate asin(x) by x. Small = 2^-12 for correct +- rounding. If WANT_SIMD_EXCEPT = 0, Small = 0 and we proceed with the +- following approximation. + +- For |x| in [Small, 0.5], use order 4 polynomial P such that the final ++ For |x| <0.5, use order 4 polynomial P such that the final + approximation is an odd polynomial: asin(x) ~ x + x^3 P(x^2). + + The largest observed error in this region is 0.83 ulps, +@@ -80,24 +76,31 @@ float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (asin) (float32x4_t x) + #endif + + float32x4_t ax = vreinterpretq_f32_u32 (ia); +- uint32x4_t a_lt_half = vcltq_u32 (ia, v_u32 (Half)); ++ uint32x4_t a_lt_half = vcaltq_f32 (x, v_f32 (0.5f)); + + /* Evaluate polynomial Q(x) = y + y * z * P(z) with + z = x ^ 2 and y = |x| , if |x| < 0.5 + z = (1 - |x|) / 2 and y = sqrt(z), if |x| >= 0.5. */ + float32x4_t z2 = vbslq_f32 (a_lt_half, vmulq_f32 (x, x), +- vfmsq_n_f32 (v_f32 (0.5), ax, 0.5)); ++ vfmsq_n_f32 (v_f32 (0.5f), ax, 0.5f)); + float32x4_t z = vbslq_f32 (a_lt_half, ax, vsqrtq_f32 (z2)); + + /* Use a single polynomial approximation P for both intervals. */ +- float32x4_t p = v_horner_4_f32 (z2, d->poly); ++ ++ /* PW Horner 3 evaluation scheme. */ ++ float32x4_t z4 = vmulq_f32 (z2, z2); ++ float32x4_t c13 = vld1q_f32 (&d->c1); ++ float32x4_t p01 = vfmaq_laneq_f32 (d->c0, z2, c13, 0); ++ float32x4_t p23 = vfmaq_laneq_f32 (d->c2, z2, c13, 1); ++ float32x4_t p = vfmaq_f32 (p23, d->c4, z4); ++ p = vfmaq_f32 (p01, p, z4); + /* Finalize polynomial: z + z * z2 * P(z2). */ + p = vfmaq_f32 (z, vmulq_f32 (z, z2), p); + + /* asin(|x|) = Q(|x|) , for |x| < 0.5 + = pi/2 - 2 Q(|x|), for |x| >= 0.5. */ + float32x4_t y +- = vbslq_f32 (a_lt_half, p, vfmsq_n_f32 (d->pi_over_2f, p, 2.0)); ++ = vbslq_f32 (a_lt_half, p, vfmsq_n_f32 (d->pi_over_2f, p, 2.0f)); + + /* Copy sign. */ + return vbslq_f32 (v_u32 (AbsMask), y, x); +diff --git a/sysdeps/aarch64/fpu/atan2_advsimd.c b/sysdeps/aarch64/fpu/atan2_advsimd.c +index 1a8f02109f..1e5d20602e 100644 +--- a/sysdeps/aarch64/fpu/atan2_advsimd.c ++++ b/sysdeps/aarch64/fpu/atan2_advsimd.c +@@ -19,40 +19,38 @@ + + #include "math_config.h" + #include "v_math.h" +-#include "poly_advsimd_f64.h" + + static const struct data + { ++ double c1, c3, c5, c7, c9, c11, c13, c15, c17, c19; + float64x2_t c0, c2, c4, c6, c8, c10, c12, c14, c16, c18; + float64x2_t pi_over_2; +- double c1, c3, c5, c7, c9, c11, c13, c15, c17, c19; +- uint64x2_t zeroinfnan, minustwo; ++ uint64x2_t zeroinfnan; + } data = { +- /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on +- [2**-1022, 1.0]. */ +- .c0 = V2 (-0x1.5555555555555p-2), +- .c1 = 0x1.99999999996c1p-3, +- .c2 = V2 (-0x1.2492492478f88p-3), +- .c3 = 0x1.c71c71bc3951cp-4, +- .c4 = V2 (-0x1.745d160a7e368p-4), +- .c5 = 0x1.3b139b6a88ba1p-4, +- .c6 = V2 (-0x1.11100ee084227p-4), +- .c7 = 0x1.e1d0f9696f63bp-5, +- .c8 = V2 (-0x1.aebfe7b418581p-5), +- .c9 = 0x1.842dbe9b0d916p-5, +- .c10 = V2 (-0x1.5d30140ae5e99p-5), +- .c11 = 0x1.338e31eb2fbbcp-5, +- .c12 = V2 (-0x1.00e6eece7de8p-5), +- .c13 = 0x1.860897b29e5efp-6, +- .c14 = V2 (-0x1.0051381722a59p-6), +- .c15 = 0x1.14e9dc19a4a4ep-7, +- .c16 = V2 (-0x1.d0062b42fe3bfp-9), +- .c17 = 0x1.17739e210171ap-10, +- .c18 = V2 (-0x1.ab24da7be7402p-13), +- .c19 = 0x1.358851160a528p-16, ++ /* Coefficients of polynomial P such that ++ atan(x)~x+x*P(x^2) on [2^-1022, 1.0]. */ ++ .c0 = V2 (-0x1.555555555552ap-2), ++ .c1 = 0x1.9999999995aebp-3, ++ .c2 = V2 (-0x1.24924923923f6p-3), ++ .c3 = 0x1.c71c7184288a2p-4, ++ .c4 = V2 (-0x1.745d11fb3d32bp-4), ++ .c5 = 0x1.3b136a18051b9p-4, ++ .c6 = V2 (-0x1.110e6d985f496p-4), ++ .c7 = 0x1.e1bcf7f08801dp-5, ++ .c8 = V2 (-0x1.ae644e28058c3p-5), ++ .c9 = 0x1.82eeb1fed85c6p-5, ++ .c10 = V2 (-0x1.59d7f901566cbp-5), ++ .c11 = 0x1.2c982855ab069p-5, ++ .c12 = V2 (-0x1.eb49592998177p-6), ++ .c13 = 0x1.69d8b396e3d38p-6, ++ .c14 = V2 (-0x1.ca980345c4204p-7), ++ .c15 = 0x1.dc050eafde0b3p-8, ++ .c16 = V2 (-0x1.7ea70755b8eccp-9), ++ .c17 = 0x1.ba3da3de903e8p-11, ++ .c18 = V2 (-0x1.44a4b059b6f67p-13), ++ .c19 = 0x1.c4a45029e5a91p-17, + .pi_over_2 = V2 (0x1.921fb54442d18p+0), + .zeroinfnan = V2 (2 * 0x7ff0000000000000ul - 1), +- .minustwo = V2 (0xc000000000000000), + }; + + #define SignMask v_u64 (0x8000000000000000) +@@ -77,10 +75,9 @@ zeroinfnan (uint64x2_t i, const struct data *d) + } + + /* Fast implementation of vector atan2. +- Maximum observed error is 2.8 ulps: +- _ZGVnN2vv_atan2 (0x1.9651a429a859ap+5, 0x1.953075f4ee26p+5) +- got 0x1.92d628ab678ccp-1 +- want 0x1.92d628ab678cfp-1. */ ++ Maximum observed error is 1.97 ulps: ++ _ZGVnN2vv_atan2 (0x1.42337dba73768p+5, 0x1.422d748cd3e29p+5) ++ got 0x1.9224810264efcp-1 want 0x1.9224810264efep-1. */ + float64x2_t VPCS_ATTR V_NAME_D2 (atan2) (float64x2_t y, float64x2_t x) + { + const struct data *d = ptr_barrier (&data); +@@ -101,26 +98,29 @@ float64x2_t VPCS_ATTR V_NAME_D2 (atan2) (float64x2_t y, float64x2_t x) + uint64x2_t pred_xlt0 = vcltzq_f64 (x); + uint64x2_t pred_aygtax = vcagtq_f64 (y, x); + +- /* Set up z for call to atan. */ +- float64x2_t n = vbslq_f64 (pred_aygtax, vnegq_f64 (ax), ay); +- float64x2_t q = vbslq_f64 (pred_aygtax, ay, ax); +- float64x2_t z = vdivq_f64 (n, q); +- +- /* Work out the correct shift. */ +- float64x2_t shift +- = vreinterpretq_f64_u64 (vandq_u64 (pred_xlt0, d->minustwo)); +- shift = vbslq_f64 (pred_aygtax, vaddq_f64 (shift, v_f64 (1.0)), shift); +- shift = vmulq_f64 (shift, d->pi_over_2); +- +- /* Calculate the polynomial approximation. +- Use split Estrin scheme for P(z^2) with deg(P)=19. Use split instead of +- full scheme to avoid underflow in x^16. +- The order 19 polynomial P approximates +- (atan(sqrt(x))-sqrt(x))/x^(3/2). */ ++ /* Set up z for evaluation of atan. */ ++ float64x2_t num = vbslq_f64 (pred_aygtax, vnegq_f64 (ax), ay); ++ float64x2_t den = vbslq_f64 (pred_aygtax, ay, ax); ++ float64x2_t z = vdivq_f64 (num, den); ++ ++ /* Work out the correct shift for atan2: ++ Multiplication by pi is done later. ++ -pi when x < 0 and ax < ay ++ -pi/2 when x < 0 and ax > ay ++ 0 when x >= 0 and ax < ay ++ pi/2 when x >= 0 and ax > ay. */ ++ float64x2_t shift = vreinterpretq_f64_u64 ( ++ vandq_u64 (pred_xlt0, vreinterpretq_u64_f64 (v_f64 (-2.0)))); ++ float64x2_t shift2 = vreinterpretq_f64_u64 ( ++ vandq_u64 (pred_aygtax, vreinterpretq_u64_f64 (v_f64 (1.0)))); ++ shift = vaddq_f64 (shift, shift2); ++ ++ /* Calculate the polynomial approximation. */ + float64x2_t z2 = vmulq_f64 (z, z); +- float64x2_t x2 = vmulq_f64 (z2, z2); +- float64x2_t x4 = vmulq_f64 (x2, x2); +- float64x2_t x8 = vmulq_f64 (x4, x4); ++ float64x2_t z3 = vmulq_f64 (z2, z); ++ float64x2_t z4 = vmulq_f64 (z2, z2); ++ float64x2_t z8 = vmulq_f64 (z4, z4); ++ float64x2_t z16 = vmulq_f64 (z8, z8); + + float64x2_t c13 = vld1q_f64 (&d->c1); + float64x2_t c57 = vld1q_f64 (&d->c5); +@@ -128,45 +128,43 @@ float64x2_t VPCS_ATTR V_NAME_D2 (atan2) (float64x2_t y, float64x2_t x) + float64x2_t c1315 = vld1q_f64 (&d->c13); + float64x2_t c1719 = vld1q_f64 (&d->c17); + +- /* estrin_7. */ ++ /* Order-7 Estrin. */ + float64x2_t p01 = vfmaq_laneq_f64 (d->c0, z2, c13, 0); + float64x2_t p23 = vfmaq_laneq_f64 (d->c2, z2, c13, 1); +- float64x2_t p03 = vfmaq_f64 (p01, x2, p23); ++ float64x2_t p03 = vfmaq_f64 (p01, z4, p23); + + float64x2_t p45 = vfmaq_laneq_f64 (d->c4, z2, c57, 0); + float64x2_t p67 = vfmaq_laneq_f64 (d->c6, z2, c57, 1); +- float64x2_t p47 = vfmaq_f64 (p45, x2, p67); ++ float64x2_t p47 = vfmaq_f64 (p45, z4, p67); + +- float64x2_t p07 = vfmaq_f64 (p03, x4, p47); ++ float64x2_t p07 = vfmaq_f64 (p03, z8, p47); + +- /* estrin_11. */ ++ /* Order-11 Estrin. */ + float64x2_t p89 = vfmaq_laneq_f64 (d->c8, z2, c911, 0); + float64x2_t p1011 = vfmaq_laneq_f64 (d->c10, z2, c911, 1); +- float64x2_t p811 = vfmaq_f64 (p89, x2, p1011); ++ float64x2_t p811 = vfmaq_f64 (p89, z4, p1011); + + float64x2_t p1213 = vfmaq_laneq_f64 (d->c12, z2, c1315, 0); + float64x2_t p1415 = vfmaq_laneq_f64 (d->c14, z2, c1315, 1); +- float64x2_t p1215 = vfmaq_f64 (p1213, x2, p1415); ++ float64x2_t p1215 = vfmaq_f64 (p1213, z4, p1415); + + float64x2_t p1617 = vfmaq_laneq_f64 (d->c16, z2, c1719, 0); + float64x2_t p1819 = vfmaq_laneq_f64 (d->c18, z2, c1719, 1); +- float64x2_t p1619 = vfmaq_f64 (p1617, x2, p1819); ++ float64x2_t p1619 = vfmaq_f64 (p1617, z4, p1819); + +- float64x2_t p815 = vfmaq_f64 (p811, x4, p1215); +- float64x2_t p819 = vfmaq_f64 (p815, x8, p1619); ++ float64x2_t p815 = vfmaq_f64 (p811, z8, p1215); ++ float64x2_t p819 = vfmaq_f64 (p815, z16, p1619); + +- float64x2_t ret = vfmaq_f64 (p07, p819, x8); ++ float64x2_t poly = vfmaq_f64 (p07, p819, z16); + + /* Finalize. y = shift + z + z^3 * P(z^2). */ +- ret = vfmaq_f64 (z, ret, vmulq_f64 (z2, z)); +- ret = vaddq_f64 (ret, shift); ++ float64x2_t ret = vfmaq_f64 (z, shift, d->pi_over_2); ++ ret = vfmaq_f64 (ret, z3, poly); + + if (__glibc_unlikely (v_any_u64 (special_cases))) + return special_case (y, x, ret, sign_xy, special_cases); + + /* Account for the sign of x and y. */ +- ret = vreinterpretq_f64_u64 ( ++ return vreinterpretq_f64_u64 ( + veorq_u64 (vreinterpretq_u64_f64 (ret), sign_xy)); +- +- return ret; + } +diff --git a/sysdeps/aarch64/fpu/atan2_sve.c b/sysdeps/aarch64/fpu/atan2_sve.c +index ed9f683436..0337ea57b7 100644 +--- a/sysdeps/aarch64/fpu/atan2_sve.c ++++ b/sysdeps/aarch64/fpu/atan2_sve.c +@@ -19,25 +19,25 @@ + + #include "math_config.h" + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[20]; +- float64_t pi_over_2; ++ float64_t c0, c2, c4, c6, c8, c10, c12, c14, c16, c18; ++ float64_t c1, c3, c5, c7, c9, c11, c13, c15, c17, c19; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-1022, 1.0]. */ +- .poly = { -0x1.5555555555555p-2, 0x1.99999999996c1p-3, -0x1.2492492478f88p-3, +- 0x1.c71c71bc3951cp-4, -0x1.745d160a7e368p-4, 0x1.3b139b6a88ba1p-4, +- -0x1.11100ee084227p-4, 0x1.e1d0f9696f63bp-5, -0x1.aebfe7b418581p-5, +- 0x1.842dbe9b0d916p-5, -0x1.5d30140ae5e99p-5, 0x1.338e31eb2fbbcp-5, +- -0x1.00e6eece7de8p-5, 0x1.860897b29e5efp-6, -0x1.0051381722a59p-6, +- 0x1.14e9dc19a4a4ep-7, -0x1.d0062b42fe3bfp-9, 0x1.17739e210171ap-10, +- -0x1.ab24da7be7402p-13, 0x1.358851160a528p-16, }, +- .pi_over_2 = 0x1.921fb54442d18p+0, ++ .c0 = -0x1.555555555552ap-2, .c1 = 0x1.9999999995aebp-3, ++ .c2 = -0x1.24924923923f6p-3, .c3 = 0x1.c71c7184288a2p-4, ++ .c4 = -0x1.745d11fb3d32bp-4, .c5 = 0x1.3b136a18051b9p-4, ++ .c6 = -0x1.110e6d985f496p-4, .c7 = 0x1.e1bcf7f08801dp-5, ++ .c8 = -0x1.ae644e28058c3p-5, .c9 = 0x1.82eeb1fed85c6p-5, ++ .c10 = -0x1.59d7f901566cbp-5, .c11 = 0x1.2c982855ab069p-5, ++ .c12 = -0x1.eb49592998177p-6, .c13 = 0x1.69d8b396e3d38p-6, ++ .c14 = -0x1.ca980345c4204p-7, .c15 = 0x1.dc050eafde0b3p-8, ++ .c16 = -0x1.7ea70755b8eccp-9, .c17 = 0x1.ba3da3de903e8p-11, ++ .c18 = -0x1.44a4b059b6f67p-13, .c19 = 0x1.c4a45029e5a91p-17, + }; +- + /* Special cases i.e. 0, infinity, nan (fall back to scalar calls). */ + static svfloat64_t NOINLINE + special_case (svfloat64_t y, svfloat64_t x, svfloat64_t ret, +@@ -56,15 +56,17 @@ zeroinfnan (svuint64_t i, const svbool_t pg) + } + + /* Fast implementation of SVE atan2. Errors are greatest when y and +- x are reasonably close together. The greatest observed error is 2.28 ULP: +- _ZGVsMxvv_atan2 (-0x1.5915b1498e82fp+732, 0x1.54d11ef838826p+732) +- got -0x1.954f42f1fa841p-1 want -0x1.954f42f1fa843p-1. */ +-svfloat64_t SV_NAME_D2 (atan2) (svfloat64_t y, svfloat64_t x, const svbool_t pg) ++ x are reasonably close together. The greatest observed error is 1.94 ULP: ++ _ZGVsMxvv_atan2 (0x1.8a4bf7167228ap+5, 0x1.84971226bb57bp+5) ++ got 0x1.95db19dfef9ccp-1 want 0x1.95db19dfef9cep-1. */ ++svfloat64_t SV_NAME_D2 (atan2) (svfloat64_t y, svfloat64_t x, ++ const svbool_t pg) + { +- const struct data *data_ptr = ptr_barrier (&data); ++ const struct data *d = ptr_barrier (&data); + + svuint64_t ix = svreinterpret_u64 (x); + svuint64_t iy = svreinterpret_u64 (y); ++ svbool_t ptrue = svptrue_b64 (); + + svbool_t cmp_x = zeroinfnan (ix, pg); + svbool_t cmp_y = zeroinfnan (iy, pg); +@@ -81,32 +83,67 @@ svfloat64_t SV_NAME_D2 (atan2) (svfloat64_t y, svfloat64_t x, const svbool_t pg) + + svbool_t pred_aygtax = svcmpgt (pg, ay, ax); + +- /* Set up z for call to atan. */ +- svfloat64_t n = svsel (pred_aygtax, svneg_x (pg, ax), ay); +- svfloat64_t d = svsel (pred_aygtax, ay, ax); +- svfloat64_t z = svdiv_x (pg, n, d); +- +- /* Work out the correct shift. */ ++ /* Set up z for evaluation of atan. */ ++ svfloat64_t num = svsel (pred_aygtax, svneg_x (pg, ax), ay); ++ svfloat64_t den = svsel (pred_aygtax, ay, ax); ++ svfloat64_t z = svdiv_x (pg, num, den); ++ ++ /* Work out the correct shift for atan2: ++ Multiplication by pi is done later. ++ -pi when x < 0 and ax < ay ++ -pi/2 when x < 0 and ax > ay ++ 0 when x >= 0 and ax < ay ++ pi/2 when x >= 0 and ax > ay. */ + svfloat64_t shift = svreinterpret_f64 (svlsr_x (pg, sign_x, 1)); ++ svfloat64_t shift_mul = svreinterpret_f64 ( ++ svorr_x (pg, sign_x, svreinterpret_u64 (sv_f64 (0x1.921fb54442d18p+0)))); + shift = svsel (pred_aygtax, sv_f64 (1.0), shift); +- shift = svreinterpret_f64 (svorr_x (pg, sign_x, svreinterpret_u64 (shift))); +- shift = svmul_x (pg, shift, data_ptr->pi_over_2); ++ shift = svmla_x (pg, z, shift, shift_mul); + + /* Use split Estrin scheme for P(z^2) with deg(P)=19. */ + svfloat64_t z2 = svmul_x (pg, z, z); +- svfloat64_t x2 = svmul_x (pg, z2, z2); +- svfloat64_t x4 = svmul_x (pg, x2, x2); +- svfloat64_t x8 = svmul_x (pg, x4, x4); ++ svfloat64_t z3 = svmul_x (pg, z2, z); ++ svfloat64_t z4 = svmul_x (pg, z2, z2); ++ svfloat64_t z8 = svmul_x (pg, z4, z4); ++ svfloat64_t z16 = svmul_x (pg, z8, z8); + +- svfloat64_t ret = svmla_x ( +- pg, sv_estrin_7_f64_x (pg, z2, x2, x4, data_ptr->poly), +- sv_estrin_11_f64_x (pg, z2, x2, x4, x8, data_ptr->poly + 8), x8); ++ /* Order-7 Estrin. */ ++ svfloat64_t c13 = svld1rq (ptrue, &d->c1); ++ svfloat64_t c57 = svld1rq (ptrue, &d->c5); + +- /* y = shift + z + z^3 * P(z^2). */ +- svfloat64_t z3 = svmul_x (pg, z2, z); +- ret = svmla_x (pg, z, z3, ret); ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), z2, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), z2, c13, 1); ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), z2, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), z2, c57, 1); ++ ++ svfloat64_t p03 = svmla_x (pg, p01, z4, p23); ++ svfloat64_t p47 = svmla_x (pg, p45, z4, p67); ++ svfloat64_t p07 = svmla_x (pg, p03, z8, p47); ++ ++ /* Order-11 Estrin. */ ++ svfloat64_t c911 = svld1rq (ptrue, &d->c9); ++ svfloat64_t c1315 = svld1rq (ptrue, &d->c13); ++ svfloat64_t c1719 = svld1rq (ptrue, &d->c17); + +- ret = svadd_m (pg, ret, shift); ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), z2, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), z2, c911, 1); ++ svfloat64_t p811 = svmla_x (pg, p89, z4, p1011); ++ ++ svfloat64_t p1213 = svmla_lane (sv_f64 (d->c12), z2, c1315, 0); ++ svfloat64_t p1415 = svmla_lane (sv_f64 (d->c14), z2, c1315, 1); ++ svfloat64_t p1215 = svmla_x (pg, p1213, z4, p1415); ++ ++ svfloat64_t p1617 = svmla_lane (sv_f64 (d->c16), z2, c1719, 0); ++ svfloat64_t p1819 = svmla_lane (sv_f64 (d->c18), z2, c1719, 1); ++ svfloat64_t p1619 = svmla_x (pg, p1617, z4, p1819); ++ ++ svfloat64_t p815 = svmla_x (pg, p811, z8, p1215); ++ svfloat64_t p819 = svmla_x (pg, p815, z16, p1619); ++ ++ svfloat64_t poly = svmla_x (pg, p07, z16, p819); ++ ++ /* y = shift + z + z^3 * P(z^2). */ ++ svfloat64_t ret = svmla_x (pg, shift, z3, poly); + + /* Account for the sign of x and y. */ + if (__glibc_unlikely (svptest_any (pg, cmp_xy))) +diff --git a/sysdeps/aarch64/fpu/atan2f_advsimd.c b/sysdeps/aarch64/fpu/atan2f_advsimd.c +index 88daacd76c..23a825e63b 100644 +--- a/sysdeps/aarch64/fpu/atan2f_advsimd.c ++++ b/sysdeps/aarch64/fpu/atan2f_advsimd.c +@@ -18,22 +18,22 @@ + . */ + + #include "v_math.h" +-#include "poly_advsimd_f32.h" + + static const struct data + { +- float32x4_t c0, pi_over_2, c4, c6, c2; ++ float32x4_t c0, c4, c6, c2; + float c1, c3, c5, c7; + uint32x4_t comp_const; ++ float32x4_t pi; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-128, 1.0]. + Generated using fpminimax between FLT_MIN and 1. */ +- .c0 = V4 (-0x1.55555p-2f), .c1 = 0x1.99935ep-3f, +- .c2 = V4 (-0x1.24051ep-3f), .c3 = 0x1.bd7368p-4f, +- .c4 = V4 (-0x1.491f0ep-4f), .c5 = 0x1.93a2c0p-5f, +- .c6 = V4 (-0x1.4c3c60p-6f), .c7 = 0x1.01fd88p-8f, +- .pi_over_2 = V4 (0x1.921fb6p+0f), .comp_const = V4 (2 * 0x7f800000lu - 1), ++ .c0 = V4 (-0x1.5554dcp-2), .c1 = 0x1.9978ecp-3, ++ .c2 = V4 (-0x1.230a94p-3), .c3 = 0x1.b4debp-4, ++ .c4 = V4 (-0x1.3550dap-4), .c5 = 0x1.61eebp-5, ++ .c6 = V4 (-0x1.0c17d4p-6), .c7 = 0x1.7ea694p-9, ++ .pi = V4 (0x1.921fb6p+1f), .comp_const = V4 (2 * 0x7f800000lu - 1), + }; + + #define SignMask v_u32 (0x80000000) +@@ -54,13 +54,13 @@ static inline uint32x4_t + zeroinfnan (uint32x4_t i, const struct data *d) + { + /* 2 * i - 1 >= 2 * 0x7f800000lu - 1. */ +- return vcgeq_u32 (vsubq_u32 (vmulq_n_u32 (i, 2), v_u32 (1)), d->comp_const); ++ return vcgeq_u32 (vsubq_u32 (vshlq_n_u32 (i, 1), v_u32 (1)), d->comp_const); + } + + /* Fast implementation of vector atan2f. Maximum observed error is +- 2.95 ULP in [0x1.9300d6p+6 0x1.93c0c6p+6] x [0x1.8c2dbp+6 0x1.8cea6p+6]: +- _ZGVnN4vv_atan2f (0x1.93836cp+6, 0x1.8cae1p+6) got 0x1.967f06p-1 +- want 0x1.967f00p-1. */ ++ 2.13 ULP in [0x1.9300d6p+6 0x1.93c0c6p+6] x [0x1.8c2dbp+6 0x1.8cea6p+6]: ++ _ZGVnN4vv_atan2f (0x1.14a9d4p-87, 0x1.0eb886p-87) got 0x1.97aea2p-1 ++ want 0x1.97ae9ep-1. */ + float32x4_t VPCS_ATTR NOINLINE V_NAME_F2 (atan2) (float32x4_t y, float32x4_t x) + { + const struct data *d = ptr_barrier (&data); +@@ -81,28 +81,31 @@ float32x4_t VPCS_ATTR NOINLINE V_NAME_F2 (atan2) (float32x4_t y, float32x4_t x) + uint32x4_t pred_xlt0 = vcltzq_f32 (x); + uint32x4_t pred_aygtax = vcgtq_f32 (ay, ax); + +- /* Set up z for call to atanf. */ +- float32x4_t n = vbslq_f32 (pred_aygtax, vnegq_f32 (ax), ay); +- float32x4_t q = vbslq_f32 (pred_aygtax, ay, ax); +- float32x4_t z = vdivq_f32 (n, q); +- +- /* Work out the correct shift. */ ++ /* Set up z for evaluation of atanf. */ ++ float32x4_t num = vbslq_f32 (pred_aygtax, vnegq_f32 (ax), ay); ++ float32x4_t den = vbslq_f32 (pred_aygtax, ay, ax); ++ float32x4_t z = vdivq_f32 (num, den); ++ ++ /* Work out the correct shift for atan2: ++ Multiplication by pi is done later. ++ -pi when x < 0 and ax < ay ++ -pi/2 when x < 0 and ax > ay ++ 0 when x >= 0 and ax < ay ++ pi/2 when x >= 0 and ax > ay. */ + float32x4_t shift = vreinterpretq_f32_u32 ( +- vandq_u32 (pred_xlt0, vreinterpretq_u32_f32 (v_f32 (-2.0f)))); +- shift = vbslq_f32 (pred_aygtax, vaddq_f32 (shift, v_f32 (1.0f)), shift); +- shift = vmulq_f32 (shift, d->pi_over_2); +- +- /* Calculate the polynomial approximation. +- Use 2-level Estrin scheme for P(z^2) with deg(P)=7. However, +- a standard implementation using z8 creates spurious underflow +- in the very last fma (when z^8 is small enough). +- Therefore, we split the last fma into a mul and an fma. +- Horner and single-level Estrin have higher errors that exceed +- threshold. */ ++ vandq_u32 (pred_xlt0, vreinterpretq_u32_f32 (v_f32 (-1.0f)))); ++ float32x4_t shift2 = vreinterpretq_f32_u32 ( ++ vandq_u32 (pred_aygtax, vreinterpretq_u32_f32 (v_f32 (0.5f)))); ++ shift = vaddq_f32 (shift, shift2); ++ ++ /* Calculate the polynomial approximation. */ + float32x4_t z2 = vmulq_f32 (z, z); ++ float32x4_t z3 = vmulq_f32 (z2, z); + float32x4_t z4 = vmulq_f32 (z2, z2); ++ float32x4_t z8 = vmulq_f32 (z4, z4); + + float32x4_t c1357 = vld1q_f32 (&d->c1); ++ + float32x4_t p01 = vfmaq_laneq_f32 (d->c0, z2, c1357, 0); + float32x4_t p23 = vfmaq_laneq_f32 (d->c2, z2, c1357, 1); + float32x4_t p45 = vfmaq_laneq_f32 (d->c4, z2, c1357, 2); +@@ -110,10 +113,11 @@ float32x4_t VPCS_ATTR NOINLINE V_NAME_F2 (atan2) (float32x4_t y, float32x4_t x) + float32x4_t p03 = vfmaq_f32 (p01, z4, p23); + float32x4_t p47 = vfmaq_f32 (p45, z4, p67); + +- float32x4_t ret = vfmaq_f32 (p03, z4, vmulq_f32 (z4, p47)); ++ float32x4_t poly = vfmaq_f32 (p03, z8, p47); + + /* y = shift + z * P(z^2). */ +- ret = vaddq_f32 (vfmaq_f32 (z, ret, vmulq_f32 (z2, z)), shift); ++ float32x4_t ret = vfmaq_f32 (z, shift, d->pi); ++ ret = vfmaq_f32 (ret, z3, poly); + + if (__glibc_unlikely (v_any_u32 (special_cases))) + { +diff --git a/sysdeps/aarch64/fpu/atan2f_sve.c b/sysdeps/aarch64/fpu/atan2f_sve.c +index 9ea197147c..f7f6d40ca6 100644 +--- a/sysdeps/aarch64/fpu/atan2f_sve.c ++++ b/sysdeps/aarch64/fpu/atan2f_sve.c +@@ -18,18 +18,18 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f32.h" + + static const struct data + { +- float32_t poly[8]; ++ float32_t c0, c2, c4, c6; ++ float32_t c1, c3, c5, c7; + float32_t pi_over_2; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-128, 1.0]. */ +- .poly = { -0x1.55555p-2f, 0x1.99935ep-3f, -0x1.24051ep-3f, 0x1.bd7368p-4f, +- -0x1.491f0ep-4f, 0x1.93a2c0p-5f, -0x1.4c3c60p-6f, 0x1.01fd88p-8f }, +- .pi_over_2 = 0x1.921fb6p+0f, ++ .c0 = -0x1.5554dcp-2, .c1 = 0x1.9978ecp-3, .c2 = -0x1.230a94p-3, ++ .c3 = 0x1.b4debp-4, .c4 = -0x1.3550dap-4, .c5 = 0x1.61eebp-5, ++ .c6 = -0x1.0c17d4p-6, .c7 = 0x1.7ea694p-9, .pi_over_2 = 0x1.921fb6p+0f, + }; + + /* Special cases i.e. 0, infinity, nan (fall back to scalar calls). */ +@@ -51,12 +51,14 @@ zeroinfnan (svuint32_t i, const svbool_t pg) + + /* Fast implementation of SVE atan2f based on atan(x) ~ shift + z + z^3 * + P(z^2) with reduction to [0,1] using z=1/x and shift = pi/2. Maximum +- observed error is 2.95 ULP: +- _ZGVsMxvv_atan2f (0x1.93836cp+6, 0x1.8cae1p+6) got 0x1.967f06p-1 +- want 0x1.967f00p-1. */ +-svfloat32_t SV_NAME_F2 (atan2) (svfloat32_t y, svfloat32_t x, const svbool_t pg) ++ observed error is 2.21 ULP: ++ _ZGVnN4vv_atan2f (0x1.a04aa8p+6, 0x1.9a274p+6) got 0x1.95ed3ap-1 ++ want 0x1.95ed36p-1. */ ++svfloat32_t SV_NAME_F2 (atan2) (svfloat32_t y, svfloat32_t x, ++ const svbool_t pg) + { +- const struct data *data_ptr = ptr_barrier (&data); ++ const struct data *d = ptr_barrier (&data); ++ svbool_t ptrue = svptrue_b32 (); + + svuint32_t ix = svreinterpret_u32 (x); + svuint32_t iy = svreinterpret_u32 (y); +@@ -76,29 +78,42 @@ svfloat32_t SV_NAME_F2 (atan2) (svfloat32_t y, svfloat32_t x, const svbool_t pg) + + svbool_t pred_aygtax = svcmpgt (pg, ay, ax); + +- /* Set up z for call to atan. */ +- svfloat32_t n = svsel (pred_aygtax, svneg_x (pg, ax), ay); +- svfloat32_t d = svsel (pred_aygtax, ay, ax); +- svfloat32_t z = svdiv_x (pg, n, d); +- +- /* Work out the correct shift. */ ++ /* Set up z for evaluation of atanf. */ ++ svfloat32_t num = svsel (pred_aygtax, svneg_x (pg, ax), ay); ++ svfloat32_t den = svsel (pred_aygtax, ay, ax); ++ svfloat32_t z = svdiv_x (ptrue, num, den); ++ ++ /* Work out the correct shift for atan2: ++ Multiplication by pi is done later. ++ -pi when x < 0 and ax < ay ++ -pi/2 when x < 0 and ax > ay ++ 0 when x >= 0 and ax < ay ++ pi/2 when x >= 0 and ax > ay. */ + svfloat32_t shift = svreinterpret_f32 (svlsr_x (pg, sign_x, 1)); + shift = svsel (pred_aygtax, sv_f32 (1.0), shift); + shift = svreinterpret_f32 (svorr_x (pg, sign_x, svreinterpret_u32 (shift))); +- shift = svmul_x (pg, shift, sv_f32 (data_ptr->pi_over_2)); + + /* Use pure Estrin scheme for P(z^2) with deg(P)=7. */ +- svfloat32_t z2 = svmul_x (pg, z, z); ++ svfloat32_t z2 = svmul_x (ptrue, z, z); ++ svfloat32_t z3 = svmul_x (pg, z2, z); + svfloat32_t z4 = svmul_x (pg, z2, z2); + svfloat32_t z8 = svmul_x (pg, z4, z4); + +- svfloat32_t ret = sv_estrin_7_f32_x (pg, z2, z4, z8, data_ptr->poly); ++ svfloat32_t odd_coeffs = svld1rq (ptrue, &d->c1); + +- /* ret = shift + z + z^3 * P(z^2). */ +- svfloat32_t z3 = svmul_x (pg, z2, z); +- ret = svmla_x (pg, z, z3, ret); ++ svfloat32_t p01 = svmla_lane (sv_f32 (d->c0), z2, odd_coeffs, 0); ++ svfloat32_t p23 = svmla_lane (sv_f32 (d->c2), z2, odd_coeffs, 1); ++ svfloat32_t p45 = svmla_lane (sv_f32 (d->c4), z2, odd_coeffs, 2); ++ svfloat32_t p67 = svmla_lane (sv_f32 (d->c6), z2, odd_coeffs, 3); + +- ret = svadd_m (pg, ret, shift); ++ svfloat32_t p03 = svmla_x (pg, p01, z4, p23); ++ svfloat32_t p47 = svmla_x (pg, p45, z4, p67); ++ ++ svfloat32_t poly = svmla_x (pg, p03, z8, p47); ++ ++ /* ret = shift + z + z^3 * P(z^2). */ ++ svfloat32_t ret = svmla_x (pg, z, shift, sv_f32 (d->pi_over_2)); ++ ret = svmla_x (pg, ret, z3, poly); + + /* Account for the sign of x and y. */ + +diff --git a/sysdeps/aarch64/fpu/atan_advsimd.c b/sysdeps/aarch64/fpu/atan_advsimd.c +index 14f1809796..f835dae828 100644 +--- a/sysdeps/aarch64/fpu/atan_advsimd.c ++++ b/sysdeps/aarch64/fpu/atan_advsimd.c +@@ -18,7 +18,6 @@ + . */ + + #include "v_math.h" +-#include "poly_advsimd_f64.h" + + static const struct data + { +@@ -28,16 +27,16 @@ static const struct data + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-1022, 1.0]. */ +- .c0 = V2 (-0x1.5555555555555p-2), .c1 = 0x1.99999999996c1p-3, +- .c2 = V2 (-0x1.2492492478f88p-3), .c3 = 0x1.c71c71bc3951cp-4, +- .c4 = V2 (-0x1.745d160a7e368p-4), .c5 = 0x1.3b139b6a88ba1p-4, +- .c6 = V2 (-0x1.11100ee084227p-4), .c7 = 0x1.e1d0f9696f63bp-5, +- .c8 = V2 (-0x1.aebfe7b418581p-5), .c9 = 0x1.842dbe9b0d916p-5, +- .c10 = V2 (-0x1.5d30140ae5e99p-5), .c11 = 0x1.338e31eb2fbbcp-5, +- .c12 = V2 (-0x1.00e6eece7de8p-5), .c13 = 0x1.860897b29e5efp-6, +- .c14 = V2 (-0x1.0051381722a59p-6), .c15 = 0x1.14e9dc19a4a4ep-7, +- .c16 = V2 (-0x1.d0062b42fe3bfp-9), .c17 = 0x1.17739e210171ap-10, +- .c18 = V2 (-0x1.ab24da7be7402p-13), .c19 = 0x1.358851160a528p-16, ++ .c0 = V2 (-0x1.555555555552ap-2), .c1 = 0x1.9999999995aebp-3, ++ .c2 = V2 (-0x1.24924923923f6p-3), .c3 = 0x1.c71c7184288a2p-4, ++ .c4 = V2 (-0x1.745d11fb3d32bp-4), .c5 = 0x1.3b136a18051b9p-4, ++ .c6 = V2 (-0x1.110e6d985f496p-4), .c7 = 0x1.e1bcf7f08801dp-5, ++ .c8 = V2 (-0x1.ae644e28058c3p-5), .c9 = 0x1.82eeb1fed85c6p-5, ++ .c10 = V2 (-0x1.59d7f901566cbp-5), .c11 = 0x1.2c982855ab069p-5, ++ .c12 = V2 (-0x1.eb49592998177p-6), .c13 = 0x1.69d8b396e3d38p-6, ++ .c14 = V2 (-0x1.ca980345c4204p-7), .c15 = 0x1.dc050eafde0b3p-8, ++ .c16 = V2 (-0x1.7ea70755b8eccp-9), .c17 = 0x1.ba3da3de903e8p-11, ++ .c18 = V2 (-0x1.44a4b059b6f67p-13), .c19 = 0x1.c4a45029e5a91p-17, + .pi_over_2 = V2 (0x1.921fb54442d18p+0), + }; + +@@ -47,9 +46,9 @@ static const struct data + + /* Fast implementation of vector atan. + Based on atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1] using +- z=1/x and shift = pi/2. Maximum observed error is 2.27 ulps: +- _ZGVnN2v_atan (0x1.0005af27c23e9p+0) got 0x1.9225645bdd7c1p-1 +- want 0x1.9225645bdd7c3p-1. */ ++ z=1/x and shift = pi/2. Maximum observed error is 2.45 ulps: ++ _ZGVnN2v_atan (0x1.0008d737eb3e6p+0) got 0x1.92288c551a4c1p-1 ++ want 0x1.92288c551a4c3p-1. */ + float64x2_t VPCS_ATTR V_NAME_D1 (atan) (float64x2_t x) + { + const struct data *d = ptr_barrier (&data); +@@ -78,59 +77,53 @@ float64x2_t VPCS_ATTR V_NAME_D1 (atan) (float64x2_t x) + y := arctan(x) for x < 1 + y := pi/2 + arctan(-1/x) for x > 1 + Hence, use z=-1/a if x>=1, otherwise z=a. */ +- uint64x2_t red = vcagtq_f64 (x, v_f64 (1.0)); ++ uint64x2_t red = vcagtq_f64 (x, v_f64 (-1.0)); + /* Avoid dependency in abs(x) in division (and comparison). */ +- float64x2_t z = vbslq_f64 (red, vdivq_f64 (v_f64 (1.0), x), x); ++ float64x2_t z = vbslq_f64 (red, vdivq_f64 (v_f64 (-1.0), x), x); ++ + float64x2_t shift = vreinterpretq_f64_u64 ( + vandq_u64 (red, vreinterpretq_u64_f64 (d->pi_over_2))); +- /* Use absolute value only when needed (odd powers of z). */ +- float64x2_t az = vbslq_f64 ( +- SignMask, vreinterpretq_f64_u64 (vandq_u64 (SignMask, red)), z); +- +- /* Calculate the polynomial approximation. +- Use split Estrin scheme for P(z^2) with deg(P)=19. Use split instead of +- full scheme to avoid underflow in x^16. +- The order 19 polynomial P approximates +- (atan(sqrt(x))-sqrt(x))/x^(3/2). */ ++ ++ /* Reinsert sign bit from argument into the shift value. */ ++ shift = vreinterpretq_f64_u64 ( ++ veorq_u64 (vreinterpretq_u64_f64 (shift), sign)); ++ ++ /* Calculate polynomial approximation P(z^2) with deg(P)=19. */ + float64x2_t z2 = vmulq_f64 (z, z); +- float64x2_t x2 = vmulq_f64 (z2, z2); +- float64x2_t x4 = vmulq_f64 (x2, x2); +- float64x2_t x8 = vmulq_f64 (x4, x4); ++ float64x2_t z4 = vmulq_f64 (z2, z2); ++ float64x2_t z8 = vmulq_f64 (z4, z4); ++ float64x2_t z16 = vmulq_f64 (z8, z8); + +- /* estrin_7. */ ++ /* Order-7 Estrin. */ + float64x2_t p01 = vfmaq_laneq_f64 (d->c0, z2, c13, 0); + float64x2_t p23 = vfmaq_laneq_f64 (d->c2, z2, c13, 1); +- float64x2_t p03 = vfmaq_f64 (p01, x2, p23); ++ float64x2_t p03 = vfmaq_f64 (p01, z4, p23); + + float64x2_t p45 = vfmaq_laneq_f64 (d->c4, z2, c57, 0); + float64x2_t p67 = vfmaq_laneq_f64 (d->c6, z2, c57, 1); +- float64x2_t p47 = vfmaq_f64 (p45, x2, p67); ++ float64x2_t p47 = vfmaq_f64 (p45, z4, p67); + +- float64x2_t p07 = vfmaq_f64 (p03, x4, p47); ++ float64x2_t p07 = vfmaq_f64 (p03, z8, p47); + +- /* estrin_11. */ ++ /* Order-11 Estrin. */ + float64x2_t p89 = vfmaq_laneq_f64 (d->c8, z2, c911, 0); + float64x2_t p1011 = vfmaq_laneq_f64 (d->c10, z2, c911, 1); +- float64x2_t p811 = vfmaq_f64 (p89, x2, p1011); ++ float64x2_t p811 = vfmaq_f64 (p89, z4, p1011); + + float64x2_t p1213 = vfmaq_laneq_f64 (d->c12, z2, c1315, 0); + float64x2_t p1415 = vfmaq_laneq_f64 (d->c14, z2, c1315, 1); +- float64x2_t p1215 = vfmaq_f64 (p1213, x2, p1415); ++ float64x2_t p1215 = vfmaq_f64 (p1213, z4, p1415); + + float64x2_t p1617 = vfmaq_laneq_f64 (d->c16, z2, c1719, 0); + float64x2_t p1819 = vfmaq_laneq_f64 (d->c18, z2, c1719, 1); +- float64x2_t p1619 = vfmaq_f64 (p1617, x2, p1819); ++ float64x2_t p1619 = vfmaq_f64 (p1617, z4, p1819); + +- float64x2_t p815 = vfmaq_f64 (p811, x4, p1215); +- float64x2_t p819 = vfmaq_f64 (p815, x8, p1619); ++ float64x2_t p815 = vfmaq_f64 (p811, z8, p1215); ++ float64x2_t p819 = vfmaq_f64 (p815, z16, p1619); + +- float64x2_t y = vfmaq_f64 (p07, p819, x8); ++ float64x2_t y = vfmaq_f64 (p07, p819, z16); + + /* Finalize. y = shift + z + z^3 * P(z^2). */ +- y = vfmaq_f64 (az, y, vmulq_f64 (z2, az)); +- y = vaddq_f64 (y, shift); +- +- /* y = atan(x) if x>0, -atan(-x) otherwise. */ +- y = vreinterpretq_f64_u64 (veorq_u64 (vreinterpretq_u64_f64 (y), sign)); +- return y; ++ y = vfmsq_f64 (v_f64 (-1.0), z2, y); ++ return vfmsq_f64 (shift, z, y); + } +diff --git a/sysdeps/aarch64/fpu/atan_sve.c b/sysdeps/aarch64/fpu/atan_sve.c +index fa1630304c..046c04fbb1 100644 +--- a/sysdeps/aarch64/fpu/atan_sve.c ++++ b/sysdeps/aarch64/fpu/atan_sve.c +@@ -18,23 +18,26 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[20]; +- float64_t pi_over_2; ++ float64_t c0, c2, c4, c6, c8, c10, c12, c14, c16, c18; ++ float64_t c1, c3, c5, c7, c9, c11, c13, c15, c17, c19; ++ float64_t shift_val, neg_one; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-1022, 1.0]. */ +- .poly = { -0x1.5555555555555p-2, 0x1.99999999996c1p-3, -0x1.2492492478f88p-3, +- 0x1.c71c71bc3951cp-4, -0x1.745d160a7e368p-4, 0x1.3b139b6a88ba1p-4, +- -0x1.11100ee084227p-4, 0x1.e1d0f9696f63bp-5, -0x1.aebfe7b418581p-5, +- 0x1.842dbe9b0d916p-5, -0x1.5d30140ae5e99p-5, 0x1.338e31eb2fbbcp-5, +- -0x1.00e6eece7de8p-5, 0x1.860897b29e5efp-6, -0x1.0051381722a59p-6, +- 0x1.14e9dc19a4a4ep-7, -0x1.d0062b42fe3bfp-9, 0x1.17739e210171ap-10, +- -0x1.ab24da7be7402p-13, 0x1.358851160a528p-16, }, +- .pi_over_2 = 0x1.921fb54442d18p+0, ++ .c0 = -0x1.555555555552ap-2, .c1 = 0x1.9999999995aebp-3, ++ .c2 = -0x1.24924923923f6p-3, .c3 = 0x1.c71c7184288a2p-4, ++ .c4 = -0x1.745d11fb3d32bp-4, .c5 = 0x1.3b136a18051b9p-4, ++ .c6 = -0x1.110e6d985f496p-4, .c7 = 0x1.e1bcf7f08801dp-5, ++ .c8 = -0x1.ae644e28058c3p-5, .c9 = 0x1.82eeb1fed85c6p-5, ++ .c10 = -0x1.59d7f901566cbp-5, .c11 = 0x1.2c982855ab069p-5, ++ .c12 = -0x1.eb49592998177p-6, .c13 = 0x1.69d8b396e3d38p-6, ++ .c14 = -0x1.ca980345c4204p-7, .c15 = 0x1.dc050eafde0b3p-8, ++ .c16 = -0x1.7ea70755b8eccp-9, .c17 = 0x1.ba3da3de903e8p-11, ++ .c18 = -0x1.44a4b059b6f67p-13, .c19 = 0x1.c4a45029e5a91p-17, ++ .shift_val = 0x1.490fdaa22168cp+1, .neg_one = -1, + }; + + /* Useful constants. */ +@@ -43,15 +46,14 @@ static const struct data + /* Fast implementation of SVE atan. + Based on atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1] using + z=1/x and shift = pi/2. Largest errors are close to 1. The maximum observed +- error is 2.27 ulps: +- _ZGVsMxv_atan (0x1.0005af27c23e9p+0) got 0x1.9225645bdd7c1p-1 +- want 0x1.9225645bdd7c3p-1. */ ++ error is 2.08 ulps: ++ _ZGVsMxv_atan (0x1.000a7c56975e8p+0) got 0x1.922a3163e15c2p-1 ++ want 0x1.922a3163e15c4p-1. */ + svfloat64_t SV_NAME_D1 (atan) (svfloat64_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); + +- /* No need to trigger special case. Small cases, infs and nans +- are supported by our approximation technique. */ ++ svbool_t ptrue = svptrue_b64 (); + svuint64_t ix = svreinterpret_u64 (x); + svuint64_t sign = svand_x (pg, ix, SignMask); + +@@ -59,32 +61,60 @@ svfloat64_t SV_NAME_D1 (atan) (svfloat64_t x, const svbool_t pg) + y := arctan(x) for x < 1 + y := pi/2 + arctan(-1/x) for x > 1 + Hence, use z=-1/a if x>=1, otherwise z=a. */ +- svbool_t red = svacgt (pg, x, 1.0); +- /* Avoid dependency in abs(x) in division (and comparison). */ +- svfloat64_t z = svsel (red, svdivr_x (pg, x, 1.0), x); +- /* Use absolute value only when needed (odd powers of z). */ +- svfloat64_t az = svabs_x (pg, z); +- az = svneg_m (az, red, az); ++ svbool_t red = svacgt (pg, x, d->neg_one); ++ svfloat64_t z = svsel (red, svdiv_x (pg, sv_f64 (d->neg_one), x), x); ++ ++ /* Reuse of -1.0f to reduce constant loads, ++ We need a shift value of 1/2, which is created via -1 + (1 + 1/2). */ ++ svfloat64_t shift ++ = svadd_z (red, sv_f64 (d->neg_one), sv_f64 (d->shift_val)); ++ ++ /* Reinserts the sign bit of the argument to handle the case of x < -1. */ ++ shift = svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (shift), sign)); + + /* Use split Estrin scheme for P(z^2) with deg(P)=19. */ +- svfloat64_t z2 = svmul_x (pg, z, z); +- svfloat64_t x2 = svmul_x (pg, z2, z2); +- svfloat64_t x4 = svmul_x (pg, x2, x2); +- svfloat64_t x8 = svmul_x (pg, x4, x4); ++ svfloat64_t z2 = svmul_x (ptrue, z, z); ++ svfloat64_t z4 = svmul_x (ptrue, z2, z2); ++ svfloat64_t z8 = svmul_x (ptrue, z4, z4); ++ svfloat64_t z16 = svmul_x (ptrue, z8, z8); + +- svfloat64_t y +- = svmla_x (pg, sv_estrin_7_f64_x (pg, z2, x2, x4, d->poly), +- sv_estrin_11_f64_x (pg, z2, x2, x4, x8, d->poly + 8), x8); ++ /* Order-7 Estrin. */ ++ svfloat64_t c13 = svld1rq (ptrue, &d->c1); ++ svfloat64_t c57 = svld1rq (ptrue, &d->c5); + +- /* y = shift + z + z^3 * P(z^2). */ +- svfloat64_t z3 = svmul_x (pg, z2, az); +- y = svmla_x (pg, az, z3, y); ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), z2, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), z2, c13, 1); ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), z2, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), z2, c57, 1); ++ ++ svfloat64_t p03 = svmla_x (pg, p01, z4, p23); ++ svfloat64_t p47 = svmla_x (pg, p45, z4, p67); ++ svfloat64_t p07 = svmla_x (pg, p03, z8, p47); ++ ++ /* Order-11 Estrin. */ ++ svfloat64_t c911 = svld1rq (ptrue, &d->c9); ++ svfloat64_t c1315 = svld1rq (ptrue, &d->c13); ++ svfloat64_t c1719 = svld1rq (ptrue, &d->c17); + +- /* Apply shift as indicated by `red` predicate. */ +- y = svadd_m (red, y, d->pi_over_2); ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), z2, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), z2, c911, 1); ++ svfloat64_t p811 = svmla_x (pg, p89, z4, p1011); + +- /* y = atan(x) if x>0, -atan(-x) otherwise. */ +- y = svreinterpret_f64 (sveor_x (pg, svreinterpret_u64 (y), sign)); ++ svfloat64_t p1213 = svmla_lane (sv_f64 (d->c12), z2, c1315, 0); ++ svfloat64_t p1415 = svmla_lane (sv_f64 (d->c14), z2, c1315, 1); ++ svfloat64_t p1215 = svmla_x (pg, p1213, z4, p1415); + +- return y; ++ svfloat64_t p1617 = svmla_lane (sv_f64 (d->c16), z2, c1719, 0); ++ svfloat64_t p1819 = svmla_lane (sv_f64 (d->c18), z2, c1719, 1); ++ svfloat64_t p1619 = svmla_x (pg, p1617, z4, p1819); ++ ++ svfloat64_t p815 = svmla_x (pg, p811, z8, p1215); ++ svfloat64_t p819 = svmla_x (pg, p815, z16, p1619); ++ ++ svfloat64_t y = svmla_x (pg, p07, z16, p819); ++ ++ /* y = shift + z + z^3 * P(z^2). */ ++ shift = svadd_m (red, z, shift); ++ y = svmul_x (pg, z2, y); ++ return svmla_x (pg, shift, z, y); + } +diff --git a/sysdeps/aarch64/fpu/atanf_advsimd.c b/sysdeps/aarch64/fpu/atanf_advsimd.c +index d015cc70ad..e72074ec62 100644 +--- a/sysdeps/aarch64/fpu/atanf_advsimd.c ++++ b/sysdeps/aarch64/fpu/atanf_advsimd.c +@@ -22,26 +22,35 @@ + + static const struct data + { ++ uint32x4_t sign_mask, pi_over_2; ++ float32x4_t neg_one; ++#if WANT_SIMD_EXCEPT + float32x4_t poly[8]; +- float32x4_t pi_over_2; ++} data = { ++ .poly = { V4 (-0x1.5554dcp-2), V4 (0x1.9978ecp-3), V4 (-0x1.230a94p-3), ++ V4 (0x1.b4debp-4), V4 (-0x1.3550dap-4), V4 (0x1.61eebp-5), ++ V4 (-0x1.0c17d4p-6), V4 (0x1.7ea694p-9) }, ++#else ++ float32x4_t c0, c2, c4, c6; ++ float c1, c3, c5, c7; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-128, 1.0]. + Generated using fpminimax between FLT_MIN and 1. */ +- .poly = { V4 (-0x1.55555p-2f), V4 (0x1.99935ep-3f), V4 (-0x1.24051ep-3f), +- V4 (0x1.bd7368p-4f), V4 (-0x1.491f0ep-4f), V4 (0x1.93a2c0p-5f), +- V4 (-0x1.4c3c60p-6f), V4 (0x1.01fd88p-8f) }, +- .pi_over_2 = V4 (0x1.921fb6p+0f), ++ .c0 = V4 (-0x1.5554dcp-2), .c1 = 0x1.9978ecp-3, ++ .c2 = V4 (-0x1.230a94p-3), .c3 = 0x1.b4debp-4, ++ .c4 = V4 (-0x1.3550dap-4), .c5 = 0x1.61eebp-5, ++ .c6 = V4 (-0x1.0c17d4p-6), .c7 = 0x1.7ea694p-9, ++#endif ++ .pi_over_2 = V4 (0x3fc90fdb), ++ .neg_one = V4 (-1.0f), ++ .sign_mask = V4 (0x80000000), + }; + +-#define SignMask v_u32 (0x80000000) +- +-#define P(i) d->poly[i] +- ++#if WANT_SIMD_EXCEPT + #define TinyBound 0x30800000 /* asuint(0x1p-30). */ + #define BigBound 0x4e800000 /* asuint(0x1p30). */ + +-#if WANT_SIMD_EXCEPT + static float32x4_t VPCS_ATTR NOINLINE + special_case (float32x4_t x, float32x4_t y, uint32x4_t special) + { +@@ -51,19 +60,20 @@ special_case (float32x4_t x, float32x4_t y, uint32x4_t special) + + /* Fast implementation of vector atanf based on + atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1] +- using z=-1/x and shift = pi/2. Maximum observed error is 2.9ulps: +- _ZGVnN4v_atanf (0x1.0468f6p+0) got 0x1.967f06p-1 want 0x1.967fp-1. */ ++ using z=-1/x and shift = pi/2. Maximum observed error is 2.02 ulps: ++ _ZGVnN4v_atanf (0x1.03d4cep+0) got 0x1.95ed3ap-1 ++ want 0x1.95ed36p-1. */ + float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (atan) (float32x4_t x) + { + const struct data *d = ptr_barrier (&data); + +- /* Small cases, infs and nans are supported by our approximation technique, +- but do not set fenv flags correctly. Only trigger special case if we need +- fenv. */ + uint32x4_t ix = vreinterpretq_u32_f32 (x); +- uint32x4_t sign = vandq_u32 (ix, SignMask); ++ uint32x4_t sign = vandq_u32 (ix, d->sign_mask); + + #if WANT_SIMD_EXCEPT ++ /* Small cases, infs and nans are supported by our approximation technique, ++ but do not set fenv flags correctly. Only trigger special case if we need ++ fenv. */ + uint32x4_t ia = vandq_u32 (ix, v_u32 (0x7ff00000)); + uint32x4_t special = vcgtq_u32 (vsubq_u32 (ia, v_u32 (TinyBound)), + v_u32 (BigBound - TinyBound)); +@@ -71,41 +81,52 @@ float32x4_t VPCS_ATTR NOINLINE V_NAME_F1 (atan) (float32x4_t x) + if (__glibc_unlikely (v_any_u32 (special))) + return special_case (x, x, v_u32 (-1)); + #endif +- + /* Argument reduction: +- y := arctan(x) for x < 1 +- y := pi/2 + arctan(-1/x) for x > 1 +- Hence, use z=-1/a if x>=1, otherwise z=a. */ +- uint32x4_t red = vcagtq_f32 (x, v_f32 (1.0)); +- /* Avoid dependency in abs(x) in division (and comparison). */ +- float32x4_t z = vbslq_f32 (red, vdivq_f32 (v_f32 (1.0f), x), x); ++ y := arctan(x) for |x| < 1 ++ y := arctan(-1/x) + pi/2 for x > +1 ++ y := arctan(-1/x) - pi/2 for x < -1 ++ Hence, use z=-1/a if x>=|-1|, otherwise z=a. */ ++ uint32x4_t red = vcagtq_f32 (x, d->neg_one); ++ ++ float32x4_t z = vbslq_f32 (red, vdivq_f32 (d->neg_one, x), x); ++ ++ /* Shift is calculated as +-pi/2 or 0, depending on the argument case. */ + float32x4_t shift = vreinterpretq_f32_u32 ( +- vandq_u32 (red, vreinterpretq_u32_f32 (d->pi_over_2))); +- /* Use absolute value only when needed (odd powers of z). */ +- float32x4_t az = vbslq_f32 ( +- SignMask, vreinterpretq_f32_u32 (vandq_u32 (SignMask, red)), z); ++ vandq_u32 (red, veorq_u32 (d->pi_over_2, sign))); ++ ++ float32x4_t z2 = vmulq_f32 (z, z); ++ float32x4_t z3 = vmulq_f32 (z, z2); ++ float32x4_t z4 = vmulq_f32 (z2, z2); ++#if WANT_SIMD_EXCEPT + + /* Calculate the polynomial approximation. + Use 2-level Estrin scheme for P(z^2) with deg(P)=7. However, + a standard implementation using z8 creates spurious underflow + in the very last fma (when z^8 is small enough). +- Therefore, we split the last fma into a mul and an fma. +- Horner and single-level Estrin have higher errors that exceed +- threshold. */ +- float32x4_t z2 = vmulq_f32 (z, z); +- float32x4_t z4 = vmulq_f32 (z2, z2); +- ++ Therefore, we split the last fma into a mul and an fma. */ + float32x4_t y = vfmaq_f32 ( + v_pairwise_poly_3_f32 (z2, z4, d->poly), z4, + vmulq_f32 (z4, v_pairwise_poly_3_f32 (z2, z4, d->poly + 4))); + +- /* y = shift + z * P(z^2). */ +- y = vaddq_f32 (vfmaq_f32 (az, y, vmulq_f32 (z2, az)), shift); ++#else ++ float32x4_t z8 = vmulq_f32 (z4, z4); ++ ++ /* Uses an Estrin scheme for polynomial approximation. */ ++ float32x4_t odd_coeffs = vld1q_f32 (&d->c1); ++ ++ float32x4_t p01 = vfmaq_laneq_f32 (d->c0, z2, odd_coeffs, 0); ++ float32x4_t p23 = vfmaq_laneq_f32 (d->c2, z2, odd_coeffs, 1); ++ float32x4_t p45 = vfmaq_laneq_f32 (d->c4, z2, odd_coeffs, 2); ++ float32x4_t p67 = vfmaq_laneq_f32 (d->c6, z2, odd_coeffs, 3); + +- /* y = atan(x) if x>0, -atan(-x) otherwise. */ +- y = vreinterpretq_f32_u32 (veorq_u32 (vreinterpretq_u32_f32 (y), sign)); ++ float32x4_t p03 = vfmaq_f32 (p01, z4, p23); ++ float32x4_t p47 = vfmaq_f32 (p45, z4, p67); + +- return y; ++ float32x4_t y = vfmaq_f32 (p03, z8, p47); ++#endif ++ ++ /* y = shift + z * P(z^2). */ ++ return vfmaq_f32 (vaddq_f32 (shift, z), z3, y); + } + libmvec_hidden_def (V_NAME_F1 (atan)) + HALF_WIDTH_ALIAS_F1 (atan) +diff --git a/sysdeps/aarch64/fpu/atanf_sve.c b/sysdeps/aarch64/fpu/atanf_sve.c +index 7b54094586..0f5a054743 100644 +--- a/sysdeps/aarch64/fpu/atanf_sve.c ++++ b/sysdeps/aarch64/fpu/atanf_sve.c +@@ -18,18 +18,26 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f32.h" + + static const struct data + { +- float32_t poly[8]; +- float32_t pi_over_2; ++ float32_t c1, c3, c5, c7; ++ float32_t c0, c2, c4, c6; ++ float32_t shift_val, neg_one; + } data = { + /* Coefficients of polynomial P such that atan(x)~x+x*P(x^2) on + [2**-128, 1.0]. */ +- .poly = { -0x1.55555p-2f, 0x1.99935ep-3f, -0x1.24051ep-3f, 0x1.bd7368p-4f, +- -0x1.491f0ep-4f, 0x1.93a2c0p-5f, -0x1.4c3c60p-6f, 0x1.01fd88p-8f }, +- .pi_over_2 = 0x1.921fb6p+0f, ++ .c0 = -0x1.5554dcp-2, ++ .c1 = 0x1.9978ecp-3, ++ .c2 = -0x1.230a94p-3, ++ .c3 = 0x1.b4debp-4, ++ .c4 = -0x1.3550dap-4, ++ .c5 = 0x1.61eebp-5, ++ .c6 = -0x1.0c17d4p-6, ++ .c7 = 0x1.7ea694p-9, ++ /* pi/2, used as a shift value after reduction. */ ++ .shift_val = 0x1.921fb54442d18p+0, ++ .neg_one = -1.0f, + }; + + #define SignMask (0x80000000) +@@ -37,43 +45,49 @@ static const struct data + /* Fast implementation of SVE atanf based on + atan(x) ~ shift + z + z^3 * P(z^2) with reduction to [0,1] using + z=-1/x and shift = pi/2. +- Largest observed error is 2.9 ULP, close to +/-1.0: +- _ZGVsMxv_atanf (0x1.0468f6p+0) got -0x1.967f06p-1 +- want -0x1.967fp-1. */ ++ Largest observed error is 2.12 ULP: ++ _ZGVsMxv_atanf (0x1.03d4cep+0) got 0x1.95ed3ap-1 ++ want 0x1.95ed36p-1. */ + svfloat32_t SV_NAME_F1 (atan) (svfloat32_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); ++ svbool_t ptrue = svptrue_b32 (); + + /* No need to trigger special case. Small cases, infs and nans + are supported by our approximation technique. */ + svuint32_t ix = svreinterpret_u32 (x); +- svuint32_t sign = svand_x (pg, ix, SignMask); ++ svuint32_t sign = svand_x (ptrue, ix, SignMask); + + /* Argument reduction: + y := arctan(x) for x < 1 +- y := pi/2 + arctan(-1/x) for x > 1 +- Hence, use z=-1/a if x>=1, otherwise z=a. */ +- svbool_t red = svacgt (pg, x, 1.0f); +- /* Avoid dependency in abs(x) in division (and comparison). */ +- svfloat32_t z = svsel (red, svdiv_x (pg, sv_f32 (1.0f), x), x); +- /* Use absolute value only when needed (odd powers of z). */ +- svfloat32_t az = svabs_x (pg, z); +- az = svneg_m (az, red, az); +- +- /* Use split Estrin scheme for P(z^2) with deg(P)=7. */ +- svfloat32_t z2 = svmul_x (pg, z, z); +- svfloat32_t z4 = svmul_x (pg, z2, z2); +- svfloat32_t z8 = svmul_x (pg, z4, z4); +- +- svfloat32_t y = sv_estrin_7_f32_x (pg, z2, z4, z8, d->poly); +- +- /* y = shift + z + z^3 * P(z^2). */ +- svfloat32_t z3 = svmul_x (pg, z2, az); +- y = svmla_x (pg, az, z3, y); +- +- /* Apply shift as indicated by 'red' predicate. */ +- y = svadd_m (red, y, sv_f32 (d->pi_over_2)); +- +- /* y = atan(x) if x>0, -atan(-x) otherwise. */ +- return svreinterpret_f32 (sveor_x (pg, svreinterpret_u32 (y), sign)); ++ y := arctan(-1/x) + pi/2 for x > +1 ++ y := arctan(-1/x) - pi/2 for x < -1 ++ Hence, use z=-1/a if |x|>=|-1|, otherwise z=a. */ ++ svbool_t red = svacgt (pg, x, d->neg_one); ++ svfloat32_t z = svsel (red, svdiv_x (pg, sv_f32 (d->neg_one), x), x); ++ ++ /* Reinserts the sign bit of the argument to handle the case of x < -1. */ ++ svfloat32_t shift = svreinterpret_f32 ( ++ sveor_x (red, svreinterpret_u32 (sv_f32 (d->shift_val)), sign)); ++ ++ svfloat32_t z2 = svmul_x (ptrue, z, z); ++ svfloat32_t z3 = svmul_x (ptrue, z2, z); ++ svfloat32_t z4 = svmul_x (ptrue, z2, z2); ++ svfloat32_t z8 = svmul_x (ptrue, z4, z4); ++ ++ svfloat32_t odd_coeffs = svld1rq (ptrue, &d->c1); ++ ++ svfloat32_t p01 = svmla_lane (sv_f32 (d->c0), z2, odd_coeffs, 0); ++ svfloat32_t p23 = svmla_lane (sv_f32 (d->c2), z2, odd_coeffs, 1); ++ svfloat32_t p45 = svmla_lane (sv_f32 (d->c4), z2, odd_coeffs, 2); ++ svfloat32_t p67 = svmla_lane (sv_f32 (d->c6), z2, odd_coeffs, 3); ++ ++ svfloat32_t p03 = svmla_x (pg, p01, z4, p23); ++ svfloat32_t p47 = svmla_x (pg, p45, z4, p67); ++ ++ svfloat32_t y = svmla_x (pg, p03, z8, p47); ++ ++ /* shift + z + z^3 * P(z^2). */ ++ shift = svadd_m (red, z, shift); ++ return svmla_x (pg, shift, z3, y); + } + +commit 0348dd8b981ef892accd4a2a7c43e179eee91480 +Author: Luna Lamb +Date: Thu May 29 15:22:51 2025 +0000 + + AArch64: Improve codegen in SVE log1p + + Improves memory access, reformat evaluation scheme to pack coefficients. + 5% improvement in throughput microbenchmark on Neoverse V1. + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit da196e6134ede64728006518352d75b6c3902fec) + +diff --git a/sysdeps/aarch64/fpu/log1p_sve.c b/sysdeps/aarch64/fpu/log1p_sve.c +index 04f7e5720e..5251f3c075 100644 +--- a/sysdeps/aarch64/fpu/log1p_sve.c ++++ b/sysdeps/aarch64/fpu/log1p_sve.c +@@ -22,19 +22,33 @@ + + static const struct data + { +- double poly[19]; ++ float64_t c0, c2, c4, c6, c8, c10, c12, c14, c16; ++ float64_t c1, c3, c5, c7, c9, c11, c13, c15, c17, c18; + double ln2_hi, ln2_lo; + uint64_t hfrt2_top, onemhfrt2_top, inf, mone; + } data = { + /* Generated using Remez in [ sqrt(2)/2 - 1, sqrt(2) - 1]. Order 20 +- polynomial, however first 2 coefficients are 0 and 1 so are not stored. */ +- .poly = { -0x1.ffffffffffffbp-2, 0x1.55555555551a9p-2, -0x1.00000000008e3p-2, +- 0x1.9999999a32797p-3, -0x1.555555552fecfp-3, 0x1.249248e071e5ap-3, +- -0x1.ffffff8bf8482p-4, 0x1.c71c8f07da57ap-4, -0x1.9999ca4ccb617p-4, +- 0x1.7459ad2e1dfa3p-4, -0x1.554d2680a3ff2p-4, 0x1.3b4c54d487455p-4, +- -0x1.2548a9ffe80e6p-4, 0x1.0f389a24b2e07p-4, -0x1.eee4db15db335p-5, +- 0x1.e95b494d4a5ddp-5, -0x1.15fdf07cb7c73p-4, 0x1.0310b70800fcfp-4, +- -0x1.cfa7385bdb37ep-6, }, ++ polynomial, however first 2 coefficients are 0 and 1 so are not ++ stored. */ ++ .c0 = -0x1.ffffffffffffbp-2, ++ .c1 = 0x1.55555555551a9p-2, ++ .c2 = -0x1.00000000008e3p-2, ++ .c3 = 0x1.9999999a32797p-3, ++ .c4 = -0x1.555555552fecfp-3, ++ .c5 = 0x1.249248e071e5ap-3, ++ .c6 = -0x1.ffffff8bf8482p-4, ++ .c7 = 0x1.c71c8f07da57ap-4, ++ .c8 = -0x1.9999ca4ccb617p-4, ++ .c9 = 0x1.7459ad2e1dfa3p-4, ++ .c10 = -0x1.554d2680a3ff2p-4, ++ .c11 = 0x1.3b4c54d487455p-4, ++ .c12 = -0x1.2548a9ffe80e6p-4, ++ .c13 = 0x1.0f389a24b2e07p-4, ++ .c14 = -0x1.eee4db15db335p-5, ++ .c15 = 0x1.e95b494d4a5ddp-5, ++ .c16 = -0x1.15fdf07cb7c73p-4, ++ .c17 = 0x1.0310b70800fcfp-4, ++ .c18 = -0x1.cfa7385bdb37ep-6, + .ln2_hi = 0x1.62e42fefa3800p-1, + .ln2_lo = 0x1.ef35793c76730p-45, + /* top32(asuint64(sqrt(2)/2)) << 32. */ +@@ -49,7 +63,7 @@ static const struct data + #define BottomMask 0xffffffff + + static svfloat64_t NOINLINE +-special_case (svbool_t special, svfloat64_t x, svfloat64_t y) ++special_case (svfloat64_t x, svfloat64_t y, svbool_t special) + { + return sv_call_f64 (log1p, x, y, special); + } +@@ -91,8 +105,9 @@ svfloat64_t SV_NAME_D1 (log1p) (svfloat64_t x, svbool_t pg) + /* Reduce x to f in [sqrt(2)/2, sqrt(2)]. */ + svuint64_t utop + = svadd_x (pg, svand_x (pg, u, 0x000fffff00000000), d->hfrt2_top); +- svuint64_t u_red = svorr_x (pg, utop, svand_x (pg, mi, BottomMask)); +- svfloat64_t f = svsub_x (pg, svreinterpret_f64 (u_red), 1); ++ svuint64_t u_red ++ = svorr_x (pg, utop, svand_x (svptrue_b64 (), mi, BottomMask)); ++ svfloat64_t f = svsub_x (svptrue_b64 (), svreinterpret_f64 (u_red), 1); + + /* Correction term c/m. */ + svfloat64_t cm = svdiv_x (pg, svsub_x (pg, x, svsub_x (pg, m, 1)), m); +@@ -103,16 +118,47 @@ svfloat64_t SV_NAME_D1 (log1p) (svfloat64_t x, svbool_t pg) + Hence approximation has the form f + f^2 * P(f) + where P(x) = C0 + C1*x + C2x^2 + ... + Assembling this all correctly is dealt with at the final step. */ +- svfloat64_t f2 = svmul_x (pg, f, f), f4 = svmul_x (pg, f2, f2), +- f8 = svmul_x (pg, f4, f4), f16 = svmul_x (pg, f8, f8); +- svfloat64_t p = sv_estrin_18_f64_x (pg, f, f2, f4, f8, f16, d->poly); ++ svfloat64_t f2 = svmul_x (svptrue_b64 (), f, f), ++ f4 = svmul_x (svptrue_b64 (), f2, f2), ++ f8 = svmul_x (svptrue_b64 (), f4, f4), ++ f16 = svmul_x (svptrue_b64 (), f8, f8); ++ ++ svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); ++ svfloat64_t c57 = svld1rq (svptrue_b64 (), &d->c5); ++ svfloat64_t c911 = svld1rq (svptrue_b64 (), &d->c9); ++ svfloat64_t c1315 = svld1rq (svptrue_b64 (), &d->c13); ++ svfloat64_t c1718 = svld1rq (svptrue_b64 (), &d->c17); ++ ++ /* Order-18 Estrin scheme. */ ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), f, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), f, c13, 1); ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), f, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), f, c57, 1); ++ ++ svfloat64_t p03 = svmla_x (pg, p01, f2, p23); ++ svfloat64_t p47 = svmla_x (pg, p45, f2, p67); ++ svfloat64_t p07 = svmla_x (pg, p03, f4, p47); ++ ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), f, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), f, c911, 1); ++ svfloat64_t p1213 = svmla_lane (sv_f64 (d->c12), f, c1315, 0); ++ svfloat64_t p1415 = svmla_lane (sv_f64 (d->c14), f, c1315, 1); ++ ++ svfloat64_t p811 = svmla_x (pg, p89, f2, p1011); ++ svfloat64_t p1215 = svmla_x (pg, p1213, f2, p1415); ++ svfloat64_t p815 = svmla_x (pg, p811, f4, p1215); ++ ++ svfloat64_t p015 = svmla_x (pg, p07, f8, p815); ++ svfloat64_t p1617 = svmla_lane (sv_f64 (d->c16), f, c1718, 0); ++ svfloat64_t p1618 = svmla_lane (p1617, f2, c1718, 1); ++ svfloat64_t p = svmla_x (pg, p015, f16, p1618); + + svfloat64_t ylo = svmla_x (pg, cm, k, d->ln2_lo); + svfloat64_t yhi = svmla_x (pg, f, k, d->ln2_hi); +- svfloat64_t y = svmla_x (pg, svadd_x (pg, ylo, yhi), f2, p); + + if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (special, x, y); +- +- return y; ++ return special_case ( ++ x, svmla_x (svptrue_b64 (), svadd_x (svptrue_b64 (), ylo, yhi), f2, p), ++ special); ++ return svmla_x (svptrue_b64 (), svadd_x (svptrue_b64 (), ylo, yhi), f2, p); + } + +commit 01ab94cf780dffce9529374229bd2d80baf9c26f +Author: Dylan Fleming +Date: Wed Jun 18 16:17:12 2025 +0000 + + AArch64: Optimize SVE exp functions + + Improve performance of SVE exps by making better use + of the SVE FEXPA instruction. + + Performance improvement on Neoverse V1: + exp2_sve: 21% + exp2f_sve: 24% + exp10f_sve: 23% + expm1_sve: 25% + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 1e3d1ddf977ecd653de8d0d10eb083d80ac21cf3) + +diff --git a/sysdeps/aarch64/fpu/exp10f_sve.c b/sysdeps/aarch64/fpu/exp10f_sve.c +index 8aa3fa9c43..0a4c264506 100644 +--- a/sysdeps/aarch64/fpu/exp10f_sve.c ++++ b/sysdeps/aarch64/fpu/exp10f_sve.c +@@ -19,26 +19,19 @@ + + #include "sv_math.h" + +-/* For x < -Thres, the result is subnormal and not handled correctly by +- FEXPA. */ +-#define Thres 37.9 ++/* For x < -Thres (-log10(2^126)), the result is subnormal and not handled ++ correctly by FEXPA. */ ++#define Thres 0x1.2f702p+5 + + static const struct data + { +- float log2_10_lo, c0, c2, c4; +- float c1, c3, log10_2; +- float shift, log2_10_hi, thres; ++ float log10_2, log2_10_hi, log2_10_lo, c1; ++ float c0, shift, thres; + } data = { + /* Coefficients generated using Remez algorithm with minimisation of relative +- error. +- rel error: 0x1.89dafa3p-24 +- abs error: 0x1.167d55p-23 in [-log10(2)/2, log10(2)/2] +- maxerr: 0.52 +0.5 ulp. */ +- .c0 = 0x1.26bb16p+1f, +- .c1 = 0x1.5350d2p+1f, +- .c2 = 0x1.04744ap+1f, +- .c3 = 0x1.2d8176p+0f, +- .c4 = 0x1.12b41ap-1f, ++ error. */ ++ .c0 = 0x1.26bb62p1, ++ .c1 = 0x1.53524cp1, + /* 1.5*2^17 + 127, a shift value suitable for FEXPA. */ + .shift = 0x1.803f8p17f, + .log10_2 = 0x1.a934fp+1, +@@ -53,28 +46,23 @@ sv_exp10f_inline (svfloat32_t x, const svbool_t pg, const struct data *d) + /* exp10(x) = 2^(n/N) * 10^r = 2^n * (1 + poly (r)), + with poly(r) in [1/sqrt(2), sqrt(2)] and + x = r + n * log10(2) / N, with r in [-log10(2)/2N, log10(2)/2N]. */ +- +- svfloat32_t lane_consts = svld1rq (svptrue_b32 (), &d->log2_10_lo); ++ svfloat32_t lane_consts = svld1rq (svptrue_b32 (), &d->log10_2); + + /* n = round(x/(log10(2)/N)). */ + svfloat32_t shift = sv_f32 (d->shift); +- svfloat32_t z = svmad_x (pg, sv_f32 (d->log10_2), x, shift); +- svfloat32_t n = svsub_x (svptrue_b32 (), z, shift); ++ svfloat32_t z = svmla_lane (shift, x, lane_consts, 0); ++ svfloat32_t n = svsub_x (pg, z, shift); + + /* r = x - n*log10(2)/N. */ +- svfloat32_t r = svmsb_x (pg, sv_f32 (d->log2_10_hi), n, x); +- r = svmls_lane (r, n, lane_consts, 0); ++ svfloat32_t r = x; ++ r = svmls_lane (r, n, lane_consts, 1); ++ r = svmls_lane (r, n, lane_consts, 2); + + svfloat32_t scale = svexpa (svreinterpret_u32 (z)); + + /* Polynomial evaluation: poly(r) ~ exp10(r)-1. */ +- svfloat32_t p12 = svmla_lane (sv_f32 (d->c1), r, lane_consts, 2); +- svfloat32_t p34 = svmla_lane (sv_f32 (d->c3), r, lane_consts, 3); +- svfloat32_t r2 = svmul_x (svptrue_b32 (), r, r); +- svfloat32_t p14 = svmla_x (pg, p12, p34, r2); +- svfloat32_t p0 = svmul_lane (r, lane_consts, 1); +- svfloat32_t poly = svmla_x (pg, p0, r2, p14); +- ++ svfloat32_t poly = svmla_lane (sv_f32 (d->c0), r, lane_consts, 3); ++ poly = svmul_x (pg, poly, r); + return svmla_x (pg, scale, scale, poly); + } + +@@ -85,11 +73,10 @@ special_case (svfloat32_t x, svbool_t special, const struct data *d) + special); + } + +-/* Single-precision SVE exp10f routine. Implements the same algorithm +- as AdvSIMD exp10f. +- Worst case error is 1.02 ULPs. +- _ZGVsMxv_exp10f(-0x1.040488p-4) got 0x1.ba5f9ep-1 +- want 0x1.ba5f9cp-1. */ ++/* Single-precision SVE exp10f routine. Based on the FEXPA instruction. ++ Worst case error is 1.10 ULP. ++ _ZGVsMxv_exp10f (0x1.cc76dep+3) got 0x1.be0172p+47 ++ want 0x1.be017p+47. */ + svfloat32_t SV_NAME_F1 (exp10) (svfloat32_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +diff --git a/sysdeps/aarch64/fpu/exp2_sve.c b/sysdeps/aarch64/fpu/exp2_sve.c +index 5dfb77cdbc..ed11423e45 100644 +--- a/sysdeps/aarch64/fpu/exp2_sve.c ++++ b/sysdeps/aarch64/fpu/exp2_sve.c +@@ -19,23 +19,21 @@ + + #include "sv_math.h" + +-#define N (1 << V_EXP_TABLE_BITS) +- + #define BigBound 1022 + #define UOFlowBound 1280 + + static const struct data + { +- double c0, c2; +- double c1, c3; ++ double c2, c4; ++ double c0, c1, c3; + double shift, big_bound, uoflow_bound; + } data = { + /* Coefficients are computed using Remez algorithm with + minimisation of the absolute error. */ +- .c0 = 0x1.62e42fefa3686p-1, .c1 = 0x1.ebfbdff82c241p-3, +- .c2 = 0x1.c6b09b16de99ap-5, .c3 = 0x1.3b2abf5571ad8p-7, +- .shift = 0x1.8p52 / N, .uoflow_bound = UOFlowBound, +- .big_bound = BigBound, ++ .c0 = 0x1.62e42fefa39efp-1, .c1 = 0x1.ebfbdff82a31bp-3, ++ .c2 = 0x1.c6b08d706c8a5p-5, .c3 = 0x1.3b2ad2ff7d2f3p-7, ++ .c4 = 0x1.5d8761184beb3p-10, .shift = 0x1.800000000ffc0p+46, ++ .uoflow_bound = UOFlowBound, .big_bound = BigBound, + }; + + #define SpecialOffset 0x6000000000000000 /* 0x1p513. */ +@@ -64,50 +62,52 @@ special_case (svbool_t pg, svfloat64_t s, svfloat64_t y, svfloat64_t n, + svadd_x (pg, svsub_x (pg, svreinterpret_u64 (s), SpecialBias2), b)); + + /* |n| > 1280 => 2^(n) overflows. */ +- svbool_t p_cmp = svacgt (pg, n, d->uoflow_bound); ++ svbool_t p_cmp = svacle (pg, n, d->uoflow_bound); + + svfloat64_t r1 = svmul_x (svptrue_b64 (), s1, s1); + svfloat64_t r2 = svmla_x (pg, s2, s2, y); + svfloat64_t r0 = svmul_x (svptrue_b64 (), r2, s1); + +- return svsel (p_cmp, r1, r0); ++ return svsel (p_cmp, r0, r1); + } + + /* Fast vector implementation of exp2. +- Maximum measured error is 1.65 ulp. +- _ZGVsMxv_exp2(-0x1.4c264ab5b559bp-6) got 0x1.f8db0d4df721fp-1 +- want 0x1.f8db0d4df721dp-1. */ ++ Maximum measured error is 0.52 + 0.5 ulp. ++ _ZGVsMxv_exp2 (0x1.3b72ad5b701bfp-1) got 0x1.8861641b49e08p+0 ++ want 0x1.8861641b49e07p+0. */ + svfloat64_t SV_NAME_D1 (exp2) (svfloat64_t x, svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +- svbool_t no_big_scale = svacle (pg, x, d->big_bound); +- svbool_t special = svnot_z (pg, no_big_scale); +- +- /* Reduce x to k/N + r, where k is integer and r in [-1/2N, 1/2N]. */ +- svfloat64_t shift = sv_f64 (d->shift); +- svfloat64_t kd = svadd_x (pg, x, shift); +- svuint64_t ki = svreinterpret_u64 (kd); +- /* kd = k/N. */ +- kd = svsub_x (pg, kd, shift); +- svfloat64_t r = svsub_x (pg, x, kd); +- +- /* scale ~= 2^(k/N). */ +- svuint64_t idx = svand_x (pg, ki, N - 1); +- svuint64_t sbits = svld1_gather_index (pg, __v_exp_data, idx); +- /* This is only a valid scale when -1023*N < k < 1024*N. */ +- svuint64_t top = svlsl_x (pg, ki, 52 - V_EXP_TABLE_BITS); +- svfloat64_t scale = svreinterpret_f64 (svadd_x (pg, sbits, top)); +- +- svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); +- /* Approximate exp2(r) using polynomial. */ +- /* y = exp2(r) - 1 ~= C0 r + C1 r^2 + C2 r^3 + C3 r^4. */ ++ svbool_t special = svacge (pg, x, d->big_bound); ++ ++ svfloat64_t z = svadd_x (svptrue_b64 (), x, d->shift); ++ svfloat64_t n = svsub_x (svptrue_b64 (), z, d->shift); ++ svfloat64_t r = svsub_x (svptrue_b64 (), x, n); ++ ++ svfloat64_t scale = svexpa (svreinterpret_u64 (z)); ++ + svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); +- svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), r, c13, 0); +- svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), r, c13, 1); +- svfloat64_t p = svmla_x (pg, p01, p23, r2); ++ svfloat64_t c24 = svld1rq (svptrue_b64 (), &d->c2); ++ ++ /* Approximate exp2(r) using polynomial. */ ++ /* y = exp2(r) - 1 ~= r * (C0 + C1 r + C2 r^2 + C3 r^3 + C4 r^4). */ ++ svfloat64_t p12 = svmla_lane (sv_f64 (d->c1), r, c24, 0); ++ svfloat64_t p34 = svmla_lane (sv_f64 (d->c3), r, c24, 1); ++ svfloat64_t p = svmla_x (pg, p12, p34, r2); ++ p = svmad_x (pg, p, r, d->c0); + svfloat64_t y = svmul_x (svptrue_b64 (), r, p); ++ + /* Assemble exp2(x) = exp2(r) * scale. */ + if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (pg, scale, y, kd, d); ++ { ++ /* FEXPA zeroes the sign bit, however the sign is meaningful to the ++ special case function so needs to be copied. ++ e = sign bit of u << 46. */ ++ svuint64_t e = svand_x (pg, svlsl_x (pg, svreinterpret_u64 (z), 46), ++ 0x8000000000000000); ++ scale = svreinterpret_f64 (svadd_x (pg, e, svreinterpret_u64 (scale))); ++ return special_case (pg, scale, y, n, d); ++ } ++ + return svmla_x (pg, scale, scale, y); + } +diff --git a/sysdeps/aarch64/fpu/exp2f_sve.c b/sysdeps/aarch64/fpu/exp2f_sve.c +index c6216bed9e..cf01820288 100644 +--- a/sysdeps/aarch64/fpu/exp2f_sve.c ++++ b/sysdeps/aarch64/fpu/exp2f_sve.c +@@ -18,21 +18,17 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f32.h" + + #define Thres 0x1.5d5e2ap+6f + + static const struct data + { +- float c0, c2, c4, c1, c3; +- float shift, thres; ++ float c0, c1, shift, thres; + } data = { +- /* Coefficients copied from the polynomial in AdvSIMD variant. */ +- .c0 = 0x1.62e422p-1f, +- .c1 = 0x1.ebf9bcp-3f, +- .c2 = 0x1.c6bd32p-5f, +- .c3 = 0x1.3ce9e4p-7f, +- .c4 = 0x1.59977ap-10f, ++ /* Coefficients generated using Remez algorithm with minimisation of relative ++ error. */ ++ .c0 = 0x1.62e485p-1, ++ .c1 = 0x1.ebfbe0p-3, + /* 1.5*2^17 + 127. */ + .shift = 0x1.803f8p17f, + /* Roughly 87.3. For x < -Thres, the result is subnormal and not handled +@@ -51,16 +47,8 @@ sv_exp2f_inline (svfloat32_t x, const svbool_t pg, const struct data *d) + + svfloat32_t scale = svexpa (svreinterpret_u32 (z)); + +- /* Polynomial evaluation: poly(r) ~ exp2(r)-1. +- Evaluate polynomial use hybrid scheme - offset ESTRIN by 1 for +- coefficients 1 to 4, and apply most significant coefficient directly. */ +- svfloat32_t even_coeffs = svld1rq (svptrue_b32 (), &d->c0); +- svfloat32_t r2 = svmul_x (svptrue_b32 (), r, r); +- svfloat32_t p12 = svmla_lane (sv_f32 (d->c1), r, even_coeffs, 1); +- svfloat32_t p34 = svmla_lane (sv_f32 (d->c3), r, even_coeffs, 2); +- svfloat32_t p14 = svmla_x (pg, p12, r2, p34); +- svfloat32_t p0 = svmul_lane (r, even_coeffs, 0); +- svfloat32_t poly = svmla_x (pg, p0, r2, p14); ++ svfloat32_t poly = svmla_x (pg, sv_f32 (d->c0), r, sv_f32 (d->c1)); ++ poly = svmul_x (svptrue_b32 (), poly, r); + + return svmla_x (pg, scale, scale, poly); + } +@@ -72,11 +60,10 @@ special_case (svfloat32_t x, svbool_t special, const struct data *d) + special); + } + +-/* Single-precision SVE exp2f routine. Implements the same algorithm +- as AdvSIMD exp2f. +- Worst case error is 1.04 ULPs. +- _ZGVsMxv_exp2f(-0x1.af994ap-3) got 0x1.ba6a66p-1 +- want 0x1.ba6a64p-1. */ ++/* Single-precision SVE exp2f routine, based on the FEXPA instruction. ++ Worst case error is 1.09 ULPs. ++ _ZGVsMxv_exp2f (0x1.9a2a94p-1) got 0x1.be1054p+0 ++ want 0x1.be1052p+0. */ + svfloat32_t SV_NAME_F1 (exp2) (svfloat32_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +diff --git a/sysdeps/aarch64/fpu/expm1_sve.c b/sysdeps/aarch64/fpu/expm1_sve.c +index c933cf9c0e..4c35e0341d 100644 +--- a/sysdeps/aarch64/fpu/expm1_sve.c ++++ b/sysdeps/aarch64/fpu/expm1_sve.c +@@ -18,82 +18,164 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + +-#define SpecialBound 0x1.62b7d369a5aa9p+9 +-#define ExponentBias 0x3ff0000000000000 ++#define FexpaBound 0x1.4cb5ecef28adap-3 /* 15*ln2/64. */ ++#define SpecialBound 0x1.628c2855bfaddp+9 /* ln(2^(1023 + 1/128)). */ + + static const struct data + { +- double poly[11]; +- double shift, inv_ln2, special_bound; +- /* To be loaded in one quad-word. */ ++ double c2, c4; ++ double inv_ln2; + double ln2_hi, ln2_lo; ++ double c0, c1, c3; ++ double shift, thres; ++ uint64_t expm1_data[32]; + } data = { +- /* Generated using fpminimax. */ +- .poly = { 0x1p-1, 0x1.5555555555559p-3, 0x1.555555555554bp-5, +- 0x1.111111110f663p-7, 0x1.6c16c16c1b5f3p-10, 0x1.a01a01affa35dp-13, +- 0x1.a01a018b4ecbbp-16, 0x1.71ddf82db5bb4p-19, 0x1.27e517fc0d54bp-22, +- 0x1.af5eedae67435p-26, 0x1.1f143d060a28ap-29, }, +- +- .special_bound = SpecialBound, +- .inv_ln2 = 0x1.71547652b82fep0, +- .ln2_hi = 0x1.62e42fefa39efp-1, +- .ln2_lo = 0x1.abc9e3b39803fp-56, +- .shift = 0x1.8p52, ++ /* Table emulating FEXPA - 1, for values of FEXPA close to 1. ++ The table holds values of 2^(i/64) - 1, computed in arbitrary precision. ++ The first half of the table stores values associated to i from 0 to 15. ++ The second half of the table stores values associated to i from 0 to -15. */ ++ .expm1_data = { ++ 0x0000000000000000, 0x3f864d1f3bc03077, 0x3f966c34c5615d0f, 0x3fa0e8a30eb37901, ++ 0x3fa6ab0d9f3121ec, 0x3fac7d865a7a3440, 0x3fb1301d0125b50a, 0x3fb429aaea92ddfb, ++ 0x3fb72b83c7d517ae, 0x3fba35beb6fcb754, 0x3fbd4873168b9aa8, 0x3fc031dc431466b2, ++ 0x3fc1c3d373ab11c3, 0x3fc35a2b2f13e6e9, 0x3fc4f4efa8fef709, 0x3fc6942d3720185a, ++ 0x0000000000000000, 0xbfc331751ec3a814, 0xbfc20224341286e4, 0xbfc0cf85bed0f8b7, ++ 0xbfbf332113d56b1f, 0xbfbcc0768d4175a6, 0xbfba46f918837cb7, 0xbfb7c695afc3b424, ++ 0xbfb53f391822dbc7, 0xbfb2b0cfe1266bd4, 0xbfb01b466423250a, 0xbfaafd11874c009e, ++ 0xbfa5b505d5b6f268, 0xbfa05e4119ea5d89, 0xbf95f134923757f3, 0xbf860f9f985bc9f4, ++ }, ++ ++ /* Generated using Remez, in [-log(2)/128, log(2)/128]. */ ++ .c0 = 0x1p-1, ++ .c1 = 0x1.55555555548f9p-3, ++ .c2 = 0x1.5555555554c22p-5, ++ .c3 = 0x1.111123aaa2fb2p-7, ++ .c4 = 0x1.6c16d77d98e5bp-10, ++ .ln2_hi = 0x1.62e42fefa3800p-1, ++ .ln2_lo = 0x1.ef35793c76730p-45, ++ .inv_ln2 = 0x1.71547652b82fep+0, ++ .shift = 0x1.800000000ffc0p+46, /* 1.5*2^46+1023. */ ++ .thres = SpecialBound, + }; + +-static svfloat64_t NOINLINE +-special_case (svfloat64_t x, svfloat64_t y, svbool_t pg) ++#define SpecialOffset 0x6000000000000000 /* 0x1p513. */ ++/* SpecialBias1 + SpecialBias1 = asuint(1.0). */ ++#define SpecialBias1 0x7000000000000000 /* 0x1p769. */ ++#define SpecialBias2 0x3010000000000000 /* 0x1p-254. */ ++ ++static NOINLINE svfloat64_t ++special_case (svbool_t pg, svfloat64_t y, svfloat64_t s, svfloat64_t p, ++ svfloat64_t n) + { +- return sv_call_f64 (expm1, x, y, pg); ++ /* s=2^n may overflow, break it up into s=s1*s2, ++ such that exp = s + s*y can be computed as s1*(s2+s2*y) ++ and s1*s1 overflows only if n>0. */ ++ ++ /* If n<=0 then set b to 0x6, 0 otherwise. */ ++ svbool_t p_sign = svcmple (pg, n, 0.0); /* n <= 0. */ ++ svuint64_t b ++ = svdup_u64_z (p_sign, SpecialOffset); /* Inactive lanes set to 0. */ ++ ++ /* Set s1 to generate overflow depending on sign of exponent n, ++ ie. s1 = 0x70...0 - b. */ ++ svfloat64_t s1 = svreinterpret_f64 (svsubr_x (pg, b, SpecialBias1)); ++ /* Offset s to avoid overflow in final result if n is below threshold. ++ ie. s2 = as_u64 (s) - 0x3010...0 + b. */ ++ svfloat64_t s2 = svreinterpret_f64 ( ++ svadd_x (pg, svsub_x (pg, svreinterpret_u64 (s), SpecialBias2), b)); ++ ++ /* |n| > 1280 => 2^(n) overflows. */ ++ svbool_t p_cmp = svacgt (pg, n, 1280.0); ++ ++ svfloat64_t r1 = svmul_x (svptrue_b64 (), s1, s1); ++ svfloat64_t r2 = svmla_x (pg, s2, s2, p); ++ svfloat64_t r0 = svmul_x (svptrue_b64 (), r2, s1); ++ ++ svbool_t is_safe = svacle (pg, n, 1023); /* Only correct special lanes. */ ++ return svsel (is_safe, y, svsub_x (pg, svsel (p_cmp, r1, r0), 1.0)); + } + +-/* Double-precision vector exp(x) - 1 function. +- The maximum error observed error is 2.18 ULP: +- _ZGVsMxv_expm1(0x1.634ba0c237d7bp-2) got 0x1.a8b9ea8d66e22p-2 +- want 0x1.a8b9ea8d66e2p-2. */ ++/* FEXPA based SVE expm1 algorithm. ++ Maximum measured error is 2.81 + 0.5 ULP: ++ _ZGVsMxv_expm1 (0x1.974060e619bfp-3) got 0x1.c290e5858bb53p-3 ++ want 0x1.c290e5858bb5p-3. */ + svfloat64_t SV_NAME_D1 (expm1) (svfloat64_t x, svbool_t pg) + { + const struct data *d = ptr_barrier (&data); + +- /* Large, Nan/Inf. */ +- svbool_t special = svnot_z (pg, svaclt (pg, x, d->special_bound)); +- +- /* Reduce argument to smaller range: +- Let i = round(x / ln2) +- and f = x - i * ln2, then f is in [-ln2/2, ln2/2]. +- exp(x) - 1 = 2^i * (expm1(f) + 1) - 1 +- where 2^i is exact because i is an integer. */ +- svfloat64_t shift = sv_f64 (d->shift); +- svfloat64_t n = svsub_x (pg, svmla_x (pg, shift, x, d->inv_ln2), shift); +- svint64_t i = svcvt_s64_x (pg, n); +- svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); +- svfloat64_t f = svmls_lane (x, n, ln2, 0); +- f = svmls_lane (f, n, ln2, 1); +- +- /* Approximate expm1(f) using polynomial. +- Taylor expansion for expm1(x) has the form: +- x + ax^2 + bx^3 + cx^4 .... +- So we calculate the polynomial P(f) = a + bf + cf^2 + ... +- and assemble the approximation expm1(f) ~= f + f^2 * P(f). */ +- svfloat64_t f2 = svmul_x (pg, f, f); +- svfloat64_t f4 = svmul_x (pg, f2, f2); +- svfloat64_t f8 = svmul_x (pg, f4, f4); +- svfloat64_t p +- = svmla_x (pg, f, f2, sv_estrin_10_f64_x (pg, f, f2, f4, f8, d->poly)); +- +- /* Assemble the result. +- expm1(x) ~= 2^i * (p + 1) - 1 +- Let t = 2^i. */ +- svint64_t u = svadd_x (pg, svlsl_x (pg, i, 52), ExponentBias); +- svfloat64_t t = svreinterpret_f64 (u); +- +- /* expm1(x) ~= p * t + (t - 1). */ +- svfloat64_t y = svmla_x (pg, svsub_x (pg, t, 1), p, t); ++ svbool_t special = svacgt (pg, x, d->thres); + +- if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (x, y, special); ++ svfloat64_t z = svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2); ++ svuint64_t u = svreinterpret_u64 (z); ++ svfloat64_t n = svsub_x (pg, z, d->shift); + ++ /* r = x - n * ln2, r is in [-ln2/128, ln2/128]. */ ++ svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); ++ svfloat64_t r = x; ++ r = svmls_lane (r, n, ln2, 0); ++ r = svmls_lane (r, n, ln2, 1); ++ ++ /* y = exp(r) - 1 ~= r + C0 r^2 + C1 r^3 + C2 r^4 + C3 r^5 + C4 r^6. */ ++ svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); ++ svfloat64_t c24 = svld1rq (svptrue_b64 (), &d->c2); ++ ++ svfloat64_t p; ++ svfloat64_t c12 = svmla_lane (sv_f64 (d->c1), r, c24, 0); ++ svfloat64_t c34 = svmla_lane (sv_f64 (d->c3), r, c24, 1); ++ p = svmad_x (pg, c34, r2, c12); ++ p = svmad_x (pg, p, r, sv_f64 (d->c0)); ++ p = svmad_x (pg, p, r2, r); ++ ++ svfloat64_t scale = svexpa (u); ++ svfloat64_t scalem1 = svsub_x (pg, scale, sv_f64 (1.0)); ++ ++ /* We want to construct expm1(x) = (scale - 1) + scale * poly. ++ However, for values of scale close to 1, scale-1 causes large ULP errors ++ due to cancellation. ++ ++ This can be circumvented by using a small lookup for scale-1 ++ when our input is below a certain bound, otherwise we can use FEXPA. ++ ++ This bound is based upon the table size: ++ Bound = (TableSize-1/64) * ln2. ++ The current bound is based upon a table size of 16. */ ++ svbool_t is_small = svaclt (pg, x, FexpaBound); ++ ++ if (svptest_any (pg, is_small)) ++ { ++ /* Index via the input of FEXPA, but we only care about the lower 4 bits. ++ */ ++ svuint64_t base_idx = svand_x (pg, u, 0xf); ++ ++ /* We can use the sign of x as a fifth bit to account for the asymmetry ++ of e^x around 0. */ ++ svuint64_t signBit ++ = svlsl_x (pg, svlsr_x (pg, svreinterpret_u64 (x), 63), 4); ++ svuint64_t idx = svorr_x (pg, base_idx, signBit); ++ ++ /* Lookup values for scale - 1 for small x. */ ++ svfloat64_t lookup = svreinterpret_f64 ( ++ svld1_gather_index (is_small, d->expm1_data, idx)); ++ ++ /* Select the appropriate scale - 1 value based on x. */ ++ scalem1 = svsel (is_small, lookup, scalem1); ++ } ++ ++ svfloat64_t y = svmla_x (pg, scalem1, scale, p); ++ ++ /* FEXPA returns nan for large inputs so we special case those. */ ++ if (__glibc_unlikely (svptest_any (pg, special))) ++ { ++ /* FEXPA zeroes the sign bit, however the sign is meaningful to the ++ special case function so needs to be copied. ++ e = sign bit of u << 46. */ ++ svuint64_t e = svand_x (pg, svlsl_x (pg, u, 46), 0x8000000000000000); ++ /* Copy sign to s. */ ++ scale = svreinterpret_f64 (svadd_x (pg, e, svreinterpret_u64 (scale))); ++ return special_case (pg, y, scale, p, n); ++ } ++ ++ /* return expm1 = (scale - 1) + (scale * poly). */ + return y; + } + +commit a79fbf10e762ae2cb615d57fd10446e0db95c50f +Author: Dylan Fleming +Date: Wed Jun 18 16:19:22 2025 +0000 + + AArch64: Optimise SVE FP64 Hyperbolics + + Reworke SVE FP64 hyperbolics to use the SVE FEXPA + instruction. + + Also update the special case handelling for large + inputs to be entirely vectorised. + + Performance improvements on Neoverse V1: + + cosh_sve: 19% for |x| < 709, 5x otherwise + sinh_sve: 24% for |x| < 709, 5.9x otherwise + tanh_sve: 12% for |x| < 19, 9x otherwise + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit dee22d2a81ab59afc165fb6dcb45d723f13582a0) + +diff --git a/sysdeps/aarch64/fpu/cosh_sve.c b/sysdeps/aarch64/fpu/cosh_sve.c +index e375dd8a34..3561893ae6 100644 +--- a/sysdeps/aarch64/fpu/cosh_sve.c ++++ b/sysdeps/aarch64/fpu/cosh_sve.c +@@ -21,71 +21,99 @@ + + static const struct data + { +- float64_t poly[3]; +- float64_t inv_ln2, ln2_hi, ln2_lo, shift, thres; ++ double c0, c2; ++ double c1, c3; ++ float64_t inv_ln2, ln2_hi, ln2_lo, shift; + uint64_t special_bound; + } data = { +- .poly = { 0x1.fffffffffffd4p-2, 0x1.5555571d6b68cp-3, +- 0x1.5555576a59599p-5, }, +- +- .inv_ln2 = 0x1.71547652b82fep8, /* N/ln2. */ +- /* -ln2/N. */ +- .ln2_hi = -0x1.62e42fefa39efp-9, +- .ln2_lo = -0x1.abc9e3b39803f3p-64, +- .shift = 0x1.8p+52, +- .thres = 704.0, +- +- /* 0x1.6p9, above which exp overflows. */ +- .special_bound = 0x4086000000000000, ++ /* Generated using Remez, in [-log(2)/128, log(2)/128]. */ ++ .c0 = 0x1.fffffffffdbcdp-2, ++ .c1 = 0x1.555555555444cp-3, ++ .c2 = 0x1.555573c6a9f7dp-5, ++ .c3 = 0x1.1111266d28935p-7, ++ .ln2_hi = 0x1.62e42fefa3800p-1, ++ .ln2_lo = 0x1.ef35793c76730p-45, ++ /* 1/ln2. */ ++ .inv_ln2 = 0x1.71547652b82fep+0, ++ .shift = 0x1.800000000ff80p+46, /* 1.5*2^46+1022. */ ++ ++ /* asuint(ln(2^(1024 - 1/128))), the value above which exp overflows. */ ++ .special_bound = 0x40862e37e7d8ba72, + }; + +-static svfloat64_t NOINLINE +-special_case (svfloat64_t x, svbool_t pg, svfloat64_t t, svbool_t special) +-{ +- svfloat64_t half_t = svmul_x (svptrue_b64 (), t, 0.5); +- svfloat64_t half_over_t = svdivr_x (pg, t, 0.5); +- svfloat64_t y = svadd_x (pg, half_t, half_over_t); +- return sv_call_f64 (cosh, x, y, special); +-} +- +-/* Helper for approximating exp(x). Copied from sv_exp_tail, with no +- special-case handling or tail. */ ++/* Helper for approximating exp(x)/2. ++ Functionally identical to FEXPA exp(x), but an adjustment in ++ the shift value which leads to a reduction in the exponent of scale by 1, ++ thus halving the result at no cost. */ + static inline svfloat64_t +-exp_inline (svfloat64_t x, const svbool_t pg, const struct data *d) ++exp_over_two_inline (const svbool_t pg, svfloat64_t x, const struct data *d) + { + /* Calculate exp(x). */ + svfloat64_t z = svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2); ++ svuint64_t u = svreinterpret_u64 (z); + svfloat64_t n = svsub_x (pg, z, d->shift); + +- svfloat64_t r = svmla_x (pg, x, n, d->ln2_hi); +- r = svmla_x (pg, r, n, d->ln2_lo); ++ svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); ++ svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); + +- svuint64_t u = svreinterpret_u64 (z); +- svuint64_t e = svlsl_x (pg, u, 52 - V_EXP_TAIL_TABLE_BITS); +- svuint64_t i = svand_x (svptrue_b64 (), u, 0xff); ++ svfloat64_t r = x; ++ r = svmls_lane (r, n, ln2, 0); ++ r = svmls_lane (r, n, ln2, 1); + +- svfloat64_t y = svmla_x (pg, sv_f64 (d->poly[1]), r, d->poly[2]); +- y = svmla_x (pg, sv_f64 (d->poly[0]), r, y); +- y = svmla_x (pg, sv_f64 (1.0), r, y); +- y = svmul_x (svptrue_b64 (), r, y); ++ svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), r, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), r, c13, 1); ++ svfloat64_t p04 = svmla_x (pg, p01, p23, r2); ++ svfloat64_t p = svmla_x (pg, r, p04, r2); + +- /* s = 2^(n/N). */ +- u = svld1_gather_index (pg, __v_exp_tail_data, i); +- svfloat64_t s = svreinterpret_f64 (svadd_x (pg, u, e)); ++ svfloat64_t scale = svexpa (u); + +- return svmla_x (pg, s, s, y); ++ return svmla_x (pg, scale, scale, p); ++} ++ ++/* Vectorised special case to handle values past where exp_inline overflows. ++ Halves the input value and uses the identity exp(x) = exp(x/2)^2 to double ++ the valid range of inputs, and returns inf for anything past that. */ ++static svfloat64_t NOINLINE ++special_case (svbool_t pg, svbool_t special, svfloat64_t ax, svfloat64_t t, ++ const struct data *d) ++{ ++ /* Finish fast path to compute values for non-special cases. */ ++ svfloat64_t inv_twoexp = svdivr_x (pg, t, 0.25); ++ svfloat64_t y = svadd_x (pg, t, inv_twoexp); ++ ++ /* Halves input value, and then check if any cases ++ are still going to overflow. */ ++ ax = svmul_x (special, ax, 0.5); ++ svbool_t is_safe ++ = svcmplt (special, svreinterpret_u64 (ax), d->special_bound); ++ ++ /* Computes exp(x/2), and sets any overflowing lanes to inf. */ ++ svfloat64_t half_exp = exp_over_two_inline (special, ax, d); ++ half_exp = svsel (is_safe, half_exp, sv_f64 (INFINITY)); ++ ++ /* Construct special case cosh(x) = (exp(x/2)^2)/2. */ ++ svfloat64_t exp = svmul_x (svptrue_b64 (), half_exp, 2); ++ svfloat64_t special_y = svmul_x (special, exp, half_exp); ++ ++ /* Select correct return values for special and non-special cases. */ ++ special_y = svsel (special, special_y, y); ++ ++ /* Ensure an input of nan is correctly propagated. */ ++ svbool_t is_nan ++ = svcmpgt (special, svreinterpret_u64 (ax), sv_u64 (0x7ff0000000000000)); ++ return svsel (is_nan, ax, svsel (special, special_y, y)); + } + + /* Approximation for SVE double-precision cosh(x) using exp_inline. + cosh(x) = (exp(x) + exp(-x)) / 2. +- The greatest observed error is in the scalar fall-back region, so is the +- same as the scalar routine, 1.93 ULP: +- _ZGVsMxv_cosh (0x1.628ad45039d2fp+9) got 0x1.fd774e958236dp+1021 +- want 0x1.fd774e958236fp+1021. +- +- The greatest observed error in the non-special region is 1.54 ULP: +- _ZGVsMxv_cosh (0x1.ba5651dd4486bp+2) got 0x1.f5e2bb8d5c98fp+8 +- want 0x1.f5e2bb8d5c991p+8. */ ++ The greatest observed error in special case region is 2.66 + 0.5 ULP: ++ _ZGVsMxv_cosh (0x1.633b532ffbc1ap+9) got 0x1.f9b2d3d22399ep+1023 ++ want 0x1.f9b2d3d22399bp+1023 ++ ++ The greatest observed error in the non-special region is 1.01 + 0.5 ULP: ++ _ZGVsMxv_cosh (0x1.998ecbb3c1f81p+1) got 0x1.890b225657f84p+3 ++ want 0x1.890b225657f82p+3. */ + svfloat64_t SV_NAME_D1 (cosh) (svfloat64_t x, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +@@ -94,14 +122,13 @@ svfloat64_t SV_NAME_D1 (cosh) (svfloat64_t x, const svbool_t pg) + svbool_t special = svcmpgt (pg, svreinterpret_u64 (ax), d->special_bound); + + /* Up to the point that exp overflows, we can use it to calculate cosh by +- exp(|x|) / 2 + 1 / (2 * exp(|x|)). */ +- svfloat64_t t = exp_inline (ax, pg, d); ++ (exp(|x|)/2 + 1) / (2 * exp(|x|)). */ ++ svfloat64_t half_exp = exp_over_two_inline (pg, ax, d); + +- /* Fall back to scalar for any special cases. */ ++ /* Falls back to entirely standalone vectorized special case. */ + if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (x, pg, t, special); ++ return special_case (pg, special, ax, half_exp, d); + +- svfloat64_t half_t = svmul_x (svptrue_b64 (), t, 0.5); +- svfloat64_t half_over_t = svdivr_x (pg, t, 0.5); +- return svadd_x (pg, half_t, half_over_t); ++ svfloat64_t inv_twoexp = svdivr_x (pg, half_exp, 0.25); ++ return svadd_x (pg, half_exp, inv_twoexp); + } +diff --git a/sysdeps/aarch64/fpu/sinh_sve.c b/sysdeps/aarch64/fpu/sinh_sve.c +index df5f6c8c06..ac7b306018 100644 +--- a/sysdeps/aarch64/fpu/sinh_sve.c ++++ b/sysdeps/aarch64/fpu/sinh_sve.c +@@ -18,90 +18,153 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[11]; +- float64_t inv_ln2, m_ln2_hi, m_ln2_lo, shift; + uint64_t halff; +- int64_t onef; +- uint64_t large_bound; ++ double c2, c4; ++ double inv_ln2; ++ double ln2_hi, ln2_lo; ++ double c0, c1, c3; ++ double shift, special_bound, bound; ++ uint64_t expm1_data[20]; + } data = { +- /* Generated using Remez, deg=12 in [-log(2)/2, log(2)/2]. */ +- .poly = { 0x1p-1, 0x1.5555555555559p-3, 0x1.555555555554bp-5, +- 0x1.111111110f663p-7, 0x1.6c16c16c1b5f3p-10, +- 0x1.a01a01affa35dp-13, 0x1.a01a018b4ecbbp-16, +- 0x1.71ddf82db5bb4p-19, 0x1.27e517fc0d54bp-22, +- 0x1.af5eedae67435p-26, 0x1.1f143d060a28ap-29, }, +- +- .inv_ln2 = 0x1.71547652b82fep0, +- .m_ln2_hi = -0x1.62e42fefa39efp-1, +- .m_ln2_lo = -0x1.abc9e3b39803fp-56, +- .shift = 0x1.8p52, +- ++ /* Table lookup of 2^(i/64) - 1, for values of i from 0..19. */ ++ .expm1_data = { ++ 0x0000000000000000, 0x3f864d1f3bc03077, 0x3f966c34c5615d0f, 0x3fa0e8a30eb37901, ++ 0x3fa6ab0d9f3121ec, 0x3fac7d865a7a3440, 0x3fb1301d0125b50a, 0x3fb429aaea92ddfb, ++ 0x3fb72b83c7d517ae, 0x3fba35beb6fcb754, 0x3fbd4873168b9aa8, 0x3fc031dc431466b2, ++ 0x3fc1c3d373ab11c3, 0x3fc35a2b2f13e6e9, 0x3fc4f4efa8fef709, 0x3fc6942d3720185a, ++ 0x3fc837f0518db8a9, 0x3fc9e0459320b7fa, 0x3fcb8d39b9d54e55, 0x3fcd3ed9a72cffb7, ++ }, ++ ++ /* Generated using Remez, in [-log(2)/128, log(2)/128]. */ ++ .c0 = 0x1p-1, ++ .c1 = 0x1.55555555548f9p-3, ++ .c2 = 0x1.5555555554c22p-5, ++ .c3 = 0x1.111123aaa2fb2p-7, ++ .c4 = 0x1.6c16d77d98e5bp-10, ++ .ln2_hi = 0x1.62e42fefa3800p-1, ++ .ln2_lo = 0x1.ef35793c76730p-45, ++ .inv_ln2 = 0x1.71547652b82fep+0, ++ .shift = 0x1.800000000ffc0p+46, /* 1.5*2^46+1023. */ + .halff = 0x3fe0000000000000, +- .onef = 0x3ff0000000000000, +- /* 2^9. expm1 helper overflows for large input. */ +- .large_bound = 0x4080000000000000, ++ .special_bound = 0x1.62e37e7d8ba72p+9, /* ln(2^(1024 - 1/128)). */ ++ .bound = 0x1.a56ef8ec924ccp-3 /* 19*ln2/64. */ + }; + ++/* A specialised FEXPA expm1 that is only valid for positive inputs and ++ has no special cases. Based off the full FEXPA expm1 implementated for ++ _ZGVsMxv_expm1, with a slightly modified file to keep sinh under 3.5ULP. */ + static inline svfloat64_t +-expm1_inline (svfloat64_t x, svbool_t pg) ++expm1_inline (svbool_t pg, svfloat64_t x) + { + const struct data *d = ptr_barrier (&data); + +- /* Reduce argument: +- exp(x) - 1 = 2^i * (expm1(f) + 1) - 1 +- where i = round(x / ln2) +- and f = x - i * ln2 (f in [-ln2/2, ln2/2]). */ +- svfloat64_t j +- = svsub_x (pg, svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2), d->shift); +- svint64_t i = svcvt_s64_x (pg, j); +- svfloat64_t f = svmla_x (pg, x, j, d->m_ln2_hi); +- f = svmla_x (pg, f, j, d->m_ln2_lo); +- /* Approximate expm1(f) using polynomial. */ +- svfloat64_t f2 = svmul_x (pg, f, f); +- svfloat64_t f4 = svmul_x (pg, f2, f2); +- svfloat64_t f8 = svmul_x (pg, f4, f4); +- svfloat64_t p +- = svmla_x (pg, f, f2, sv_estrin_10_f64_x (pg, f, f2, f4, f8, d->poly)); +- /* t = 2^i. */ +- svfloat64_t t = svscale_x (pg, sv_f64 (1), i); +- /* expm1(x) ~= p * t + (t - 1). */ +- return svmla_x (pg, svsub_x (pg, t, 1.0), p, t); ++ svfloat64_t z = svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2); ++ svuint64_t u = svreinterpret_u64 (z); ++ svfloat64_t n = svsub_x (pg, z, d->shift); ++ ++ svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); ++ svfloat64_t c24 = svld1rq (svptrue_b64 (), &d->c2); ++ ++ svfloat64_t r = x; ++ r = svmls_lane (r, n, ln2, 0); ++ r = svmls_lane (r, n, ln2, 1); ++ ++ svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); ++ ++ svfloat64_t p; ++ svfloat64_t c12 = svmla_lane (sv_f64 (d->c1), r, c24, 0); ++ svfloat64_t c34 = svmla_lane (sv_f64 (d->c3), r, c24, 1); ++ p = svmad_x (pg, c34, r2, c12); ++ p = svmad_x (pg, p, r, sv_f64 (d->c0)); ++ p = svmad_x (pg, p, r2, r); ++ ++ svfloat64_t scale = svexpa (u); ++ ++ /* We want to construct expm1(x) = (scale - 1) + scale * poly. ++ However, for values of scale close to 1, scale-1 causes large ULP errors ++ due to cancellation. ++ ++ This can be circumvented by using a small lookup for scale-1 ++ when our input is below a certain bound, otherwise we can use FEXPA. */ ++ svbool_t is_small = svaclt (pg, x, d->bound); ++ ++ /* Index via the input of FEXPA, but we only care about the lower 5 bits. */ ++ svuint64_t base_idx = svand_x (pg, u, 0x1f); ++ ++ /* Compute scale - 1 from FEXPA, and lookup values where this fails. */ ++ svfloat64_t scalem1_estimate = svsub_x (pg, scale, sv_f64 (1.0)); ++ svuint64_t scalem1_lookup ++ = svld1_gather_index (is_small, d->expm1_data, base_idx); ++ ++ /* Select the appropriate scale - 1 value based on x. */ ++ svfloat64_t scalem1 ++ = svsel (is_small, svreinterpret_f64 (scalem1_lookup), scalem1_estimate); ++ ++ /* return expm1 = scale - 1 + (scale * poly). */ ++ return svmla_x (pg, scalem1, scale, p); + } + ++/* Vectorised special case to handle values past where exp_inline overflows. ++ Halves the input value and uses the identity exp(x) = exp(x/2)^2 to double ++ the valid range of inputs, and returns inf for anything past that. */ + static svfloat64_t NOINLINE +-special_case (svfloat64_t x, svbool_t pg) ++special_case (svbool_t pg, svbool_t special, svfloat64_t ax, ++ svfloat64_t halfsign, const struct data *d) + { +- return sv_call_f64 (sinh, x, x, pg); ++ /* Halves input value, and then check if any cases ++ are still going to overflow. */ ++ ax = svmul_x (special, ax, 0.5); ++ svbool_t is_safe = svaclt (special, ax, d->special_bound); ++ ++ svfloat64_t t = expm1_inline (pg, ax); ++ ++ /* Finish fastpass to compute values for non-special cases. */ ++ svfloat64_t y = svadd_x (pg, t, svdiv_x (pg, t, svadd_x (pg, t, 1.0))); ++ y = svmul_x (pg, y, halfsign); ++ ++ /* Computes special lane, and set remaining overflow lanes to inf. */ ++ svfloat64_t half_special_y = svmul_x (svptrue_b64 (), t, halfsign); ++ svfloat64_t special_y = svmul_x (svptrue_b64 (), half_special_y, t); ++ ++ svuint64_t signed_inf ++ = svorr_x (svptrue_b64 (), svreinterpret_u64 (halfsign), ++ sv_u64 (0x7ff0000000000000)); ++ special_y = svsel (is_safe, special_y, svreinterpret_f64 (signed_inf)); ++ ++ /* Join resulting vectors together and return. */ ++ return svsel (special, special_y, y); + } + +-/* Approximation for SVE double-precision sinh(x) using expm1. +- sinh(x) = (exp(x) - exp(-x)) / 2. +- The greatest observed error is 2.57 ULP: +- _ZGVsMxv_sinh (0x1.a008538399931p-2) got 0x1.ab929fc64bd66p-2 +- want 0x1.ab929fc64bd63p-2. */ ++/* Approximation for SVE double-precision sinh(x) using FEXPA expm1. ++ Uses sinh(x) = e^2x - 1 / 2e^x, rewritten for accuracy. ++ The greatest observed error in the non-special region is 2.63 + 0.5 ULP: ++ _ZGVsMxv_sinh (0x1.b5e0e13ba88aep-2) got 0x1.c3587faf97b0cp-2 ++ want 0x1.c3587faf97b09p-2 ++ ++ The greatest observed error in the special region is 2.65 + 0.5 ULP: ++ _ZGVsMxv_sinh (0x1.633ce847dab1ap+9) got 0x1.fffd30eea0066p+1023 ++ want 0x1.fffd30eea0063p+1023. */ + svfloat64_t SV_NAME_D1 (sinh) (svfloat64_t x, svbool_t pg) + { + const struct data *d = ptr_barrier (&data); + ++ svbool_t special = svacge (pg, x, d->special_bound); + svfloat64_t ax = svabs_x (pg, x); + svuint64_t sign + = sveor_x (pg, svreinterpret_u64 (x), svreinterpret_u64 (ax)); + svfloat64_t halfsign = svreinterpret_f64 (svorr_x (pg, sign, d->halff)); + +- svbool_t special = svcmpge (pg, svreinterpret_u64 (ax), d->large_bound); +- + /* Fall back to scalar variant for all lanes if any are special. */ + if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (x, pg); ++ return special_case (pg, special, ax, halfsign, d); + + /* Up to the point that expm1 overflows, we can use it to calculate sinh + using a slight rearrangement of the definition of sinh. This allows us to + retain acceptable accuracy for very small inputs. */ +- svfloat64_t t = expm1_inline (ax, pg); ++ svfloat64_t t = expm1_inline (pg, ax); + t = svadd_x (pg, t, svdiv_x (pg, t, svadd_x (pg, t, 1.0))); + return svmul_x (pg, t, halfsign); + } +diff --git a/sysdeps/aarch64/fpu/tanh_sve.c b/sysdeps/aarch64/fpu/tanh_sve.c +index d25e011cea..805669845d 100644 +--- a/sysdeps/aarch64/fpu/tanh_sve.c ++++ b/sysdeps/aarch64/fpu/tanh_sve.c +@@ -18,83 +18,117 @@ + . */ + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct data + { +- float64_t poly[11]; +- float64_t inv_ln2, ln2_hi, ln2_lo, shift; +- uint64_t thresh, tiny_bound; ++ double ln2_hi, ln2_lo; ++ double c2, c4; ++ double c0, c1, c3; ++ double two_over_ln2, shift; ++ uint64_t tiny_bound; ++ double large_bound, fexpa_bound; ++ uint64_t e2xm1_data[20]; + } data = { +- /* Generated using Remez, deg=12 in [-log(2)/2, log(2)/2]. */ +- .poly = { 0x1p-1, 0x1.5555555555559p-3, 0x1.555555555554bp-5, +- 0x1.111111110f663p-7, 0x1.6c16c16c1b5f3p-10, +- 0x1.a01a01affa35dp-13, 0x1.a01a018b4ecbbp-16, +- 0x1.71ddf82db5bb4p-19, 0x1.27e517fc0d54bp-22, +- 0x1.af5eedae67435p-26, 0x1.1f143d060a28ap-29, }, +- +- .inv_ln2 = 0x1.71547652b82fep0, +- .ln2_hi = -0x1.62e42fefa39efp-1, +- .ln2_lo = -0x1.abc9e3b39803fp-56, +- .shift = 0x1.8p52, +- ++ /* Generated using Remez, in [-log(2)/128, log(2)/128]. */ ++ .c0 = 0x1p-1, ++ .c1 = 0x1.55555555548f9p-3, ++ .c2 = 0x1.5555555554c22p-5, ++ .c3 = 0x1.111123aaa2fb2p-7, ++ .c4 = 0x1.6c16d77d98e5bp-10, ++ .ln2_hi = 0x1.62e42fefa3800p-1, ++ .ln2_lo = 0x1.ef35793c76730p-45, ++ .two_over_ln2 = 0x1.71547652b82fep+1, ++ .shift = 0x1.800000000ffc0p+46, /* 1.5*2^46+1023. */ + .tiny_bound = 0x3e40000000000000, /* asuint64 (0x1p-27). */ +- /* asuint64(0x1.241bf835f9d5fp+4) - asuint64(tiny_bound). */ +- .thresh = 0x01f241bf835f9d5f, ++ .large_bound = 0x1.30fc1931f09cap+4, /* arctanh(1 - 2^-54). */ ++ .fexpa_bound = 0x1.a56ef8ec924ccp-4, /* 19/64 * ln2/2. */ ++ /* Table lookup of 2^(i/64) - 1, for values of i from 0..19. */ ++ .e2xm1_data = { ++ 0x0000000000000000, 0x3f864d1f3bc03077, 0x3f966c34c5615d0f, 0x3fa0e8a30eb37901, ++ 0x3fa6ab0d9f3121ec, 0x3fac7d865a7a3440, 0x3fb1301d0125b50a, 0x3fb429aaea92ddfb, ++ 0x3fb72b83c7d517ae, 0x3fba35beb6fcb754, 0x3fbd4873168b9aa8, 0x3fc031dc431466b2, ++ 0x3fc1c3d373ab11c3, 0x3fc35a2b2f13e6e9, 0x3fc4f4efa8fef709, 0x3fc6942d3720185a, ++ 0x3fc837f0518db8a9, 0x3fc9e0459320b7fa, 0x3fcb8d39b9d54e55, 0x3fcd3ed9a72cffb7, ++ }, + }; + ++/* An expm1 inspired, FEXPA based helper function that returns an ++ accurate estimate for e^2x - 1. With no special case or support for ++ negative inputs of x. */ + static inline svfloat64_t +-expm1_inline (svfloat64_t x, const svbool_t pg, const struct data *d) +-{ +- /* Helper routine for calculating exp(x) - 1. Vector port of the helper from +- the scalar variant of tanh. */ +- +- /* Reduce argument: f in [-ln2/2, ln2/2], i is exact. */ +- svfloat64_t j +- = svsub_x (pg, svmla_x (pg, sv_f64 (d->shift), x, d->inv_ln2), d->shift); +- svint64_t i = svcvt_s64_x (pg, j); +- svfloat64_t f = svmla_x (pg, x, j, d->ln2_hi); +- f = svmla_x (pg, f, j, d->ln2_lo); +- +- /* Approximate expm1(f) using polynomial. */ +- svfloat64_t f2 = svmul_x (pg, f, f); +- svfloat64_t f4 = svmul_x (pg, f2, f2); +- svfloat64_t p = svmla_x ( +- pg, f, f2, +- sv_estrin_10_f64_x (pg, f, f2, f4, svmul_x (pg, f4, f4), d->poly)); +- +- /* t = 2 ^ i. */ +- svfloat64_t t = svscale_x (pg, sv_f64 (1), i); +- /* expm1(x) = p * t + (t - 1). */ +- return svmla_x (pg, svsub_x (pg, t, 1), p, t); +-} +- +-static svfloat64_t NOINLINE +-special_case (svfloat64_t x, svfloat64_t y, svbool_t special) ++e2xm1_inline (const svbool_t pg, svfloat64_t x, const struct data *d) + { +- return sv_call_f64 (tanh, x, y, special); ++ svfloat64_t z = svmla_x (pg, sv_f64 (d->shift), x, d->two_over_ln2); ++ svuint64_t u = svreinterpret_u64 (z); ++ svfloat64_t n = svsub_x (pg, z, d->shift); ++ ++ /* r = x - n * ln2/2, r is in [-ln2/(2N), ln2/(2N)]. */ ++ svfloat64_t ln2 = svld1rq (svptrue_b64 (), &d->ln2_hi); ++ svfloat64_t r = svadd_x (pg, x, x); ++ r = svmls_lane (r, n, ln2, 0); ++ r = svmls_lane (r, n, ln2, 1); ++ ++ /* y = exp(r) - 1 ~= r + C0 r^2 + C1 r^3 + C2 r^4 + C3 r^5 + C4 r^6. */ ++ svfloat64_t r2 = svmul_x (svptrue_b64 (), r, r); ++ svfloat64_t c24 = svld1rq (svptrue_b64 (), &d->c2); ++ ++ svfloat64_t p; ++ svfloat64_t c12 = svmla_lane (sv_f64 (d->c1), r, c24, 0); ++ svfloat64_t c34 = svmla_lane (sv_f64 (d->c3), r, c24, 1); ++ p = svmad_x (pg, c34, r2, c12); ++ p = svmad_x (pg, p, r, sv_f64 (d->c0)); ++ p = svmad_x (pg, p, r2, r); ++ ++ svfloat64_t scale = svexpa (u); ++ ++ /* We want to construct e2xm1(x) = (scale - 1) + scale * poly. ++ However, for values of scale close to 1, scale-1 causes large ULP errors ++ due to cancellation. ++ ++ This can be circumvented by using a small lookup for scale-1 ++ when our input is below a certain bound, otherwise we can use FEXPA. */ ++ svbool_t is_small = svaclt (pg, x, d->fexpa_bound); ++ ++ /* Index via the input of FEXPA, but we only care about the lower 5 bits. */ ++ svuint64_t base_idx = svand_x (pg, u, 0x1f); ++ ++ /* Compute scale - 1 from FEXPA, and lookup values where this fails. */ ++ svfloat64_t scalem1_estimate = svsub_x (pg, scale, sv_f64 (1.0)); ++ svuint64_t scalem1_lookup ++ = svld1_gather_index (is_small, d->e2xm1_data, base_idx); ++ ++ /* Select the appropriate scale - 1 value based on x. */ ++ svfloat64_t scalem1 ++ = svsel (is_small, svreinterpret_f64 (scalem1_lookup), scalem1_estimate); ++ return svmla_x (pg, scalem1, scale, p); + } + +-/* SVE approximation for double-precision tanh(x), using a simplified +- version of expm1. The greatest observed error is 2.77 ULP: +- _ZGVsMxv_tanh(-0x1.c4a4ca0f9f3b7p-3) got -0x1.bd6a21a163627p-3 +- want -0x1.bd6a21a163624p-3. */ ++/* SVE approximation for double-precision tanh(x), using a modified version of ++ FEXPA expm1 to calculate e^2x - 1. ++ The greatest observed error is 2.79 + 0.5 ULP: ++ _ZGVsMxv_tanh (0x1.fff868eb3c223p-9) got 0x1.fff7be486cae6p-9 ++ want 0x1.fff7be486cae9p-9. */ + svfloat64_t SV_NAME_D1 (tanh) (svfloat64_t x, svbool_t pg) + { + const struct data *d = ptr_barrier (&data); + +- svuint64_t ia = svreinterpret_u64 (svabs_x (pg, x)); ++ svbool_t large = svacge (pg, x, d->large_bound); + +- /* Trigger special-cases for tiny, boring and infinity/NaN. */ +- svbool_t special = svcmpgt (pg, svsub_x (pg, ia, d->tiny_bound), d->thresh); ++ /* We can use tanh(x) = (e^2x - 1) / (e^2x + 1) to approximate tanh. ++ As an additional optimisation, we can ensure more accurate values of e^x ++ by only using positive inputs. So we calculate tanh(|x|), and restore the ++ sign of the input before returning. */ ++ svfloat64_t ax = svabs_x (pg, x); ++ svuint64_t sign_bit ++ = sveor_x (pg, svreinterpret_u64 (x), svreinterpret_u64 (ax)); + +- svfloat64_t u = svadd_x (pg, x, x); ++ svfloat64_t p = e2xm1_inline (pg, ax, d); ++ svfloat64_t q = svadd_x (pg, p, 2); + +- /* tanh(x) = (e^2x - 1) / (e^2x + 1). */ +- svfloat64_t q = expm1_inline (u, pg, d); +- svfloat64_t qp2 = svadd_x (pg, q, 2); ++ /* For sufficiently high inputs, the result of tanh(|x|) is 1 when correctly ++ rounded, at this point we can return 1 directly, with sign correction. ++ This will also act as a guard against our approximation overflowing. */ ++ svfloat64_t y = svsel (large, sv_f64 (1.0), svdiv_x (pg, p, q)); + +- if (__glibc_unlikely (svptest_any (pg, special))) +- return special_case (x, svdiv_x (pg, q, qp2), special); +- return svdiv_x (pg, q, qp2); ++ return svreinterpret_f64 (svorr_x (pg, sign_bit, svreinterpret_u64 (y))); + } + +commit 3e5dfac7cc569117b6998425a259561890c893cd +Author: Luna Lamb +Date: Wed Jun 18 16:12:19 2025 +0000 + + AArch64: Improve codegen SVE log1p helper + + Improve codegen by packing coefficients. + 4% and 2% improvement in throughput microbenchmark on Neoverse V1, for acosh + and atanh respectively. + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 6849c5b791edd216f2ec3fdbe4d138bc69b9b333) + +diff --git a/sysdeps/aarch64/fpu/acosh_sve.c b/sysdeps/aarch64/fpu/acosh_sve.c +index 3e4faaa5ca..78ebcffbb5 100644 +--- a/sysdeps/aarch64/fpu/acosh_sve.c ++++ b/sysdeps/aarch64/fpu/acosh_sve.c +@@ -30,10 +30,10 @@ special_case (svfloat64_t x, svfloat64_t y, svbool_t special) + } + + /* SVE approximation for double-precision acosh, based on log1p. +- The largest observed error is 3.19 ULP in the region where the ++ The largest observed error is 3.14 ULP in the region where the + argument to log1p falls in the k=0 interval, i.e. x close to 1: +- SV_NAME_D1 (acosh)(0x1.1e4388d4ca821p+0) got 0x1.ed23399f5137p-2 +- want 0x1.ed23399f51373p-2. */ ++ SV_NAME_D1 (acosh)(0x1.1e80ed12f0ad1p+0) got 0x1.ef0cee7c33ce1p-2 ++ want 0x1.ef0cee7c33ce4p-2. */ + svfloat64_t SV_NAME_D1 (acosh) (svfloat64_t x, const svbool_t pg) + { + /* (ix - One) >= (BigBound - One). */ +diff --git a/sysdeps/aarch64/fpu/atanh_sve.c b/sysdeps/aarch64/fpu/atanh_sve.c +index 7a52728d70..a4803e5c13 100644 +--- a/sysdeps/aarch64/fpu/atanh_sve.c ++++ b/sysdeps/aarch64/fpu/atanh_sve.c +@@ -30,7 +30,7 @@ special_case (svfloat64_t x, svfloat64_t y, svbool_t special) + } + + /* SVE approximation for double-precision atanh, based on log1p. +- The greatest observed error is 2.81 ULP: ++ The greatest observed error is 3.3 ULP: + _ZGVsMxv_atanh(0x1.ffae6288b601p-6) got 0x1.ffd8ff31b5019p-6 + want 0x1.ffd8ff31b501cp-6. */ + svfloat64_t SV_NAME_D1 (atanh) (svfloat64_t x, const svbool_t pg) +@@ -42,7 +42,6 @@ svfloat64_t SV_NAME_D1 (atanh) (svfloat64_t x, const svbool_t pg) + svfloat64_t halfsign = svreinterpret_f64 (svorr_x (pg, sign, Half)); + + /* It is special if iax >= 1. */ +-// svbool_t special = svcmpge (pg, iax, One); + svbool_t special = svacge (pg, x, 1.0); + + /* Computation is performed based on the following sequence of equality: +diff --git a/sysdeps/aarch64/fpu/sv_log1p_inline.h b/sysdeps/aarch64/fpu/sv_log1p_inline.h +index da019674f9..a9ecd75d19 100644 +--- a/sysdeps/aarch64/fpu/sv_log1p_inline.h ++++ b/sysdeps/aarch64/fpu/sv_log1p_inline.h +@@ -21,11 +21,12 @@ + #define AARCH64_FPU_SV_LOG1P_INLINE_H + + #include "sv_math.h" +-#include "poly_sve_f64.h" + + static const struct sv_log1p_data + { +- double poly[19], ln2[2]; ++ double c0, c2, c4, c6, c8, c10, c12, c14, c16; ++ double c1, c3, c5, c7, c9, c11, c13, c15, c17, c18; ++ double ln2_lo, ln2_hi; + uint64_t hf_rt2_top; + uint64_t one_m_hf_rt2_top; + uint32_t bottom_mask; +@@ -33,15 +34,30 @@ static const struct sv_log1p_data + } sv_log1p_data = { + /* Coefficients generated using Remez, deg=20, in [sqrt(2)/2-1, sqrt(2)-1]. + */ +- .poly = { -0x1.ffffffffffffbp-2, 0x1.55555555551a9p-2, -0x1.00000000008e3p-2, +- 0x1.9999999a32797p-3, -0x1.555555552fecfp-3, 0x1.249248e071e5ap-3, +- -0x1.ffffff8bf8482p-4, 0x1.c71c8f07da57ap-4, -0x1.9999ca4ccb617p-4, +- 0x1.7459ad2e1dfa3p-4, -0x1.554d2680a3ff2p-4, 0x1.3b4c54d487455p-4, +- -0x1.2548a9ffe80e6p-4, 0x1.0f389a24b2e07p-4, -0x1.eee4db15db335p-5, +- 0x1.e95b494d4a5ddp-5, -0x1.15fdf07cb7c73p-4, 0x1.0310b70800fcfp-4, +- -0x1.cfa7385bdb37ep-6 }, +- .ln2 = { 0x1.62e42fefa3800p-1, 0x1.ef35793c76730p-45 }, ++ .c0 = -0x1.ffffffffffffbp-2, ++ .c1 = 0x1.55555555551a9p-2, ++ .c2 = -0x1.00000000008e3p-2, ++ .c3 = 0x1.9999999a32797p-3, ++ .c4 = -0x1.555555552fecfp-3, ++ .c5 = 0x1.249248e071e5ap-3, ++ .c6 = -0x1.ffffff8bf8482p-4, ++ .c7 = 0x1.c71c8f07da57ap-4, ++ .c8 = -0x1.9999ca4ccb617p-4, ++ .c9 = 0x1.7459ad2e1dfa3p-4, ++ .c10 = -0x1.554d2680a3ff2p-4, ++ .c11 = 0x1.3b4c54d487455p-4, ++ .c12 = -0x1.2548a9ffe80e6p-4, ++ .c13 = 0x1.0f389a24b2e07p-4, ++ .c14 = -0x1.eee4db15db335p-5, ++ .c15 = 0x1.e95b494d4a5ddp-5, ++ .c16 = -0x1.15fdf07cb7c73p-4, ++ .c17 = 0x1.0310b70800fcfp-4, ++ .c18 = -0x1.cfa7385bdb37ep-6, ++ .ln2_lo = 0x1.62e42fefa3800p-1, ++ .ln2_hi = 0x1.ef35793c76730p-45, ++ /* top32(asuint64(sqrt(2)/2)) << 32. */ + .hf_rt2_top = 0x3fe6a09e00000000, ++ /* (top32(asuint64(1)) - top32(asuint64(sqrt(2)/2))) << 32. */ + .one_m_hf_rt2_top = 0x00095f6200000000, + .bottom_mask = 0xffffffff, + .one_top = 0x3ff +@@ -51,14 +67,14 @@ static inline svfloat64_t + sv_log1p_inline (svfloat64_t x, const svbool_t pg) + { + /* Helper for calculating log(x + 1). Adapted from v_log1p_inline.h, which +- differs from v_log1p_2u5.c by: ++ differs from advsimd/log1p.c by: + - No special-case handling - this should be dealt with by the caller. + - Pairwise Horner polynomial evaluation for improved accuracy. + - Optionally simulate the shortcut for k=0, used in the scalar routine, + using svsel, for improved accuracy when the argument to log1p is close + to 0. This feature is enabled by defining WANT_SV_LOG1P_K0_SHORTCUT as 1 + in the source of the caller before including this file. +- See sv_log1p_2u1.c for details of the algorithm. */ ++ See sve/log1p.c for details of the algorithm. */ + const struct sv_log1p_data *d = ptr_barrier (&sv_log1p_data); + svfloat64_t m = svadd_x (pg, x, 1); + svuint64_t mi = svreinterpret_u64 (m); +@@ -79,7 +95,7 @@ sv_log1p_inline (svfloat64_t x, const svbool_t pg) + svfloat64_t cm; + + #ifndef WANT_SV_LOG1P_K0_SHORTCUT +-#error \ ++#error \ + "Cannot use sv_log1p_inline.h without specifying whether you need the k0 shortcut for greater accuracy close to 0" + #elif WANT_SV_LOG1P_K0_SHORTCUT + /* Shortcut if k is 0 - set correction term to 0 and f to x. The result is +@@ -96,14 +112,46 @@ sv_log1p_inline (svfloat64_t x, const svbool_t pg) + #endif + + /* Approximate log1p(f) on the reduced input using a polynomial. */ +- svfloat64_t f2 = svmul_x (pg, f, f); +- svfloat64_t p = sv_pw_horner_18_f64_x (pg, f, f2, d->poly); ++ svfloat64_t f2 = svmul_x (svptrue_b64 (), f, f), ++ f4 = svmul_x (svptrue_b64 (), f2, f2), ++ f8 = svmul_x (svptrue_b64 (), f4, f4), ++ f16 = svmul_x (svptrue_b64 (), f8, f8); ++ ++ svfloat64_t c13 = svld1rq (svptrue_b64 (), &d->c1); ++ svfloat64_t c57 = svld1rq (svptrue_b64 (), &d->c5); ++ svfloat64_t c911 = svld1rq (svptrue_b64 (), &d->c9); ++ svfloat64_t c1315 = svld1rq (svptrue_b64 (), &d->c13); ++ svfloat64_t c1718 = svld1rq (svptrue_b64 (), &d->c17); ++ ++ /* Order-18 Estrin scheme. */ ++ svfloat64_t p01 = svmla_lane (sv_f64 (d->c0), f, c13, 0); ++ svfloat64_t p23 = svmla_lane (sv_f64 (d->c2), f, c13, 1); ++ svfloat64_t p45 = svmla_lane (sv_f64 (d->c4), f, c57, 0); ++ svfloat64_t p67 = svmla_lane (sv_f64 (d->c6), f, c57, 1); ++ ++ svfloat64_t p03 = svmla_x (pg, p01, f2, p23); ++ svfloat64_t p47 = svmla_x (pg, p45, f2, p67); ++ svfloat64_t p07 = svmla_x (pg, p03, f4, p47); ++ ++ svfloat64_t p89 = svmla_lane (sv_f64 (d->c8), f, c911, 0); ++ svfloat64_t p1011 = svmla_lane (sv_f64 (d->c10), f, c911, 1); ++ svfloat64_t p1213 = svmla_lane (sv_f64 (d->c12), f, c1315, 0); ++ svfloat64_t p1415 = svmla_lane (sv_f64 (d->c14), f, c1315, 1); ++ ++ svfloat64_t p811 = svmla_x (pg, p89, f2, p1011); ++ svfloat64_t p1215 = svmla_x (pg, p1213, f2, p1415); ++ svfloat64_t p815 = svmla_x (pg, p811, f4, p1215); ++ ++ svfloat64_t p015 = svmla_x (pg, p07, f8, p815); ++ svfloat64_t p1617 = svmla_lane (sv_f64 (d->c16), f, c1718, 0); ++ svfloat64_t p1618 = svmla_lane (p1617, f2, c1718, 1); ++ svfloat64_t p = svmla_x (pg, p015, f16, p1618); + + /* Assemble log1p(x) = k * log2 + log1p(f) + c/m. */ +- svfloat64_t ylo = svmla_x (pg, cm, k, d->ln2[0]); +- svfloat64_t yhi = svmla_x (pg, f, k, d->ln2[1]); ++ svfloat64_t ln2_lo_hi = svld1rq (svptrue_b64 (), &d->ln2_lo); ++ svfloat64_t ylo = svmla_lane (cm, k, ln2_lo_hi, 0); ++ svfloat64_t yhi = svmla_lane (f, k, ln2_lo_hi, 1); + +- return svmla_x (pg, svadd_x (pg, ylo, yhi), f2, p); ++ return svmad_x (pg, p, f2, svadd_x (pg, ylo, yhi)); + } +- + #endif + +commit e8ac8a9844ba6ef92d49354c103c1320fcfc0087 +Author: Florian Weimer +Date: Sat Feb 1 12:37:58 2025 +0100 + + elf: Do not add a copy of _dl_find_object to libc.so + + This reduces code size and dependencies on ld.so internals from + libc.so. + + Fixes commit f4c142bb9fe6b02c0af8cfca8a920091e2dba44b + ("arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)"). + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 96429bcc91a14f71b177ddc5e716de3069060f2c) + +diff --git a/elf/Makefile b/elf/Makefile +index afd4eb6fdd..5abf61758d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -34,7 +34,6 @@ routines = \ + dl-addr \ + dl-addr-obj \ + dl-early_allocate \ +- dl-find_object \ + dl-iteratephdr \ + dl-libc \ + dl-origin \ +@@ -61,6 +60,7 @@ dl-routines = \ + dl-deps \ + dl-exception \ + dl-execstack \ ++ dl-find_object \ + dl-fini \ + dl-init \ + dl-load \ +diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c +index ae18b438d3..2e41fd064a 100644 +--- a/elf/dl-find_object.c ++++ b/elf/dl-find_object.c +@@ -356,7 +356,7 @@ _dlfo_lookup (uintptr_t pc, struct dl_find_object_internal *first1, size_t size) + } + + int +-__dl_find_object (void *pc1, struct dl_find_object *result) ++_dl_find_object (void *pc1, struct dl_find_object *result) + { + uintptr_t pc = (uintptr_t) pc1; + +@@ -463,8 +463,7 @@ __dl_find_object (void *pc1, struct dl_find_object *result) + return -1; + } /* Transaction retry loop. */ + } +-hidden_def (__dl_find_object) +-weak_alias (__dl_find_object, _dl_find_object) ++rtld_hidden_def (_dl_find_object) + + /* _dlfo_process_initial is called twice. First to compute the array + sizes from the initial loaded mappings. Second to fill in the +diff --git a/include/dlfcn.h b/include/dlfcn.h +index f49ee1b0c9..a44420fa37 100644 +--- a/include/dlfcn.h ++++ b/include/dlfcn.h +@@ -4,8 +4,7 @@ + #include /* For ElfW. */ + #include + +-extern __typeof (_dl_find_object) __dl_find_object; +-hidden_proto (__dl_find_object) ++rtld_hidden_proto (_dl_find_object) + + /* Internally used flag. */ + #define __RTLD_DLOPEN 0x80000000 +diff --git a/sysdeps/arm/find_exidx.c b/sysdeps/arm/find_exidx.c +index a924d59b9f..4257c26838 100644 +--- a/sysdeps/arm/find_exidx.c ++++ b/sysdeps/arm/find_exidx.c +@@ -15,6 +15,7 @@ + License along with the GNU C Library. If not, see + . */ + ++#include + #include + + /* Find the exception index table containing PC. */ +@@ -23,7 +24,7 @@ _Unwind_Ptr + __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount) + { + struct dl_find_object data; +- if (__dl_find_object ((void *) pc, &data) < 0) ++ if (GLRO(dl_find_object) ((void *) pc, &data) < 0) + return 0; + *pcount = data.dlfo_eh_count; + return (_Unwind_Ptr) data.dlfo_eh_frame; + +commit 0e1fea8879c82769540a3c6bdc14c6a49798a2f7 +Author: Florian Weimer +Date: Fri Aug 1 10:20:23 2025 +0200 + + elf: Extract rtld_setup_phdr function from dl_main + + Remove historic binutils reference from comment and update + how this data is used by applications. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 2cac9559e06044ba520e785c151fbbd25011865f) + +diff --git a/elf/rtld.c b/elf/rtld.c +index 09b9c9993b..6f50aeeafc 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1284,6 +1284,37 @@ rtld_setup_main_map (struct link_map *main_map) + return has_interp; + } + ++/* Set up the program header information for the dynamic linker ++ itself. It can be accessed via _r_debug and dl_iterate_phdr ++ callbacks. */ ++static void ++rtld_setup_phdr (void) ++{ ++ /* Starting from binutils-2.23, the linker will define the magic ++ symbol __ehdr_start to point to our own ELF header if it is ++ visible in a segment that also includes the phdrs. */ ++ ++ const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start; ++ assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr); ++ assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr))); ++ ++ const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff; ++ ++ GL(dl_rtld_map).l_phdr = rtld_phdr; ++ GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum; ++ ++ ++ /* PT_GNU_RELRO is usually the last phdr. */ ++ size_t cnt = rtld_ehdr->e_phnum; ++ while (cnt-- > 0) ++ if (rtld_phdr[cnt].p_type == PT_GNU_RELRO) ++ { ++ GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr; ++ GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz; ++ break; ++ } ++} ++ + /* Adjusts the contents of the stack and related globals for the user + entry point. The ld.so processed skip_args arguments and bumped + _dl_argv and _dl_argc accordingly. Those arguments are removed from +@@ -1750,33 +1781,7 @@ dl_main (const ElfW(Phdr) *phdr, + ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded; + ++GL(dl_load_adds); + +- /* Starting from binutils-2.23, the linker will define the magic symbol +- __ehdr_start to point to our own ELF header if it is visible in a +- segment that also includes the phdrs. If that's not available, we use +- the old method that assumes the beginning of the file is part of the +- lowest-addressed PT_LOAD segment. */ +- +- /* Set up the program header information for the dynamic linker +- itself. It is needed in the dl_iterate_phdr callbacks. */ +- const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start; +- assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr); +- assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr))); +- +- const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff; +- +- GL(dl_rtld_map).l_phdr = rtld_phdr; +- GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum; +- +- +- /* PT_GNU_RELRO is usually the last phdr. */ +- size_t cnt = rtld_ehdr->e_phnum; +- while (cnt-- > 0) +- if (rtld_phdr[cnt].p_type == PT_GNU_RELRO) +- { +- GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr; +- GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz; +- break; +- } ++ rtld_setup_phdr (); + + /* Add the dynamic linker to the TLS list if it also uses TLS. */ + if (GL(dl_rtld_map).l_tls_blocksize != 0) + +commit 2193f42655a9687ce66362905add03a4cfbc580e +Author: Florian Weimer +Date: Fri Aug 1 12:19:49 2025 +0200 + + elf: Handle ld.so with LOAD segment gaps in _dl_find_object (bug 31943) + + Detect if ld.so not contiguous and handle that case in _dl_find_object. + Set l_find_object_processed even for initially loaded link maps, + otherwise dlopen of an initially loaded object adds it to + _dlfo_loaded_mappings (where maps are expected to be contiguous), + in addition to _dlfo_nodelete_mappings. + + Test elf/tst-link-map-contiguous-ldso iterates over the loader + image, reading every word to make sure memory is actually mapped. + It only does that if the l_contiguous flag is set for the link map. + Otherwise, it finds gaps with mmap and checks that _dl_find_object + does not return the ld.so mapping for them. + + The test elf/tst-link-map-contiguous-main does the same thing for + the libc.so shared object. This only works if the kernel loaded + the main program because the glibc dynamic loader may fill + the gaps with PROT_NONE mappings in some cases, making it contiguous, + but accesses to individual words may still fault. + + Test elf/tst-link-map-contiguous-libc is again slightly different + because the dynamic loader always fills the gaps with PROT_NONE + mappings, so a different form of probing has to be used. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 20681be149b9eb1b6c1f4246bf4bd801221c86cd) + +diff --git a/NEWS b/NEWS +index 253b07ae99..1b3fd48158 100644 +--- a/NEWS ++++ b/NEWS +@@ -14,6 +14,7 @@ The following bugs are resolved with this release: + [31394] clone on sparc might fail with -EFAULT for no valid reason + [31717] elf: Avoid re-initializing already allocated TLS in dlopen + [31890] resolv: Allow short error responses to match any DNS query ++ [31943] _dl_find_object can fail if ld.so contains gaps between load segments + [31968] mremap implementation in C does not handle arguments correctly + [32026] strerror/strsignal TLS not handled correctly for secondary namespaces + [32052] Name space violation in fortify wrappers +diff --git a/elf/Makefile b/elf/Makefile +index 5abf61758d..b0b8c3aaf6 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -515,6 +515,8 @@ tests-internal += \ + tst-dl_find_object \ + tst-dl_find_object-threads \ + tst-dlmopen2 \ ++ tst-link-map-contiguous-ldso \ ++ tst-link-map-contiguous-libc \ + tst-ptrguard1 \ + tst-stackguard1 \ + tst-tls-surplus \ +@@ -526,6 +528,10 @@ tests-internal += \ + unload2 \ + # tests-internal + ++ifeq ($(build-hardcoded-path-in-tests),yes) ++tests-internal += tst-link-map-contiguous-main ++endif ++ + tests-container += \ + tst-dlopen-self-container \ + tst-dlopen-tlsmodid-container \ +diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c +index 2e41fd064a..f258665a71 100644 +--- a/elf/dl-find_object.c ++++ b/elf/dl-find_object.c +@@ -465,6 +465,37 @@ _dl_find_object (void *pc1, struct dl_find_object *result) + } + rtld_hidden_def (_dl_find_object) + ++/* Subroutine of _dlfo_process_initial to split out noncontigous link ++ maps. NODELETE is the number of used _dlfo_nodelete_mappings ++ elements. It is incremented as needed, and the new NODELETE value ++ is returned. */ ++static size_t ++_dlfo_process_initial_noncontiguous_map (struct link_map *map, ++ size_t nodelete) ++{ ++ struct dl_find_object_internal dlfo; ++ _dl_find_object_from_map (map, &dlfo); ++ ++ /* PT_LOAD segments for a non-contiguous link map are added to the ++ non-closeable mappings. */ ++ const ElfW(Phdr) *ph = map->l_phdr; ++ const ElfW(Phdr) *ph_end = map->l_phdr + map->l_phnum; ++ for (; ph < ph_end; ++ph) ++ if (ph->p_type == PT_LOAD) ++ { ++ if (_dlfo_nodelete_mappings != NULL) ++ { ++ /* Second pass only. */ ++ _dlfo_nodelete_mappings[nodelete] = dlfo; ++ ElfW(Addr) start = ph->p_vaddr + map->l_addr; ++ _dlfo_nodelete_mappings[nodelete].map_start = start; ++ _dlfo_nodelete_mappings[nodelete].map_end = start + ph->p_memsz; ++ } ++ ++nodelete; ++ } ++ return nodelete; ++} ++ + /* _dlfo_process_initial is called twice. First to compute the array + sizes from the initial loaded mappings. Second to fill in the + bases and infos arrays with the (still unsorted) data. Returns the +@@ -476,29 +507,8 @@ _dlfo_process_initial (void) + + size_t nodelete = 0; + if (!main_map->l_contiguous) +- { +- struct dl_find_object_internal dlfo; +- _dl_find_object_from_map (main_map, &dlfo); +- +- /* PT_LOAD segments for a non-contiguous are added to the +- non-closeable mappings. */ +- for (const ElfW(Phdr) *ph = main_map->l_phdr, +- *ph_end = main_map->l_phdr + main_map->l_phnum; +- ph < ph_end; ++ph) +- if (ph->p_type == PT_LOAD) +- { +- if (_dlfo_nodelete_mappings != NULL) +- { +- /* Second pass only. */ +- _dlfo_nodelete_mappings[nodelete] = dlfo; +- _dlfo_nodelete_mappings[nodelete].map_start +- = ph->p_vaddr + main_map->l_addr; +- _dlfo_nodelete_mappings[nodelete].map_end +- = _dlfo_nodelete_mappings[nodelete].map_start + ph->p_memsz; +- } +- ++nodelete; +- } +- } ++ /* Contiguous case already handled in _dl_find_object_init. */ ++ nodelete = _dlfo_process_initial_noncontiguous_map (main_map, nodelete); + + size_t loaded = 0; + for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns) +@@ -510,11 +520,22 @@ _dlfo_process_initial (void) + /* lt_library link maps are implicitly NODELETE. */ + if (l->l_type == lt_library || l->l_nodelete_active) + { +- if (_dlfo_nodelete_mappings != NULL) +- /* Second pass only. */ +- _dl_find_object_from_map +- (l, _dlfo_nodelete_mappings + nodelete); +- ++nodelete; ++ /* The kernel may have loaded ld.so with gaps. */ ++ if (!l->l_contiguous ++#ifdef SHARED ++ && l == &GL(dl_rtld_map) ++#endif ++ ) ++ nodelete ++ = _dlfo_process_initial_noncontiguous_map (l, nodelete); ++ else ++ { ++ if (_dlfo_nodelete_mappings != NULL) ++ /* Second pass only. */ ++ _dl_find_object_from_map ++ (l, _dlfo_nodelete_mappings + nodelete); ++ ++nodelete; ++ } + } + else if (l->l_type == lt_loaded) + { +@@ -764,7 +785,6 @@ _dl_find_object_update_1 (struct link_map **loaded, size_t count) + /* Prefer newly loaded link map. */ + assert (loaded_index1 > 0); + _dl_find_object_from_map (loaded[loaded_index1 - 1], dlfo); +- loaded[loaded_index1 - 1]->l_find_object_processed = 1; + --loaded_index1; + } + +diff --git a/elf/dl-find_object.h b/elf/dl-find_object.h +index 0915065be0..8894c6657c 100644 +--- a/elf/dl-find_object.h ++++ b/elf/dl-find_object.h +@@ -87,7 +87,7 @@ _dl_find_object_to_external (struct dl_find_object_internal *internal, + } + + /* Extract the object location data from a link map and writes it to +- *RESULT using relaxed MO stores. */ ++ *RESULT using relaxed MO stores. Set L->l_find_object_processed. */ + static void __attribute__ ((unused)) + _dl_find_object_from_map (struct link_map *l, + struct dl_find_object_internal *result) +@@ -100,6 +100,8 @@ _dl_find_object_from_map (struct link_map *l, + atomic_store_relaxed (&result->eh_dbase, (void *) l->l_info[DT_PLTGOT]); + #endif + ++ l->l_find_object_processed = 1; ++ + for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum; + ph < ph_end; ++ph) + if (ph->p_type == DLFO_EH_SEGMENT_TYPE) +diff --git a/elf/rtld.c b/elf/rtld.c +index 6f50aeeafc..e577006708 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1286,7 +1286,7 @@ rtld_setup_main_map (struct link_map *main_map) + + /* Set up the program header information for the dynamic linker + itself. It can be accessed via _r_debug and dl_iterate_phdr +- callbacks. */ ++ callbacks, and it is used by _dl_find_object. */ + static void + rtld_setup_phdr (void) + { +@@ -1304,6 +1304,29 @@ rtld_setup_phdr (void) + GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum; + + ++ GL(dl_rtld_map).l_contiguous = 1; ++ /* The linker may not have produced a contiguous object. The kernel ++ will load the object with actual gaps (unlike the glibc loader ++ for shared objects, which always produces a contiguous mapping). ++ See similar logic in rtld_setup_main_map above. */ ++ { ++ ElfW(Addr) expected_load_address = 0; ++ for (const ElfW(Phdr) *ph = rtld_phdr; ph < &rtld_phdr[rtld_ehdr->e_phnum]; ++ ++ph) ++ if (ph->p_type == PT_LOAD) ++ { ++ ElfW(Addr) mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1); ++ if (GL(dl_rtld_map).l_contiguous && expected_load_address != 0 ++ && expected_load_address != mapstart) ++ GL(dl_rtld_map).l_contiguous = 0; ++ ElfW(Addr) allocend = ph->p_vaddr + ph->p_memsz; ++ /* The next expected address is the page following this load ++ segment. */ ++ expected_load_address = ((allocend + GLRO(dl_pagesize) - 1) ++ & ~(GLRO(dl_pagesize) - 1)); ++ } ++ } ++ + /* PT_GNU_RELRO is usually the last phdr. */ + size_t cnt = rtld_ehdr->e_phnum; + while (cnt-- > 0) +diff --git a/elf/tst-link-map-contiguous-ldso.c b/elf/tst-link-map-contiguous-ldso.c +new file mode 100644 +index 0000000000..04de808bb2 +--- /dev/null ++++ b/elf/tst-link-map-contiguous-ldso.c +@@ -0,0 +1,98 @@ ++/* Check that _dl_find_object behavior matches up with gaps. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct link_map *l = xdlopen (LD_SO, RTLD_NOW); ++ if (!l->l_contiguous) ++ { ++ puts ("info: ld.so link map is not contiguous"); ++ ++ /* Try to find holes by probing with mmap. */ ++ int pagesize = getpagesize (); ++ bool gap_found = false; ++ ElfW(Addr) addr = l->l_map_start; ++ TEST_COMPARE (addr % pagesize, 0); ++ while (addr < l->l_map_end) ++ { ++ void *expected = (void *) addr; ++ void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1); ++ struct dl_find_object dlfo; ++ int dlfo_ret = _dl_find_object (expected, &dlfo); ++ if (ptr == expected) ++ { ++ if (dlfo_ret < 0) ++ { ++ TEST_COMPARE (dlfo_ret, -1); ++ printf ("info: hole without mapping data found at %p\n", ptr); ++ } ++ else ++ FAIL ("object \"%s\" found in gap at %p", ++ dlfo.dlfo_link_map->l_name, ptr); ++ gap_found = true; ++ } ++ else if (dlfo_ret == 0) ++ { ++ if ((void *) dlfo.dlfo_link_map != (void *) l) ++ { ++ printf ("info: object \"%s\" found at %p\n", ++ dlfo.dlfo_link_map->l_name, ptr); ++ gap_found = true; ++ } ++ } ++ else ++ TEST_COMPARE (dlfo_ret, -1); ++ xmunmap (ptr, 1); ++ addr += pagesize; ++ } ++ if (!gap_found) ++ FAIL ("no ld.so gap found"); ++ } ++ else ++ { ++ puts ("info: ld.so link map is contiguous"); ++ ++ /* Assert that ld.so is truly contiguous in memory. */ ++ volatile long int *p = (volatile long int *) l->l_map_start; ++ volatile long int *end = (volatile long int *) l->l_map_end; ++ while (p < end) ++ { ++ *p; ++ ++p; ++ } ++ } ++ ++ xdlclose (l); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-link-map-contiguous-libc.c b/elf/tst-link-map-contiguous-libc.c +new file mode 100644 +index 0000000000..eb5728c765 +--- /dev/null ++++ b/elf/tst-link-map-contiguous-libc.c +@@ -0,0 +1,57 @@ ++/* Check that the entire libc.so program image is readable if contiguous. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct link_map *l = xdlopen (LIBC_SO, RTLD_NOW); ++ ++ /* The dynamic loader fills holes with PROT_NONE mappings. */ ++ if (!l->l_contiguous) ++ FAIL_EXIT1 ("libc.so link map is not contiguous"); ++ ++ /* Direct probing does not work because not everything is readable ++ due to PROT_NONE mappings. */ ++ int pagesize = getpagesize (); ++ ElfW(Addr) addr = l->l_map_start; ++ TEST_COMPARE (addr % pagesize, 0); ++ while (addr < l->l_map_end) ++ { ++ void *expected = (void *) addr; ++ void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1); ++ if (ptr == expected) ++ FAIL ("hole in libc.so memory image after %lu bytes", ++ (unsigned long int) (addr - l->l_map_start)); ++ xmunmap (ptr, 1); ++ addr += pagesize; ++ } ++ ++ xdlclose (l); ++ ++ return 0; ++} ++#include +diff --git a/elf/tst-link-map-contiguous-main.c b/elf/tst-link-map-contiguous-main.c +new file mode 100644 +index 0000000000..2d1a054f0f +--- /dev/null ++++ b/elf/tst-link-map-contiguous-main.c +@@ -0,0 +1,45 @@ ++/* Check that the entire main program image is readable if contiguous. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct link_map *l = xdlopen ("", RTLD_NOW); ++ if (!l->l_contiguous) ++ FAIL_UNSUPPORTED ("main link map is not contiguous"); ++ ++ /* This check only works if the kernel loaded the main program. The ++ dynamic loader replaces gaps with PROT_NONE mappings, resulting ++ in faults. */ ++ volatile long int *p = (volatile long int *) l->l_map_start; ++ volatile long int *end = (volatile long int *) l->l_map_end; ++ while (p < end) ++ { ++ *p; ++ ++p; ++ } ++ ++ xdlclose (l); ++ ++ return 0; ++} ++#include + +commit ff17e7180af38356750cf829224c2b494af03502 +Author: Florian Weimer +Date: Fri May 16 19:53:09 2025 +0200 + + Remove + + Use __thread variables directly instead. The macros do not save any + typing. It seems unlikely that a future port will lack __thread + variable support. + + Some of the __libc_tsd_* variables are referenced from assembler + files, so keep their names. Previously, included + , which in turn included , so a few direct includes + of are now required. + + Reviewed-by: Frédéric Bérat + (cherry picked from commit 10a66a8e421b09682b774c795ef1da402235dddc) + +diff --git a/ctype/ctype-info.c b/ctype/ctype-info.c +index 9032547567..71d1c8e3b4 100644 +--- a/ctype/ctype-info.c ++++ b/ctype/ctype-info.c +@@ -19,20 +19,20 @@ + #include + #include + +-__libc_tsd_define (, const uint16_t *, CTYPE_B) +-__libc_tsd_define (, const int32_t *, CTYPE_TOLOWER) +-__libc_tsd_define (, const int32_t *, CTYPE_TOUPPER) ++__thread const uint16_t * __libc_tsd_CTYPE_B; ++__thread const int32_t * __libc_tsd_CTYPE_TOLOWER; ++__thread const int32_t * __libc_tsd_CTYPE_TOUPPER; + + + void + __ctype_init (void) + { +- const uint16_t **bp = __libc_tsd_address (const uint16_t *, CTYPE_B); +- *bp = (const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS) + 128; +- const int32_t **up = __libc_tsd_address (const int32_t *, CTYPE_TOUPPER); +- *up = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER) + 128); +- const int32_t **lp = __libc_tsd_address (const int32_t *, CTYPE_TOLOWER); +- *lp = ((int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER) + 128); ++ __libc_tsd_CTYPE_B ++ = ((const uint16_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS)) + 128; ++ __libc_tsd_CTYPE_TOUPPER ++ = ((const int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOUPPER)) + 128; ++ __libc_tsd_CTYPE_TOLOWER = ++ ((const int32_t *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TOLOWER)) + 128; + } + libc_hidden_def (__ctype_init) + +diff --git a/include/ctype.h b/include/ctype.h +index 493a6f80ce..e993adc86d 100644 +--- a/include/ctype.h ++++ b/include/ctype.h +@@ -24,33 +24,32 @@ libc_hidden_proto (toupper) + NL_CURRENT_INDIRECT. */ + + # include "../locale/localeinfo.h" +-# include + + # ifndef CTYPE_EXTERN_INLINE /* Used by ctype/ctype-info.c, which see. */ + # define CTYPE_EXTERN_INLINE extern inline + # endif + +-__libc_tsd_define (extern, const uint16_t *, CTYPE_B) +-__libc_tsd_define (extern, const int32_t *, CTYPE_TOUPPER) +-__libc_tsd_define (extern, const int32_t *, CTYPE_TOLOWER) ++extern __thread const uint16_t * __libc_tsd_CTYPE_B; ++extern __thread const int32_t * __libc_tsd_CTYPE_TOUPPER; ++extern __thread const int32_t * __libc_tsd_CTYPE_TOLOWER; + + + CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const)) + __ctype_b_loc (void) + { +- return __libc_tsd_address (const uint16_t *, CTYPE_B); ++ return &__libc_tsd_CTYPE_B; + } + + CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const)) + __ctype_toupper_loc (void) + { +- return __libc_tsd_address (const int32_t *, CTYPE_TOUPPER); ++ return &__libc_tsd_CTYPE_TOUPPER; + } + + CTYPE_EXTERN_INLINE const int32_t ** __attribute__ ((const)) + __ctype_tolower_loc (void) + { +- return __libc_tsd_address (const int32_t *, CTYPE_TOLOWER); ++ return &__libc_tsd_CTYPE_TOLOWER; + } + + # ifndef __NO_CTYPE +diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h +index f5cee6caef..936ea3cebb 100644 +--- a/include/rpc/rpc.h ++++ b/include/rpc/rpc.h +@@ -3,8 +3,6 @@ + + # ifndef _ISOMAC + +-#include +- + /* Now define the internal interfaces. */ + extern unsigned long _create_xid (void); + +@@ -47,7 +45,7 @@ extern void __rpc_thread_key_cleanup (void) attribute_hidden; + + extern void __rpc_thread_destroy (void) attribute_hidden; + +-__libc_tsd_define (extern, struct rpc_thread_variables *, RPC_VARS) ++extern __thread struct rpc_thread_variables *__libc_tsd_RPC_VARS; + + #define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x) + +diff --git a/locale/lc-ctype.c b/locale/lc-ctype.c +index c77ec51cb8..70556acaf0 100644 +--- a/locale/lc-ctype.c ++++ b/locale/lc-ctype.c +@@ -64,12 +64,9 @@ _nl_postload_ctype (void) + in fact using the global locale. */ + if (_NL_CURRENT_LOCALE == &_nl_global_locale) + { +- __libc_tsd_set (const uint16_t *, CTYPE_B, +- (void *) _nl_global_locale.__ctype_b); +- __libc_tsd_set (const int32_t *, CTYPE_TOUPPER, +- (void *) _nl_global_locale.__ctype_toupper); +- __libc_tsd_set (const int32_t *, CTYPE_TOLOWER, +- (void *) _nl_global_locale.__ctype_tolower); ++ __libc_tsd_CTYPE_B = _nl_global_locale.__ctype_b; ++ __libc_tsd_CTYPE_TOUPPER = _nl_global_locale.__ctype_toupper; ++ __libc_tsd_CTYPE_TOLOWER = _nl_global_locale.__ctype_tolower; + } + + #include +diff --git a/locale/localeinfo.h b/locale/localeinfo.h +index ed698faef1..bc8e92e4dc 100644 +--- a/locale/localeinfo.h ++++ b/locale/localeinfo.h +@@ -236,10 +236,8 @@ extern struct __locale_struct _nl_global_locale attribute_hidden; + + /* This fetches the thread-local locale_t pointer, either one set with + uselocale or &_nl_global_locale. */ +-#define _NL_CURRENT_LOCALE (__libc_tsd_get (locale_t, LOCALE)) +-#include +-__libc_tsd_define (extern, locale_t, LOCALE) +- ++#define _NL_CURRENT_LOCALE __libc_tsd_LOCALE ++extern __thread locale_t __libc_tsd_LOCALE; + + /* For static linking it is desireable to avoid always linking in the code + and data for every category when we can tell at link time that they are +diff --git a/locale/uselocale.c b/locale/uselocale.c +index 8136caf61b..0b247a77d5 100644 +--- a/locale/uselocale.c ++++ b/locale/uselocale.c +@@ -34,7 +34,7 @@ __uselocale (locale_t newloc) + { + const locale_t locobj + = newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc; +- __libc_tsd_set (locale_t, LOCALE, locobj); ++ __libc_tsd_LOCALE = locobj; + + #ifdef NL_CURRENT_INDIRECT + /* Now we must update all the per-category thread-local variables to +@@ -62,11 +62,9 @@ __uselocale (locale_t newloc) + #endif + + /* Update the special tsd cache of some locale data. */ +- __libc_tsd_set (const uint16_t *, CTYPE_B, (void *) locobj->__ctype_b); +- __libc_tsd_set (const int32_t *, CTYPE_TOLOWER, +- (void *) locobj->__ctype_tolower); +- __libc_tsd_set (const int32_t *, CTYPE_TOUPPER, +- (void *) locobj->__ctype_toupper); ++ __libc_tsd_CTYPE_B = locobj->__ctype_b; ++ __libc_tsd_CTYPE_TOLOWER = locobj->__ctype_tolower; ++ __libc_tsd_CTYPE_TOUPPER = locobj->__ctype_toupper; + } + + return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc; +diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c +index ab9fafb5ec..8db18f11b3 100644 +--- a/stdio-common/printf-parsemb.c ++++ b/stdio-common/printf-parsemb.c +@@ -17,6 +17,7 @@ + . */ + + #include ++#include + #include + #include + #include +diff --git a/string/strerror.c b/string/strerror.c +index 107d9d39c2..efa4e903ea 100644 +--- a/string/strerror.c ++++ b/string/strerror.c +@@ -21,5 +21,5 @@ + char * + strerror (int errnum) + { +- return __strerror_l (errnum, __libc_tsd_get (locale_t, LOCALE)); ++ return __strerror_l (errnum, __libc_tsd_LOCALE); + } +diff --git a/sunrpc/rpc_thread.c b/sunrpc/rpc_thread.c +index a04b7ec47f..e20f0a6230 100644 +--- a/sunrpc/rpc_thread.c ++++ b/sunrpc/rpc_thread.c +@@ -3,7 +3,6 @@ + #include + + #include +-#include + #include + #include + +diff --git a/sysdeps/generic/libc-tsd.h b/sysdeps/generic/libc-tsd.h +deleted file mode 100644 +index ac0e99e14b..0000000000 +--- a/sysdeps/generic/libc-tsd.h ++++ /dev/null +@@ -1,60 +0,0 @@ +-/* libc-internal interface for thread-specific data. Stub or TLS version. +- Copyright (C) 1998-2024 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library 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. +- +- The GNU C Library 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 the GNU C Library; if not, see +- . */ +- +-#ifndef _GENERIC_LIBC_TSD_H +-#define _GENERIC_LIBC_TSD_H 1 +- +-/* This file defines the following macros for accessing a small fixed +- set of thread-specific `void *' data used only internally by libc. +- +- __libc_tsd_define(CLASS, TYPE, KEY) -- Define or declare a datum with TYPE +- for KEY. CLASS can be `static' for +- keys used in only one source file, +- empty for global definitions, or +- `extern' for global declarations. +- __libc_tsd_address(TYPE, KEY) -- Return the `TYPE *' pointing to +- the current thread's datum for KEY. +- __libc_tsd_get(TYPE, KEY) -- Return the `TYPE' datum for KEY. +- __libc_tsd_set(TYPE, KEY, VALUE) -- Set the datum for KEY to VALUE. +- +- The set of available KEY's will usually be provided as an enum, +- and contains (at least): +- _LIBC_TSD_KEY_MALLOC +- _LIBC_TSD_KEY_DL_ERROR +- _LIBC_TSD_KEY_RPC_VARS +- All uses must be the literal _LIBC_TSD_* name in the __libc_tsd_* macros. +- Some implementations may not provide any enum at all and instead +- using string pasting in the macros. */ +- +-#include +- +-/* When full support for __thread variables is available, this interface is +- just a trivial wrapper for it. Without TLS, this is the generic/stub +- implementation for wholly single-threaded systems. +- +- We don't define an enum for the possible key values, because the KEYs +- translate directly into variables by macro magic. */ +- +-#define __libc_tsd_define(CLASS, TYPE, KEY) \ +- CLASS __thread TYPE __libc_tsd_##KEY attribute_tls_model_ie; +- +-#define __libc_tsd_address(TYPE, KEY) (&__libc_tsd_##KEY) +-#define __libc_tsd_get(TYPE, KEY) (__libc_tsd_##KEY) +-#define __libc_tsd_set(TYPE, KEY, VALUE) (__libc_tsd_##KEY = (VALUE)) +- +-#endif /* libc-tsd.h */ +diff --git a/time/strftime_l.c b/time/strftime_l.c +index 77adec9050..066c839c2f 100644 +--- a/time/strftime_l.c ++++ b/time/strftime_l.c +@@ -40,6 +40,7 @@ + #endif + + #include ++#include + #include /* Some systems define `time_t' here. */ + + #ifdef TIME_WITH_SYS_TIME + +commit a0cc6a7e1cb07fdf476241fbc84c67d01fb8efad +Author: Florian Weimer +Date: Fri May 16 19:53:09 2025 +0200 + + Use proper extern declaration for _nl_C_LC_CTYPE_{class,toupper,tolower} + + The existing initializers already contain explicit casts. Keep them + due to int/uint32_t mismatch. + + Reviewed-by: Frédéric Bérat + (cherry picked from commit e0c0f856f58ceb68800a964c36c15c606e7a8c4c) + +diff --git a/ctype/ctype-info.c b/ctype/ctype-info.c +index 71d1c8e3b4..94e312d91f 100644 +--- a/ctype/ctype-info.c ++++ b/ctype/ctype-info.c +@@ -41,10 +41,7 @@ libc_hidden_def (__ctype_init) + #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) + + /* Defined in locale/C-ctype.c. */ +-extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; + extern const char _nl_C_LC_CTYPE_class32[] attribute_hidden; +-extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; +-extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden; + extern const char _nl_C_LC_CTYPE_class_upper[] attribute_hidden; + extern const char _nl_C_LC_CTYPE_class_lower[] attribute_hidden; + extern const char _nl_C_LC_CTYPE_class_alpha[] attribute_hidden; +diff --git a/include/ctype.h b/include/ctype.h +index e993adc86d..ae078a63d3 100644 +--- a/include/ctype.h ++++ b/include/ctype.h +@@ -63,6 +63,11 @@ __ctype_tolower_loc (void) + # define __isdigit_l(c, l) ({ int __c = (c); __c >= '0' && __c <= '9'; }) + # endif /* Not __NO_CTYPE. */ + ++/* For use in initializers. */ ++extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; ++extern const uint32_t _nl_C_LC_CTYPE_toupper[] attribute_hidden; ++extern const uint32_t _nl_C_LC_CTYPE_tolower[] attribute_hidden; ++ + # endif /* IS_IN (libc). */ + #endif /* Not _ISOMAC. */ + +diff --git a/locale/xlocale.c b/locale/xlocale.c +index f2b9d03303..d11c1cbf8c 100644 +--- a/locale/xlocale.c ++++ b/locale/xlocale.c +@@ -18,18 +18,13 @@ + + #include + #include "localeinfo.h" ++#include + + #define DEFINE_CATEGORY(category, category_name, items, a) \ + extern struct __locale_data _nl_C_##category; + #include "categories.def" + #undef DEFINE_CATEGORY + +-/* Defined in locale/C-ctype.c. */ +-extern const char _nl_C_LC_CTYPE_class[] attribute_hidden; +-extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden; +-extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden; +- +- + const struct __locale_struct _nl_C_locobj attribute_hidden = + { + .__locales = + +commit 434e7e144a3825f910a5051af5f02d2e2198d4d9 +Author: Florian Weimer +Date: Fri May 16 19:53:09 2025 +0200 + + ctype: Fallback initialization of TLS using relocations (bug 19341, bug 32483) + + This ensures that the ctype data pointers in TLS are valid + in secondary namespaces even without initialization via + __ctype_init. + + Reviewed-by: Frédéric Bérat + (cherry picked from commit 2745db8dd3ec31045acd761b612516490085bc20) + +diff --git a/NEWS b/NEWS +index 1b3fd48158..c9982aabed 100644 +--- a/NEWS ++++ b/NEWS +@@ -9,6 +9,7 @@ Version 2.40.1 + + The following bugs are resolved with this release: + ++ [19341] ctype: Fallback initialization of TLS using relocations + [27821] ungetc: Fix backup buffer leak on program exit + [30081] resolv: Do not wait for non-existing second DNS response after error + [31394] clone on sparc might fail with -EFAULT for no valid reason +@@ -23,6 +24,7 @@ The following bugs are resolved with this release: + [32231] elf: Change ldconfig auxcache magic number + [32245] glibc -Wstringop-overflow= build failure on hppa + [32470] x86: Avoid integer truncation with large cache sizes ++ [32483] ctype macros segfault in multithreaded programs with multiple libc.so + [32810] Crash on x86-64 if XSAVEC disable via tunable + [32987] elf: Fix subprocess status handling for tst-dlopen-sgid + [33185] Fix double-free after allocation failure in regcomp +diff --git a/ctype/Makefile b/ctype/Makefile +index 3e09938bd1..b7cd5f2282 100644 +--- a/ctype/Makefile ++++ b/ctype/Makefile +@@ -36,6 +36,23 @@ aux := ctype-info + + tests := \ + test_ctype \ ++ tst-ctype-tls-dlmopen \ ++ tst-ctype-tls-dlopen-static \ + # tests + ++tests-static := \ ++ tst-ctype-tls-dlopen-static \ ++ # tests-static ++ ++modules-names := \ ++ tst-ctype-tls-mod \ ++ # modules-names ++ + include ../Rules ++ ++$(objpfx)tst-ctype-tls-dlmopen: $(shared-thread-library) ++$(objpfx)tst-ctype-tls-dlmopen.out: $(objpfx)tst-ctype-tls-mod.so ++$(objpfx)tst-ctype-tls-dlopen-static: $(static-thread-library) ++$(objpfx)tst-ctype-tls-dlopen-static.out: $(objpfx)tst-ctype-tls-mod.so ++tst-ctype-tls-dlopen-static-ENV = \ ++ LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx):$(common-objpfx)elf +diff --git a/ctype/ctype-info.c b/ctype/ctype-info.c +index 94e312d91f..621bd4239c 100644 +--- a/ctype/ctype-info.c ++++ b/ctype/ctype-info.c +@@ -19,9 +19,17 @@ + #include + #include + +-__thread const uint16_t * __libc_tsd_CTYPE_B; +-__thread const int32_t * __libc_tsd_CTYPE_TOLOWER; +-__thread const int32_t * __libc_tsd_CTYPE_TOUPPER; ++/* Fallback initialization using relocations. See the _nl_C_locobj ++ initializers in locale/xlocale.c. Usually, this is overwritten by ++ __ctype_init before user code runs, but this does not happen for ++ threads in secondary namespaces. With the initializers, secondary ++ namespaces at least get locale data from the C locale. */ ++__thread const uint16_t * __libc_tsd_CTYPE_B ++ = (const uint16_t *) _nl_C_LC_CTYPE_class + 128; ++__thread const int32_t * __libc_tsd_CTYPE_TOLOWER ++ = (const int32_t *) _nl_C_LC_CTYPE_tolower + 128; ++__thread const int32_t * __libc_tsd_CTYPE_TOUPPER ++ = (const int32_t *) _nl_C_LC_CTYPE_toupper + 128; + + + void +diff --git a/ctype/tst-ctype-tls-dlmopen.c b/ctype/tst-ctype-tls-dlmopen.c +new file mode 100644 +index 0000000000..f7eeb65551 +--- /dev/null ++++ b/ctype/tst-ctype-tls-dlmopen.c +@@ -0,0 +1,2 @@ ++#define DO_STATIC_TEST 0 ++#include "tst-ctype-tls-skeleton.c" +diff --git a/ctype/tst-ctype-tls-dlopen-static.c b/ctype/tst-ctype-tls-dlopen-static.c +new file mode 100644 +index 0000000000..c2c09c362c +--- /dev/null ++++ b/ctype/tst-ctype-tls-dlopen-static.c +@@ -0,0 +1,2 @@ ++#define DO_STATIC_TEST 1 ++#include "tst-ctype-tls-skeleton.c" +diff --git a/ctype/tst-ctype-tls-mod.c b/ctype/tst-ctype-tls-mod.c +new file mode 100644 +index 0000000000..52cbb9dcb6 +--- /dev/null ++++ b/ctype/tst-ctype-tls-mod.c +@@ -0,0 +1,37 @@ ++/* Wrappers for macros in a secondary namespace. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++int ++my_isalpha (int ch) ++{ ++ return isalpha (ch); ++} ++ ++int ++my_toupper (int ch) ++{ ++ return toupper (ch); ++} ++ ++int ++my_tolower (int ch) ++{ ++ return tolower (ch); ++} +diff --git a/ctype/tst-ctype-tls-skeleton.c b/ctype/tst-ctype-tls-skeleton.c +new file mode 100644 +index 0000000000..8c53e35899 +--- /dev/null ++++ b/ctype/tst-ctype-tls-skeleton.c +@@ -0,0 +1,67 @@ ++/* Test that in a secondary namespace works. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++/* Before this file is included, define DO_STATIC_TEST to 0 or 1. ++ With 0, dlmopen is used for the test. With 1, dlopen is used. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int (*my_isalpha) (int); ++static int (*my_toupper) (int); ++static int (*my_tolower) (int); ++ ++static void * ++checks (void *ignore) ++{ ++ TEST_VERIFY (my_isalpha ('a')); ++ TEST_VERIFY (!my_isalpha ('0')); ++ TEST_COMPARE (my_toupper ('a'), 'A'); ++ TEST_COMPARE (my_toupper ('A'), 'A'); ++ TEST_COMPARE (my_tolower ('a'), 'a'); ++ TEST_COMPARE (my_tolower ('A'), 'a'); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ char *dso = xasprintf ("%s/ctype/tst-ctype-tls-mod.so", support_objdir_root); ++#if DO_STATIC_TEST ++ void *handle = xdlopen (dso, RTLD_LAZY); ++#else ++ void *handle = xdlmopen (LM_ID_NEWLM, dso, RTLD_LAZY); ++#endif ++ my_isalpha = xdlsym (handle, "my_isalpha"); ++ my_toupper = xdlsym (handle, "my_toupper"); ++ my_tolower = xdlsym (handle, "my_tolower"); ++ ++ checks (NULL); ++ xpthread_join (xpthread_create (NULL, checks, NULL)); ++ ++ xdlclose (handle); ++ free (dso); ++ ++ return 0; ++} ++ ++#include + +commit 1b305e7e53bd850542c9dccfcc17ff31cf605b62 +Author: Jens Remus +Date: Fri Jul 25 15:40:03 2025 +0200 + + Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables [BZ #33234] + + Commit 10a66a8e421b ("Remove ") removed the TLS initial-exec + (IE) model attribute from the __libc_tsd_CTYPE_* thread variable declarations + and definitions. Commit a894f04d8776 ("Optimize __libc_tsd_* thread + variable access") restored it on declarations. + + Restore the TLS initial-exec model attribute on __libc_tsd_CTYPE_* thread + variable definitions. + + This resolves test tst-locale1 failure on s390 32-bit, when using a + GNU linker without the fix from GNU binutils commit aefebe82dc89 + ("IBM zSystems: Fix offset relative to static TLS"). + + Reviewed-by: Florian Weimer + (cherry picked from commit e5363e6f460c2d58809bf10fc96d70fd1ef8b5b2) + +diff --git a/NEWS b/NEWS +index c9982aabed..acb5179088 100644 +--- a/NEWS ++++ b/NEWS +@@ -28,6 +28,7 @@ The following bugs are resolved with this release: + [32810] Crash on x86-64 if XSAVEC disable via tunable + [32987] elf: Fix subprocess status handling for tst-dlopen-sgid + [33185] Fix double-free after allocation failure in regcomp ++ [33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables + + Version 2.40 + +diff --git a/ctype/ctype-info.c b/ctype/ctype-info.c +index 621bd4239c..b6cdf7eb66 100644 +--- a/ctype/ctype-info.c ++++ b/ctype/ctype-info.c +@@ -24,11 +24,11 @@ + __ctype_init before user code runs, but this does not happen for + threads in secondary namespaces. With the initializers, secondary + namespaces at least get locale data from the C locale. */ +-__thread const uint16_t * __libc_tsd_CTYPE_B ++__thread const uint16_t * __libc_tsd_CTYPE_B attribute_tls_model_ie + = (const uint16_t *) _nl_C_LC_CTYPE_class + 128; +-__thread const int32_t * __libc_tsd_CTYPE_TOLOWER ++__thread const int32_t * __libc_tsd_CTYPE_TOLOWER attribute_tls_model_ie + = (const int32_t *) _nl_C_LC_CTYPE_tolower + 128; +-__thread const int32_t * __libc_tsd_CTYPE_TOUPPER ++__thread const int32_t * __libc_tsd_CTYPE_TOUPPER attribute_tls_model_ie + = (const int32_t *) _nl_C_LC_CTYPE_toupper + 128; + + + +commit 666939940bfb6fc3c36b1039afcc3341a6c4ca0d +Author: Joe Ramsay +Date: Fri Jan 3 19:13:36 2025 +0000 + + math: Remove no-mathvec flag + + More routines are to follow, some of which hit many failures in the + current testsuite due to wrong sign of zero (mathvec routines are not + required to get this right). Instead of disabling a large number of + tests, change the failure condition such that, for vector routines, + tests pass as long as computed == expected == 0.0, regardless of sign. + + Affected tests (vector tests for expm1, log1p, sin, tan and tanh) all + still pass. + + (cherry picked from commit 939e770e0196ebd763cacc602421b76d62df0798) + +diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in +index 8f0c3d87bb..7100171346 100644 +--- a/math/auto-libm-test-in ++++ b/math/auto-libm-test-in +@@ -5555,7 +5555,7 @@ exp2m1 -0x1p-1021 + exp2m1 -0x1p-16381 + + expm1 0 +-expm1 -0 no-mathvec ++expm1 -0 + expm1 1 + expm1 0.75 + expm1 2 +@@ -5620,7 +5620,7 @@ expm1 -0x1p-100 + expm1 0x1p-600 + expm1 -0x1p-600 + expm1 0x1p-10000 +-expm1 -0x1p-10000 no-mathvec ++expm1 -0x1p-10000 + expm1 0xe.4152ac57cd1ea7ap-60 + expm1 0x6.660247486aed8p-4 + expm1 0x6.289a78p-4 +@@ -6835,7 +6835,7 @@ log10p1 -0x6.3fef3067427e43dfcde9e48f74bcp-4 + log10p1 0x6.af53d00fd2845d4772260ef5adc4p-4 + + log1p 0 +-log1p -0 no-mathvec ++log1p -0 + log1p e-1 + log1p -0.25 + log1p -0.875 +@@ -7627,7 +7627,7 @@ pow 0x1.7ac7cp+5 23 + pow -0x1.7ac7cp+5 23 + + sin 0 +-sin -0 no-mathvec ++sin -0 + sin pi/6 + sin -pi/6 + sin pi/2 +@@ -7964,7 +7964,7 @@ sqrt min + sqrt min_subnorm + + tan 0 +-tan -0 no-mathvec ++tan -0 + tan pi/4 + tan pi/2 + tan -pi/2 +@@ -8056,7 +8056,7 @@ tan min_subnorm + tan -min_subnorm + + tanh 0 +-tanh -0 no-mathvec ++tanh -0 + tanh 0.75 + tanh -0.75 + tanh 1.0 +diff --git a/math/auto-libm-test-out-expm1 b/math/auto-libm-test-out-expm1 +index 91da41b7f6..8483455801 100644 +--- a/math/auto-libm-test-out-expm1 ++++ b/math/auto-libm-test-out-expm1 +@@ -23,31 +23,31 @@ expm1 0 + = expm1 tonearest ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = expm1 towardzero ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = expm1 upward ibm128 0x0p+0 : 0x0p+0 : inexact-ok +-expm1 -0 no-mathvec +-= expm1 downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok ++expm1 -0 ++= expm1 downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok + expm1 1 + = expm1 downward binary32 0x1p+0 : 0x1.b7e15p+0 : inexact-ok + = expm1 tonearest binary32 0x1p+0 : 0x1.b7e152p+0 : inexact-ok +@@ -1880,87 +1880,87 @@ expm1 0x1p-10000 + = expm1 tonearest binary128 0x1p-10000 : 0x1p-10000 : inexact-ok + = expm1 towardzero binary128 0x1p-10000 : 0x1p-10000 : inexact-ok + = expm1 upward binary128 0x1p-10000 : 0x1.0000000000000000000000000001p-10000 : inexact-ok +-expm1 -0x1p-10000 no-mathvec +-= expm1 downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= expm1 downward binary32 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 tonearest binary32 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 towardzero binary32 -0x8p-152 : -0x0p+0 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 upward binary32 -0x8p-152 : -0x0p+0 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 downward binary64 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 tonearest binary64 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 towardzero binary64 -0x8p-152 : -0x7.ffffffffffffcp-152 : no-mathvec inexact-ok +-= expm1 upward binary64 -0x8p-152 : -0x7.ffffffffffffcp-152 : no-mathvec inexact-ok +-= expm1 downward intel96 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 tonearest intel96 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 towardzero intel96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : no-mathvec inexact-ok +-= expm1 upward intel96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : no-mathvec inexact-ok +-= expm1 downward m68k96 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 tonearest m68k96 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 towardzero m68k96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : no-mathvec inexact-ok +-= expm1 upward m68k96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : no-mathvec inexact-ok +-= expm1 downward binary128 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 tonearest binary128 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 towardzero binary128 -0x8p-152 : -0x7.fffffffffffffffffffffffffffcp-152 : no-mathvec inexact-ok +-= expm1 upward binary128 -0x8p-152 : -0x7.fffffffffffffffffffffffffffcp-152 : no-mathvec inexact-ok +-= expm1 downward ibm128 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 tonearest ibm128 -0x8p-152 : -0x8p-152 : no-mathvec inexact-ok +-= expm1 towardzero ibm128 -0x8p-152 : -0x7.fffffffffffffffffffffffffep-152 : no-mathvec inexact-ok +-= expm1 upward ibm128 -0x8p-152 : -0x7.fffffffffffffffffffffffffep-152 : no-mathvec inexact-ok +-= expm1 downward binary64 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 tonearest binary64 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 towardzero binary64 -0x4p-1076 : -0x0p+0 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 upward binary64 -0x4p-1076 : -0x0p+0 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 downward intel96 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 tonearest intel96 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 towardzero intel96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : no-mathvec inexact-ok +-= expm1 upward intel96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : no-mathvec inexact-ok +-= expm1 downward m68k96 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 tonearest m68k96 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 towardzero m68k96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : no-mathvec inexact-ok +-= expm1 upward m68k96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : no-mathvec inexact-ok +-= expm1 downward binary128 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 tonearest binary128 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok +-= expm1 towardzero binary128 -0x4p-1076 : -0x3.fffffffffffffffffffffffffffep-1076 : no-mathvec inexact-ok +-= expm1 upward binary128 -0x4p-1076 : -0x3.fffffffffffffffffffffffffffep-1076 : no-mathvec inexact-ok +-= expm1 downward ibm128 -0x4p-1076 : -0x4p-1076 : no-mathvec xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok +-= expm1 tonearest ibm128 -0x4p-1076 : -0x4p-1076 : no-mathvec inexact-ok underflow errno-erange-ok +-= expm1 towardzero ibm128 -0x4p-1076 : -0x0p+0 : no-mathvec xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok +-= expm1 upward ibm128 -0x4p-1076 : -0x0p+0 : no-mathvec xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok +-= expm1 downward intel96 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 tonearest intel96 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 towardzero intel96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : no-mathvec inexact-ok +-= expm1 upward intel96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : no-mathvec inexact-ok +-= expm1 downward m68k96 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 tonearest m68k96 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 towardzero m68k96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : no-mathvec inexact-ok +-= expm1 upward m68k96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : no-mathvec inexact-ok +-= expm1 downward binary128 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 tonearest binary128 -0x1p-10000 : -0x1p-10000 : no-mathvec inexact-ok +-= expm1 towardzero binary128 -0x1p-10000 : -0xf.fffffffffffffffffffffffffff8p-10004 : no-mathvec inexact-ok +-= expm1 upward binary128 -0x1p-10000 : -0xf.fffffffffffffffffffffffffff8p-10004 : no-mathvec inexact-ok ++expm1 -0x1p-10000 ++= expm1 downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= expm1 downward binary32 -0x8p-152 : -0x8p-152 : inexact-ok underflow errno-erange-ok ++= expm1 tonearest binary32 -0x8p-152 : -0x8p-152 : inexact-ok underflow errno-erange-ok ++= expm1 towardzero binary32 -0x8p-152 : -0x0p+0 : inexact-ok underflow errno-erange-ok ++= expm1 upward binary32 -0x8p-152 : -0x0p+0 : inexact-ok underflow errno-erange-ok ++= expm1 downward binary64 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 tonearest binary64 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 towardzero binary64 -0x8p-152 : -0x7.ffffffffffffcp-152 : inexact-ok ++= expm1 upward binary64 -0x8p-152 : -0x7.ffffffffffffcp-152 : inexact-ok ++= expm1 downward intel96 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 tonearest intel96 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 towardzero intel96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : inexact-ok ++= expm1 upward intel96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : inexact-ok ++= expm1 downward m68k96 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 tonearest m68k96 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 towardzero m68k96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : inexact-ok ++= expm1 upward m68k96 -0x8p-152 : -0x7.fffffffffffffff8p-152 : inexact-ok ++= expm1 downward binary128 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 tonearest binary128 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 towardzero binary128 -0x8p-152 : -0x7.fffffffffffffffffffffffffffcp-152 : inexact-ok ++= expm1 upward binary128 -0x8p-152 : -0x7.fffffffffffffffffffffffffffcp-152 : inexact-ok ++= expm1 downward ibm128 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 tonearest ibm128 -0x8p-152 : -0x8p-152 : inexact-ok ++= expm1 towardzero ibm128 -0x8p-152 : -0x7.fffffffffffffffffffffffffep-152 : inexact-ok ++= expm1 upward ibm128 -0x8p-152 : -0x7.fffffffffffffffffffffffffep-152 : inexact-ok ++= expm1 downward binary64 -0x4p-1076 : -0x4p-1076 : inexact-ok underflow errno-erange-ok ++= expm1 tonearest binary64 -0x4p-1076 : -0x4p-1076 : inexact-ok underflow errno-erange-ok ++= expm1 towardzero binary64 -0x4p-1076 : -0x0p+0 : inexact-ok underflow errno-erange-ok ++= expm1 upward binary64 -0x4p-1076 : -0x0p+0 : inexact-ok underflow errno-erange-ok ++= expm1 downward intel96 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 tonearest intel96 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 towardzero intel96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : inexact-ok ++= expm1 upward intel96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : inexact-ok ++= expm1 downward m68k96 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 tonearest m68k96 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 towardzero m68k96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : inexact-ok ++= expm1 upward m68k96 -0x4p-1076 : -0x3.fffffffffffffffcp-1076 : inexact-ok ++= expm1 downward binary128 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 tonearest binary128 -0x4p-1076 : -0x4p-1076 : inexact-ok ++= expm1 towardzero binary128 -0x4p-1076 : -0x3.fffffffffffffffffffffffffffep-1076 : inexact-ok ++= expm1 upward binary128 -0x4p-1076 : -0x3.fffffffffffffffffffffffffffep-1076 : inexact-ok ++= expm1 downward ibm128 -0x4p-1076 : -0x4p-1076 : xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok ++= expm1 tonearest ibm128 -0x4p-1076 : -0x4p-1076 : inexact-ok underflow errno-erange-ok ++= expm1 towardzero ibm128 -0x4p-1076 : -0x0p+0 : xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok ++= expm1 upward ibm128 -0x4p-1076 : -0x0p+0 : xfail:ibm128-libgcc inexact-ok underflow errno-erange-ok ++= expm1 downward intel96 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 tonearest intel96 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 towardzero intel96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : inexact-ok ++= expm1 upward intel96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : inexact-ok ++= expm1 downward m68k96 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 tonearest m68k96 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 towardzero m68k96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : inexact-ok ++= expm1 upward m68k96 -0x1p-10000 : -0xf.fffffffffffffffp-10004 : inexact-ok ++= expm1 downward binary128 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 tonearest binary128 -0x1p-10000 : -0x1p-10000 : inexact-ok ++= expm1 towardzero binary128 -0x1p-10000 : -0xf.fffffffffffffffffffffffffff8p-10004 : inexact-ok ++= expm1 upward binary128 -0x1p-10000 : -0xf.fffffffffffffffffffffffffff8p-10004 : inexact-ok + expm1 0xe.4152ac57cd1ea7ap-60 + = expm1 downward binary32 0xe.4152bp-60 : 0xe.4152bp-60 : inexact-ok + = expm1 tonearest binary32 0xe.4152bp-60 : 0xe.4152bp-60 : inexact-ok +diff --git a/math/auto-libm-test-out-log1p b/math/auto-libm-test-out-log1p +index f83241f51a..f7d3b35e6d 100644 +--- a/math/auto-libm-test-out-log1p ++++ b/math/auto-libm-test-out-log1p +@@ -23,31 +23,31 @@ log1p 0 + = log1p tonearest ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = log1p towardzero ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = log1p upward ibm128 0x0p+0 : 0x0p+0 : inexact-ok +-log1p -0 no-mathvec +-= log1p downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= log1p upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok ++log1p -0 ++= log1p downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= log1p upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok + log1p e-1 + = log1p downward binary32 0x1.b7e152p+0 : 0x1p+0 : inexact-ok + = log1p tonearest binary32 0x1.b7e152p+0 : 0x1p+0 : inexact-ok +diff --git a/math/auto-libm-test-out-sin b/math/auto-libm-test-out-sin +index e1f6845283..f1d21b179c 100644 +--- a/math/auto-libm-test-out-sin ++++ b/math/auto-libm-test-out-sin +@@ -23,31 +23,31 @@ sin 0 + = sin tonearest ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = sin towardzero ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = sin upward ibm128 0x0p+0 : 0x0p+0 : inexact-ok +-sin -0 no-mathvec +-= sin downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= sin upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok ++sin -0 ++= sin downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= sin upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok + sin pi/6 + = sin downward binary32 0x8.60a92p-4 : 0x8p-4 : inexact-ok + = sin tonearest binary32 0x8.60a92p-4 : 0x8p-4 : inexact-ok +diff --git a/math/auto-libm-test-out-tan b/math/auto-libm-test-out-tan +index f46fdc7ec6..7d00d03e1d 100644 +--- a/math/auto-libm-test-out-tan ++++ b/math/auto-libm-test-out-tan +@@ -23,31 +23,31 @@ tan 0 + = tan tonearest ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = tan towardzero ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = tan upward ibm128 0x0p+0 : 0x0p+0 : inexact-ok +-tan -0 no-mathvec +-= tan downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tan upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok ++tan -0 ++= tan downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tan upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok + tan pi/4 + = tan downward binary32 0xc.90fdbp-4 : 0x1p+0 : inexact-ok + = tan tonearest binary32 0xc.90fdbp-4 : 0x1p+0 : inexact-ok +diff --git a/math/auto-libm-test-out-tanh b/math/auto-libm-test-out-tanh +index 19ce2e7b93..8b9427c917 100644 +--- a/math/auto-libm-test-out-tanh ++++ b/math/auto-libm-test-out-tanh +@@ -23,31 +23,31 @@ tanh 0 + = tanh tonearest ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = tanh towardzero ibm128 0x0p+0 : 0x0p+0 : inexact-ok + = tanh upward ibm128 0x0p+0 : 0x0p+0 : inexact-ok +-tanh -0 no-mathvec +-= tanh downward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward binary32 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh downward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward binary64 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh downward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward intel96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh downward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward m68k96 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh downward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward binary128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh downward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh tonearest ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh towardzero ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok +-= tanh upward ibm128 -0x0p+0 : -0x0p+0 : no-mathvec inexact-ok ++tanh -0 ++= tanh downward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward binary32 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh downward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward binary64 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh downward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward intel96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh downward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward m68k96 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh downward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward binary128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh downward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh tonearest ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh towardzero ibm128 -0x0p+0 : -0x0p+0 : inexact-ok ++= tanh upward ibm128 -0x0p+0 : -0x0p+0 : inexact-ok + tanh 0.75 + = tanh downward binary32 0xcp-4 : 0xa.2991fp-4 : inexact-ok + = tanh tonearest binary32 0xcp-4 : 0xa.2991fp-4 : inexact-ok +diff --git a/math/gen-auto-libm-tests.c b/math/gen-auto-libm-tests.c +index 0b1e307fae..ff8a22b90f 100644 +--- a/math/gen-auto-libm-tests.c ++++ b/math/gen-auto-libm-tests.c +@@ -96,8 +96,7 @@ + zero and infinite results should be ignored; "xfail" indicates the + test is disabled as expected to produce incorrect results, + "xfail-rounding" indicates the test is disabled only in rounding +- modes other than round-to-nearest; "no-mathvec" indicates the test +- is disabled in vector math libraries. Otherwise, test flags are of ++ modes other than round-to-nearest. Otherwise, test flags are of + the form "spurious-" and "missing-", for any + exception ("overflow", "underflow", "inexact", "invalid", + "divbyzero"), "spurious-errno" and "missing-errno", to indicate +@@ -353,7 +352,6 @@ typedef enum + flag_missing_overflow, + flag_missing_underflow, + flag_missing_errno, +- flag_no_mathvec, + num_input_flag_types, + flag_first_flag = 0, + flag_spurious_first = flag_spurious_divbyzero, +@@ -379,7 +377,6 @@ static const char *const input_flags[num_input_flag_types] = + "missing-overflow", + "missing-underflow", + "missing-errno", +- "no-mathvec", + }; + + /* An input flag, possibly conditional. */ +@@ -2056,7 +2053,6 @@ output_for_one_input_case (FILE *fp, const char *filename, test_function *tf, + { + case flag_ignore_zero_inf_sign: + case flag_xfail: +- case flag_no_mathvec: + if (fprintf (fp, " %s%s", + input_flags[it->flags[i].type], + (it->flags[i].cond +diff --git a/math/gen-libm-test.py b/math/gen-libm-test.py +index 397dbd3259..6e8bb56437 100755 +--- a/math/gen-libm-test.py ++++ b/math/gen-libm-test.py +@@ -93,8 +93,7 @@ BEAUTIFY_MAP = {'minus_zero': '-0', + + # Flags in auto-libm-test-out that map directly to C flags. + FLAGS_SIMPLE = {'ignore-zero-inf-sign': 'IGNORE_ZERO_INF_SIGN', +- 'xfail': 'XFAIL_TEST', +- 'no-mathvec': 'NO_TEST_MATHVEC'} ++ 'xfail': 'XFAIL_TEST'} + + # Exceptions in auto-libm-test-out, and their corresponding C flags + # for being required, OK or required to be absent. +diff --git a/math/libm-test-support.c b/math/libm-test-support.c +index 0796f9d495..3fecd87064 100644 +--- a/math/libm-test-support.c ++++ b/math/libm-test-support.c +@@ -776,7 +776,7 @@ check_float_internal (const char *test_name, FLOAT computed, FLOAT expected, + ulps = ULPDIFF (computed, expected); + set_max_error (ulps, curr_max_error); + print_diff = 1; +- if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0 ++ if (((exceptions & IGNORE_ZERO_INF_SIGN) == 0) && !flag_test_mathvec + && computed == 0.0 && expected == 0.0 + && signbit(computed) != signbit (expected)) + ok = 0; + +commit 6916013ce98feaa6f86380d79f545aae10aecb10 +Author: H.J. Lu +Date: Mon Jul 28 12:18:22 2025 -0700 + + x86-64: Add GLIBC_ABI_GNU2_TLS version [BZ #33129] + + Programs and shared libraries compiled with -mtls-dialect=gnu2 may fail + silently at run-time against glibc without the GNU2 TLS run-time fix + for: + + https://sourceware.org/bugzilla/show_bug.cgi?id=31372 + + Add GLIBC_ABI_GNU2_TLS version to indicate that glibc has the working + GNU2 TLS run-time. Linker can add the GLIBC_ABI_GNU2_TLS version to + binaries which depend on the working GNU2 TLS run-time: + + https://sourceware.org/bugzilla/show_bug.cgi?id=33130 + + so that such programs and shared libraries will fail to load and run at + run-time against libc.so without the GLIBC_ABI_GNU2_TLS version, instead + of fail silently at random. + + This fixes BZ #33129. + + Signed-off-by: H.J. Lu + Reviewed-by: Sam James + (cherry picked from commit 9df8fa397d515dc86ff5565f6c45625e672d539e) + +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index ce949dba27..a54c9be4bf 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -209,6 +209,15 @@ LDFLAGS-tst-plt-rewrite2 = -Wl,-z,now + LDFLAGS-tst-plt-rewritemod2.so = -Wl,-z,now,-z,undefs + tst-plt-rewrite2-ENV = GLIBC_TUNABLES=glibc.cpu.plt_rewrite=2 + $(objpfx)tst-plt-rewrite2: $(objpfx)tst-plt-rewritemod2.so ++ ++tests-special += $(objpfx)check-gnu2-tls.out ++ ++$(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so ++ LC_ALL=C $(READELF) -V -W $< \ ++ | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ ++ | grep GLIBC_ABI_GNU2_TLS > $@; \ ++ $(evaluate-test) ++generated += check-gnu2-tls.out + endif + + test-internal-extras += tst-gnu2-tls2mod1 +diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions +index e94758b236..a63c11bcb2 100644 +--- a/sysdeps/x86_64/Versions ++++ b/sysdeps/x86_64/Versions +@@ -5,6 +5,11 @@ libc { + GLIBC_2.13 { + __fentry__; + } ++ GLIBC_ABI_GNU2_TLS { ++ # This symbol is used only for empty version map and will be removed ++ # by scripts/versions.awk. ++ __placeholder_only_for_empty_version_map; ++ } + } + libm { + GLIBC_2.1 { + +commit 62e2c1d21fdf74f6146977ba97ace2efc61a3c18 +Author: H.J. Lu +Date: Thu Aug 14 07:03:20 2025 -0700 + + x86-64: Add GLIBC_ABI_DT_X86_64_PLT [BZ #33212] + + When the linker -z mark-plt option is used to add DT_X86_64_PLT, + DT_X86_64_PLTSZ and DT_X86_64_PLTENT, the r_addend field of the + R_X86_64_JUMP_SLOT relocation stores the offset of the indirect + branch instruction. However, glibc versions without the commit: + + commit f8587a61892cbafd98ce599131bf4f103466f084 + Author: H.J. Lu + Date: Fri May 20 19:21:48 2022 -0700 + + x86-64: Ignore r_addend for R_X86_64_GLOB_DAT/R_X86_64_JUMP_SLOT + + According to x86-64 psABI, r_addend should be ignored for R_X86_64_GLOB_DAT + and R_X86_64_JUMP_SLOT. Since linkers always set their r_addends to 0, we + can ignore their r_addends. + + Reviewed-by: Fangrui Song + + won't ignore the r_addend value in the R_X86_64_JUMP_SLOT relocation. + Such programs and shared libraries will fail at run-time randomly. + + Add GLIBC_ABI_DT_X86_64_PLT version to indicate that glibc is compatible + with DT_X86_64_PLT. + + The linker can add the glibc GLIBC_ABI_DT_X86_64_PLT version dependency + whenever -z mark-plt is passed to the linker. The resulting programs and + shared libraries will fail to load at run-time against libc.so without the + GLIBC_ABI_DT_X86_64_PLT version, instead of fail randomly. + + This fixes BZ #33212. + + Signed-off-by: H.J. Lu + Reviewed-by: Sam James + (cherry picked from commit 399384e0c8193e31aea014220ccfa24300ae5938) + +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index a54c9be4bf..e4895bd730 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -210,6 +210,15 @@ LDFLAGS-tst-plt-rewritemod2.so = -Wl,-z,now,-z,undefs + tst-plt-rewrite2-ENV = GLIBC_TUNABLES=glibc.cpu.plt_rewrite=2 + $(objpfx)tst-plt-rewrite2: $(objpfx)tst-plt-rewritemod2.so + ++tests-special += $(objpfx)check-dt-x86-64-plt.out ++ ++$(objpfx)check-dt-x86-64-plt.out: $(common-objpfx)libc.so ++ LC_ALL=C $(READELF) -V -W $< \ ++ | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ ++ | grep GLIBC_ABI_DT_X86_64_PLT > $@; \ ++ $(evaluate-test) ++generated += check-dt-x86-64-plt.out ++ + tests-special += $(objpfx)check-gnu2-tls.out + + $(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so +diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions +index a63c11bcb2..0a759029e5 100644 +--- a/sysdeps/x86_64/Versions ++++ b/sysdeps/x86_64/Versions +@@ -10,6 +10,11 @@ libc { + # by scripts/versions.awk. + __placeholder_only_for_empty_version_map; + } ++ GLIBC_ABI_DT_X86_64_PLT { ++ # This symbol is used only for empty version map and will be removed ++ # by scripts/versions.awk. ++ __placeholder_only_for_empty_version_map; ++ } + } + libm { + GLIBC_2.1 { + +commit e08360c48482ef8836030af6814c31881e1c4a4c +Author: Florian Weimer +Date: Fri Oct 25 16:50:10 2024 +0200 + + elf: Run constructors on cyclic recursive dlopen (bug 31986) + + This is conceptually similar to the reported bug, but does not + depend on auditing. The fix is simple: just complete execution + of the constructors. This exposed the fact that the link map + for statically linked executables does not have l_init_called + set, even though constructors have run. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 9897ced8e78db5d813166a7ccccfd5a42c69ef20) + +diff --git a/elf/Makefile b/elf/Makefile +index b0b8c3aaf6..83b5ceff9c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -416,6 +416,7 @@ tests += \ + tst-dlmopen1 \ + tst-dlmopen3 \ + tst-dlmopen4 \ ++ tst-dlopen-recurse \ + tst-dlopen-self \ + tst-dlopen-tlsmodid \ + tst-dlopen-tlsreinit1 \ +@@ -866,6 +867,8 @@ modules-names += \ + tst-dlmopen-twice-mod1 \ + tst-dlmopen-twice-mod2 \ + tst-dlmopen1mod \ ++ tst-dlopen-recursemod1 \ ++ tst-dlopen-recursemod2 \ + tst-dlopen-sgid-mod \ + tst-dlopen-tlsreinitmod1 \ + tst-dlopen-tlsreinitmod2 \ +@@ -3163,3 +3166,6 @@ $(objpfx)tst-dlopen-tlsreinit4.out: $(objpfx)tst-auditmod1.so + tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + + $(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so ++ ++$(objpfx)tst-dlopen-recurse.out: $(objpfx)tst-dlopen-recursemod1.so ++$(objpfx)tst-dlopen-recursemod1.so: $(objpfx)tst-dlopen-recursemod2.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 8556e7bd2f..5139d276e0 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -601,6 +601,14 @@ dl_open_worker_begin (void *a) + = _dl_debug_update (args->nsid)->r_state; + assert (r_state == RT_CONSISTENT); + ++ /* Do not return without calling the (supposedly new) map's ++ constructor. This case occurs if a dependency of a directly ++ opened map has a constructor that calls dlopen again on the ++ initially opened map. The new map is initialized last, so ++ checking only it is enough. */ ++ if (!new->l_init_called) ++ _dl_catch_exception (NULL, call_dl_init, args); ++ + return; + } + +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 451932dd03..94e8197c63 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -99,6 +99,7 @@ static struct link_map _dl_main_map = + .l_used = 1, + .l_tls_offset = NO_TLS_OFFSET, + .l_serial = 1, ++ .l_init_called = 1, + }; + + /* Namespace information. */ +diff --git a/elf/tst-dlopen-recurse.c b/elf/tst-dlopen-recurse.c +new file mode 100644 +index 0000000000..c7fb379d37 +--- /dev/null ++++ b/elf/tst-dlopen-recurse.c +@@ -0,0 +1,34 @@ ++/* Test that recursive dlopen runs constructors before return (bug 31986). ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlopen ("tst-dlopen-recursemod1.so", RTLD_NOW); ++ int *status = dlsym (handle, "recursemod1_status"); ++ printf ("info: recursemod1_status == %d (from main)\n", *status); ++ TEST_COMPARE (*status, 2); ++ xdlclose (handle); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-dlopen-recursemod1.c b/elf/tst-dlopen-recursemod1.c +new file mode 100644 +index 0000000000..5e0cc0eb8c +--- /dev/null ++++ b/elf/tst-dlopen-recursemod1.c +@@ -0,0 +1,50 @@ ++/* Directly opened test module that gets recursively opened again. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++int recursemod1_status; ++ ++/* Force linking against st-dlopen-recursemod2.so. Also allows ++ checking for relocation. */ ++extern int recursemod2_status; ++int *force_recursemod2_reference = &recursemod2_status; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ ++recursemod1_status; ++ printf ("info: tst-dlopen-recursemod1.so constructor called (status %d)\n", ++ recursemod1_status); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ /* The recursemod1_status variable was incremented in the ++ tst-dlopen-recursemod2.so constructor. */ ++ printf ("info: tst-dlopen-recursemod1.so destructor called (status %d)\n", ++ recursemod1_status); ++ if (recursemod1_status != 2) ++ { ++ puts ("error: recursemod1_status == 2 expected"); ++ exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-recursemod2.c b/elf/tst-dlopen-recursemod2.c +new file mode 100644 +index 0000000000..edd2f2526b +--- /dev/null ++++ b/elf/tst-dlopen-recursemod2.c +@@ -0,0 +1,66 @@ ++/* Indirectly opened module that recursively opens the directly opened module. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++int recursemod2_status; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ ++recursemod2_status; ++ printf ("info: tst-dlopen-recursemod2.so constructor called (status %d)\n", ++ recursemod2_status); ++ void *handle = dlopen ("tst-dlopen-recursemod1.so", RTLD_NOW); ++ if (handle == NULL) ++ { ++ printf ("error: dlopen: %s\n", dlerror ()); ++ exit (1); ++ } ++ int *status = dlsym (handle, "recursemod1_status"); ++ if (status == NULL) ++ { ++ printf ("error: dlsym: %s\n", dlerror ()); ++ exit (1); ++ } ++ printf ("info: recursemod1_status == %d\n", *status); ++ if (*status != 1) ++ { ++ puts ("error: recursemod1_status == 1 expected"); ++ exit (1); ++ } ++ ++*status; ++ printf ("info: recursemod1_status == %d\n", *status); ++ ++ int **mod2_status = dlsym (handle, "force_recursemod2_reference"); ++ if (mod2_status == NULL || *mod2_status != &recursemod2_status) ++ { ++ puts ("error: invalid recursemod2_status address in" ++ " tst-dlopen-recursemod1.so"); ++ exit (1); ++ } ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ printf ("info: tst-dlopen-recursemod2.so destructor called (status %d)\n", ++ recursemod2_status); ++} + +commit aeb63faf58ac8466f7b4e6d1101a5ffe1c4a426e +Author: Florian Weimer +Date: Fri Oct 25 16:50:10 2024 +0200 + + elf: Signal LA_ACT_CONSISTENT to auditors after RT_CONSISTENT switch + + Auditors can call into the dynamic loader again if + LA_ACT_CONSISTENT, and those recursive calls could observe + r_state != RT_CONSISTENT. + + We should consider failing dlopen/dlmopen/dlclose if + r_state != RT_CONSISTENT. The dynamic linker is probably not + in a state in which it can handle reentrant calls. This + needs further investigation. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit e096b7a1896886eb7dd2732ccbf1184b0eec9a63) + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 88226245eb..b6f4daac79 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -723,6 +723,11 @@ _dl_close_worker (struct link_map *map, bool force) + /* TLS is cleaned up for the unloaded modules. */ + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + ++ /* Notify the debugger those objects are finalized and gone. */ ++ r->r_state = RT_CONSISTENT; ++ _dl_debug_state (); ++ LIBC_PROBE (unmap_complete, 2, nsid, r); ++ + #ifdef SHARED + /* Auditing checkpoint: we have deleted all objects. Also, do not notify + auditors of the cleanup of a failed audit module loading attempt. */ +@@ -735,11 +740,6 @@ _dl_close_worker (struct link_map *map, bool force) + --GL(dl_nns); + while (GL(dl_ns)[GL(dl_nns) - 1]._ns_loaded == NULL); + +- /* Notify the debugger those objects are finalized and gone. */ +- r->r_state = RT_CONSISTENT; +- _dl_debug_state (); +- LIBC_PROBE (unmap_complete, 2, nsid, r); +- + /* Recheck if we need to retry, release the lock. */ + out: + if (dl_close_state == rerun) +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 5139d276e0..5a30a57ee1 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -639,17 +639,17 @@ dl_open_worker_begin (void *a) + #endif + } + +-#ifdef SHARED +- /* Auditing checkpoint: we have added all objects. */ +- _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT); +-#endif +- + /* Notify the debugger all new objects are now ready to go. */ + struct r_debug *r = _dl_debug_update (args->nsid); + r->r_state = RT_CONSISTENT; + _dl_debug_state (); + LIBC_PROBE (map_complete, 3, args->nsid, r, new); + ++#ifdef SHARED ++ /* Auditing checkpoint: we have added all objects. */ ++ _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT); ++#endif ++ + _dl_open_check (new); + + /* Print scope information. */ +diff --git a/elf/rtld.c b/elf/rtld.c +index e577006708..e012a597b4 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2417,9 +2417,6 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_relocate_object might need to call `mprotect' for DT_TEXTREL. */ + _dl_sysdep_start_cleanup (); + +- /* Auditing checkpoint: we have added all objects. */ +- _dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT); +- + /* Notify the debugger all new objects are now ready to go. We must re-get + the address since by now the variable might be in another object. */ + r = _dl_debug_update (LM_ID_BASE); +@@ -2427,6 +2424,9 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_debug_state (); + LIBC_PROBE (init_complete, 2, LM_ID_BASE, r); + ++ /* Auditing checkpoint: we have added all objects. */ ++ _dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT); ++ + #if defined USE_LDCONFIG && !defined MAP_COPY + /* We must munmap() the cache file. */ + _dl_unload_cache (); + +commit 91473c4eeab513ea2c502b987e0778a7591d847a +Author: Florian Weimer +Date: Fri Oct 25 16:50:10 2024 +0200 + + elf: Signal RT_CONSISTENT after relocation processing in dlopen (bug 31986) + + Previously, a la_activity audit event was generated before + relocation processing completed. This does did not match what + happened during initial startup in elf/rtld.c (towards the end + of dl_main). It also caused various problems if an auditor + tried to open the same shared object again using dlmopen: + If it was the directly loaded object, it had a search scope + associated with it, so the early exit in dl_open_worker_begin + was taken even though the object was unrelocated. This caused + the r_state == RT_CONSISTENT assert to fail. Avoidance of the + assert also depends on reversing the order of r_state update + and auditor event (already implemented in a previous commit). + + At the later point, args->map can be NULL due to failure, + so use the assigned namespace ID instead if that is available. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 43db5e2c0672cae7edea7c9685b22317eae25471) + +diff --git a/elf/Makefile b/elf/Makefile +index 83b5ceff9c..80a290074d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -416,6 +416,7 @@ tests += \ + tst-dlmopen1 \ + tst-dlmopen3 \ + tst-dlmopen4 \ ++ tst-dlopen-auditdup \ + tst-dlopen-recurse \ + tst-dlopen-self \ + tst-dlopen-tlsmodid \ +@@ -867,6 +868,8 @@ modules-names += \ + tst-dlmopen-twice-mod1 \ + tst-dlmopen-twice-mod2 \ + tst-dlmopen1mod \ ++ tst-dlopen-auditdup-auditmod \ ++ tst-dlopen-auditdupmod \ + tst-dlopen-recursemod1 \ + tst-dlopen-recursemod2 \ + tst-dlopen-sgid-mod \ +@@ -3169,3 +3172,6 @@ $(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so + + $(objpfx)tst-dlopen-recurse.out: $(objpfx)tst-dlopen-recursemod1.so + $(objpfx)tst-dlopen-recursemod1.so: $(objpfx)tst-dlopen-recursemod2.so ++tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so ++$(objpfx)tst-dlopen-auditdup.out: \ ++ $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 5a30a57ee1..88e8ad8d3a 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -576,6 +576,14 @@ dl_open_worker_begin (void *a) + _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + ++#ifdef SHARED ++ /* No relocation processing on this execution path. But ++ relocation has not been performed for static ++ position-dependent executables, so disable the assert for ++ static linking. */ ++ assert (new->l_relocated); ++#endif ++ + /* If the user requested the object to be in the global + namespace but it is not so far, prepare to add it now. This + can raise an exception to do a malloc failure. */ +@@ -597,10 +605,6 @@ dl_open_worker_begin (void *a) + if ((mode & RTLD_GLOBAL) && new->l_global == 0) + add_to_global_update (new); + +- const int r_state __attribute__ ((unused)) +- = _dl_debug_update (args->nsid)->r_state; +- assert (r_state == RT_CONSISTENT); +- + /* Do not return without calling the (supposedly new) map's + constructor. This case occurs if a dependency of a directly + opened map has a constructor that calls dlopen again on the +@@ -639,17 +643,6 @@ dl_open_worker_begin (void *a) + #endif + } + +- /* Notify the debugger all new objects are now ready to go. */ +- struct r_debug *r = _dl_debug_update (args->nsid); +- r->r_state = RT_CONSISTENT; +- _dl_debug_state (); +- LIBC_PROBE (map_complete, 3, args->nsid, r, new); +- +-#ifdef SHARED +- /* Auditing checkpoint: we have added all objects. */ +- _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT); +-#endif +- + _dl_open_check (new); + + /* Print scope information. */ +@@ -696,6 +689,7 @@ dl_open_worker_begin (void *a) + created dlmopen namespaces. Do not do this for static dlopen + because libc has relocations against ld.so, which may not have + been relocated at this point. */ ++ struct r_debug *r = _dl_debug_update (args->nsid); + #ifdef SHARED + if (GL(dl_ns)[args->nsid].libc_map != NULL) + _dl_open_relocate_one_object (args, r, GL(dl_ns)[args->nsid].libc_map, +@@ -787,6 +781,26 @@ dl_open_worker (void *a) + + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + ++ /* Auditing checkpoint and debugger signalling. Do this even on ++ error, so that dlopen exists with consistent state. */ ++ if (args->nsid >= 0 || args->map != NULL) ++ { ++ Lmid_t nsid = args->map != NULL ? args->map->l_ns : args->nsid; ++ struct r_debug *r = _dl_debug_update (nsid); ++#ifdef SHARED ++ bool was_not_consistent = r->r_state != RT_CONSISTENT; ++#endif ++ r->r_state = RT_CONSISTENT; ++ _dl_debug_state (); ++ LIBC_PROBE (map_complete, 3, nsid, r, new); ++ ++#ifdef SHARED ++ if (was_not_consistent) ++ /* Avoid redudant/recursive signalling. */ ++ _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT); ++#endif ++ } ++ + if (__glibc_unlikely (ex.errstring != NULL)) + /* Reraise the error. */ + _dl_signal_exception (err, &ex, NULL); +diff --git a/elf/tst-dlopen-auditdup-auditmod.c b/elf/tst-dlopen-auditdup-auditmod.c +new file mode 100644 +index 0000000000..9b67295e94 +--- /dev/null ++++ b/elf/tst-dlopen-auditdup-auditmod.c +@@ -0,0 +1,100 @@ ++/* Auditor that opens again an object that just has been opened. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ return LAV_CURRENT; ++} ++ ++static bool trigger_on_la_activity; ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ printf ("info: la_objopen: \"%s\"\n", map->l_name); ++ if (strstr (map->l_name, "/tst-dlopen-auditdupmod.so") != NULL) ++ trigger_on_la_activity = true; ++ return 0; ++} ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ static unsigned int calls; ++ ++calls; ++ printf ("info: la_activity: call %u (flag %u)\n", calls, flag); ++ fflush (stdout); ++ if (trigger_on_la_activity) ++ { ++ /* Avoid triggering on the dlmopen call below. */ ++ static bool recursion; ++ if (recursion) ++ return; ++ recursion = true; ++ ++ puts ("info: about to dlmopen tst-dlopen-auditdupmod.so"); ++ fflush (stdout); ++ void *handle = dlmopen (LM_ID_BASE, "tst-dlopen-auditdupmod.so", ++ RTLD_NOW); ++ if (handle == NULL) ++ { ++ printf ("error: dlmopen: %s\n", dlerror ()); ++ fflush (stdout); ++ _exit (1); ++ } ++ ++ /* Check that the constructor has run. */ ++ int *status = dlsym (handle, "auditdupmod_status"); ++ if (status == NULL) ++ { ++ printf ("error: dlsym: %s\n", dlerror ()); ++ fflush (stdout); ++ _exit (1); ++ } ++ printf ("info: auditdupmod_status == %d\n", *status); ++ if (*status != 1) ++ { ++ puts ("error: auditdupmod_status == 1 expected"); ++ fflush (stdout); ++ _exit (1); ++ } ++ /* Checked in the destructor and the main program. */ ++ ++*status; ++ printf ("info: auditdupmod_status == %d\n", *status); ++ ++ /* Check that the module has been relocated. */ ++ int **status_address = dlsym (handle, "auditdupmod_status_address"); ++ if (status_address == NULL || *status_address != status) ++ { ++ puts ("error: invalid auditdupmod_status address in" ++ " tst-dlopen-auditdupmod.so"); ++ fflush (stdout); ++ _exit (1); ++ } ++ ++ fflush (stdout); ++ } ++} +diff --git a/elf/tst-dlopen-auditdup.c b/elf/tst-dlopen-auditdup.c +new file mode 100644 +index 0000000000..d022c58ae3 +--- /dev/null ++++ b/elf/tst-dlopen-auditdup.c +@@ -0,0 +1,36 @@ ++/* Test that recursive dlopen from auditor works (bug 31986). ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ puts ("info: about to dlopen tst-dlopen-auditdupmod.so"); ++ fflush (stdout); ++ void *handle = xdlopen ("tst-dlopen-auditdupmod.so", RTLD_NOW); ++ int *status = xdlsym (handle, "auditdupmod_status"); ++ printf ("info: auditdupmod_status == %d (from main)\n", *status); ++ TEST_COMPARE (*status, 2); ++ xdlclose (handle); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-dlopen-auditdupmod.c b/elf/tst-dlopen-auditdupmod.c +new file mode 100644 +index 0000000000..59b7e21daa +--- /dev/null ++++ b/elf/tst-dlopen-auditdupmod.c +@@ -0,0 +1,48 @@ ++/* Directly opened test module that gets reopened from the auditor. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++int auditdupmod_status; ++ ++/* Used to check for successful relocation processing. */ ++int *auditdupmod_status_address = &auditdupmod_status; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ ++auditdupmod_status; ++ printf ("info: tst-dlopen-auditdupmod.so constructor called (status %d)\n", ++ auditdupmod_status); ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ /* The tst-dlopen-auditdup-auditmod.so auditor incremented ++ auditdupmod_status. */ ++ printf ("info: tst-dlopen-auditdupmod.so destructor called (status %d)\n", ++ auditdupmod_status); ++ if (auditdupmod_status != 2) ++ { ++ puts ("error: auditdupmod_status == 2 expected"); ++ exit (1); ++ } ++} + +commit d9bd6f386912ef1dbc0434d7cc03eae5ded86181 +Author: Florian Weimer +Date: Fri Oct 25 17:41:53 2024 +0200 + + elf: Fix map_complete Systemtap probe in dl_open_worker + + The refactoring did not take the change of variable into account. + Fixes commit 43db5e2c0672cae7edea7c9685b22317eae25471 + ("elf: Signal RT_CONSISTENT after relocation processing in dlopen + (bug 31986)"). + + (cherry picked from commit ac73067cb7a328bf106ecd041c020fc61be7e087) + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 88e8ad8d3a..bd15f5f6a4 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -792,7 +792,7 @@ dl_open_worker (void *a) + #endif + r->r_state = RT_CONSISTENT; + _dl_debug_state (); +- LIBC_PROBE (map_complete, 3, nsid, r, new); ++ LIBC_PROBE (map_complete, 3, nsid, r, args->map); + + #ifdef SHARED + if (was_not_consistent) + +commit 23f95986fca6bc23538050332af297cda4805e45 +Author: Florian Weimer +Date: Mon Oct 28 14:45:30 2024 +0100 + + Revert "elf: Run constructors on cyclic recursive dlopen (bug 31986)" + + This reverts commit 9897ced8e78db5d813166a7ccccfd5a42c69ef20. + + Adjust the test expectations in elf/tst-dlopen-auditdup-auditmod.c + accordingly. + + (cherry picked from commit 95129e6b8fabdaa8cd8a4a5cc20be0f4cb0ba59f) + +diff --git a/elf/Makefile b/elf/Makefile +index 80a290074d..0d018be60f 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -417,7 +417,6 @@ tests += \ + tst-dlmopen3 \ + tst-dlmopen4 \ + tst-dlopen-auditdup \ +- tst-dlopen-recurse \ + tst-dlopen-self \ + tst-dlopen-tlsmodid \ + tst-dlopen-tlsreinit1 \ +@@ -870,8 +869,6 @@ modules-names += \ + tst-dlmopen1mod \ + tst-dlopen-auditdup-auditmod \ + tst-dlopen-auditdupmod \ +- tst-dlopen-recursemod1 \ +- tst-dlopen-recursemod2 \ + tst-dlopen-sgid-mod \ + tst-dlopen-tlsreinitmod1 \ + tst-dlopen-tlsreinitmod2 \ +@@ -3170,8 +3167,6 @@ tst-dlopen-tlsreinit4-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + + $(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so + +-$(objpfx)tst-dlopen-recurse.out: $(objpfx)tst-dlopen-recursemod1.so +-$(objpfx)tst-dlopen-recursemod1.so: $(objpfx)tst-dlopen-recursemod2.so + tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so + $(objpfx)tst-dlopen-auditdup.out: \ + $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index bd15f5f6a4..b00f283c42 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -605,14 +605,6 @@ dl_open_worker_begin (void *a) + if ((mode & RTLD_GLOBAL) && new->l_global == 0) + add_to_global_update (new); + +- /* Do not return without calling the (supposedly new) map's +- constructor. This case occurs if a dependency of a directly +- opened map has a constructor that calls dlopen again on the +- initially opened map. The new map is initialized last, so +- checking only it is enough. */ +- if (!new->l_init_called) +- _dl_catch_exception (NULL, call_dl_init, args); +- + return; + } + +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 94e8197c63..451932dd03 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -99,7 +99,6 @@ static struct link_map _dl_main_map = + .l_used = 1, + .l_tls_offset = NO_TLS_OFFSET, + .l_serial = 1, +- .l_init_called = 1, + }; + + /* Namespace information. */ +diff --git a/elf/tst-dlopen-auditdup-auditmod.c b/elf/tst-dlopen-auditdup-auditmod.c +index 9b67295e94..270a595ec4 100644 +--- a/elf/tst-dlopen-auditdup-auditmod.c ++++ b/elf/tst-dlopen-auditdup-auditmod.c +@@ -66,7 +66,11 @@ la_activity (uintptr_t *cookie, unsigned int flag) + _exit (1); + } + +- /* Check that the constructor has run. */ ++ /* Check that the constructor has not run. Running the ++ constructor would require constructing its dependencies, but ++ the constructor call that triggered this auditing activity ++ has not completed, and constructors among the dependencies ++ may not be able to deal with that. */ + int *status = dlsym (handle, "auditdupmod_status"); + if (status == NULL) + { +@@ -75,9 +79,9 @@ la_activity (uintptr_t *cookie, unsigned int flag) + _exit (1); + } + printf ("info: auditdupmod_status == %d\n", *status); +- if (*status != 1) ++ if (*status != 0) + { +- puts ("error: auditdupmod_status == 1 expected"); ++ puts ("error: auditdupmod_status == 0 expected"); + fflush (stdout); + _exit (1); + } +diff --git a/elf/tst-dlopen-recurse.c b/elf/tst-dlopen-recurse.c +deleted file mode 100644 +index c7fb379d37..0000000000 +--- a/elf/tst-dlopen-recurse.c ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* Test that recursive dlopen runs constructors before return (bug 31986). +- Copyright (C) 2024 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library 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. +- +- The GNU C Library 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 the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +- +-static int +-do_test (void) +-{ +- void *handle = xdlopen ("tst-dlopen-recursemod1.so", RTLD_NOW); +- int *status = dlsym (handle, "recursemod1_status"); +- printf ("info: recursemod1_status == %d (from main)\n", *status); +- TEST_COMPARE (*status, 2); +- xdlclose (handle); +- return 0; +-} +- +-#include +diff --git a/elf/tst-dlopen-recursemod1.c b/elf/tst-dlopen-recursemod1.c +deleted file mode 100644 +index 5e0cc0eb8c..0000000000 +--- a/elf/tst-dlopen-recursemod1.c ++++ /dev/null +@@ -1,50 +0,0 @@ +-/* Directly opened test module that gets recursively opened again. +- Copyright (C) 2024 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library 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. +- +- The GNU C Library 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 the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +- +-int recursemod1_status; +- +-/* Force linking against st-dlopen-recursemod2.so. Also allows +- checking for relocation. */ +-extern int recursemod2_status; +-int *force_recursemod2_reference = &recursemod2_status; +- +-static void __attribute__ ((constructor)) +-init (void) +-{ +- ++recursemod1_status; +- printf ("info: tst-dlopen-recursemod1.so constructor called (status %d)\n", +- recursemod1_status); +-} +- +-static void __attribute__ ((destructor)) +-fini (void) +-{ +- /* The recursemod1_status variable was incremented in the +- tst-dlopen-recursemod2.so constructor. */ +- printf ("info: tst-dlopen-recursemod1.so destructor called (status %d)\n", +- recursemod1_status); +- if (recursemod1_status != 2) +- { +- puts ("error: recursemod1_status == 2 expected"); +- exit (1); +- } +-} +diff --git a/elf/tst-dlopen-recursemod2.c b/elf/tst-dlopen-recursemod2.c +deleted file mode 100644 +index edd2f2526b..0000000000 +--- a/elf/tst-dlopen-recursemod2.c ++++ /dev/null +@@ -1,66 +0,0 @@ +-/* Indirectly opened module that recursively opens the directly opened module. +- Copyright (C) 2024 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library 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. +- +- The GNU C Library 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 the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +- +-int recursemod2_status; +- +-static void __attribute__ ((constructor)) +-init (void) +-{ +- ++recursemod2_status; +- printf ("info: tst-dlopen-recursemod2.so constructor called (status %d)\n", +- recursemod2_status); +- void *handle = dlopen ("tst-dlopen-recursemod1.so", RTLD_NOW); +- if (handle == NULL) +- { +- printf ("error: dlopen: %s\n", dlerror ()); +- exit (1); +- } +- int *status = dlsym (handle, "recursemod1_status"); +- if (status == NULL) +- { +- printf ("error: dlsym: %s\n", dlerror ()); +- exit (1); +- } +- printf ("info: recursemod1_status == %d\n", *status); +- if (*status != 1) +- { +- puts ("error: recursemod1_status == 1 expected"); +- exit (1); +- } +- ++*status; +- printf ("info: recursemod1_status == %d\n", *status); +- +- int **mod2_status = dlsym (handle, "force_recursemod2_reference"); +- if (mod2_status == NULL || *mod2_status != &recursemod2_status) +- { +- puts ("error: invalid recursemod2_status address in" +- " tst-dlopen-recursemod1.so"); +- exit (1); +- } +-} +- +-static void __attribute__ ((destructor)) +-fini (void) +-{ +- printf ("info: tst-dlopen-recursemod2.so destructor called (status %d)\n", +- recursemod2_status); +-} + +commit 812918bbde0e44d2cca303084b16a43f6a10190c +Author: Florian Weimer +Date: Wed Nov 6 10:33:44 2024 +0100 + + elf: rtld_multiple_ref is always true + + For a long time, libc.so.6 has dependend on ld.so, which + means that there is a reference to ld.so in all processes, + and rtld_multiple_ref is always true. In fact, if + rtld_multiple_ref were false, some of the ld.so setup code + would not run. + + Reviewed-by: DJ Delorie + (cherry picked from commit 8f8dd904c4a2207699bb666f30acceb5209c8d3f) + +diff --git a/elf/rtld.c b/elf/rtld.c +index e012a597b4..32c1b86697 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2011,43 +2011,37 @@ dl_main (const ElfW(Phdr) *phdr, + if (main_map->l_searchlist.r_list[i] == &GL(dl_rtld_map)) + break; + +- bool rtld_multiple_ref = false; +- if (__glibc_likely (i < main_map->l_searchlist.r_nlist)) +- { +- /* Some DT_NEEDED entry referred to the interpreter object itself, so +- put it back in the list of visible objects. We insert it into the +- chain in symbol search order because gdb uses the chain's order as +- its symbol search order. */ +- rtld_multiple_ref = true; ++ /* Insert the link map for the dynamic loader into the chain in ++ symbol search order because gdb uses the chain's order as its ++ symbol search order. */ + +- GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1]; +- if (__glibc_likely (state.mode == rtld_mode_normal)) +- { +- GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist +- ? main_map->l_searchlist.r_list[i + 1] +- : NULL); ++ GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1]; ++ if (__glibc_likely (state.mode == rtld_mode_normal)) ++ { ++ GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist ++ ? main_map->l_searchlist.r_list[i + 1] ++ : NULL); + #ifdef NEED_DL_SYSINFO_DSO +- if (GLRO(dl_sysinfo_map) != NULL +- && GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map) +- && GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map)) +- GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map); ++ if (GLRO(dl_sysinfo_map) != NULL ++ && GL(dl_rtld_map).l_prev->l_next == GLRO(dl_sysinfo_map) ++ && GL(dl_rtld_map).l_next != GLRO(dl_sysinfo_map)) ++ GL(dl_rtld_map).l_prev = GLRO(dl_sysinfo_map); + #endif +- } +- else +- /* In trace mode there might be an invisible object (which we +- could not find) after the previous one in the search list. +- In this case it doesn't matter much where we put the +- interpreter object, so we just initialize the list pointer so +- that the assertion below holds. */ +- GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next; +- +- assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next); +- GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map); +- if (GL(dl_rtld_map).l_next != NULL) +- { +- assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev); +- GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map); +- } ++ } ++ else ++ /* In trace mode there might be an invisible object (which we ++ could not find) after the previous one in the search list. ++ In this case it doesn't matter much where we put the ++ interpreter object, so we just initialize the list pointer so ++ that the assertion below holds. */ ++ GL(dl_rtld_map).l_next = GL(dl_rtld_map).l_prev->l_next; ++ ++ assert (GL(dl_rtld_map).l_prev->l_next == GL(dl_rtld_map).l_next); ++ GL(dl_rtld_map).l_prev->l_next = &GL(dl_rtld_map); ++ if (GL(dl_rtld_map).l_next != NULL) ++ { ++ assert (GL(dl_rtld_map).l_next->l_prev == GL(dl_rtld_map).l_prev); ++ GL(dl_rtld_map).l_next->l_prev = &GL(dl_rtld_map); + } + + /* Now let us see whether all libraries are available in the +@@ -2375,35 +2369,33 @@ dl_main (const ElfW(Phdr) *phdr, + /* Make sure no new search directories have been added. */ + assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); + +- if (rtld_multiple_ref) +- { +- /* There was an explicit ref to the dynamic linker as a shared lib. +- Re-relocate ourselves with user-controlled symbol definitions. ++ /* Re-relocate ourselves with user-controlled symbol definitions. + +- We must do this after TLS initialization in case after this +- re-relocation, we might call a user-supplied function +- (e.g. calloc from _dl_relocate_object) that uses TLS data. */ ++ We must do this after TLS initialization in case after this ++ re-relocation, we might call a user-supplied function ++ (e.g. calloc from _dl_relocate_object) that uses TLS data. */ + +- /* Set up the object lookup structures. */ +- _dl_find_object_init (); ++ /* Set up the object lookup structures. */ ++ _dl_find_object_init (); + +- /* The malloc implementation has been relocated, so resolving +- its symbols (and potentially calling IFUNC resolvers) is safe +- at this point. */ +- __rtld_malloc_init_real (main_map); ++ /* The malloc implementation has been relocated, so resolving ++ its symbols (and potentially calling IFUNC resolvers) is safe ++ at this point. */ ++ __rtld_malloc_init_real (main_map); + +- /* Likewise for the locking implementation. */ +- __rtld_mutex_init (); ++ /* Likewise for the locking implementation. */ ++ __rtld_mutex_init (); + +- RTLD_TIMING_VAR (start); +- rtld_timer_start (&start); ++ { ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + +- /* Mark the link map as not yet relocated again. */ +- GL(dl_rtld_map).l_relocated = 0; +- _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); ++ /* Mark the link map as not yet relocated again. */ ++ GL(dl_rtld_map).l_relocated = 0; ++ _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); + +- rtld_timer_accum (&relocate_time, start); +- } ++ rtld_timer_accum (&relocate_time, start); ++ } + + /* Relocation is complete. Perform early libc initialization. This + is the initial libc, even if audit modules have been loaded with + +commit 3b03a301e7452dbacd92fc1558cd50b9bbab7e78 +Author: Florian Weimer +Date: Wed Nov 6 10:33:44 2024 +0100 + + elf: Do not define consider_profiling, consider_symbind as macros + + This avoids surprises when refactoring the code if these identifiers + are re-used later in the file. + + Reviewed-by: DJ Delorie + (cherry picked from commit a79642204537dec8a1e1c58d1e0a074b3c624f46) + +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index 4bf7aec88b..b2c1627ceb 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -220,8 +220,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + int lazy = reloc_mode & RTLD_LAZY; + int skip_ifunc = reloc_mode & __RTLD_NOIFUNC; + +-#ifdef SHARED + bool consider_symbind = false; ++#ifdef SHARED + /* If we are auditing, install the same handlers we need for profiling. */ + if ((reloc_mode & __RTLD_AUDIT) == 0) + { +@@ -240,9 +240,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + } + #elif defined PROF + /* Never use dynamic linker profiling for gprof profiling code. */ +-# define consider_profiling 0 +-#else +-# define consider_symbind 0 ++ consider_profiling = 0; + #endif + + /* If DT_BIND_NOW is set relocate all references in this object. We +@@ -300,7 +298,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + + ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); + +-#ifndef PROF + if ((consider_profiling || consider_symbind) + && l->l_info[DT_PLTRELSZ] != NULL) + { +@@ -321,7 +318,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + _dl_fatal_printf (errstring, RTLD_PROGNAME, l->l_name); + } + } +-#endif + } + + /* Mark the object so we know this work has been done. */ + +commit 7fd2dac6d6604822597dafb9d1b3e2c6a11f8422 +Author: Florian Weimer +Date: Wed Nov 6 10:33:44 2024 +0100 + + elf: Introduce _dl_relocate_object_no_relro + + And make _dl_protect_relro apply RELRO conditionally. + + Reviewed-by: DJ Delorie + (cherry picked from commit f2326c2ec0a0a8db7bc7f4db8cce3002768fc3b6) + +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index b2c1627ceb..76d14830dd 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -202,12 +202,9 @@ resolve_map (lookup_t l, struct r_scope_elem *scope[], const ElfW(Sym) **ref, + #include "dynamic-link.h" + + void +-_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], +- int reloc_mode, int consider_profiling) ++_dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[], ++ int reloc_mode, int consider_profiling) + { +- if (l->l_relocated) +- return; +- + struct textrels + { + caddr_t start; +@@ -338,17 +335,24 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + + textrels = textrels->next; + } +- +- /* In case we can protect the data now that the relocations are +- done, do it. */ +- if (l->l_relro_size != 0) +- _dl_protect_relro (l); + } + ++void ++_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], ++ int reloc_mode, int consider_profiling) ++{ ++ if (l->l_relocated) ++ return; ++ _dl_relocate_object_no_relro (l, scope, reloc_mode, consider_profiling); ++ _dl_protect_relro (l); ++} + + void + _dl_protect_relro (struct link_map *l) + { ++ if (l->l_relro_size == 0) ++ return; ++ + ElfW(Addr) start = ALIGN_DOWN((l->l_addr + + l->l_relro_addr), + GLRO(dl_pagesize)); +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 259ce2e7d6..91447a5e77 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1014,6 +1014,13 @@ extern void _dl_relocate_object (struct link_map *map, + int reloc_mode, int consider_profiling) + attribute_hidden; + ++/* Perform relocation, but do not apply RELRO. Does not check ++ L->relocated. Otherwise the same as _dl_relocate_object. */ ++void _dl_relocate_object_no_relro (struct link_map *map, ++ struct r_scope_elem *scope[], ++ int reloc_mode, int consider_profiling) ++ attribute_hidden; ++ + /* Protect PT_GNU_RELRO area. */ + extern void _dl_protect_relro (struct link_map *map) attribute_hidden; + + +commit 630be04e0430f044d32f45c912b4f5d9cdf57007 +Author: Florian Weimer +Date: Wed Nov 6 10:33:44 2024 +0100 + + elf: Switch to main malloc after final ld.so self-relocation + + Before commit ee1ada1bdb8074de6e1bdc956ab19aef7b6a7872 + ("elf: Rework exception handling in the dynamic loader + [BZ #25486]"), the previous order called the main calloc + to allocate a shadow GOT/PLT array for auditing support. + This happened before libc.so.6 ELF constructors were run, so + a user malloc could run without libc.so.6 having been + initialized fully. One observable effect was that + environ was NULL at this point. + + It does not seem to be possible at present to trigger such + an allocation, but it seems more robust to delay switching + to main malloc after ld.so self-relocation is complete. + The elf/tst-rtld-no-malloc-audit test case fails with a + 2.34-era glibc that does not have this fix. + + Reviewed-by: DJ Delorie + (cherry picked from commit c1560f3f75c0e892b5522c16f91b4e303f677094) + +diff --git a/elf/Makefile b/elf/Makefile +index 0d018be60f..fed2ff15f9 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -455,6 +455,9 @@ tests += \ + tst-recursive-tls \ + tst-relsort1 \ + tst-ro-dynamic \ ++ tst-rtld-no-malloc \ ++ tst-rtld-no-malloc-audit \ ++ tst-rtld-no-malloc-preload \ + tst-rtld-run-static \ + tst-single_threaded \ + tst-single_threaded-pthread \ +@@ -3170,3 +3173,9 @@ $(objpfx)tst-dlopen-sgid.out: $(objpfx)tst-dlopen-sgid-mod.so + tst-dlopen-auditdup-ENV = LD_AUDIT=$(objpfx)tst-dlopen-auditdup-auditmod.so + $(objpfx)tst-dlopen-auditdup.out: \ + $(objpfx)tst-dlopen-auditdupmod.so $(objpfx)tst-dlopen-auditdup-auditmod.so ++ ++# Reuse an audit module which provides ample debug logging. ++tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so ++ ++# Any shared object should do. ++tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 451932dd03..ee590edf93 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -338,8 +338,7 @@ _dl_non_dynamic_init (void) + call_function_static_weak (_dl_find_object_init); + + /* Setup relro on the binary itself. */ +- if (_dl_main_map.l_relro_size != 0) +- _dl_protect_relro (&_dl_main_map); ++ _dl_protect_relro (&_dl_main_map); + } + + #ifdef DL_SYSINFO_IMPLEMENTATION +diff --git a/elf/rtld.c b/elf/rtld.c +index 32c1b86697..4adfc67260 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2369,30 +2369,27 @@ dl_main (const ElfW(Phdr) *phdr, + /* Make sure no new search directories have been added. */ + assert (GLRO(dl_init_all_dirs) == GL(dl_all_dirs)); + +- /* Re-relocate ourselves with user-controlled symbol definitions. +- +- We must do this after TLS initialization in case after this +- re-relocation, we might call a user-supplied function +- (e.g. calloc from _dl_relocate_object) that uses TLS data. */ +- + /* Set up the object lookup structures. */ + _dl_find_object_init (); + +- /* The malloc implementation has been relocated, so resolving +- its symbols (and potentially calling IFUNC resolvers) is safe +- at this point. */ +- __rtld_malloc_init_real (main_map); +- + /* Likewise for the locking implementation. */ + __rtld_mutex_init (); + ++ /* Re-relocate ourselves with user-controlled symbol definitions. */ ++ + { + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); + +- /* Mark the link map as not yet relocated again. */ +- GL(dl_rtld_map).l_relocated = 0; +- _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); ++ _dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0); ++ ++ /* The malloc implementation has been relocated, so resolving ++ its symbols (and potentially calling IFUNC resolvers) is safe ++ at this point. */ ++ __rtld_malloc_init_real (main_map); ++ ++ if (GL(dl_rtld_map).l_relro_size != 0) ++ _dl_protect_relro (&GL(dl_rtld_map)); + + rtld_timer_accum (&relocate_time, start); + } +diff --git a/elf/tst-rtld-no-malloc-audit.c b/elf/tst-rtld-no-malloc-audit.c +new file mode 100644 +index 0000000000..a028377ad1 +--- /dev/null ++++ b/elf/tst-rtld-no-malloc-audit.c +@@ -0,0 +1 @@ ++#include "tst-rtld-no-malloc.c" +diff --git a/elf/tst-rtld-no-malloc-preload.c b/elf/tst-rtld-no-malloc-preload.c +new file mode 100644 +index 0000000000..a028377ad1 +--- /dev/null ++++ b/elf/tst-rtld-no-malloc-preload.c +@@ -0,0 +1 @@ ++#include "tst-rtld-no-malloc.c" +diff --git a/elf/tst-rtld-no-malloc.c b/elf/tst-rtld-no-malloc.c +new file mode 100644 +index 0000000000..5f24d4bd72 +--- /dev/null ++++ b/elf/tst-rtld-no-malloc.c +@@ -0,0 +1,76 @@ ++/* Test that program loading does not call malloc. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++ ++#include ++#include ++ ++static void ++print (const char *s) ++{ ++ const char *end = s + strlen (s); ++ while (s < end) ++ { ++ ssize_t ret = write (STDOUT_FILENO, s, end - s); ++ if (ret <= 0) ++ _exit (2); ++ s += ret; ++ } ++} ++ ++static void __attribute__ ((noreturn)) ++unexpected_call (const char *function) ++{ ++ print ("error: unexpected call to "); ++ print (function); ++ print ("\n"); ++ _exit (1); ++} ++ ++/* These are the malloc functions implement in elf/dl-minimal.c. */ ++ ++void ++free (void *ignored) ++{ ++ unexpected_call ("free"); ++} ++ ++void * ++calloc (size_t ignored1, size_t ignored2) ++{ ++ unexpected_call ("calloc"); ++} ++ ++void * ++malloc (size_t ignored) ++{ ++ unexpected_call ("malloc"); ++} ++ ++void * ++realloc (void *ignored1, size_t ignored2) ++{ ++ unexpected_call ("realloc"); ++} ++ ++int ++main (void) ++{ ++ /* Do not use the test wrapper, to avoid spurious malloc calls from it. */ ++ return 0; ++} + +commit f86839fc158e571ad99774fdeaaa2ad12d9109c1 +Author: Florian Weimer +Date: Tue Sep 3 17:52:47 2024 +0200 + + elf: Update DSO list, write audit log to elf/tst-audit23.out + + After commit 1d5024f4f052c12e404d42d3b5bfe9c3e9fd27c4 + ("support: Build with exceptions and asynchronous unwind tables + [BZ #30587]"), libgcc_s is expected to show up in the DSO + list on 32-bit Arm. Do not update max_objs because vdso is not + tracked (and which is the reason why the test currently passes + even with libgcc_s present). + + Also write the log output from the auditor to standard output, + for easier test debugging. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 4a50fdf8b2c1106b50cd9056b4c6f3a72cdeed5f) + +diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c +index d2640fe8b2..895dab08ea 100644 +--- a/elf/tst-audit23.c ++++ b/elf/tst-audit23.c +@@ -85,13 +85,28 @@ do_test (int argc, char *argv[]) + = support_capture_subprogram (spargv[0], spargv, NULL); + support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); + ++ { ++ FILE *fp = fmemopen (result.err.buffer, result.err.length, "r"); ++ TEST_VERIFY (fp != NULL); ++ unsigned int line = 0; ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ puts ("info: *** audit log start ***"); ++ while (xgetline (&buffer, &buffer_length, fp)) ++ printf ("%6u\t%s", ++line, buffer); ++ puts ("info: *** audit log end ***"); ++ free (buffer); ++ xfclose (fp); ++ } ++ + /* The expected la_objopen/la_objclose: + 1. executable + 2. loader + 3. libc.so +- 4. tst-audit23mod.so +- 5. libc.so (LM_ID_NEWLM). +- 6. vdso (optional and ignored). */ ++ 4. libgcc_s.so (one some architectures, for libsupport) ++ 5. tst-audit23mod.so ++ 6. libc.so (LM_ID_NEWLM). ++ vdso (optional and ignored). */ + enum { max_objs = 6 }; + struct la_obj_t + { +@@ -115,8 +130,10 @@ do_test (int argc, char *argv[]) + TEST_VERIFY (out != NULL); + char *buffer = NULL; + size_t buffer_length = 0; ++ unsigned int line = 0; + while (xgetline (&buffer, &buffer_length, out)) + { ++ ++line; + if (startswith (buffer, "la_activity: ")) + { + uintptr_t cookie; +@@ -174,8 +191,8 @@ do_test (int argc, char *argv[]) + if (is_vdso (lname)) + continue; + if (nobjs == max_objs) +- FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld", +- lname, laddr, lmid); ++ FAIL_EXIT1 ("(line %u) non expected la_objopen: %s %"PRIxPTR" %ld", ++ line, lname, laddr, lmid); + objs[nobjs].lname = lname; + objs[nobjs].laddr = laddr; + objs[nobjs].lmid = lmid; + +commit 341233a2507209872e5a6fe80efbd16c40c3c2cd +Author: Florian Weimer +Date: Fri Nov 29 15:36:40 2024 +0100 + + elf: Add the endswith function to + + And include for a definition of bool. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit a20bc2f6233a726c7df8eaa332b6e498bd59321f) + +diff --git a/elf/endswith.h b/elf/endswith.h +index c6430c48be..3954e57f8e 100644 +--- a/elf/endswith.h ++++ b/elf/endswith.h +@@ -17,6 +17,7 @@ + #ifndef _ENDSWITH_H + #define _ENDSWITH_H + ++#include + #include + + /* Return true if the N bytes at NAME end with with the characters in +@@ -30,4 +31,11 @@ endswithn (const char *name, size_t n, const char *suffix) + strlen (suffix)) == 0); + } + ++/* Same as endswithn, but uses the entire SUBJECT for matching. */ ++static inline bool ++endswith (const char *subject, const char *suffix) ++{ ++ return endswithn (subject, strlen (subject), suffix); ++} ++ + #endif /* _ENDSWITH_H */ + +commit c10543d15b0e41057c8436ce1c88f6b92db47a07 +Author: Florian Weimer +Date: Fri Aug 9 15:31:18 2024 +0200 + + elf: Signal la_objopen for the proxy link map in dlmopen (bug 31985) + + Previously, the ld.so link map was silently added to the namespace. + This change produces an auditing event for it. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 8f36b1469677afe37168f9af1b77402d7a70c673) + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 8a89b71016..54c9c4d779 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -918,6 +918,37 @@ _dl_process_pt_gnu_property (struct link_map *l, int fd, const ElfW(Phdr) *ph) + } + } + ++static void ++_dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l) ++{ ++ /* Signal that we are going to add new objects. */ ++ struct r_debug *r = _dl_debug_update (nsid); ++ if (r->r_state == RT_CONSISTENT) ++ { ++#ifdef SHARED ++ /* Auditing checkpoint: we are going to add new objects. Since this ++ is called after _dl_add_to_namespace_list the namespace is guaranteed ++ to not be empty. */ ++ if ((mode & __RTLD_AUDIT) == 0) ++ _dl_audit_activity_nsid (nsid, LA_ACT_ADD); ++#endif ++ ++ /* Notify the debugger we have added some objects. We need to ++ call _dl_debug_initialize in a static program in case dynamic ++ linking has not been used before. */ ++ r->r_state = RT_ADD; ++ _dl_debug_state (); ++ LIBC_PROBE (map_start, 2, nsid, r); ++ } ++ else ++ assert (r->r_state == RT_ADD); ++ ++#ifdef SHARED ++ /* Auditing checkpoint: we have a new object. */ ++ if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) ++ _dl_audit_objopen (l, nsid); ++#endif ++} + + /* Map in the shared object NAME, actually located in REALNAME, and already + opened on FD. */ +@@ -1018,6 +1049,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + /* Add the map for the mirrored object to the object list. */ + _dl_add_to_namespace_list (l, nsid); + ++ _dl_notify_new_object (mode, nsid, l); ++ + return l; + } + #endif +@@ -1442,33 +1475,7 @@ cannot enable executable stack as shared object requires"); + if (mode & __RTLD_SPROF) + return l; + +- /* Signal that we are going to add new objects. */ +- struct r_debug *r = _dl_debug_update (nsid); +- if (r->r_state == RT_CONSISTENT) +- { +-#ifdef SHARED +- /* Auditing checkpoint: we are going to add new objects. Since this +- is called after _dl_add_to_namespace_list the namespace is guaranteed +- to not be empty. */ +- if ((mode & __RTLD_AUDIT) == 0) +- _dl_audit_activity_nsid (nsid, LA_ACT_ADD); +-#endif +- +- /* Notify the debugger we have added some objects. We need to +- call _dl_debug_initialize in a static program in case dynamic +- linking has not been used before. */ +- r->r_state = RT_ADD; +- _dl_debug_state (); +- LIBC_PROBE (map_start, 2, nsid, r); +- } +- else +- assert (r->r_state == RT_ADD); +- +-#ifdef SHARED +- /* Auditing checkpoint: we have a new object. */ +- if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) +- _dl_audit_objopen (l, nsid); +-#endif ++ _dl_notify_new_object (mode, nsid, l); + + return l; + } +diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c +index 895dab08ea..c8c6553b8f 100644 +--- a/elf/tst-audit23.c ++++ b/elf/tst-audit23.c +@@ -17,6 +17,7 @@ + . */ + + #include ++#include + #include + #include + #include +@@ -106,8 +107,9 @@ do_test (int argc, char *argv[]) + 4. libgcc_s.so (one some architectures, for libsupport) + 5. tst-audit23mod.so + 6. libc.so (LM_ID_NEWLM). ++ 7. loader (proxy link map in new namespace) + vdso (optional and ignored). */ +- enum { max_objs = 6 }; ++ enum { max_objs = 7 }; + struct la_obj_t + { + char *lname; +@@ -236,7 +238,9 @@ do_test (int argc, char *argv[]) + + for (size_t i = 0; i < nobjs; i++) + { +- TEST_COMPARE (objs[i].closed, true); ++ /* This subtest currently does not pass because of bug 32065. */ ++ if (! (endswith (objs[i].lname, LD_SO) && objs[i].lmid != LM_ID_BASE)) ++ TEST_COMPARE (objs[i].closed, true); + free (objs[i].lname); + } + + +commit 196fce69506d0b3aede8e333ed3a5e777a645352 +Author: Florian Weimer +Date: Fri Aug 9 16:06:40 2024 +0200 + + elf: Call la_objclose for proxy link maps in _dl_fini (bug 32065) + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit c4b160744cb39eca20dc36b39c7fa6e10352706c) + +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index db996270de..a1a4c25829 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -69,6 +69,7 @@ _dl_fini (void) + + unsigned int i; + struct link_map *l; ++ struct link_map *proxy_link_map = NULL; + assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL); + for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next) + /* Do not handle ld.so in secondary namespaces. */ +@@ -84,6 +85,11 @@ _dl_fini (void) + are not dlclose()ed from underneath us. */ + ++l->l_direct_opencount; + } ++ else ++ /* Used below to call la_objclose for the ld.so proxy ++ link map. */ ++ proxy_link_map = l; ++ + assert (ns != LM_ID_BASE || i == nloaded); + assert (ns == LM_ID_BASE || i == nloaded || i == nloaded - 1); + unsigned int nmaps = i; +@@ -122,6 +128,9 @@ _dl_fini (void) + --l->l_direct_opencount; + } + ++ if (proxy_link_map != NULL) ++ _dl_audit_objclose (proxy_link_map); ++ + #ifdef SHARED + _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT); + #endif +diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c +index c8c6553b8f..583c45f38a 100644 +--- a/elf/tst-audit23.c ++++ b/elf/tst-audit23.c +@@ -236,13 +236,26 @@ do_test (int argc, char *argv[]) + } + } + ++ Lmid_t lmid_other = LM_ID_NEWLM; ++ unsigned int other_namespace_count = 0; + for (size_t i = 0; i < nobjs; i++) + { +- /* This subtest currently does not pass because of bug 32065. */ +- if (! (endswith (objs[i].lname, LD_SO) && objs[i].lmid != LM_ID_BASE)) +- TEST_COMPARE (objs[i].closed, true); ++ if (objs[i].lmid != LM_ID_BASE) ++ { ++ if (lmid_other == LM_ID_NEWLM) ++ lmid_other = objs[i].lmid; ++ TEST_COMPARE (objs[i].lmid, lmid_other); ++ ++other_namespace_count; ++ if (!(endswith (objs[i].lname, "/" LIBC_SO) ++ || endswith (objs[i].lname, "/" LD_SO))) ++ FAIL ("unexpected object in secondary namespace: %s", ++ objs[i].lname); ++ } ++ TEST_COMPARE (objs[i].closed, true); + free (objs[i].lname); + } ++ /* Both libc.so and ld.so should be present. */ ++ TEST_COMPARE (other_namespace_count, 2); + + /* la_activity(LA_ACT_CONSISTENT) should be the last callback received. + Since only one link map may be not-CONSISTENT at a time, this also + +commit bab46c3dbddab9cbdae493da3006694e31e946a5 +Author: Florian Weimer +Date: Tue Sep 3 17:57:46 2024 +0200 + + elf: Reorder audit events in dlcose to match _dl_fini (bug 32066) + + This was discovered after extending elf/tst-audit23 to cover + dlclose of the dlmopen namespace. + + Auditors already experience the new order during process + shutdown (_dl_fini), so no LAV_CURRENT bump or backwards + compatibility code seems necessary. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 495b96e064da605630a23092d1e484ade4bdc093) + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index b6f4daac79..4c963097f4 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -264,6 +264,12 @@ _dl_close_worker (struct link_map *map, bool force) + _dl_catch_exception (NULL, _dl_call_fini, imap); + + #ifdef SHARED ++ /* Auditing checkpoint: we will start deleting objects. ++ This is supposed to happen before la_objclose (see _dl_fini), ++ but only once per non-recursive dlclose call. */ ++ if (!unload_any) ++ _dl_audit_activity_nsid (nsid, LA_ACT_DELETE); ++ + /* Auditing checkpoint: we remove an object. */ + _dl_audit_objclose (imap); + #endif +@@ -424,12 +430,8 @@ _dl_close_worker (struct link_map *map, bool force) + if (!unload_any) + goto out; + +-#ifdef SHARED +- /* Auditing checkpoint: we will start deleting objects. */ +- _dl_audit_activity_nsid (nsid, LA_ACT_DELETE); +-#endif +- +- /* Notify the debugger we are about to remove some loaded objects. */ ++ /* Notify the debugger we are about to remove some loaded objects. ++ LA_ACT_DELETE has already been signalled above for !unload_any. */ + struct r_debug *r = _dl_debug_update (nsid); + r->r_state = RT_DELETE; + _dl_debug_state (); +diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c +index 583c45f38a..7786a74e64 100644 +--- a/elf/tst-audit23.c ++++ b/elf/tst-audit23.c +@@ -31,16 +31,21 @@ + #include + #include + #include ++#include + + static int restart; ++static int do_dlclose; + #define CMDLINE_OPTIONS \ +- { "restart", no_argument, &restart, 1 }, ++ { "restart", no_argument, &restart, 1 }, \ ++ { "dlclose", no_argument, &do_dlclose, 1 }, \ + + static int + handle_restart (void) + { + xdlopen ("tst-audit23mod.so", RTLD_NOW); +- xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); ++ void *handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); ++ if (do_dlclose) ++ xdlclose (handle); + + return 0; + } +@@ -60,8 +65,8 @@ is_vdso (const char *str) + || startswith (str, "linux-vdso"); + } + +-static int +-do_test (int argc, char *argv[]) ++static void ++do_one_test (int argc, char *argv[], bool pass_dlclose_flag) + { + /* We must have either: + - One or four parameters left if called initially: +@@ -69,16 +74,15 @@ do_test (int argc, char *argv[]) + + "--library-path" optional + + the library path optional + + the application name */ +- if (restart) +- return handle_restart (); +- +- char *spargv[9]; ++ char *spargv[10]; + TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv)); + int i = 0; + for (; i < argc - 1; i++) + spargv[i] = argv[i + 1]; + spargv[i++] = (char *) "--direct"; + spargv[i++] = (char *) "--restart"; ++ if (pass_dlclose_flag) ++ spargv[i++] = (char *) "--dlclose"; + spargv[i] = NULL; + + setenv ("LD_AUDIT", "tst-auditmod23.so", 0); +@@ -146,8 +150,14 @@ do_test (int argc, char *argv[]) + + /* The cookie identifies the object at the head of the link map, + so we only add a new namespace if it changes from the previous +- one. This works since dlmopen is the last in the test body. */ +- if (cookie != last_act_cookie && last_act_cookie != -1) ++ one. This works since dlmopen is the last in the test body. ++ ++ Currently, this does not work as expected because there ++ is no head link map if a namespace is completely deleted. ++ No LA_ACT_CONSISTENT event is generated in that case. ++ See the comment in _dl_audit_activity_nsid and bug 32068. */ ++ if (cookie != last_act_cookie && last_act_cookie != -1 ++ && !pass_dlclose_flag) + TEST_COMPARE (last_act, LA_ACT_CONSISTENT); + + if (this_act == LA_ACT_ADD && acts[nacts] != cookie) +@@ -265,7 +275,16 @@ do_test (int argc, char *argv[]) + + free (buffer); + xfclose (out); ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ if (restart) ++ return handle_restart (); + ++ do_one_test (argc, argv, false); ++ do_one_test (argc, argv, true); + return 0; + } + + +commit 46adca40b8e656a5c33321c4afbb0602f85d2689 +Author: Florian Weimer +Date: Fri Mar 7 17:37:50 2025 +0100 + + elf: Fix handling of symbol versions which hash to zero (bug 29190) + + This was found through code inspection. No application impact is + known. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 46d31980943d8be2f421c1e3276b265c7552636e) + +diff --git a/elf/Makefile b/elf/Makefile +index fed2ff15f9..08b3e8514e 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -489,6 +489,7 @@ tests += \ + tst-unique2 \ + tst-unwind-ctor \ + tst-unwind-main \ ++ tst-version-hash-zero \ + unload3 \ + unload4 \ + unload5 \ +@@ -987,6 +988,9 @@ modules-names += \ + tst-unique2mod1 \ + tst-unique2mod2 \ + tst-unwind-ctor-lib \ ++ tst-version-hash-zero-linkmod \ ++ tst-version-hash-zero-mod \ ++ tst-version-hash-zero-refmod \ + unload2dep \ + unload2mod \ + unload3mod1 \ +@@ -3179,3 +3183,20 @@ tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + + # Any shared object should do. + tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so ++ ++$(objpfx)tst-version-hash-zero.out: \ ++ $(objpfx)tst-version-hash-zero-mod.so \ ++ $(objpfx)tst-version-hash-zero-refmod.so ++LDFLAGS-tst-version-hash-zero-mod.so = \ ++ -Wl,--version-script=tst-version-hash-zero-mod.map ++# The run-time test module tst-version-hash-zero-refmod.so is linked ++# to a stub module, tst-version-hash-zero-linkmod.so, to produce an ++# expected relocation error. ++$(objpfx)tst-version-hash-zero-refmod.so: \ ++ $(objpfx)tst-version-hash-zero-linkmod.so ++LDFLAGS-tst-version-hash-zero-linkmod.so = \ ++ -Wl,--version-script=tst-version-hash-zero-linkmod.map \ ++ -Wl,--soname=tst-version-hash-zero-mod.so ++$(objpfx)tst-version-hash-zero-refmod.so: \ ++ $(objpfx)tst-version-hash-zero-linkmod.so ++tst-version-hash-zero-refmod.so-no-z-defs = yes +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 19ad2a25c5..7a70f1df2d 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -113,12 +113,22 @@ check_match (const char *const undef_name, + /* We can match the version information or use the + default one if it is not hidden. */ + ElfW(Half) ndx = verstab[symidx] & 0x7fff; +- if ((map->l_versions[ndx].hash != version->hash +- || strcmp (map->l_versions[ndx].name, version->name)) +- && (version->hidden || map->l_versions[ndx].hash +- || (verstab[symidx] & 0x8000))) +- /* It's not the version we want. */ +- return NULL; ++ if (map->l_versions[ndx].hash == version->hash ++ && strcmp (map->l_versions[ndx].name, version->name) == 0) ++ /* This is an exact version match. Return the symbol below. */ ++ ; ++ else ++ { ++ if (!version->hidden ++ && map->l_versions[ndx].name[0] == '\0' ++ && (verstab[symidx] & 0x8000) == 0 ++ && (*num_versions)++ == 0) ++ /* This is the global default version. Store it as a ++ fallback match. */ ++ *versioned_sym = sym; ++ ++ return NULL; ++ } + } + } + else +diff --git a/elf/dl-version.c b/elf/dl-version.c +index 8966d612cc..708b1c94ea 100644 +--- a/elf/dl-version.c ++++ b/elf/dl-version.c +@@ -357,6 +357,13 @@ _dl_check_map_versions (struct link_map *map, int verbose, int trace_mode) + ent = (ElfW(Verdef) *) ((char *) ent + ent->vd_next); + } + } ++ ++ /* The empty string has ELF hash zero. This avoids a NULL check ++ before the version string comparison in check_match in ++ dl-lookup.c. */ ++ for (unsigned int i = 0; i < map->l_nversions; ++i) ++ if (map->l_versions[i].name == NULL) ++ map->l_versions[i].name = ""; + } + + /* When there is a DT_VERNEED entry with libc.so on DT_NEEDED, issue +diff --git a/elf/tst-version-hash-zero-linkmod.c b/elf/tst-version-hash-zero-linkmod.c +new file mode 100644 +index 0000000000..15e2506d01 +--- /dev/null ++++ b/elf/tst-version-hash-zero-linkmod.c +@@ -0,0 +1,22 @@ ++/* Stub module for linking tst-version-hash-zero-refmod.so. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* The version script assigns a different symbol version for the stub ++ module. Loading the module with the incorrect version is expected ++ to fail. */ ++#include "tst-version-hash-zero-mod.c" +diff --git a/elf/tst-version-hash-zero-linkmod.map b/elf/tst-version-hash-zero-linkmod.map +new file mode 100644 +index 0000000000..2dba7c22d7 +--- /dev/null ++++ b/elf/tst-version-hash-zero-linkmod.map +@@ -0,0 +1,7 @@ ++Base { ++ local: *; ++}; ++ ++OTHER_VERSION { ++ global: global_variable; ++} Base; +diff --git a/elf/tst-version-hash-zero-mod.c b/elf/tst-version-hash-zero-mod.c +new file mode 100644 +index 0000000000..ac6b0dc4a5 +--- /dev/null ++++ b/elf/tst-version-hash-zero-mod.c +@@ -0,0 +1,20 @@ ++/* Test module with a zero version symbol hash. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* The symbol version is assigned by version script. */ ++int global_variable; +diff --git a/elf/tst-version-hash-zero-mod.map b/elf/tst-version-hash-zero-mod.map +new file mode 100644 +index 0000000000..41eaff7914 +--- /dev/null ++++ b/elf/tst-version-hash-zero-mod.map +@@ -0,0 +1,13 @@ ++Base { ++ local: *; ++}; ++ ++/* Define the version so that tst-version-hash-zero-refmod.so passes ++ the initial symbol version check. */ ++OTHER_VERSION { ++} Base; ++ ++/* This version string hashes to zero. */ ++PPPPPPPPPPPP { ++ global: global_variable; ++} Base; +diff --git a/elf/tst-version-hash-zero-refmod.c b/elf/tst-version-hash-zero-refmod.c +new file mode 100644 +index 0000000000..cd8b3dcef5 +--- /dev/null ++++ b/elf/tst-version-hash-zero-refmod.c +@@ -0,0 +1,23 @@ ++/* Test module that triggers a relocation failure in tst-version-hash-zero. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* This is bound to global_variable@@OTHER_VERSION via ++ tst-version-hash-zero-linkmod.so, but at run time, only ++ global_variable@PPPPPPPPPPPP exists. */ ++extern int global_variable; ++int *pointer_variable = &global_variable; +diff --git a/elf/tst-version-hash-zero.c b/elf/tst-version-hash-zero.c +new file mode 100644 +index 0000000000..66a0db4f51 +--- /dev/null ++++ b/elf/tst-version-hash-zero.c +@@ -0,0 +1,56 @@ ++/* Symbols with version hash zero should not match any version (bug 29190). ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlopen ("tst-version-hash-zero-mod.so", RTLD_NOW); ++ ++ /* This used to crash because some struct r_found_version entries ++ with hash zero did not have valid version strings. */ ++ TEST_VERIFY (xdlvsym (handle, "global_variable", "PPPPPPPPPPPP") != NULL); ++ ++ /* Consistency check. */ ++ TEST_VERIFY (xdlsym (handle, "global_variable") ++ == xdlvsym (handle, "global_variable", "PPPPPPPPPPPP")); ++ ++ /* This symbol version is supposed to be missing. */ ++ TEST_VERIFY (dlvsym (handle, "global_variable", "OTHER_VERSION") == NULL); ++ ++ /* tst-version-hash-zero-refmod.so references ++ global_variable@@OTHER_VERSION and is expected to fail to load. ++ dlvsym sets the hidden flag during lookup. Relocation does not, ++ so this exercises a different failure case. */ ++ TEST_VERIFY_EXIT (dlopen ("tst-version-hash-zero-refmod.so", RTLD_NOW) ++ == NULL); ++ const char *message = dlerror (); ++ if (strstr (message, ++ ": undefined symbol: global_variable, version OTHER_VERSION") ++ == NULL) ++ FAIL_EXIT1 ("unexpected dlopen failure: %s", message); ++ ++ xdlclose (handle); ++ return 0; ++} ++ ++#include + +commit cadc0a84503b6d0f6d5bb88b2888475c5dc1d426 +Author: Florian Weimer +Date: Tue Jan 7 09:18:07 2025 +0100 + + elf: Second ld.so relocation only if libc.so has been loaded + + Commit 8f8dd904c4a2207699bb666f30acceb5209c8d3f (“elf: + rtld_multiple_ref is always true”) removed some code that happened + to enable compatibility with programs that do not link against + libc.so. Such programs cannot call dlopen or any dynamic linker + functions (except __tls_get_addr), so this is not really useful. + Still ld.so should not crash with a null-pointer dereference + or undefined symbol reference in these cases. + + In the main relocation loop, call _dl_relocate_object unconditionally + because it already checks if the object has been relocated. + + If libc.so was loaded, self-relocate ld.so against it and call + __rtld_mutex_init and __rtld_malloc_init_real to activate the full + implementations. Those are available only if libc.so is there, + so skip these initialization steps if libc.so is absent. Without + libc.so, the global scope can be completely empty. This can cause + ld.so self-relocation to fail because if it uses symbol-based + relocations, which is why the second ld.so self-relocation is not + performed if libc.so is missing. + + The previous concern regarding GOT updates through self-relocation + no longer applies because function pointers are updated + explicitly through __rtld_mutex_init and __rtld_malloc_init_real, + and not through relocation. However, the second ld.so self-relocation + is still delayed, in case there are other symbols being used. + + Fixes commit 8f8dd904c4a2207699bb666f30acceb5209c8d3f (“elf: + rtld_multiple_ref is always true”). + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 706209867f1ba89c458033408d419e92d8055f58) + +diff --git a/elf/Makefile b/elf/Makefile +index 08b3e8514e..1d21bfadc7 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -3200,3 +3200,20 @@ LDFLAGS-tst-version-hash-zero-linkmod.so = \ + $(objpfx)tst-version-hash-zero-refmod.so: \ + $(objpfx)tst-version-hash-zero-linkmod.so + tst-version-hash-zero-refmod.so-no-z-defs = yes ++ ++# These rules link and run the special elf/tst-nolink-libc-* tests if ++# a port adds them to the tests variables. Neither test variant is ++# linked against libc.so, but tst-nolink-libc-1 is linked against ++# ld.so. The test is always run directly, not under the dynamic ++# linker. ++CFLAGS-tst-nolink-libc.c += $(no-stack-protector) ++$(objpfx)tst-nolink-libc-1: $(objpfx)tst-nolink-libc.o $(objpfx)ld.so ++ $(LINK.o) -nostdlib -nostartfiles -o $@ $< \ ++ -Wl,--dynamic-linker=$(objpfx)ld.so,--no-as-needed $(objpfx)ld.so ++$(objpfx)tst-nolink-libc-1.out: $(objpfx)tst-nolink-libc-1 $(objpfx)ld.so ++ $< > $@ 2>&1; $(evaluate-test) ++$(objpfx)tst-nolink-libc-2: $(objpfx)tst-nolink-libc.o ++ $(LINK.o) -nostdlib -nostartfiles -o $@ $< \ ++ -Wl,--dynamic-linker=$(objpfx)ld.so ++$(objpfx)tst-nolink-libc-2.out: $(objpfx)tst-nolink-libc-2 $(objpfx)ld.so ++ $< > $@ 2>&1; $(evaluate-test) +diff --git a/elf/rtld.c b/elf/rtld.c +index 4adfc67260..ee015c58c6 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2291,25 +2291,25 @@ dl_main (const ElfW(Phdr) *phdr, + + _rtld_main_check (main_map, _dl_argv[0]); + +- /* Now we have all the objects loaded. Relocate them all except for +- the dynamic linker itself. We do this in reverse order so that copy +- relocs of earlier objects overwrite the data written by later +- objects. We do not re-relocate the dynamic linker itself in this +- loop because that could result in the GOT entries for functions we +- call being changed, and that would break us. It is safe to relocate +- the dynamic linker out of order because it has no copy relocations. +- Likewise for libc, which is relocated early to ensure that IFUNC +- resolvers in libc work. */ ++ /* Now we have all the objects loaded. */ + + int consider_profiling = GLRO(dl_profile) != NULL; + + /* If we are profiling we also must do lazy reloaction. */ + GLRO(dl_lazy) |= consider_profiling; + ++ /* If libc.so has been loaded, relocate it early, after the dynamic ++ loader itself. The initial self-relocation of ld.so should be ++ sufficient for IFUNC resolvers in libc.so. */ + if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) +- _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map, +- GL(dl_ns)[LM_ID_BASE].libc_map->l_scope, +- GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); ++ { ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); ++ _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map, ++ GL(dl_ns)[LM_ID_BASE].libc_map->l_scope, ++ GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); ++ rtld_timer_accum (&relocate_time, start); ++ } + + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); +@@ -2332,9 +2332,8 @@ dl_main (const ElfW(Phdr) *phdr, + /* Also allocated with the fake malloc(). */ + l->l_free_initfini = 0; + +- if (l != &GL(dl_rtld_map)) +- _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, +- consider_profiling); ++ _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0, ++ consider_profiling); + + /* Add object to slot information data if necessasy. */ + if (l->l_tls_blocksize != 0 && __rtld_tls_init_tp_called) +@@ -2372,27 +2371,22 @@ dl_main (const ElfW(Phdr) *phdr, + /* Set up the object lookup structures. */ + _dl_find_object_init (); + +- /* Likewise for the locking implementation. */ +- __rtld_mutex_init (); +- +- /* Re-relocate ourselves with user-controlled symbol definitions. */ +- +- { +- RTLD_TIMING_VAR (start); +- rtld_timer_start (&start); +- +- _dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0); +- +- /* The malloc implementation has been relocated, so resolving +- its symbols (and potentially calling IFUNC resolvers) is safe +- at this point. */ +- __rtld_malloc_init_real (main_map); ++ /* If libc.so was loaded, relocate ld.so against it. Complete ld.so ++ initialization with mutex symbols from libc.so and malloc symbols ++ from the global scope. */ ++ if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) ++ { ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); ++ _dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0); ++ rtld_timer_accum (&relocate_time, start); + +- if (GL(dl_rtld_map).l_relro_size != 0) +- _dl_protect_relro (&GL(dl_rtld_map)); ++ __rtld_mutex_init (); ++ __rtld_malloc_init_real (main_map); ++ } + +- rtld_timer_accum (&relocate_time, start); +- } ++ /* All ld.so initialization is complete. Apply RELRO. */ ++ _dl_protect_relro (&GL(dl_rtld_map)); + + /* Relocation is complete. Perform early libc initialization. This + is the initial libc, even if audit modules have been loaded with +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 34890ef69a..b7ff9c5293 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -639,7 +639,15 @@ install-bin += \ + # install-bin + + $(objpfx)pldd: $(objpfx)xmalloc.o ++ ++test-internal-extras += tst-nolink-libc ++ifeq ($(run-built-tests),yes) ++tests-special += \ ++ $(objpfx)tst-nolink-libc-1.out \ ++ $(objpfx)tst-nolink-libc-2.out \ ++ # tests-special + endif ++endif # $(subdir) == elf + + ifeq ($(subdir),rt) + CFLAGS-mq_send.c += -fexceptions +diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile +index a73c897f43..e73ce4f811 100644 +--- a/sysdeps/unix/sysv/linux/arm/Makefile ++++ b/sysdeps/unix/sysv/linux/arm/Makefile +@@ -1,5 +1,8 @@ + ifeq ($(subdir),elf) + sysdep-rtld-routines += aeabi_read_tp libc-do-syscall ++# The test uses INTERNAL_SYSCALL_CALL. In thumb mode, this uses ++# an undefined reference to __libc_do_syscall. ++CFLAGS-tst-nolink-libc.c += -marm + endif + + ifeq ($(subdir),misc) +diff --git a/sysdeps/unix/sysv/linux/tst-nolink-libc.c b/sysdeps/unix/sysv/linux/tst-nolink-libc.c +new file mode 100644 +index 0000000000..817f37784b +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-nolink-libc.c +@@ -0,0 +1,25 @@ ++/* Test program not linked against libc.so and not using any glibc functions. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++void ++_start (void) ++{ ++ INTERNAL_SYSCALL_CALL (exit_group, 0); ++} + +commit 5177ccdbcb24406a93dff1c7b21160bb62e3a240 +Author: Florian Weimer +Date: Tue Mar 11 15:30:52 2025 +0100 + + elf: Test dlopen (NULL, RTLD_LAZY) from an ELF constructor + + This call must not complete initialization of all shared objects + in the global scope because the ELF constructor which makes the call + likely has not finished initialization. Calling more constructors + at this point would expose those to a partially constructed + dependency. + + This completes the revert of commit 9897ced8e78db5d813166a7ccccfd5a + ("elf: Run constructors on cyclic recursive dlopen (bug 31986)"). + + (cherry picked from commit d604f9c500570e80febfcc6a52b63a002b466f35) + +diff --git a/elf/Makefile b/elf/Makefile +index 1d21bfadc7..bf1a1ce05a 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -417,6 +417,7 @@ tests += \ + tst-dlmopen3 \ + tst-dlmopen4 \ + tst-dlopen-auditdup \ ++ tst-dlopen-constructor-null \ + tst-dlopen-self \ + tst-dlopen-tlsmodid \ + tst-dlopen-tlsreinit1 \ +@@ -873,6 +874,8 @@ modules-names += \ + tst-dlmopen1mod \ + tst-dlopen-auditdup-auditmod \ + tst-dlopen-auditdupmod \ ++ tst-dlopen-constructor-null-mod1 \ ++ tst-dlopen-constructor-null-mod2 \ + tst-dlopen-sgid-mod \ + tst-dlopen-tlsreinitmod1 \ + tst-dlopen-tlsreinitmod2 \ +@@ -3217,3 +3220,9 @@ $(objpfx)tst-nolink-libc-2: $(objpfx)tst-nolink-libc.o + -Wl,--dynamic-linker=$(objpfx)ld.so + $(objpfx)tst-nolink-libc-2.out: $(objpfx)tst-nolink-libc-2 $(objpfx)ld.so + $< > $@ 2>&1; $(evaluate-test) ++ ++$(objpfx)tst-dlopen-constructor-null: \ ++ $(objpfx)tst-dlopen-constructor-null-mod1.so \ ++ $(objpfx)tst-dlopen-constructor-null-mod2.so ++$(objpfx)tst-dlopen-constructor-null-mod2.so: \ ++ $(objpfx)tst-dlopen-constructor-null-mod1.so +diff --git a/elf/dl-open.c b/elf/dl-open.c +index b00f283c42..80f084d5c8 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -605,6 +605,16 @@ dl_open_worker_begin (void *a) + if ((mode & RTLD_GLOBAL) && new->l_global == 0) + add_to_global_update (new); + ++ /* It is not possible to run the ELF constructor for the new ++ link map if it has not executed yet: If this dlopen call came ++ from an ELF constructor that has not put that object into a ++ consistent state, completing initialization for the entire ++ scope will expose objects that have this partially ++ constructed object among its dependencies to this ++ inconsistent state. This could happen even with a benign ++ dlopen (NULL, RTLD_LAZY) call from a constructor of an ++ initially loaded shared object. */ ++ + return; + } + +diff --git a/elf/tst-dlopen-constructor-null-mod1.c b/elf/tst-dlopen-constructor-null-mod1.c +new file mode 100644 +index 0000000000..70a7a0ad46 +--- /dev/null ++++ b/elf/tst-dlopen-constructor-null-mod1.c +@@ -0,0 +1,55 @@ ++/* Module calling dlopen (NULL, RTLD_LAZY) to obtain the global scope. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++int mod1_status; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlopen-constructor-null-mod1.so constructor"); ++ ++ void *handle = dlopen (NULL, RTLD_LAZY); ++ if (handle == NULL) ++ { ++ printf ("error: %s\n", dlerror ()); ++ exit (1); ++ } ++ puts ("info: dlopen returned"); ++ if (dlsym (handle, "malloc") != malloc) ++ { ++ puts ("error: dlsym did not produce expected result"); ++ exit (1); ++ } ++ dlclose (handle); ++ ++ /* Check that the second module's constructor has not executed. */ ++ if (getenv ("mod2_status") != NULL) ++ { ++ printf ("error: mod2_status environment variable set: %s\n", ++ getenv ("mod2_status")); ++ exit (1); ++ } ++ ++ /* Communicate to the second module that the constructor executed. */ ++ mod1_status = 1; ++} +diff --git a/elf/tst-dlopen-constructor-null-mod2.c b/elf/tst-dlopen-constructor-null-mod2.c +new file mode 100644 +index 0000000000..d6e945beae +--- /dev/null ++++ b/elf/tst-dlopen-constructor-null-mod2.c +@@ -0,0 +1,37 @@ ++/* Module whose constructor should not be invoked by dlopen (NULL, RTLD_LAZY). ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++extern int mod1_status; ++int mod2_status; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ printf ("info: tst-dlopen-constructor-null-mod2.so constructor" ++ " (mod1_status=%d)", mod1_status); ++ if (!(mod1_status == 1 && mod2_status == 0)) ++ { ++ puts ("error: mod1_status == 1 && mod2_status == 0 expected"); ++ exit (1); ++ } ++ setenv ("mod2_status", "constructed", 1); ++ mod2_status = 1; ++} +diff --git a/elf/tst-dlopen-constructor-null.c b/elf/tst-dlopen-constructor-null.c +new file mode 100644 +index 0000000000..db90643325 +--- /dev/null ++++ b/elf/tst-dlopen-constructor-null.c +@@ -0,0 +1,38 @@ ++/* Verify that dlopen (NULL, RTLD_LAZY) does not complete initialization. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++/* This test mimics what the glvndSetupPthreads function in libglvnd ++ does. */ ++ ++#include ++#include ++ ++/* Defined and initialized in the shared objects. */ ++extern int mod1_status; ++extern int mod2_status; ++ ++static int ++do_test (void) ++{ ++ TEST_COMPARE (mod1_status, 1); ++ TEST_COMPARE (mod2_status, 1); ++ TEST_COMPARE_STRING (getenv ("mod2_status"), "constructed"); ++ return 0; ++} ++ ++#include + +commit 1eba4921c7762a94b032ba70d5d22eb2963ee440 +Author: Florian Weimer +Date: Fri Jul 4 21:46:05 2025 +0200 + + elf: Introduce separate _r_debug_array variable + + It replaces the ns_debug member of the namespaces. Previously, + the base namespace had an unused ns_debug member. + + This change also fixes a concurrency issue: Now _dl_debug_initialize + only updates r_next of the previous namespace's r_debug after the new + r_debug is initialized, so that only the initialized version is + observed. (Client code accessing _r_debug will benefit from load + dependency tracking in CPUs even without explicit barriers.) + + Reviewed-by: H.J. Lu + (cherry picked from commit 7278d11f3a0cd528188c719bab75575b0aea2c6e) + +diff --git a/elf/dl-debug.c b/elf/dl-debug.c +index ef56de7a29..5c49fa847e 100644 +--- a/elf/dl-debug.c ++++ b/elf/dl-debug.c +@@ -30,17 +30,37 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr) + && VERIFY_MEMBER (l_prev)) + ? 1 : -1]; + ++#ifdef SHARED ++/* r_debug structs for secondary namespaces. The first namespace is ++ handled separately because its r_debug structure must overlap with ++ the public _r_debug symbol, so the first array element corresponds ++ to LM_ID_BASE + 1. See elf/dl-debug-symbols.S. */ ++struct r_debug_extended _r_debug_array[DL_NNS - 1]; ++ ++/* Return the r_debug object for the namespace NS. */ ++static inline struct r_debug_extended * ++get_rdebug (Lmid_t ns) ++{ ++ if (ns == LM_ID_BASE) ++ return &_r_debug_extended; ++ else ++ return &_r_debug_array[ns - 1]; ++} ++#else /* !SHARED */ ++static inline struct r_debug_extended * ++get_rdebug (Lmid_t ns) ++{ ++ return &_r_debug_extended; /* There is just one namespace. */ ++} ++#endif /* !SHARED */ ++ + /* Update the `r_map' member and return the address of `struct r_debug' + of the namespace NS. */ + + struct r_debug * + _dl_debug_update (Lmid_t ns) + { +- struct r_debug_extended *r; +- if (ns == LM_ID_BASE) +- r = &_r_debug_extended; +- else +- r = &GL(dl_ns)[ns]._ns_debug; ++ struct r_debug_extended *r = get_rdebug (ns); + if (r->base.r_map == NULL) + atomic_store_release (&r->base.r_map, + (void *) GL(dl_ns)[ns]._ns_loaded); +@@ -54,34 +74,7 @@ _dl_debug_update (Lmid_t ns) + struct r_debug * + _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + { +- struct r_debug_extended *r, **pp = NULL; +- +- if (ns == LM_ID_BASE) +- { +- r = &_r_debug_extended; +- /* Initialize r_version to 1. */ +- if (_r_debug_extended.base.r_version == 0) +- _r_debug_extended.base.r_version = 1; +- } +- else if (DL_NNS > 1) +- { +- r = &GL(dl_ns)[ns]._ns_debug; +- if (r->base.r_brk == 0) +- { +- /* Add the new namespace to the linked list. After a namespace +- is initialized, r_brk becomes non-zero. A namespace becomes +- empty (r_map == NULL) when it is unused. But it is never +- removed from the linked list. */ +- struct r_debug_extended *p; +- for (pp = &_r_debug_extended.r_next; +- (p = *pp) != NULL; +- pp = &p->r_next) +- ; +- +- r->base.r_version = 2; +- } +- } +- ++ struct r_debug_extended *r = get_rdebug (ns); + if (r->base.r_brk == 0) + { + /* Tell the debugger where to find the map of loaded objects. +@@ -89,20 +82,36 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + only once. */ + r->base.r_ldbase = ldbase ?: _r_debug_extended.base.r_ldbase; + r->base.r_brk = (ElfW(Addr)) &_dl_debug_state; +- r->r_next = NULL; ++ ++#ifdef SHARED ++ /* Add the new namespace to the linked list. This assumes that ++ namespaces are allocated in increasing order. After a ++ namespace is initialized, r_brk becomes non-zero. A ++ namespace becomes empty (r_map == NULL) when it is unused. ++ But it is never removed from the linked list. */ ++ ++ if (ns != LM_ID_BASE) ++ { ++ r->base.r_version = 2; ++ if (ns - 1 == LM_ID_BASE) ++ { ++ atomic_store_release (&_r_debug_extended.r_next, r); ++ /* Now there are multiple namespaces. */ ++ atomic_store_release (&_r_debug_extended.base.r_version, 2); ++ } ++ else ++ /* Update r_debug_extended of the previous namespace. */ ++ atomic_store_release (&_r_debug_array[ns - 2].r_next, r); ++ } ++ else ++#endif /* SHARED */ ++ r->base.r_version = 1; + } + + if (r->base.r_map == NULL) + atomic_store_release (&r->base.r_map, + (void *) GL(dl_ns)[ns]._ns_loaded); + +- if (pp != NULL) +- { +- atomic_store_release (pp, r); +- /* Bump r_version to 2 for the new namespace. */ +- atomic_store_release (&_r_debug_extended.base.r_version, 2); +- } +- + return &r->base; + } + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 91447a5e77..8b9ae37830 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -350,8 +350,6 @@ struct rtld_global + size_t n_elements; + void (*free) (void *); + } _ns_unique_sym_table; +- /* Keep track of changes to each namespace' list. */ +- struct r_debug_extended _ns_debug; + } _dl_ns[DL_NNS]; + /* One higher than index of last used namespace. */ + EXTERN size_t _dl_nns; + +commit 7d649d1c990441181c903bd2f99251cbf1552180 +Author: Florian Weimer +Date: Fri Jul 4 21:46:16 2025 +0200 + + elf: Introduce _dl_debug_change_state + + It combines updating r_state with the debugger notification. + + The second change to _dl_open introduces an additional debugger + notification for dlmopen, but debuggers are expected to ignore it. + + Reviewed-by: H.J. Lu + (cherry picked from commit 8329939a37f483a16013dd8af8303cbcb86d92cb) + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 4c963097f4..fb27a1231c 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -433,8 +433,7 @@ _dl_close_worker (struct link_map *map, bool force) + /* Notify the debugger we are about to remove some loaded objects. + LA_ACT_DELETE has already been signalled above for !unload_any. */ + struct r_debug *r = _dl_debug_update (nsid); +- r->r_state = RT_DELETE; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_DELETE); + LIBC_PROBE (unmap_start, 2, nsid, r); + + if (unload_global) +@@ -726,8 +725,7 @@ _dl_close_worker (struct link_map *map, bool force) + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + + /* Notify the debugger those objects are finalized and gone. */ +- r->r_state = RT_CONSISTENT; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_CONSISTENT); + LIBC_PROBE (unmap_complete, 2, nsid, r); + + #ifdef SHARED +diff --git a/elf/dl-debug.c b/elf/dl-debug.c +index 5c49fa847e..b3777ffc13 100644 +--- a/elf/dl-debug.c ++++ b/elf/dl-debug.c +@@ -67,6 +67,13 @@ _dl_debug_update (Lmid_t ns) + return &r->base; + } + ++void ++_dl_debug_change_state (struct r_debug *r, int state) ++{ ++ atomic_store_release (&r->r_state, state); ++ _dl_debug_state (); ++} ++ + /* Initialize _r_debug_extended for the namespace NS. LDBASE is the + run-time load address of the dynamic linker, to be put in + _r_debug_extended.r_ldbase. Return the address of _r_debug. */ +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 54c9c4d779..23b7e6a0c6 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -936,8 +936,7 @@ _dl_notify_new_object (int mode, Lmid_t nsid, struct link_map *l) + /* Notify the debugger we have added some objects. We need to + call _dl_debug_initialize in a static program in case dynamic + linking has not been used before. */ +- r->r_state = RT_ADD; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_ADD); + LIBC_PROBE (map_start, 2, nsid, r); + } + else +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 80f084d5c8..6f6d3ddbf9 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -792,8 +792,7 @@ dl_open_worker (void *a) + #ifdef SHARED + bool was_not_consistent = r->r_state != RT_CONSISTENT; + #endif +- r->r_state = RT_CONSISTENT; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_CONSISTENT); + LIBC_PROBE (map_complete, 3, nsid, r, args->map); + + #ifdef SHARED +@@ -871,7 +870,7 @@ no more namespaces available for dlmopen()")); + } + + GL(dl_ns)[nsid].libc_map = NULL; +- _dl_debug_update (nsid)->r_state = RT_CONSISTENT; ++ _dl_debug_change_state (_dl_debug_update (nsid), RT_CONSISTENT); + } + /* Never allow loading a DSO in a namespace which is empty. Such + direct placements is only causing problems. Also don't allow +diff --git a/elf/rtld.c b/elf/rtld.c +index ee015c58c6..e1b67f8ca6 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1851,8 +1851,7 @@ dl_main (const ElfW(Phdr) *phdr, + elf_setup_debug_entry (main_map, r); + + /* We start adding objects. */ +- r->r_state = RT_ADD; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_ADD); + LIBC_PROBE (init_start, 2, LM_ID_BASE, r); + + /* Auditing checkpoint: we are ready to signal that the initial map +@@ -2403,8 +2402,7 @@ dl_main (const ElfW(Phdr) *phdr, + /* Notify the debugger all new objects are now ready to go. We must re-get + the address since by now the variable might be in another object. */ + r = _dl_debug_update (LM_ID_BASE); +- r->r_state = RT_CONSISTENT; +- _dl_debug_state (); ++ _dl_debug_change_state (r, RT_CONSISTENT); + LIBC_PROBE (init_complete, 2, LM_ID_BASE, r); + + /* Auditing checkpoint: we have added all objects. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 8b9ae37830..017406e7fa 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1067,8 +1067,14 @@ extern void _dl_debug_state (void); + rtld_hidden_proto (_dl_debug_state) + + /* Initialize `struct r_debug_extended' for the namespace NS. LDBASE +- is the run-time load address of the dynamic linker, to be put in the +- `r_ldbase' member. Return the address of the structure. */ ++ is the run-time load address of the dynamic linker, to be put in ++ the `r_ldbase' member. ++ ++ Return the address of the r_debug structure for the namespace. ++ This is not merely a convenience or optimization, but it is ++ necessary for the LIBC_PROBE Systemtap/debugger probes to work ++ reliably: direct variable access can create probes that tools ++ cannot consume. */ + extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + attribute_hidden; + +@@ -1076,6 +1082,10 @@ extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + of the namespace NS. */ + extern struct r_debug *_dl_debug_update (Lmid_t ns) attribute_hidden; + ++/* Update R->r_state to STATE and notify the debugger by calling ++ _dl_debug_state. */ ++void _dl_debug_change_state (struct r_debug *r, int state) attribute_hidden; ++ + /* Initialize the basic data structure for the search paths. SOURCE + is either "LD_LIBRARY_PATH" or "--library-path". + GLIBC_HWCAPS_PREPEND adds additional glibc-hwcaps subdirectories to + +commit fbc5e95f83adb1d1fe6a518117b7aeba58c3b92e +Author: Florian Weimer +Date: Fri Jul 4 21:46:30 2025 +0200 + + elf: Restore support for _r_debug interpositions and copy relocations + + The changes in commit a93d9e03a31ec14405cb3a09aa95413b67067380 + ("Extend struct r_debug to support multiple namespaces [BZ #15971]") + break the dyninst dynamic instrumentation tool. It brings its + own definition of _r_debug (rather than a declaration). + + Furthermore, it turns out it is rather hard to use the proposed + handshake for accessing _r_debug via DT_DEBUG. If applications want + to access _r_debug, they can do so directly if the relevant code has + been built as PIC. To protect against harm from accidental copy + relocations due to linker relaxations, this commit restores copy + relocation support by adjusting both copies if interposition or + copy relocations are in play. Therefore, it is possible to + use a hidden reference in ld.so to access _r_debug. + + Only perform the copy relocation initialization if libc has been + loaded. Otherwise, the ld.so search scope can be empty, and the + lookup of the _r_debug symbol mail fail. + + Reviewed-by: H.J. Lu + (cherry picked from commit ea85e7d55087075376a29261e722e4fae14ecbe7) + +diff --git a/elf/Makefile b/elf/Makefile +index bf1a1ce05a..b0894c6430 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -416,6 +416,8 @@ tests += \ + tst-dlmopen1 \ + tst-dlmopen3 \ + tst-dlmopen4 \ ++ tst-dlmopen4-nonpic \ ++ tst-dlmopen4-pic \ + tst-dlopen-auditdup \ + tst-dlopen-constructor-null \ + tst-dlopen-self \ +@@ -2080,6 +2082,13 @@ $(objpfx)tst-dlmopen3.out: $(objpfx)tst-dlmopen1mod.so + + $(objpfx)tst-dlmopen4.out: $(objpfx)tst-dlmopen1mod.so + ++CFLAGS-tst-dlmopen4-pic.c += -fPIC ++$(objpfx)tst-dlmopen4-pic.out: $(objpfx)tst-dlmopen1mod.so ++ ++CFLAGS-tst-dlmopen4-nonpic.c += -fno-pie ++tst-dlmopen4-nonpic-no-pie = yes ++$(objpfx)tst-dlmopen4-nonpic.out: $(objpfx)tst-dlmopen1mod.so ++ + $(objpfx)tst-audit1.out: $(objpfx)tst-auditmod1.so + tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + +diff --git a/elf/dl-debug-symbols.S b/elf/dl-debug-symbols.S +index 4e35adef5d..33f0fc77de 100644 +--- a/elf/dl-debug-symbols.S ++++ b/elf/dl-debug-symbols.S +@@ -38,3 +38,4 @@ + _r_debug: + _r_debug_extended: + .zero R_DEBUG_EXTENDED_SIZE ++rtld_hidden_def (_r_debug) +diff --git a/elf/dl-debug.c b/elf/dl-debug.c +index b3777ffc13..8b51332309 100644 +--- a/elf/dl-debug.c ++++ b/elf/dl-debug.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + +@@ -37,6 +38,37 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr) + to LM_ID_BASE + 1. See elf/dl-debug-symbols.S. */ + struct r_debug_extended _r_debug_array[DL_NNS - 1]; + ++/* If not null, pointer to the _r_debug in the main executable. */ ++static struct r_debug *_r_debug_main; ++ ++void ++_dl_debug_post_relocate (struct link_map *main_map) ++{ ++ /* Perform a full symbol search in all objects, to maintain ++ compatibility if interposed _r_debug definitions. The lookup ++ cannot fail because there is a definition in ld.so, and this ++ function is only called if the ld.so search scope is not empty. */ ++ const ElfW(Sym) *sym = NULL; ++ lookup_t result =_dl_lookup_symbol_x ("_r_debug", main_map, &sym, ++ main_map->l_scope, NULL, 0, 0, NULL); ++ if (sym->st_size >= sizeof (struct r_debug)) ++ { ++ struct r_debug *main_r_debug = DL_SYMBOL_ADDRESS (result, sym); ++ if (main_r_debug != &_r_debug_extended.base) ++ { ++ /* The extended version of the struct is not available in ++ the main executable because a copy relocation has been ++ used. r_map etc. have already been copied as part of the ++ copy relocation processing. */ ++ main_r_debug->r_version = 1; ++ ++ /* Record that dual updates of the initial link map are ++ required. */ ++ _r_debug_main = main_r_debug; ++ } ++ } ++} ++ + /* Return the r_debug object for the namespace NS. */ + static inline struct r_debug_extended * + get_rdebug (Lmid_t ns) +@@ -71,6 +103,11 @@ void + _dl_debug_change_state (struct r_debug *r, int state) + { + atomic_store_release (&r->r_state, state); ++#ifdef SHARED ++ if (r == &_r_debug_extended.base && _r_debug_main != NULL) ++ /* Update the copy-relocation of _r_debug. */ ++ atomic_store_release (&_r_debug_main->r_state, state); ++#endif + _dl_debug_state (); + } + +@@ -103,7 +140,9 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + if (ns - 1 == LM_ID_BASE) + { + atomic_store_release (&_r_debug_extended.r_next, r); +- /* Now there are multiple namespaces. */ ++ /* Now there are multiple namespaces. Note that this ++ deliberately does not update the copy in the main ++ executable (if it exists). */ + atomic_store_release (&_r_debug_extended.base.r_version, 2); + } + else +@@ -116,8 +155,15 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + } + + if (r->base.r_map == NULL) +- atomic_store_release (&r->base.r_map, +- (void *) GL(dl_ns)[ns]._ns_loaded); ++ { ++ struct link_map_public *l = (void *) GL(dl_ns)[ns]._ns_loaded; ++ atomic_store_release (&r->base.r_map, l); ++#ifdef SHARED ++ if (ns == LM_ID_BASE && _r_debug_main != NULL) ++ /* Update the copy-relocation of _r_debug. */ ++ atomic_store_release (&_r_debug_main->r_map, l); ++#endif ++ } + + return &r->base; + } +diff --git a/elf/rtld.c b/elf/rtld.c +index e1b67f8ca6..dc65b6e404 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2382,6 +2382,9 @@ dl_main (const ElfW(Phdr) *phdr, + + __rtld_mutex_init (); + __rtld_malloc_init_real (main_map); ++ ++ /* Update copy-relocated _r_debug if necessary. */ ++ _dl_debug_post_relocate (main_map); + } + + /* All ld.so initialization is complete. Apply RELRO. */ +diff --git a/elf/tst-dlmopen4-nonpic.c b/elf/tst-dlmopen4-nonpic.c +new file mode 100644 +index 0000000000..ad4e409953 +--- /dev/null ++++ b/elf/tst-dlmopen4-nonpic.c +@@ -0,0 +1,2 @@ ++#define BUILD_FOR_NONPIC ++#include "tst-dlmopen4.c" +diff --git a/elf/tst-dlmopen4-pic.c b/elf/tst-dlmopen4-pic.c +new file mode 100644 +index 0000000000..919fa85c25 +--- /dev/null ++++ b/elf/tst-dlmopen4-pic.c +@@ -0,0 +1,2 @@ ++#define BUILD_FOR_PIC ++#include "tst-dlmopen4.c" +diff --git a/elf/tst-dlmopen4.c b/elf/tst-dlmopen4.c +index b1c5502621..9e053fbc59 100644 +--- a/elf/tst-dlmopen4.c ++++ b/elf/tst-dlmopen4.c +@@ -46,6 +46,15 @@ do_test (void) + TEST_COMPARE (debug->base.r_version, 1); + TEST_VERIFY_EXIT (debug->r_next == NULL); + ++#ifdef BUILD_FOR_PIC ++ /* In a PIC build, using _r_debug directly should give us the same ++ object. */ ++ TEST_VERIFY (&_r_debug == &debug->base); ++#endif ++#ifdef BUILD_FOR_NONPIC ++ TEST_COMPARE (_r_debug.r_version, 1); ++#endif ++ + void *h = xdlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", + RTLD_LAZY); + +@@ -57,6 +66,19 @@ do_test (void) + const char *name = basename (debug->r_next->base.r_map->l_name); + TEST_COMPARE_STRING (name, "tst-dlmopen1mod.so"); + ++#ifdef BUILD_FOR_NONPIC ++ /* If a copy relocation is used, it must be at version 1. */ ++ if (&_r_debug != &debug->base) ++ { ++ TEST_COMPARE (_r_debug.r_version, 1); ++ TEST_COMPARE ((uintptr_t) _r_debug.r_map, ++ (uintptr_t) debug->base.r_map); ++ TEST_COMPARE (_r_debug.r_brk, debug->base.r_brk); ++ TEST_COMPARE (_r_debug.r_state, debug->base.r_state); ++ TEST_COMPARE (_r_debug.r_ldbase, debug->base.r_ldbase); ++ } ++#endif ++ + xdlclose (h); + + return 0; +diff --git a/include/link.h b/include/link.h +index 5ed445d5a6..7ca305f780 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -365,6 +365,8 @@ struct auditstate + dynamic linker. */ + extern struct r_debug_extended _r_debug_extended attribute_hidden; + ++rtld_hidden_proto (_r_debug) ++ + #if __ELF_NATIVE_CLASS == 32 + # define symbind symbind32 + # define LA_SYMBIND "la_symbind32" +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 017406e7fa..043abd3697 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1078,6 +1078,10 @@ rtld_hidden_proto (_dl_debug_state) + extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + attribute_hidden; + ++/* This is called after relocation processing to handle a potential ++ copy relocation for _r_debug. */ ++void _dl_debug_post_relocate (struct link_map *main_map) attribute_hidden; ++ + /* Update the `r_map' member and return the address of `struct r_debug' + of the namespace NS. */ + extern struct r_debug *_dl_debug_update (Lmid_t ns) attribute_hidden; + +commit 87a6ccf0b41b7a11db27ab050bb145dffd1182c0 +Author: Florian Weimer +Date: Mon Jul 28 14:16:52 2025 +0200 + + elf: Compile _dl_debug_state separately (bug 33224) + + This ensures that the compiler will not inline it, so that + debuggers which do not use the Systemtap probes can reliably + set a breakpoint on it. + + Reviewed-by: Andreas K. Huettel + Tested-by: Andreas K. Huettel + (cherry picked from commit 620f0730f311635cd0e175a3ae4d0fc700c76366) + +diff --git a/elf/Makefile b/elf/Makefile +index b0894c6430..ab2da6c4c2 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -57,6 +57,7 @@ dl-routines = \ + dl-close \ + dl-debug \ + dl-debug-symbols \ ++ dl-debug_state \ + dl-deps \ + dl-exception \ + dl-execstack \ +diff --git a/elf/dl-debug.c b/elf/dl-debug.c +index 8b51332309..df36d61dcb 100644 +--- a/elf/dl-debug.c ++++ b/elf/dl-debug.c +@@ -167,14 +167,3 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + + return &r->base; + } +- +- +-/* This function exists solely to have a breakpoint set on it by the +- debugger. The debugger is supposed to find this function's address by +- examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks +- for this particular symbol name in the PT_INTERP file. */ +-void +-_dl_debug_state (void) +-{ +-} +-rtld_hidden_def (_dl_debug_state) +diff --git a/elf/dl-debug_state.c b/elf/dl-debug_state.c +new file mode 100644 +index 0000000000..40c134a49e +--- /dev/null ++++ b/elf/dl-debug_state.c +@@ -0,0 +1,30 @@ ++/* Debugger hook called after dynamic linker updates. ++ Copyright (C) 1996-2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++/* This function exists solely to have a breakpoint set on it by the ++ debugger. The debugger is supposed to find this function's address by ++ examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks ++ for this particular symbol name in the PT_INTERP file. Therefore, ++ this function must not be inlined. */ ++void ++_dl_debug_state (void) ++{ ++} ++rtld_hidden_def (_dl_debug_state) + +commit 3533310dd3373a095c8f84835910217c0924563c +Author: Florian Weimer +Date: Mon Aug 18 13:52:02 2025 +0200 + + elf: Preserve _rtld_global layout for the release branch + + Backporting commit 7d649d1c990441181c903bd2f99251cbf1552180 + ("elf: Introduce _dl_debug_change_state") removed the + _ns_debug member. Keep it to preseve struct layout. + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 043abd3697..b4c6e6d2ca 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -350,6 +350,8 @@ struct rtld_global + size_t n_elements; + void (*free) (void *); + } _ns_unique_sym_table; ++ /* Keep track of changes to each namespace' list. */ ++ struct r_debug_extended _ns_debug_unused; + } _dl_ns[DL_NNS]; + /* One higher than index of last used namespace. */ + EXTERN size_t _dl_nns; + +commit c789121e026208baf0f61009150cd0feac34bf66 +Author: mengqinggang +Date: Fri Jan 3 15:49:43 2025 +0800 + + LoongArch: Regenerate preconfigure. [bug 32521] + + Add "mtls_descriptor=desc" to preconfigure.ac and regenerate preconfigure. + Fix failure: elf/tst-gnu2-tls2. + + Reported-by: Joseph S. Myers + Reported-by: Andreas K. Huettel + (cherry picked from commit d4cdb601df0a125550341f85d7011314e4746308) + +diff --git a/sysdeps/loongarch/preconfigure.ac b/sysdeps/loongarch/preconfigure.ac +index 67e4357013..df07dbf41f 100644 +--- a/sysdeps/loongarch/preconfigure.ac ++++ b/sysdeps/loongarch/preconfigure.ac +@@ -41,6 +41,7 @@ loongarch*) + AC_DEFINE_UNQUOTED([LOONGARCH_ABI_FRLEN], [$abi_flen]) + + base_machine=loongarch ++ mtls_descriptor=desc + ;; + esac + + +commit 836c9f0e0b36910814900d50868f9eb7152df82d +Author: H.J. Lu +Date: Mon Jun 9 05:22:10 2025 +0800 + + i386: Update ___tls_get_addr to preserve vector registers + + Compiler generates the following instruction sequence for dynamic TLS + access: + + leal tls_var@tlsgd(,%ebx,1), %eax + call ___tls_get_addr@PLT + + CALL instruction is transparent to compiler which assumes all registers, + except for EFLAGS, AX, CX, and DX, are unchanged after CALL. But + ___tls_get_addr is a normal function which doesn't preserve any vector + registers. + + 1. Rename the generic __tls_get_addr function to ___tls_get_addr_internal. + 2. Change ___tls_get_addr to a wrapper function with implementations for + FNSAVE, FXSAVE, XSAVE and XSAVEC to save and restore all vector registers. + 3. dl-tlsdesc-dynamic.h has: + + _dl_tlsdesc_dynamic: + /* Like all TLS resolvers, preserve call-clobbered registers. + We need two scratch regs anyway. */ + subl $32, %esp + cfi_adjust_cfa_offset (32) + + It is wrong to use + + movl %ebx, -28(%esp) + movl %esp, %ebx + cfi_def_cfa_register(%ebx) + ... + mov %ebx, %esp + cfi_def_cfa_register(%esp) + movl -28(%esp), %ebx + + to preserve EBX on stack. Fix it with: + + movl %ebx, 28(%esp) + movl %esp, %ebx + cfi_def_cfa_register(%ebx) + ... + mov %ebx, %esp + cfi_def_cfa_register(%esp) + movl 28(%esp), %ebx + + 4. Update _dl_tlsdesc_dynamic to call ___tls_get_addr_internal directly. + 5. Add have-test-mtls-traditional to compile tst-tls23-mod.c with + traditional TLS variant to verify the fix. + 6. Define DL_RUNTIME_RESOLVE_REALIGN_STACK in sysdeps/x86/sysdep.h. + + This fixes BZ #32996. + + Co-Authored-By: Adhemerval Zanella + Signed-off-by: H.J. Lu + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 848f0e46f03f22404ed9a8aabf3fd5ce8809a1be) + +diff --git a/configure b/configure +index 1d543548cd..77e1601250 100755 +--- a/configure ++++ b/configure +@@ -4901,6 +4901,9 @@ with_fp_cond=1 + # A preconfigure script may define another name to TLS descriptor variant + mtls_descriptor=gnu2 + ++# A preconfigure script may define another name to traditional TLS variant ++mtls_traditional=gnu ++ + if frags=`ls -d $srcdir/sysdeps/*/preconfigure 2> /dev/null` + then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysdeps preconfigure fragments" >&5 +@@ -7223,6 +7226,39 @@ printf "%s\n" "$libc_cv_mtls_descriptor" >&6; } + config_vars="$config_vars + have-mtls-descriptor = $libc_cv_mtls_descriptor" + ++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for traditional tls support" >&5 ++printf %s "checking for traditional tls support... " >&6; } ++if test ${libc_cv_test_mtls_traditional+y} ++then : ++ printf %s "(cached) " >&6 ++else case e in #( ++ e) cat > conftest.c <&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ++then ++ libc_cv_test_mtls_traditional=$mtls_traditional ++else ++ libc_cv_test_mtls_traditional=no ++fi ++rm -f conftest* ;; ++esac ++fi ++{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_test_mtls_traditional" >&5 ++printf "%s\n" "$libc_cv_test_mtls_traditional" >&6; } ++config_vars="$config_vars ++have-test-mtls-traditional = $libc_cv_test_mtls_traditional" ++ + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if -Wno-ignored-attributes is required for aliases" >&5 + printf %s "checking if -Wno-ignored-attributes is required for aliases... " >&6; } + if test ${libc_cv_wno_ignored_attributes+y} +diff --git a/configure.ac b/configure.ac +index 9cbc0bf68f..eb4f26d592 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -469,6 +469,9 @@ with_fp_cond=1 + # A preconfigure script may define another name to TLS descriptor variant + mtls_descriptor=gnu2 + ++# A preconfigure script may define another name to traditional TLS variant ++mtls_traditional=gnu ++ + dnl Let sysdeps/*/preconfigure act here. + LIBC_PRECONFIGURE([$srcdir], [for sysdeps]) + +@@ -1334,6 +1337,28 @@ rm -f conftest*]) + AC_SUBST(libc_cv_mtls_descriptor) + LIBC_CONFIG_VAR([have-mtls-descriptor], [$libc_cv_mtls_descriptor]) + ++dnl Check if CC supports traditional tls. ++AC_CACHE_CHECK([for traditional tls support], ++ libc_cv_test_mtls_traditional, ++[dnl ++cat > conftest.c <&AS_MESSAGE_LOG_FD]) ++then ++ libc_cv_test_mtls_traditional=$mtls_traditional ++else ++ libc_cv_test_mtls_traditional=no ++fi ++rm -f conftest*]) ++LIBC_CONFIG_VAR([have-test-mtls-traditional], ++ [$libc_cv_test_mtls_traditional]) ++ + dnl clang emits an warning for a double alias redirection, to warn the + dnl original symbol is sed even when weak definition overrides it. + dnl It is a usual pattern for weak_alias, where multiple alias point to +diff --git a/elf/Makefile b/elf/Makefile +index ab2da6c4c2..0303e08557 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -486,6 +486,7 @@ tests += \ + tst-tls19 \ + tst-tls20 \ + tst-tls21 \ ++ tst-tls23 \ + tst-tlsalign \ + tst-tlsalign-extern \ + tst-tlsgap \ +@@ -964,6 +965,7 @@ modules-names += \ + tst-tls19mod3 \ + tst-tls20mod-bad \ + tst-tls21mod \ ++ tst-tls23-mod \ + tst-tlsalign-lib \ + tst-tlsgap-mod0 \ + tst-tlsgap-mod1 \ +@@ -3197,6 +3199,13 @@ tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so + # Any shared object should do. + tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so + ++$(objpfx)tst-tls23: $(shared-thread-library) ++$(objpfx)tst-tls23.out: $(objpfx)tst-tls23-mod.so ++ ++ifneq (no,$(have-test-mtls-traditional)) ++CFLAGS-tst-tls23-mod.c += -mtls-dialect=$(have-test-mtls-traditional) ++endif ++ + $(objpfx)tst-version-hash-zero.out: \ + $(objpfx)tst-version-hash-zero-mod.so \ + $(objpfx)tst-version-hash-zero-refmod.so +diff --git a/elf/tst-tls23-mod.c b/elf/tst-tls23-mod.c +new file mode 100644 +index 0000000000..3ee4c70e40 +--- /dev/null ++++ b/elf/tst-tls23-mod.c +@@ -0,0 +1,32 @@ ++/* DSO used by tst-tls23. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++__thread struct tls tls_var0 __attribute__ ((visibility ("hidden"))); ++ ++struct tls * ++apply_tls (struct tls *p) ++{ ++ INIT_TLS_CALL (); ++ BEFORE_TLS_CALL (); ++ tls_var0 = *p; ++ struct tls *ret = &tls_var0; ++ AFTER_TLS_CALL (); ++ return ret; ++} +diff --git a/elf/tst-tls23.c b/elf/tst-tls23.c +new file mode 100644 +index 0000000000..afe594c067 +--- /dev/null ++++ b/elf/tst-tls23.c +@@ -0,0 +1,106 @@ ++/* Test that __tls_get_addr preserves caller-saved registers. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef IS_SUPPORTED ++# define IS_SUPPORTED() true ++#endif ++ ++/* An architecture can define it to clobber caller-saved registers in ++ malloc below to verify that __tls_get_addr won't change caller-saved ++ registers. */ ++#ifndef PREPARE_MALLOC ++# define PREPARE_MALLOC() ++#endif ++ ++extern void * __libc_malloc (size_t); ++ ++size_t malloc_counter = 0; ++ ++void * ++malloc (size_t n) ++{ ++ PREPARE_MALLOC (); ++ malloc_counter++; ++ return __libc_malloc (n); ++} ++ ++static void *mod; ++static const char *modname = "tst-tls23-mod.so"; ++ ++static void ++open_mod (void) ++{ ++ mod = xdlopen (modname, RTLD_LAZY); ++ printf ("open %s\n", modname); ++} ++ ++static void ++close_mod (void) ++{ ++ xdlclose (mod); ++ mod = NULL; ++ printf ("close %s\n", modname); ++} ++ ++static void ++access_mod (const char *sym) ++{ ++ struct tls var = { -4, -4, -4, -4 }; ++ struct tls *(*f) (struct tls *) = xdlsym (mod, sym); ++ /* Check that our malloc is called. */ ++ malloc_counter = 0; ++ struct tls *p = f (&var); ++ TEST_VERIFY (malloc_counter != 0); ++ printf ("access %s: %s() = %p\n", modname, sym, p); ++ TEST_VERIFY_EXIT (memcmp (p, &var, sizeof (var)) == 0); ++ ++(p->a); ++} ++ ++static void * ++start (void *arg) ++{ ++ access_mod ("apply_tls"); ++ return arg; ++} ++ ++static int ++do_test (void) ++{ ++ if (!IS_SUPPORTED ()) ++ return EXIT_UNSUPPORTED; ++ ++ open_mod (); ++ pthread_t t = xpthread_create (NULL, start, NULL); ++ xpthread_join (t); ++ close_mod (); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/x86_64/dl-trampoline-save.h b/elf/tst-tls23.h +similarity index 52% +rename from sysdeps/x86_64/dl-trampoline-save.h +rename to elf/tst-tls23.h +index 84eac4a8ac..d0e734569c 100644 +--- a/sysdeps/x86_64/dl-trampoline-save.h ++++ b/elf/tst-tls23.h +@@ -1,5 +1,5 @@ +-/* x86-64 PLT trampoline register save macros. +- Copyright (C) 2024 Free Software Foundation, Inc. ++/* Test that __tls_get_addr preserves caller-saved registers. ++ Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -16,19 +16,25 @@ + License along with the GNU C Library; if not, see + . */ + +-#ifndef DL_STACK_ALIGNMENT +-/* Due to GCC bug: ++#include + +- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 ++struct tls ++{ ++ int64_t a, b, c, d; ++}; + +- __tls_get_addr may be called with 8-byte stack alignment. Although +- this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume +- that stack will be always aligned at 16 bytes. */ +-# define DL_STACK_ALIGNMENT 8 ++extern struct tls *apply_tls (struct tls *); ++ ++/* An architecture can define them to verify that caller-saved registers ++ aren't changed by __tls_get_addr. */ ++#ifndef INIT_TLS_CALL ++# define INIT_TLS_CALL() ++#endif ++ ++#ifndef BEFORE_TLS_CALL ++# define BEFORE_TLS_CALL() + #endif + +-/* True if _dl_runtime_resolve should align stack for STATE_SAVE or align +- stack to 16 bytes before calling _dl_fixup. */ +-#define DL_RUNTIME_RESOLVE_REALIGN_STACK \ +- (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ +- || 16 > DL_STACK_ALIGNMENT) ++#ifndef AFTER_TLS_CALL ++# define AFTER_TLS_CALL() ++#endif +diff --git a/sysdeps/aarch64/preconfigure b/sysdeps/aarch64/preconfigure +index 19657b627b..e1b772c586 100644 +--- a/sysdeps/aarch64/preconfigure ++++ b/sysdeps/aarch64/preconfigure +@@ -3,5 +3,6 @@ aarch64*) + base_machine=aarch64 + machine=aarch64 + mtls_descriptor=desc ++ mtls_traditional=trad + ;; + esac +diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile +index a2e8c0b128..ee6470d78e 100644 +--- a/sysdeps/i386/Makefile ++++ b/sysdeps/i386/Makefile +@@ -30,7 +30,9 @@ stack-align-test-flags += -malign-double + endif + + ifeq ($(subdir),elf) +-sysdep-dl-routines += tlsdesc dl-tlsdesc ++sysdep-dl-routines += \ ++ dl-tls-get-addr \ ++# sysdep-dl-routines + + tests += tst-audit3 + modules-names += tst-auditmod3a tst-auditmod3b +diff --git a/sysdeps/i386/dl-tls-get-addr.c b/sysdeps/i386/dl-tls-get-addr.c +new file mode 100644 +index 0000000000..c97e5c57be +--- /dev/null ++++ b/sysdeps/i386/dl-tls-get-addr.c +@@ -0,0 +1,68 @@ ++/* Ifunc selector for ___tls_get_addr. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#ifdef SHARED ++# define ___tls_get_addr __redirect____tls_get_addr ++# include ++# undef ___tls_get_addr ++# undef __tls_get_addr ++ ++# define SYMBOL_NAME ___tls_get_addr ++# include ++ ++extern __typeof (REDIRECT_NAME) OPTIMIZE (fnsave) attribute_hidden; ++extern __typeof (REDIRECT_NAME) OPTIMIZE (fxsave) attribute_hidden; ++extern __typeof (REDIRECT_NAME) OPTIMIZE (xsave) attribute_hidden; ++extern __typeof (REDIRECT_NAME) OPTIMIZE (xsavec) attribute_hidden; ++ ++static inline void * ++IFUNC_SELECTOR (void) ++{ ++ const struct cpu_features* cpu_features = __get_cpu_features (); ++ ++ if (cpu_features->xsave_state_size != 0) ++ { ++ if (CPU_FEATURE_USABLE_P (cpu_features, XSAVEC)) ++ return OPTIMIZE (xsavec); ++ else ++ return OPTIMIZE (xsave); ++ } ++ else if (CPU_FEATURE_USABLE_P (cpu_features, FXSR)) ++ return OPTIMIZE (fxsave); ++ return OPTIMIZE (fnsave); ++} ++ ++libc_ifunc_redirected (__redirect____tls_get_addr, ___tls_get_addr, ++ IFUNC_SELECTOR ()); ++ ++/* The special thing about the x86 TLS ABI is that we have two ++ variants of the __tls_get_addr function with different calling ++ conventions. The GNU version, which we are mostly concerned here, ++ takes the parameter in a register. The name is changed by adding ++ an additional underscore at the beginning. The Sun version uses ++ the normal calling convention. */ ++ ++rtld_hidden_proto (___tls_get_addr) ++rtld_hidden_def (___tls_get_addr) ++ ++void * ++__tls_get_addr (tls_index *ti) ++{ ++ return ___tls_get_addr (ti); ++} ++#endif +diff --git a/sysdeps/i386/dl-tls.h b/sysdeps/i386/dl-tls.h +index f17286703d..2380ec1bd4 100644 +--- a/sysdeps/i386/dl-tls.h ++++ b/sysdeps/i386/dl-tls.h +@@ -29,33 +29,13 @@ typedef struct dl_tls_index + /* This is the prototype for the GNU version. */ + extern void *___tls_get_addr (tls_index *ti) + __attribute__ ((__regparm__ (1))); +-extern void *___tls_get_addr_internal (tls_index *ti) +- __attribute__ ((__regparm__ (1))) attribute_hidden; +- + # if IS_IN (rtld) +-/* The special thing about the x86 TLS ABI is that we have two +- variants of the __tls_get_addr function with different calling +- conventions. The GNU version, which we are mostly concerned here, +- takes the parameter in a register. The name is changed by adding +- an additional underscore at the beginning. The Sun version uses +- the normal calling convention. */ +-void * +-__tls_get_addr (tls_index *ti) +-{ +- return ___tls_get_addr_internal (ti); +-} +- +- + /* Prepare using the definition of __tls_get_addr in the generic + version of this file. */ +-# define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr +-strong_alias (___tls_get_addr, ___tls_get_addr_internal) +-rtld_hidden_proto (___tls_get_addr) +-rtld_hidden_def (___tls_get_addr) +-#else +- ++# define __tls_get_addr \ ++ __attribute__ ((__regparm__ (1))) ___tls_get_addr_internal ++# else + /* Users should get the better interface. */ +-# define __tls_get_addr ___tls_get_addr +- ++# define __tls_get_addr ___tls_get_addr + # endif + #endif +diff --git a/sysdeps/i386/dl-tlsdesc-dynamic.h b/sysdeps/i386/dl-tlsdesc-dynamic.h +index 3627028577..8a5952421e 100644 +--- a/sysdeps/i386/dl-tlsdesc-dynamic.h ++++ b/sysdeps/i386/dl-tlsdesc-dynamic.h +@@ -16,34 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#undef REGISTER_SAVE_AREA +- +-#if !defined USE_FNSAVE && (STATE_SAVE_ALIGNMENT % 16) != 0 +-# error STATE_SAVE_ALIGNMENT must be multiple of 16 +-#endif +- +-#if DL_RUNTIME_RESOLVE_REALIGN_STACK +-# ifdef USE_FNSAVE +-# error USE_FNSAVE shouldn't be defined +-# endif +-# ifdef USE_FXSAVE +-/* Use fxsave to save all registers. */ +-# define REGISTER_SAVE_AREA 512 +-# endif +-#else +-# ifdef USE_FNSAVE +-/* Use fnsave to save x87 FPU stack registers. */ +-# define REGISTER_SAVE_AREA 108 +-# else +-# ifndef USE_FXSAVE +-# error USE_FXSAVE must be defined +-# endif +-/* Use fxsave to save all registers. Add 12 bytes to align the stack +- to 16 bytes. */ +-# define REGISTER_SAVE_AREA (512 + 12) +-# endif +-#endif +- + .hidden _dl_tlsdesc_dynamic + .global _dl_tlsdesc_dynamic + .type _dl_tlsdesc_dynamic,@function +@@ -104,85 +76,7 @@ _dl_tlsdesc_dynamic: + ret + .p2align 4,,7 + 2: +- cfi_adjust_cfa_offset (32) +-#if DL_RUNTIME_RESOLVE_REALIGN_STACK +- movl %ebx, -28(%esp) +- movl %esp, %ebx +- cfi_def_cfa_register(%ebx) +- and $-STATE_SAVE_ALIGNMENT, %esp +-#endif +-#ifdef REGISTER_SAVE_AREA +- subl $REGISTER_SAVE_AREA, %esp +-# if !DL_RUNTIME_RESOLVE_REALIGN_STACK +- cfi_adjust_cfa_offset(REGISTER_SAVE_AREA) +-# endif +-#else +-# if !DL_RUNTIME_RESOLVE_REALIGN_STACK +-# error DL_RUNTIME_RESOLVE_REALIGN_STACK must be true +-# endif +- /* Allocate stack space of the required size to save the state. */ +- LOAD_PIC_REG (cx) +- subl RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET+XSAVE_STATE_SIZE_OFFSET+_rtld_local_ro@GOTOFF(%ecx), %esp +-#endif +-#ifdef USE_FNSAVE +- fnsave (%esp) +-#elif defined USE_FXSAVE +- fxsave (%esp) +-#else +- /* Save the argument for ___tls_get_addr in EAX. */ +- movl %eax, %ecx +- movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax +- xorl %edx, %edx +- /* Clear the XSAVE Header. */ +-# ifdef USE_XSAVE +- movl %edx, (512)(%esp) +- movl %edx, (512 + 4 * 1)(%esp) +- movl %edx, (512 + 4 * 2)(%esp) +- movl %edx, (512 + 4 * 3)(%esp) +-# endif +- movl %edx, (512 + 4 * 4)(%esp) +- movl %edx, (512 + 4 * 5)(%esp) +- movl %edx, (512 + 4 * 6)(%esp) +- movl %edx, (512 + 4 * 7)(%esp) +- movl %edx, (512 + 4 * 8)(%esp) +- movl %edx, (512 + 4 * 9)(%esp) +- movl %edx, (512 + 4 * 10)(%esp) +- movl %edx, (512 + 4 * 11)(%esp) +- movl %edx, (512 + 4 * 12)(%esp) +- movl %edx, (512 + 4 * 13)(%esp) +- movl %edx, (512 + 4 * 14)(%esp) +- movl %edx, (512 + 4 * 15)(%esp) +-# ifdef USE_XSAVE +- xsave (%esp) +-# else +- xsavec (%esp) +-# endif +- /* Restore the argument for ___tls_get_addr in EAX. */ +- movl %ecx, %eax +-#endif +- call HIDDEN_JUMPTARGET (___tls_get_addr) +- /* Get register content back. */ +-#ifdef USE_FNSAVE +- frstor (%esp) +-#elif defined USE_FXSAVE +- fxrstor (%esp) +-#else +- /* Save and retore ___tls_get_addr return value stored in EAX. */ +- movl %eax, %ecx +- movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax +- xorl %edx, %edx +- xrstor (%esp) +- movl %ecx, %eax +-#endif +-#if DL_RUNTIME_RESOLVE_REALIGN_STACK +- mov %ebx, %esp +- cfi_def_cfa_register(%esp) +- movl -28(%esp), %ebx +- cfi_restore(%ebx) +-#else +- addl $REGISTER_SAVE_AREA, %esp +- cfi_adjust_cfa_offset(-REGISTER_SAVE_AREA) +-#endif ++#include "tls-get-addr-wrapper.h" + jmp 1b + cfi_endproc + .size _dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic +diff --git a/sysdeps/i386/dl-tlsdesc.S b/sysdeps/i386/dl-tlsdesc.S +index f002feee56..dec7049911 100644 +--- a/sysdeps/i386/dl-tlsdesc.S ++++ b/sysdeps/i386/dl-tlsdesc.S +@@ -22,23 +22,6 @@ + #include + #include "tlsdesc.h" + +-#ifndef DL_STACK_ALIGNMENT +-/* Due to GCC bug: +- +- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 +- +- __tls_get_addr may be called with 4-byte stack alignment. Although +- this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't assume +- that stack will be always aligned at 16 bytes. */ +-# define DL_STACK_ALIGNMENT 4 +-#endif +- +-/* True if _dl_tlsdesc_dynamic should align stack for STATE_SAVE or align +- stack to MINIMUM_ALIGNMENT bytes before calling ___tls_get_addr. */ +-#define DL_RUNTIME_RESOLVE_REALIGN_STACK \ +- (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ +- || MINIMUM_ALIGNMENT > DL_STACK_ALIGNMENT) +- + .text + + /* This function is used to compute the TP offset for symbols in +diff --git a/sysdeps/i386/tls-get-addr-wrapper.h b/sysdeps/i386/tls-get-addr-wrapper.h +new file mode 100644 +index 0000000000..0708e5ad1d +--- /dev/null ++++ b/sysdeps/i386/tls-get-addr-wrapper.h +@@ -0,0 +1,127 @@ ++/* Wrapper of i386 ___tls_get_addr to save and restore vector registers. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#undef REGISTER_SAVE_AREA ++ ++#if !defined USE_FNSAVE && (STATE_SAVE_ALIGNMENT % 16) != 0 ++# error STATE_SAVE_ALIGNMENT must be multiple of 16 ++#endif ++ ++#if DL_RUNTIME_RESOLVE_REALIGN_STACK ++# ifdef USE_FNSAVE ++# error USE_FNSAVE shouldn't be defined ++# endif ++# ifdef USE_FXSAVE ++/* Use fxsave to save all registers. */ ++# define REGISTER_SAVE_AREA 512 ++# endif ++#else ++# ifdef USE_FNSAVE ++/* Use fnsave to save x87 FPU stack registers. */ ++# define REGISTER_SAVE_AREA 108 ++# else ++# ifndef USE_FXSAVE ++# error USE_FXSAVE must be defined ++# endif ++/* Use fxsave to save all registers. Add 12 bytes to align the stack ++ to 16 bytes. */ ++# define REGISTER_SAVE_AREA (512 + 12) ++# endif ++#endif ++ ++#if DL_RUNTIME_RESOLVE_REALIGN_STACK ++ movl %ebx, 28(%esp) ++ movl %esp, %ebx ++ cfi_def_cfa_register(%ebx) ++ and $-STATE_SAVE_ALIGNMENT, %esp ++#endif ++#ifdef REGISTER_SAVE_AREA ++ subl $REGISTER_SAVE_AREA, %esp ++# if !DL_RUNTIME_RESOLVE_REALIGN_STACK ++ cfi_adjust_cfa_offset(REGISTER_SAVE_AREA) ++# endif ++#else ++# if !DL_RUNTIME_RESOLVE_REALIGN_STACK ++# error DL_RUNTIME_RESOLVE_REALIGN_STACK must be true ++# endif ++ /* Allocate stack space of the required size to save the state. */ ++ LOAD_PIC_REG (cx) ++ subl RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET \ ++ +XSAVE_STATE_SIZE_OFFSET+_rtld_local_ro@GOTOFF(%ecx), %esp ++#endif ++#ifdef USE_FNSAVE ++ fnsave (%esp) ++#elif defined USE_FXSAVE ++ fxsave (%esp) ++#else ++ /* Save the argument for ___tls_get_addr in EAX. */ ++ movl %eax, %ecx ++ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax ++ xorl %edx, %edx ++ /* Clear the XSAVE Header. */ ++# ifdef USE_XSAVE ++ movl %edx, (512)(%esp) ++ movl %edx, (512 + 4 * 1)(%esp) ++ movl %edx, (512 + 4 * 2)(%esp) ++ movl %edx, (512 + 4 * 3)(%esp) ++# endif ++ movl %edx, (512 + 4 * 4)(%esp) ++ movl %edx, (512 + 4 * 5)(%esp) ++ movl %edx, (512 + 4 * 6)(%esp) ++ movl %edx, (512 + 4 * 7)(%esp) ++ movl %edx, (512 + 4 * 8)(%esp) ++ movl %edx, (512 + 4 * 9)(%esp) ++ movl %edx, (512 + 4 * 10)(%esp) ++ movl %edx, (512 + 4 * 11)(%esp) ++ movl %edx, (512 + 4 * 12)(%esp) ++ movl %edx, (512 + 4 * 13)(%esp) ++ movl %edx, (512 + 4 * 14)(%esp) ++ movl %edx, (512 + 4 * 15)(%esp) ++# ifdef USE_XSAVE ++ xsave (%esp) ++# else ++ xsavec (%esp) ++# endif ++ /* Restore the argument for ___tls_get_addr in EAX. */ ++ movl %ecx, %eax ++#endif ++ call ___tls_get_addr_internal ++ /* Get register content back. */ ++#ifdef USE_FNSAVE ++ frstor (%esp) ++#elif defined USE_FXSAVE ++ fxrstor (%esp) ++#else ++ /* Save and retore ___tls_get_addr return value stored in EAX. */ ++ movl %eax, %ecx ++ movl $TLSDESC_CALL_STATE_SAVE_MASK, %eax ++ xorl %edx, %edx ++ xrstor (%esp) ++ movl %ecx, %eax ++#endif ++#if DL_RUNTIME_RESOLVE_REALIGN_STACK ++ mov %ebx, %esp ++ cfi_def_cfa_register(%esp) ++ movl 28(%esp), %ebx ++ cfi_restore(%ebx) ++#else ++ addl $REGISTER_SAVE_AREA, %esp ++ cfi_adjust_cfa_offset(-REGISTER_SAVE_AREA) ++#endif ++ ++#undef STATE_SAVE_ALIGNMENT +diff --git a/sysdeps/i386/tls_get_addr.S b/sysdeps/i386/tls_get_addr.S +new file mode 100644 +index 0000000000..7d143d8a23 +--- /dev/null ++++ b/sysdeps/i386/tls_get_addr.S +@@ -0,0 +1,57 @@ ++/* Thread-local storage handling in the ELF dynamic linker. i386 version. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++ .text ++#ifdef SHARED ++# define USE_FNSAVE ++# define MINIMUM_ALIGNMENT 4 ++# define STATE_SAVE_ALIGNMENT 4 ++# define ___tls_get_addr _____tls_get_addr_fnsave ++# include "tls_get_addr.h" ++# undef ___tls_get_addr ++# undef MINIMUM_ALIGNMENT ++# undef USE_FNSAVE ++ ++# define MINIMUM_ALIGNMENT 16 ++ ++# define USE_FXSAVE ++# define STATE_SAVE_ALIGNMENT 16 ++# define ___tls_get_addr _____tls_get_addr_fxsave ++# include "tls_get_addr.h" ++# undef ___tls_get_addr ++# undef USE_FXSAVE ++ ++# define USE_XSAVE ++# define STATE_SAVE_ALIGNMENT 64 ++# define ___tls_get_addr _____tls_get_addr_xsave ++# include "tls_get_addr.h" ++# undef ___tls_get_addr ++# undef USE_XSAVE ++ ++# define USE_XSAVEC ++# define STATE_SAVE_ALIGNMENT 64 ++# define ___tls_get_addr _____tls_get_addr_xsavec ++# include "tls_get_addr.h" ++# undef ___tls_get_addr ++# undef USE_XSAVEC ++#endif /* SHARED */ +diff --git a/sysdeps/i386/tls_get_addr.h b/sysdeps/i386/tls_get_addr.h +new file mode 100644 +index 0000000000..1825798724 +--- /dev/null ++++ b/sysdeps/i386/tls_get_addr.h +@@ -0,0 +1,42 @@ ++/* Thread-local storage handling in the ELF dynamic linker. i386 version. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++ .hidden ___tls_get_addr ++ .global ___tls_get_addr ++ .type ___tls_get_addr,@function ++ ++ /* This function is a wrapper of ___tls_get_addr_internal to ++ preserve caller-saved vector registers. */ ++ ++ cfi_startproc ++ .align 16 ++___tls_get_addr: ++ /* Like all TLS resolvers, preserve call-clobbered registers. ++ We need two scratch regs anyway. */ ++ subl $32, %esp ++ cfi_adjust_cfa_offset (32) ++ movl %ecx, 20(%esp) ++ movl %edx, 24(%esp) ++#include "tls-get-addr-wrapper.h" ++ movl 20(%esp), %ecx ++ movl 24(%esp), %edx ++ addl $32, %esp ++ cfi_adjust_cfa_offset (-32) ++ ret ++ cfi_endproc ++ .size ___tls_get_addr, .-___tls_get_addr +diff --git a/sysdeps/loongarch/preconfigure b/sysdeps/loongarch/preconfigure +index 0d1e9ed8df..6726ab8302 100644 +--- a/sysdeps/loongarch/preconfigure ++++ b/sysdeps/loongarch/preconfigure +@@ -44,6 +44,7 @@ loongarch*) + + base_machine=loongarch + mtls_descriptor=desc ++ mtls_traditional=trad + ;; + esac + +diff --git a/sysdeps/loongarch/preconfigure.ac b/sysdeps/loongarch/preconfigure.ac +index df07dbf41f..56402261df 100644 +--- a/sysdeps/loongarch/preconfigure.ac ++++ b/sysdeps/loongarch/preconfigure.ac +@@ -42,6 +42,7 @@ loongarch*) + + base_machine=loongarch + mtls_descriptor=desc ++ mtls_traditional=trad + ;; + esac + +diff --git a/sysdeps/powerpc/Makefile b/sysdeps/powerpc/Makefile +index 5e6cb07ce6..5cdb64f29b 100644 +--- a/sysdeps/powerpc/Makefile ++++ b/sysdeps/powerpc/Makefile +@@ -28,6 +28,11 @@ tst-cache-ppc-static-dlopen-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(c + $(objpfx)tst-cache-ppc-static-dlopen.out: $(objpfx)mod-cache-ppc.so + + $(objpfx)tst-cache-ppc: $(objpfx)mod-cache-ppc.so ++ ++# The test checks if the __tls_get_addr does not clobber caller-saved ++# register, so disable the powerpc specific optimization to force a ++# __tls_get_addr call. ++LDFLAGS-tst-tls23-mod.so = -Wl,--no-tls-get-addr-optimize + endif + + ifneq (no,$(multi-arch)) +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 01b0192ddf..f64cee3cd9 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -4,7 +4,13 @@ endif + + ifeq ($(subdir),elf) + sysdep_routines += get-cpuid-feature-leaf +-sysdep-dl-routines += dl-get-cpu-features ++sysdep-dl-routines += \ ++ dl-get-cpu-features \ ++ dl-tlsdesc \ ++ tls_get_addr \ ++ tlsdesc \ ++# sysdep-dl-routines ++ + sysdep_headers += \ + bits/platform/features.h \ + bits/platform/x86.h \ +@@ -113,6 +119,14 @@ $(objpfx)tst-gnu2-tls2-x86-noxsavexsavec.out: \ + $(objpfx)tst-gnu2-tls2mod0.so \ + $(objpfx)tst-gnu2-tls2mod1.so \ + $(objpfx)tst-gnu2-tls2mod2.so ++ ++CFLAGS-tst-tls23.c += -msse2 ++CFLAGS-tst-tls23-mod.c += -msse2 -mtune=haswell ++ ++LDFLAGS-tst-tls23 += -rdynamic ++tst-tls23-mod.so-no-z-defs = yes ++ ++$(objpfx)tst-tls23-mod.so: $(libsupport) + endif + + ifeq ($(subdir),math) +diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h +index 1d6cabd816..d5f5ec0ecc 100644 +--- a/sysdeps/x86/sysdep.h ++++ b/sysdeps/x86/sysdep.h +@@ -183,6 +183,29 @@ + + #define atom_text_section .section ".text.atom", "ax" + ++#ifndef DL_STACK_ALIGNMENT ++/* Due to GCC bug: ++ ++ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066 ++ ++ __tls_get_addr may be called with 8-byte/4-byte stack alignment. ++ Although this bug has been fixed in GCC 4.9.4, 5.3 and 6, we can't ++ assume that stack will be always aligned at 16 bytes. */ ++# ifdef __x86_64__ ++# define DL_STACK_ALIGNMENT 8 ++# define MINIMUM_ALIGNMENT 16 ++# else ++# define DL_STACK_ALIGNMENT 4 ++# endif ++#endif ++ ++/* True if _dl_runtime_resolve/_dl_tlsdesc_dynamic should align stack for ++ STATE_SAVE or align stack to MINIMUM_ALIGNMENT bytes before calling ++ _dl_fixup/__tls_get_addr. */ ++#define DL_RUNTIME_RESOLVE_REALIGN_STACK \ ++ (STATE_SAVE_ALIGNMENT > DL_STACK_ALIGNMENT \ ++ || MINIMUM_ALIGNMENT > DL_STACK_ALIGNMENT) ++ + #endif /* __ASSEMBLER__ */ + + #endif /* _X86_SYSDEP_H */ +diff --git a/sysdeps/x86/tst-tls23.c b/sysdeps/x86/tst-tls23.c +new file mode 100644 +index 0000000000..6130d91cf8 +--- /dev/null ++++ b/sysdeps/x86/tst-tls23.c +@@ -0,0 +1,22 @@ ++#ifndef __x86_64__ ++#include ++ ++#define IS_SUPPORTED() CPU_FEATURE_ACTIVE (SSE2) ++#endif ++ ++/* Set XMM0...XMM7 to all 1s. */ ++#define PREPARE_MALLOC() \ ++{ \ ++ asm volatile ("pcmpeqd %%xmm0, %%xmm0" : : : "xmm0" ); \ ++ asm volatile ("pcmpeqd %%xmm1, %%xmm1" : : : "xmm1" ); \ ++ asm volatile ("pcmpeqd %%xmm2, %%xmm2" : : : "xmm2" ); \ ++ asm volatile ("pcmpeqd %%xmm3, %%xmm3" : : : "xmm3" ); \ ++ asm volatile ("pcmpeqd %%xmm4, %%xmm4" : : : "xmm4" ); \ ++ asm volatile ("pcmpeqd %%xmm5, %%xmm5" : : : "xmm5" ); \ ++ asm volatile ("pcmpeqd %%xmm6, %%xmm6" : : : "xmm6" ); \ ++ asm volatile ("pcmpeqd %%xmm7, %%xmm7" : : : "xmm7" ); \ ++} ++ ++#include ++ ++v2di v1, v2, v3; +diff --git a/sysdeps/x86/tst-tls23.h b/sysdeps/x86/tst-tls23.h +new file mode 100644 +index 0000000000..21cee4ca07 +--- /dev/null ++++ b/sysdeps/x86/tst-tls23.h +@@ -0,0 +1,35 @@ ++/* Test that __tls_get_addr preserves XMM registers. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++typedef long long v2di __attribute__((vector_size(16))); ++extern v2di v1, v2, v3; ++ ++#define BEFORE_TLS_CALL() \ ++ v1 = __extension__(v2di){0, 0}; \ ++ v2 = __extension__(v2di){0, 0}; ++ ++#define AFTER_TLS_CALL() \ ++ v3 = __extension__(v2di){0, 0}; \ ++ asm volatile ("" : "+x" (v3)); \ ++ union { v2di x; long long a[2]; } u; \ ++ u.x = v3; \ ++ TEST_VERIFY_EXIT (u.a[0] == 0 && u.a[1] == 0); ++ ++#include +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index e4895bd730..5ca6e5d034 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -41,9 +41,6 @@ ifeq ($(subdir),elf) + CFLAGS-.os += $(if $(filter $(@F),$(patsubst %,%.os,$(all-rtld-routines))),\ + -mno-mmx) + +-sysdep-dl-routines += tlsdesc dl-tlsdesc tls_get_addr +- +-tests += ifuncmain8 + modules-names += ifuncmod8 + + $(objpfx)ifuncmain8: $(objpfx)ifuncmod8.so +diff --git a/sysdeps/x86_64/dl-tlsdesc.S b/sysdeps/x86_64/dl-tlsdesc.S +index 057a10862a..586079291a 100644 +--- a/sysdeps/x86_64/dl-tlsdesc.S ++++ b/sysdeps/x86_64/dl-tlsdesc.S +@@ -22,7 +22,6 @@ + #include + #include + #include "tlsdesc.h" +-#include "dl-trampoline-save.h" + + /* Area on stack to save and restore registers used for parameter + passing when calling _dl_tlsdesc_dynamic. */ +diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S +index 87c5137837..4c11fcf032 100644 +--- a/sysdeps/x86_64/dl-trampoline.S ++++ b/sysdeps/x86_64/dl-trampoline.S +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include "dl-trampoline-save.h" + + /* Area on stack to save and restore registers used for parameter + passing when calling _dl_fixup. */ + +commit 340df50b37c39bb50e39cf74060c6e395fed8eea +Author: Florian Weimer +Date: Mon Nov 25 17:32:54 2024 +0100 + + debug: Wire up tst-longjmp_chk3 + + The test was added in commit ac8cc9e300a002228eb7e660df3e7b333d9a7414 + without all the required Makefile scaffolding. Tweak the test + so that it actually builds (including with dynamic SIGSTKSZ). + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 4b7cfcc3fbfab55a1bbb32a2da69c048060739d6) + +diff --git a/debug/Makefile b/debug/Makefile +index 3903cc97a3..76c311d284 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -287,6 +287,7 @@ tests = \ + tst-fortify-wide \ + tst-longjmp_chk \ + tst-longjmp_chk2 \ ++ tst-longjmp_chk3 \ + tst-realpath-chk \ + tst-sprintf-fortify-rdonly \ + tst-sprintf-fortify-unchecked \ +diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c +index 9ff9977207..7bf1646b35 100644 +--- a/debug/tst-longjmp_chk3.c ++++ b/debug/tst-longjmp_chk3.c +@@ -18,9 +18,12 @@ + + #include + #include ++#include + #include + +-static char buf[SIGSTKSZ * 4]; ++#include ++ ++static char *buf; + static jmp_buf jb; + + static void +@@ -49,8 +52,10 @@ do_test (void) + set_fortify_handler (handler); + + /* Create a valid signal stack and enable it. */ ++ size_t bufsize = SIGSTKSZ * 4; ++ buf = xmalloc (bufsize); + ss.ss_sp = buf; +- ss.ss_size = sizeof (buf); ++ ss.ss_size = bufsize; + ss.ss_flags = 0; + if (sigaltstack (&ss, NULL) < 0) + { +@@ -65,8 +70,8 @@ do_test (void) + + /* Shrink the signal stack so the jmpbuf is now invalid. + We adjust the start & end to handle stacks that grow up & down. */ +- ss.ss_sp = buf + sizeof (buf) / 2; +- ss.ss_size = sizeof (buf) / 4; ++ ss.ss_sp = buf + bufsize / 2; ++ ss.ss_size = bufsize / 4; + if (sigaltstack (&ss, NULL) < 0) + { + printf ("second sigaltstack failed: %m\n"); + +commit 3e335fad3567b1634c1bb525b8defad86e488594 +Author: Florian Weimer +Date: Tue Nov 26 19:26:13 2024 +0100 + + debug: Fix tst-longjmp_chk3 build failure on Hurd + + Explicitly include for _exit and getpid. + + (cherry picked from commit 4836a9af89f1b4d482e6c72ff67e36226d36434c) + +diff --git a/debug/tst-longjmp_chk3.c b/debug/tst-longjmp_chk3.c +index 7bf1646b35..9b9db3b9e9 100644 +--- a/debug/tst-longjmp_chk3.c ++++ b/debug/tst-longjmp_chk3.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + #include + + +commit d67776356dc0ed6986e5f924cf1ac166f68324b7 +Author: H.J. Lu +Date: Mon Jul 28 12:16:11 2025 -0700 + + i386: Add GLIBC_ABI_GNU_TLS version [BZ #33221] + + On i386, programs and shared libraries with __thread usage may fail + silently at run-time against glibc without the TLS run-time fix for: + + https://sourceware.org/bugzilla/show_bug.cgi?id=32996 + + Add GLIBC_ABI_GNU_TLS version to indicate that glibc has the working + GNU TLS run-time. Linker can add the GLIBC_ABI_GNU_TLS version to + binaries which depend on the working TLS run-time so that such programs + and shared libraries will fail to load and run at run-time against + libc.so without the GLIBC_ABI_GNU_TLS version, instead of fail silently + at random. + + This fixes BZ #33221. + + Signed-off-by: H.J. Lu + Reviewed-by: Sam James + (cherry picked from commit ed1b7a5a489ab555a27fad9c101ebe2e1c1ba881) + +diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile +index ee6470d78e..c0c017b899 100644 +--- a/sysdeps/i386/Makefile ++++ b/sysdeps/i386/Makefile +@@ -60,6 +60,15 @@ $(objpfx)tst-ld-sse-use.out: ../sysdeps/i386/tst-ld-sse-use.sh $(objpfx)ld.so + @echo "Checking ld.so for SSE register use. This will take a few seconds..." + $(BASH) $< $(objpfx) '$(NM)' '$(OBJDUMP)' '$(READELF)' > $@; \ + $(evaluate-test) ++ ++tests-special += $(objpfx)check-gnu-tls.out ++ ++$(objpfx)check-gnu-tls.out: $(common-objpfx)libc.so ++ LC_ALL=C $(READELF) -V -W $< \ ++ | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ ++ | grep GLIBC_ABI_GNU_TLS > $@; \ ++ $(evaluate-test) ++generated += check-gnu-tls.out + else + CFLAGS-.os += $(if $(filter rtld-%.os,$(@F)), $(rtld-CFLAGS)) + endif +diff --git a/sysdeps/i386/Versions b/sysdeps/i386/Versions +index 36e23b466a..9c84c8ef04 100644 +--- a/sysdeps/i386/Versions ++++ b/sysdeps/i386/Versions +@@ -28,6 +28,11 @@ libc { + GLIBC_2.13 { + __fentry__; + } ++ GLIBC_ABI_GNU_TLS { ++ # This symbol is used only for empty version map and will be removed ++ # by scripts/versions.awk. ++ __placeholder_only_for_empty_version_map; ++ } + } + libm { + GLIBC_2.1 { + +commit d6f67d835c8814b77efbc005977fd754873b8784 +Author: H.J. Lu +Date: Mon Aug 18 09:06:48 2025 -0700 + + i386: Also add GLIBC_ABI_GNU2_TLS version [BZ #33129] + + Since the GNU2 TLS run-time bug: + + https://sourceware.org/bugzilla/show_bug.cgi?id=31372 + + affects both i386 and x86-64, also add GLIBC_ABI_GNU2_TLS version to i386 + to indicate the working GNU2 TLS run-time. For x86-64, the additional + GNU2 TLS run-time bug fix is needed for + + https://sourceware.org/bugzilla/show_bug.cgi?id=31501 + + Signed-off-by: H.J. Lu + Reviewed-by: Sam James + (cherry picked from commit bd4628f3f18ac312408782eea450429c6f044860) + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index f64cee3cd9..c814060e08 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -127,6 +127,15 @@ LDFLAGS-tst-tls23 += -rdynamic + tst-tls23-mod.so-no-z-defs = yes + + $(objpfx)tst-tls23-mod.so: $(libsupport) ++ ++tests-special += $(objpfx)check-gnu2-tls.out ++ ++$(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so ++ LC_ALL=C $(READELF) -V -W $< \ ++ | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ ++ | grep GLIBC_ABI_GNU2_TLS > $@; \ ++ $(evaluate-test) ++generated += check-gnu2-tls.out + endif + + ifeq ($(subdir),math) +diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions +index 4b10c4b5d7..e8dcfccbe4 100644 +--- a/sysdeps/x86/Versions ++++ b/sysdeps/x86/Versions +@@ -7,4 +7,9 @@ libc { + GLIBC_2.33 { + __x86_get_cpuid_feature_leaf; + } ++ GLIBC_ABI_GNU2_TLS { ++ # This symbol is used only for empty version map and will be removed ++ # by scripts/versions.awk. ++ __placeholder_only_for_empty_version_map; ++ } + } +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index 5ca6e5d034..27fd7ddea2 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -215,15 +215,6 @@ $(objpfx)check-dt-x86-64-plt.out: $(common-objpfx)libc.so + | grep GLIBC_ABI_DT_X86_64_PLT > $@; \ + $(evaluate-test) + generated += check-dt-x86-64-plt.out +- +-tests-special += $(objpfx)check-gnu2-tls.out +- +-$(objpfx)check-gnu2-tls.out: $(common-objpfx)libc.so +- LC_ALL=C $(READELF) -V -W $< \ +- | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \ +- | grep GLIBC_ABI_GNU2_TLS > $@; \ +- $(evaluate-test) +-generated += check-gnu2-tls.out + endif + + test-internal-extras += tst-gnu2-tls2mod1 +diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions +index 0a759029e5..6a989ad3b3 100644 +--- a/sysdeps/x86_64/Versions ++++ b/sysdeps/x86_64/Versions +@@ -5,11 +5,6 @@ libc { + GLIBC_2.13 { + __fentry__; + } +- GLIBC_ABI_GNU2_TLS { +- # This symbol is used only for empty version map and will be removed +- # by scripts/versions.awk. +- __placeholder_only_for_empty_version_map; +- } + GLIBC_ABI_DT_X86_64_PLT { + # This symbol is used only for empty version map and will be removed + # by scripts/versions.awk. + +commit f7c0193b61357cb4b52c5805dd8b58718e63ea3b +Author: Florian Weimer +Date: Fri May 16 19:53:09 2025 +0200 + + Optimize __libc_tsd_* thread variable access + + These variables are not exported, and libc.so TLS is initial-exec + anyway. Declare these variables as hidden and use the initial-exec + TLS model. + + Reviewed-by: Frédéric Bérat + (cherry picked from commit a894f04d877653bea1639fc9a4adf73bd9347bf4) + +diff --git a/include/ctype.h b/include/ctype.h +index ae078a63d3..a15e5b6678 100644 +--- a/include/ctype.h ++++ b/include/ctype.h +@@ -29,9 +29,12 @@ libc_hidden_proto (toupper) + # define CTYPE_EXTERN_INLINE extern inline + # endif + +-extern __thread const uint16_t * __libc_tsd_CTYPE_B; +-extern __thread const int32_t * __libc_tsd_CTYPE_TOUPPER; +-extern __thread const int32_t * __libc_tsd_CTYPE_TOLOWER; ++extern __thread const uint16_t * __libc_tsd_CTYPE_B ++ attribute_hidden attribute_tls_model_ie; ++extern __thread const int32_t * __libc_tsd_CTYPE_TOUPPER ++ attribute_hidden attribute_tls_model_ie; ++extern __thread const int32_t * __libc_tsd_CTYPE_TOLOWER ++ attribute_hidden attribute_tls_model_ie; + + + CTYPE_EXTERN_INLINE const uint16_t ** __attribute__ ((const)) +diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h +index 936ea3cebb..ba967833ad 100644 +--- a/include/rpc/rpc.h ++++ b/include/rpc/rpc.h +@@ -45,7 +45,8 @@ extern void __rpc_thread_key_cleanup (void) attribute_hidden; + + extern void __rpc_thread_destroy (void) attribute_hidden; + +-extern __thread struct rpc_thread_variables *__libc_tsd_RPC_VARS; ++extern __thread struct rpc_thread_variables *__libc_tsd_RPC_VARS ++ attribute_hidden attribute_tls_model_ie; + + #define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x) + +diff --git a/locale/localeinfo.h b/locale/localeinfo.h +index bc8e92e4dc..c3249d3715 100644 +--- a/locale/localeinfo.h ++++ b/locale/localeinfo.h +@@ -237,7 +237,8 @@ extern struct __locale_struct _nl_global_locale attribute_hidden; + /* This fetches the thread-local locale_t pointer, either one set with + uselocale or &_nl_global_locale. */ + #define _NL_CURRENT_LOCALE __libc_tsd_LOCALE +-extern __thread locale_t __libc_tsd_LOCALE; ++extern __thread locale_t __libc_tsd_LOCALE ++ attribute_hidden attribute_tls_model_ie; + + /* For static linking it is desireable to avoid always linking in the code + and data for every category when we can tell at link time that they are + +commit e20181e5106af0a0e228167d98cd8faf5064e23e +Author: Joseph Myers +Date: Fri Nov 8 01:53:48 2024 +0000 + + Avoid uninitialized result in sem_open when file does not exist + + A static analyzer apparently reported an uninitialized use of the + variable result in sem_open in the case where the file is required to + exist but does not exist. + + The report appears to be correct; set result to SEM_FAILED in that + case, and add a test for it. + + Note: the test passes for me even without the sem_open fix, I guess + because result happens to get value SEM_FAILED (i.e. 0) when + uninitialized. + + Tested for x86_64. + + (cherry picked from commit f745d78e2628cd5b13ca119ae0c0e21d08ad1906) + +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 04ea56559e..8039a211ec 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -254,6 +254,7 @@ tests += \ + tst-sem14 \ + tst-sem15 \ + tst-sem16 \ ++ tst-sem17 \ + tst-setuid3 \ + tst-signal1 \ + tst-signal2 \ +diff --git a/sysdeps/pthread/sem_open.c b/sysdeps/pthread/sem_open.c +index e41236157a..dab734191a 100644 +--- a/sysdeps/pthread/sem_open.c ++++ b/sysdeps/pthread/sem_open.c +@@ -76,6 +76,7 @@ __sem_open (const char *name, int oflag, ...) + goto try_create; + + /* Return. errno is already set. */ ++ result = SEM_FAILED; + } + else + /* Check whether we already have this semaphore mapped and +diff --git a/sysdeps/pthread/tst-sem17.c b/sysdeps/pthread/tst-sem17.c +new file mode 100644 +index 0000000000..c3f05d196f +--- /dev/null ++++ b/sysdeps/pthread/tst-sem17.c +@@ -0,0 +1,35 @@ ++/* Test sem_open with missing file. ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include ++ ++int ++do_test (void) ++{ ++ sem_unlink ("/glibc-tst-sem17"); ++ errno = 0; ++ sem_t *s = sem_open ("/glibc-tst-sem17", 0); ++ TEST_VERIFY (s == SEM_FAILED); ++ TEST_COMPARE (errno, ENOENT); ++ return 0; ++} ++ ++#include + +commit f03a78820ecda8795bd0ba094a70040c21fb38a6 +Author: Joseph Myers +Date: Fri Nov 8 17:08:09 2024 +0000 + + Rename new tst-sem17 test to tst-sem18 + + As noted by Adhemerval, we already have a tst-sem17 in nptl. + + Tested for x86_64. + + (cherry picked from commit c7dcf594f4c52fa7e2cc76918c8aa9abb98e9625) + +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 8039a211ec..830d9cb878 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -254,7 +254,7 @@ tests += \ + tst-sem14 \ + tst-sem15 \ + tst-sem16 \ +- tst-sem17 \ ++ tst-sem18 \ + tst-setuid3 \ + tst-signal1 \ + tst-signal2 \ +diff --git a/sysdeps/pthread/tst-sem17.c b/sysdeps/pthread/tst-sem18.c +similarity index 92% +rename from sysdeps/pthread/tst-sem17.c +rename to sysdeps/pthread/tst-sem18.c +index c3f05d196f..1be207bcbe 100644 +--- a/sysdeps/pthread/tst-sem17.c ++++ b/sysdeps/pthread/tst-sem18.c +@@ -24,9 +24,9 @@ + int + do_test (void) + { +- sem_unlink ("/glibc-tst-sem17"); ++ sem_unlink ("/glibc-tst-sem18"); + errno = 0; +- sem_t *s = sem_open ("/glibc-tst-sem17", 0); ++ sem_t *s = sem_open ("/glibc-tst-sem18", 0); + TEST_VERIFY (s == SEM_FAILED); + TEST_COMPARE (errno, ENOENT); + return 0; + +commit 2966a6a3a0fd49eb4e3c9b05bc26977a1df98c99 +Author: Pierre Blanchard +Date: Wed Aug 20 17:41:50 2025 +0000 + + AArch64: Fix SVE powf routine [BZ #33299] + + Fix a bug in predicate logic introduced in last change. + A slight performance improvement from relying on all true + predicates during conversion from single to double. + This fixes BZ #33299. + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit aac077645a645bba0d67f3250e82017c539d0f4b) + +diff --git a/sysdeps/aarch64/fpu/powf_sve.c b/sysdeps/aarch64/fpu/powf_sve.c +index 08d7019a18..33bba96054 100644 +--- a/sysdeps/aarch64/fpu/powf_sve.c ++++ b/sysdeps/aarch64/fpu/powf_sve.c +@@ -223,15 +223,15 @@ sv_powf_core (const svbool_t pg, svuint32_t i, svuint32_t iz, svint32_t k, + const svbool_t ptrue = svptrue_b64 (); + + /* Unpack and promote input vectors (pg, y, z, i, k and sign_bias) into two +- * in order to perform core computation in double precision. */ ++ in order to perform core computation in double precision. */ + const svbool_t pg_lo = svunpklo (pg); + const svbool_t pg_hi = svunpkhi (pg); +- svfloat64_t y_lo +- = svcvt_f64_x (pg, svreinterpret_f32 (svunpklo (svreinterpret_u32 (y)))); +- svfloat64_t y_hi +- = svcvt_f64_x (pg, svreinterpret_f32 (svunpkhi (svreinterpret_u32 (y)))); +- svfloat64_t z_lo = svcvt_f64_x (pg, svreinterpret_f32 (svunpklo (iz))); +- svfloat64_t z_hi = svcvt_f64_x (pg, svreinterpret_f32 (svunpkhi (iz))); ++ svfloat64_t y_lo = svcvt_f64_x ( ++ ptrue, svreinterpret_f32 (svunpklo (svreinterpret_u32 (y)))); ++ svfloat64_t y_hi = svcvt_f64_x ( ++ ptrue, svreinterpret_f32 (svunpkhi (svreinterpret_u32 (y)))); ++ svfloat64_t z_lo = svcvt_f64_x (ptrue, svreinterpret_f32 (svunpklo (iz))); ++ svfloat64_t z_hi = svcvt_f64_x (ptrue, svreinterpret_f32 (svunpkhi (iz))); + svuint64_t i_lo = svunpklo (i); + svuint64_t i_hi = svunpkhi (i); + svint64_t k_lo = svunpklo (k); +@@ -312,7 +312,7 @@ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) + (23 - V_POWF_EXP2_TABLE_BITS)); + + /* Compute core in extended precision and return intermediate ylogx results +- * to handle cases of underflow and underflow in exp. */ ++ to handle cases of underflow and overflow in exp. */ + svfloat32_t ylogx; + svfloat32_t ret + = sv_powf_core (yint_or_xpos, i, iz, k, y, sign_bias, &ylogx, d); + +commit 60795200d4deac38e2c9a49ba9a5ab7b2a96b242 +Author: Florian Weimer +Date: Fri Sep 12 21:33:34 2025 +0200 + + nss: Group merge does not react to ERANGE during merge (bug 33361) + + The break statement in CHECK_MERGE is expected to exit the surrounding + while loop, not the do-while loop with in the macro. Remove the + do-while loop from the macro. It is not needed to turn the macro + expansion into a single statement due to the way CHECK_MERGE is used + (and the statement expression would cover this anyway). + + Reviewed-by: Collin Funk + (cherry picked from commit 0fceed254559836b57ee05188deac649bc505d05) + +diff --git a/NEWS b/NEWS +index acb5179088..0756d27503 100644 +--- a/NEWS ++++ b/NEWS +@@ -29,6 +29,7 @@ The following bugs are resolved with this release: + [32987] elf: Fix subprocess status handling for tst-dlopen-sgid + [33185] Fix double-free after allocation failure in regcomp + [33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables ++ [33361] nss: Group merge does not react to ERANGE during merge + + Version 2.40 + +diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c +index fe7d5b7d0e..3a15b1a4ae 100644 +--- a/nss/getXXbyYY_r.c ++++ b/nss/getXXbyYY_r.c +@@ -157,19 +157,15 @@ __merge_einval (LOOKUP_TYPE *a, + + #define CHECK_MERGE(err, status) \ + ({ \ +- do \ ++ if (err) \ + { \ +- if (err) \ +- { \ +- __set_errno (err); \ +- if (err == ERANGE) \ +- status = NSS_STATUS_TRYAGAIN; \ +- else \ +- status = NSS_STATUS_UNAVAIL; \ +- break; \ +- } \ ++ __set_errno (err); \ ++ if (err == ERANGE) \ ++ status = NSS_STATUS_TRYAGAIN; \ ++ else \ ++ status = NSS_STATUS_UNAVAIL; \ ++ break; \ + } \ +- while (0); \ + }) + + /* Type of the lookup function we need here. */ + +commit 43ea89efc014cb9783a09318c6e2e2a7b7bb1d7f +Author: Sunil K Pandey +Date: Mon Oct 6 18:13:04 2025 -0700 + + x86: Detect Intel Wildcat Lake Processor + + Detect Intel Wildcat Lake Processor and tune it similar to Intel Panther + Lake. https://cdrdv2.intel.com/v1/dl/getContent/671368 Section 1.2. + + Reviewed-by: H.J. Lu + (cherry picked from commit f8dd52901b72805a831d5a4cb7d971e4a3c9970b) + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 52a2f03bdd..49ec19f5ee 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -543,6 +543,7 @@ enum intel_microarch + INTEL_BIGCORE_PANTHERLAKE, + INTEL_BIGCORE_GRANITERAPIDS, + INTEL_BIGCORE_DIAMONDRAPIDS, ++ INTEL_BIGCORE_WILDCATLAKE, + + /* Mixed (bigcore + atom SOC). */ + INTEL_MIXED_LAKEFIELD, +@@ -702,6 +703,8 @@ intel_get_fam6_microarch (unsigned int model, + return INTEL_BIGCORE_ARROWLAKE; + case 0xCC: + return INTEL_BIGCORE_PANTHERLAKE; ++ case 0xD5: ++ return INTEL_BIGCORE_WILDCATLAKE; + case 0xAD: + case 0xAE: + return INTEL_BIGCORE_GRANITERAPIDS; +@@ -934,6 +937,7 @@ disable_tsx: + case INTEL_BIGCORE_LUNARLAKE: + case INTEL_BIGCORE_ARROWLAKE: + case INTEL_BIGCORE_PANTHERLAKE: ++ case INTEL_BIGCORE_WILDCATLAKE: + case INTEL_BIGCORE_SAPPHIRERAPIDS: + case INTEL_BIGCORE_EMERALDRAPIDS: + case INTEL_BIGCORE_GRANITERAPIDS: + +commit c4458286b3daa728e24b8a4cf86289e7eb4a0839 +Author: Sunil K Pandey +Date: Wed Sep 24 09:38:17 2025 -0700 + + x86: Detect Intel Nova Lake Processor + + Detect Intel Nova Lake Processor and tune it similar to Intel Panther + Lake. https://cdrdv2.intel.com/v1/dl/getContent/671368 Section 1.2. + + Reviewed-by: H.J. Lu + (cherry picked from commit a114e29ddd530962d2b44aa9d89f1f6075abe7fa) + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 49ec19f5ee..89041e6e05 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -544,6 +544,7 @@ enum intel_microarch + INTEL_BIGCORE_GRANITERAPIDS, + INTEL_BIGCORE_DIAMONDRAPIDS, + INTEL_BIGCORE_WILDCATLAKE, ++ INTEL_BIGCORE_NOVALAKE, + + /* Mixed (bigcore + atom SOC). */ + INTEL_MIXED_LAKEFIELD, +@@ -821,6 +822,17 @@ disable_tsx: + break; + } + } ++ else if (family == 18) ++ switch (model) ++ { ++ case 0x01: ++ case 0x03: ++ microarch = INTEL_BIGCORE_NOVALAKE; ++ break; ++ ++ default: ++ break; ++ } + else if (family == 19) + switch (model) + { +@@ -938,6 +950,7 @@ disable_tsx: + case INTEL_BIGCORE_ARROWLAKE: + case INTEL_BIGCORE_PANTHERLAKE: + case INTEL_BIGCORE_WILDCATLAKE: ++ case INTEL_BIGCORE_NOVALAKE: + case INTEL_BIGCORE_SAPPHIRERAPIDS: + case INTEL_BIGCORE_EMERALDRAPIDS: + case INTEL_BIGCORE_GRANITERAPIDS: + +commit c0ae0450273c7346ec788bf6a933257d455ea820 +Author: Jiamei Xie +Date: Tue Oct 14 20:14:11 2025 +0800 + + x86: fix wmemset ifunc stray '!' (bug 33542) + + The ifunc selector for wmemset had a stray '!' in the + X86_ISA_CPU_FEATURES_ARCH_P(...) check: + + if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && X86_ISA_CPU_FEATURES_ARCH_P (cpu_features, + AVX_Fast_Unaligned_Load, !)) + + This effectively negated the predicate and caused the AVX2/AVX512 + paths to be skipped, making the dispatcher fall back to the SSE2 + implementation even on CPUs where AVX2/AVX512 are available. The + regression leads to noticeable throughput loss for wmemset. + + Remove the stray '!' so the AVX_Fast_Unaligned_Load capability is + tested as intended and the correct AVX2/EVEX variants are selected. + + Impact: + - On AVX2/AVX512-capable x86_64, wmemset no longer incorrectly + falls back to SSE2; perf now shows __wmemset_evex/avx2 variants. + + Testing: + - benchtests/bench-wmemset shows improved bandwidth across sizes. + - perf confirm the selected symbol is no longer SSE2. + + Signed-off-by: xiejiamei + Signed-off-by: Li jing + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 4d86b6cdd8132e0410347e07262239750f86dfb4) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-wmemset.h b/sysdeps/x86_64/multiarch/ifunc-wmemset.h +index 6e20d9dd5a..727b69f95b 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-wmemset.h ++++ b/sysdeps/x86_64/multiarch/ifunc-wmemset.h +@@ -35,7 +35,7 @@ IFUNC_SELECTOR (void) + + if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && X86_ISA_CPU_FEATURES_ARCH_P (cpu_features, +- AVX_Fast_Unaligned_Load, !)) ++ AVX_Fast_Unaligned_Load,)) + { + if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)) + { + +commit e8b9a4bcc2bb1f6c71f58d29dad51252e6336091 +Author: Florian Weimer +Date: Thu Nov 6 11:14:53 2025 +0100 + + aarch64: Do not link conform tests with -Wl,-z,force-bti (bug 33601) + + If the toolchain does not default to generate BTI markers in GCC, + the main program for conform runtime tests will not have the + BTI marker that -Wl,-z,force-bti requires. Without -Wl,-z,force-bti, + the link editor will not tell the dynamic linker to enable BTI, + and the missing BTI marker is harmless. + + Reviewed-by: Yury Khrustalev + (cherry picked from commit 75b6b263e928eaca01d836f6bb8b539346b6bb2d) + +diff --git a/NEWS b/NEWS +index 0756d27503..595998fc6e 100644 +--- a/NEWS ++++ b/NEWS +@@ -30,6 +30,7 @@ The following bugs are resolved with this release: + [33185] Fix double-free after allocation failure in regcomp + [33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables + [33361] nss: Group merge does not react to ERANGE during merge ++ [33601] aarch64: Do not link conform tests with -Wl,-z,force-bti + + Version 2.40 + +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index 141d7d9cc2..eb34f4541e 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -2,11 +2,15 @@ long-double-fcts = yes + + ifeq (yes,$(aarch64-bti)) + # Mark linker output BTI compatible, it warns on non-BTI inputs. ++# Do not do this for conform tests because they may not be compiled ++# with the appropriate compiler flags. ++ifneq ($(subdir),conform) + sysdep-LDFLAGS += -Wl,-z,force-bti + # Make warnings fatal outside the test system. + LDFLAGS-lib.so += -Wl,--fatal-warnings + LDFLAGS-rtld += -Wl,-z,force-bti,--fatal-warnings +-endif ++endif # $(subdir) != conform ++endif # $(aarch64-bit) + + ifeq ($(subdir),elf) + sysdep-dl-routines += dl-bti + +commit cdc1665bb188319b5f16ee05c04de7f2ba580e27 +Author: Yury Khrustalev +Date: Mon Apr 28 15:12:04 2025 +0100 + + aarch64: Disable ZA state of SME in setjmp and sigsetjmp + + Due to the nature of the ZA state, setjmp() should clear it in the + same manner as it is already done by longjmp. + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit a7f6fd976c17b82dc198290b4ab7087f35855a0e) + (cherry picked from commit 1f57ffdf35334ab245544cbb88f3abf2e6c77c54) + +diff --git a/sysdeps/aarch64/setjmp.S b/sysdeps/aarch64/setjmp.S +index 43fdb1b2fb..e0c65cf035 100644 +--- a/sysdeps/aarch64/setjmp.S ++++ b/sysdeps/aarch64/setjmp.S +@@ -37,6 +37,29 @@ ENTRY (__sigsetjmp) + PTR_ARG (0) + + 1: ++ ++#if IS_IN(libc) ++ /* Disable ZA state of SME in libc.a and libc.so, but not in ld.so. */ ++# if HAVE_AARCH64_PAC_RET ++ PACIASP ++ cfi_window_save ++# endif ++ stp x29, x30, [sp, -16]! ++ cfi_adjust_cfa_offset (16) ++ cfi_rel_offset (x29, 0) ++ cfi_rel_offset (x30, 8) ++ mov x29, sp ++ bl __libc_arm_za_disable ++ ldp x29, x30, [sp], 16 ++ cfi_adjust_cfa_offset (-16) ++ cfi_restore (x29) ++ cfi_restore (x30) ++# if HAVE_AARCH64_PAC_RET ++ AUTIASP ++ cfi_window_save ++# endif ++#endif ++ + stp x19, x20, [x0, #JB_X19<<3] + stp x21, x22, [x0, #JB_X21<<3] + stp x23, x24, [x0, #JB_X23<<3] + +commit 51bcc73d95051e74512bb32fe17096b3db329cf3 +Author: Yury Khrustalev +Date: Tue Apr 29 13:44:11 2025 +0100 + + aarch64: update tests for SME + + Add test that checks that ZA state is disabled after setjmp and sigsetjmp + Update existing SME test that uses setjmp + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 251f93262483b9c1184f5b72993d77a5d1c95f68) + (cherry picked from commit 97076e0cf14c635ef1d4ce1241e41c2c497533c8) + +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index eb34f4541e..62ae97fab0 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -74,7 +74,9 @@ sysdep_routines += \ + __arm_za_disable + + tests += \ +- tst-sme-jmp ++ tst-sme-jmp \ ++ tst-sme-za-state \ ++ # tests + endif + + ifeq ($(subdir),malloc) +diff --git a/sysdeps/aarch64/tst-sme-helper.h b/sysdeps/aarch64/tst-sme-helper.h +new file mode 100644 +index 0000000000..f049416c2b +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-helper.h +@@ -0,0 +1,97 @@ ++/* Utility functions for SME tests. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++/* Streaming SVE vector register size. */ ++static unsigned long svl; ++ ++struct blk { ++ void *za_save_buffer; ++ uint16_t num_za_save_slices; ++ char __reserved[6]; ++}; ++ ++/* Read SVCR to get SM (bit0) and ZA (bit1) state. */ ++static unsigned long ++get_svcr (void) ++{ ++ register unsigned long x0 asm ("x0"); ++ asm volatile ( ++ ".inst 0xd53b4240 /* mrs x0, svcr */\n" ++ : "=r" (x0)); ++ return x0; ++} ++ ++/* Returns tpidr2. */ ++static void * ++get_tpidr2 (void) ++{ ++ register unsigned long x0 asm ("x0"); ++ asm volatile ( ++ ".inst 0xd53bd0a0 /* mrs x0, tpidr2_el0 */\n" ++ : "=r"(x0) :: "memory"); ++ return (void *) x0; ++} ++ ++/* Obtains current streaming SVE vector register size. */ ++static unsigned long ++get_svl (void) ++{ ++ register unsigned long x0 asm ("x0"); ++ asm volatile ( ++ ".inst 0x04bf5820 /* rdsvl x0, 1 */\n" ++ : "=r" (x0)); ++ return x0; ++} ++ ++/* PSTATE.ZA = 1, set ZA state to active. */ ++static void ++start_za (void) ++{ ++ asm volatile ( ++ ".inst 0xd503457f /* smstart za */"); ++} ++ ++/* Load data into ZA byte by byte from p. */ ++static void __attribute__ ((noinline)) ++load_za (const void *p) ++{ ++ register unsigned long x15 asm ("x15") = 0; ++ register unsigned long x16 asm ("x16") = (unsigned long)p; ++ register unsigned long x17 asm ("x17") = svl; ++ ++ asm volatile ( ++ ".inst 0xd503437f /* smstart sm */\n" ++ ".L_ldr_loop:\n" ++ ".inst 0xe1006200 /* ldr za[w15, 0], [x16] */\n" ++ "add w15, w15, 1\n" ++ ".inst 0x04305030 /* addvl x16, x16, 1 */\n" ++ "cmp w15, w17\n" ++ "bne .L_ldr_loop\n" ++ ".inst 0xd503427f /* smstop sm */\n" ++ : "+r"(x15), "+r"(x16), "+r"(x17)); ++} ++ ++/* Set tpidr2 to BLK. */ ++static void ++set_tpidr2 (struct blk *blk) ++{ ++ register unsigned long x0 asm ("x0") = (unsigned long)blk; ++ asm volatile ( ++ ".inst 0xd51bd0a0 /* msr tpidr2_el0, x0 */\n" ++ :: "r"(x0) : "memory"); ++} +diff --git a/sysdeps/aarch64/tst-sme-jmp.c b/sysdeps/aarch64/tst-sme-jmp.c +index 35769340e7..b9638c6a71 100644 +--- a/sysdeps/aarch64/tst-sme-jmp.c ++++ b/sysdeps/aarch64/tst-sme-jmp.c +@@ -27,87 +27,12 @@ + #include + #include + +-struct blk { +- void *za_save_buffer; +- uint16_t num_za_save_slices; +- char __reserved[6]; +-}; ++#include "tst-sme-helper.h" + +-static unsigned long svl; + static uint8_t *za_orig; + static uint8_t *za_dump; + static uint8_t *za_save; + +-static unsigned long +-get_svl (void) +-{ +- register unsigned long x0 asm ("x0"); +- asm volatile ( +- ".inst 0x04bf5820 /* rdsvl x0, 1 */\n" +- : "=r" (x0)); +- return x0; +-} +- +-/* PSTATE.ZA = 1, set ZA state to active. */ +-static void +-start_za (void) +-{ +- asm volatile ( +- ".inst 0xd503457f /* smstart za */"); +-} +- +-/* Read SVCR to get SM (bit0) and ZA (bit1) state. */ +-static unsigned long +-get_svcr (void) +-{ +- register unsigned long x0 asm ("x0"); +- asm volatile ( +- ".inst 0xd53b4240 /* mrs x0, svcr */\n" +- : "=r" (x0)); +- return x0; +-} +- +-/* Load data into ZA byte by byte from p. */ +-static void __attribute__ ((noinline)) +-load_za (const void *p) +-{ +- register unsigned long x15 asm ("x15") = 0; +- register unsigned long x16 asm ("x16") = (unsigned long)p; +- register unsigned long x17 asm ("x17") = svl; +- +- asm volatile ( +- ".inst 0xd503437f /* smstart sm */\n" +- ".L_ldr_loop:\n" +- ".inst 0xe1006200 /* ldr za[w15, 0], [x16] */\n" +- "add w15, w15, 1\n" +- ".inst 0x04305030 /* addvl x16, x16, 1 */\n" +- "cmp w15, w17\n" +- "bne .L_ldr_loop\n" +- ".inst 0xd503427f /* smstop sm */\n" +- : "+r"(x15), "+r"(x16), "+r"(x17)); +-} +- +-/* Set tpidr2 to BLK. */ +-static void +-set_tpidr2 (struct blk *blk) +-{ +- register unsigned long x0 asm ("x0") = (unsigned long)blk; +- asm volatile ( +- ".inst 0xd51bd0a0 /* msr tpidr2_el0, x0 */\n" +- :: "r"(x0) : "memory"); +-} +- +-/* Returns tpidr2. */ +-static void * +-get_tpidr2 (void) +-{ +- register unsigned long x0 asm ("x0"); +- asm volatile ( +- ".inst 0xd53bd0a0 /* mrs x0, tpidr2_el0 */\n" +- : "=r"(x0) :: "memory"); +- return (void *) x0; +-} +- + static void + print_data(const char *msg, void *p) + { +@@ -168,8 +93,8 @@ longjmp_test (void) + { + p = get_tpidr2 (); + printf ("before longjmp: tp2 = %p\n", p); +- if (p != &blk) +- FAIL_EXIT1 ("tpidr2 is clobbered"); ++ if (p != NULL) ++ FAIL_EXIT1 ("tpidr2 has not been reset to null"); + do_longjmp (env); + FAIL_EXIT1 ("longjmp returned"); + } +diff --git a/sysdeps/aarch64/tst-sme-za-state.c b/sysdeps/aarch64/tst-sme-za-state.c +new file mode 100644 +index 0000000000..63f6eebeb4 +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-za-state.c +@@ -0,0 +1,119 @@ ++/* Test for SME ZA state being cleared on setjmp and longjmp. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "tst-sme-helper.h" ++ ++static uint8_t *state; ++ ++static void ++enable_sme_za_state (struct blk *ptr) ++{ ++ set_tpidr2 (ptr); ++ start_za (); ++ load_za (state); ++} ++ ++static void ++check_sme_za_state (const char msg[], bool clear) ++{ ++ unsigned long svcr = get_svcr (); ++ void *tpidr2 = get_tpidr2 (); ++ printf ("[%s]\n", msg); ++ printf ("svcr = %016lx\n", svcr); ++ printf ("tpidr2 = %016lx\n", (unsigned long)tpidr2); ++ if (clear) ++ { ++ TEST_VERIFY (svcr == 0); ++ TEST_VERIFY (tpidr2 == NULL); ++ } ++ else ++ { ++ TEST_VERIFY (svcr != 0); ++ TEST_VERIFY (tpidr2 != NULL); ++ } ++} ++ ++static void ++run (struct blk *ptr) ++{ ++ jmp_buf buf; ++ int ret; ++ ++ check_sme_za_state ("initial state", /* Clear. */ true); ++ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (ptr); ++ check_sme_za_state ("before setjmp", /* Clear. */ false); ++ ++ if ((ret = setjmp (buf)) == 0) ++ { ++ check_sme_za_state ("after setjmp", /* Clear. */ true); ++ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (ptr); ++ check_sme_za_state ("before longjmp", /* Clear. */ false); ++ ++ longjmp (buf, 42); ++ ++ /* Unreachable. */ ++ TEST_VERIFY (false); ++ __builtin_unreachable (); ++ } ++ ++ TEST_COMPARE (ret, 42); ++ check_sme_za_state ("after longjmp", /* Clear. */ true); ++} ++ ++static int ++do_test (void) ++{ ++ unsigned long hwcap2 = getauxval (AT_HWCAP2); ++ if ((hwcap2 & HWCAP2_SME) == 0) ++ return EXIT_UNSUPPORTED; ++ ++ /* Get current streaming SVE vector register size. */ ++ svl = get_svl (); ++ printf ("svl: %lu\n", svl); ++ TEST_VERIFY_EXIT (!(svl < 16 || svl % 16 != 0 || svl >= (1 << 16))); ++ ++ /* Initialise buffer for ZA state of SME. */ ++ state = xmalloc (svl * svl); ++ memset (state, 1, svl * svl); ++ struct blk blk = { ++ .za_save_buffer = state, ++ .num_za_save_slices = svl, ++ .__reserved = {0}, ++ }; ++ ++ run (&blk); ++ ++ free (state); ++ return 0; ++} ++ ++#include + +commit 7af8db46d2493521cb8e0c13907f601a61236ebf +Author: Yury Khrustalev +Date: Tue Oct 21 13:48:34 2025 +0100 + + aarch64: define macro for calling __libc_arm_za_disable + + A common sequence of instructions is used in several places + in assembly files, so define it in one place as an assembly + macro. + + Note that PAC instructions are not included in the new macro + because they are redundant given how we call the arm_za_disable + function (return address is not saved on stack, so no need to + sign it). + + (based on commits 6de12fc9ad56bc19fa6fcbd8ee502f29b5170d47 + and c0f0db2d59e0908057205b22b21dd9d626d780c1) + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 1a0ee267147d002d66af29bcf3f5002d19b3c75a) + +diff --git a/sysdeps/aarch64/__longjmp.S b/sysdeps/aarch64/__longjmp.S +index 7b6add751e..84156ee6ef 100644 +--- a/sysdeps/aarch64/__longjmp.S ++++ b/sysdeps/aarch64/__longjmp.S +@@ -51,24 +51,7 @@ ENTRY (__longjmp) + + #if IS_IN(libc) + /* Disable ZA state of SME in libc.a and libc.so, but not in ld.so. */ +-# if HAVE_AARCH64_PAC_RET +- PACIASP +- cfi_window_save +-# endif +- stp x29, x30, [sp, -16]! +- cfi_adjust_cfa_offset (16) +- cfi_rel_offset (x29, 0) +- cfi_rel_offset (x30, 8) +- mov x29, sp +- bl __libc_arm_za_disable +- ldp x29, x30, [sp], 16 +- cfi_adjust_cfa_offset (-16) +- cfi_restore (x29) +- cfi_restore (x30) +-# if HAVE_AARCH64_PAC_RET +- AUTIASP +- cfi_window_save +-# endif ++ CALL_LIBC_ARM_ZA_DISABLE + #endif + + ldp x19, x20, [x0, #JB_X19<<3] +diff --git a/sysdeps/aarch64/setjmp.S b/sysdeps/aarch64/setjmp.S +index e0c65cf035..2fa0dc768d 100644 +--- a/sysdeps/aarch64/setjmp.S ++++ b/sysdeps/aarch64/setjmp.S +@@ -40,24 +40,7 @@ ENTRY (__sigsetjmp) + + #if IS_IN(libc) + /* Disable ZA state of SME in libc.a and libc.so, but not in ld.so. */ +-# if HAVE_AARCH64_PAC_RET +- PACIASP +- cfi_window_save +-# endif +- stp x29, x30, [sp, -16]! +- cfi_adjust_cfa_offset (16) +- cfi_rel_offset (x29, 0) +- cfi_rel_offset (x30, 8) +- mov x29, sp +- bl __libc_arm_za_disable +- ldp x29, x30, [sp], 16 +- cfi_adjust_cfa_offset (-16) +- cfi_restore (x29) +- cfi_restore (x30) +-# if HAVE_AARCH64_PAC_RET +- AUTIASP +- cfi_window_save +-# endif ++ CALL_LIBC_ARM_ZA_DISABLE + #endif + + stp x19, x20, [x0, #JB_X19<<3] +diff --git a/sysdeps/unix/sysv/linux/aarch64/setcontext.S b/sysdeps/unix/sysv/linux/aarch64/setcontext.S +index ba659438c5..1be9be2c27 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/setcontext.S ++++ b/sysdeps/unix/sysv/linux/aarch64/setcontext.S +@@ -49,25 +49,8 @@ ENTRY (__setcontext) + cbz x0, 1f + b C_SYMBOL_NAME (__syscall_error) + 1: +- /* Disable ZA of SME. */ +-#if HAVE_AARCH64_PAC_RET +- PACIASP +- cfi_window_save +-#endif +- stp x29, x30, [sp, -16]! +- cfi_adjust_cfa_offset (16) +- cfi_rel_offset (x29, 0) +- cfi_rel_offset (x30, 8) +- mov x29, sp +- bl __libc_arm_za_disable +- ldp x29, x30, [sp], 16 +- cfi_adjust_cfa_offset (-16) +- cfi_restore (x29) +- cfi_restore (x30) +-#if HAVE_AARCH64_PAC_RET +- AUTIASP +- cfi_window_save +-#endif ++ /* Clear ZA state of SME. */ ++ CALL_LIBC_ARM_ZA_DISABLE + /* Restore the general purpose registers. */ + mov x0, x9 + cfi_def_cfa (x0, 0) +diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +index bbbe35723c..966769a6d6 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h ++++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +@@ -150,6 +150,18 @@ + mov x8, SYS_ify (syscall_name); \ + svc 0 + ++/* Clear ZA state of SME (ASM version). */ ++/* The __libc_arm_za_disable function has special calling convention ++ that allows to call it without stack manipulation and preserving ++ most of the registers. */ ++ .macro CALL_LIBC_ARM_ZA_DISABLE ++ mov x13, x30 ++ .cfi_register x30, x13 ++ bl __libc_arm_za_disable ++ mov x30, x13 ++ .cfi_register x13, x30 ++ .endm ++ + #else /* not __ASSEMBLER__ */ + + # ifdef __LP64__ + +commit 899ebf35691f01c357fc582b3e88db87accb5ee1 +Author: Yury Khrustalev +Date: Thu Sep 25 15:54:36 2025 +0100 + + aarch64: clear ZA state of SME before clone and clone3 syscalls + + This change adds a call to the __arm_za_disable() function immediately + before the SVC instruction inside clone() and clone3() wrappers. It also + adds a macro for inline clone() used in fork() and adds the same call to + the vfork implementation. This sets the ZA state of SME to "off" on return + from these functions (for both the child and the parent). + + The __arm_za_disable() function is described in [1] (8.1.3). Note that + the internal Glibc name for this function is __libc_arm_za_disable(). + + When this change was originally proposed [2,3], it generated a long + discussion where several questions and concerns were raised. Here we + will address these concerns and explain why this change is useful and, + in fact, necessary. + + In a nutshell, a C library that conforms to the AAPCS64 spec [1] (pertinent + to this change, mainly, the chapters 6.2 and 6.6), should have a call to the + __arm_za_disable() function in clone() and clone3() wrappers. The following + explains in detail why this is the case. + + When we consider using the __arm_za_disable() function inside the clone() + and clone3() libc wrappers, we talk about the C library subroutines clone() + and clone3() rather than the syscalls with similar names. In the current + version of Glibc, clone() is public and clone3() is private, but it being + private is not pertinent to this discussion. + + We will begin with stating that this change is NOT a bug fix for something + in the kernel. The requirement to call __arm_za_disable() does NOT come from + the kernel. It also is NOT needed to satisfy a contract between the kernel + and userspace. This is why it is not for the kernel documentation to describe + this requirement. This requirement is instead needed to satisfy a pure userspace + scheme outlined in [1] and to make sure that software that uses Glibc (or any + other C library that has correct handling of SME states (see below)) conforms + to [1] without having to unnecessarily become SME-aware thus losing portability. + + To recap (see [1] (6.2)), SME extension defines SME state which is part of + processor state. Part of this SME state is ZA state that is necessary to + manage ZA storage register in the context of the ZA lazy saving scheme [1] + (6.6). This scheme exists because it would be challenging to handle ZA + storage of SME in either callee-saved or caller-saved manner. + + There are 3 kinds of ZA state that are defined in terms of the PSTATE.ZA + bit and the TPIDR2_EL0 register (see [1] (6.6.3)): + + - "off":       PSTATE.ZA == 0 + - "active":    PSTATE.ZA == 1 TPIDR2_EL0 == null + - "dormant":   PSTATE.ZA == 1 TPIDR2_EL0 != null + + As [1] (6.7.2) outlines, every subroutine has exactly one SME-interface + depending on the permitted ZA-states on entry and on normal return from + a call to this subroutine. Callers of a subroutine must know and respect + the ZA-interface of the subroutines they are using. Using a subroutine + in a way that is not permitted by its ZA-interface is undefined behaviour. + + In particular, clone() and clone3() (the C library functions) have the + ZA-private interface. This means that the permitted ZA-states on entry + are "off" and "dormant" and that the permitted states on return are "off" + or "dormant" (but if and only if it was "dormant" on entry). + + This means that both functions in question should correctly handle both + "off" and "dormant" ZA-states on entry. The conforming states on return + are "off" and "dormant" (if inbound state was already "dormant"). + + This change ensures that the ZA-state on return is always "off". Note, + that, in the context of clone() and clone3(), "on return" means a point + when execution resumes at certain address after transferring from clone() + or clone3(). For the caller (we may refer to it as "parent") this is the + return address in the link register where the RET instruction jumps. For + the "child", this is the target branch address. + + So, the "off" state on return is permitted and conformant. Why can't we + retain the "dormant" state? In theory, we can, but we shouldn't, here is + why. + + Every subroutine with a private-ZA interface, including clone() and clone3(), + must comply with the lazy saving scheme [1] (6.7.2). This puts additional + responsibility on a subroutine if ZA-state on return is "dormant" because + this state has special meaning. The "caller" (that is the place in code + where execution is transferred to, so this include both "parent" and "child") + may check the ZA-state and use it as per the spec of the "dormant" state that + is outlined in [1] (6.6.6 and 6.6.7). + + Conforming to this would require more code inside of clone() and clone3() + which hardly is desirable. + + For the return to "parent" this could be achieved in theory, but given that + neither clone() nor clone3() are supposed to be used in the middle of an + SME operation, if wouldn't be useful. For the "return" to "child" this + would be particularly difficult to achieve given the complexity of these + functions and their interfaces. Most importantly, it would be illegal + and somewhat meaningless to allow a "child" to start execution in the + "dormant" ZA-state because the very essence of the "dormant" state implies + that there is a place to return and that there is some outer context that + we are allowed to interact with. + + To sum up, calling __arm_za_disable() to ensure the "off" ZA-state when the + execution resumes after a call to clone() or clone3() is correct and also + the most simple way to conform to [1]. + + Can there be situations when we can avoid calling __arm_za_disable()? + + Calling __arm_za_disable() implies certain (sufficiently small) overhead, + so one might rightly ponder avoiding making a call to this function when + we can afford not to. The most trivial cases like this (e.g. when the + calling thread doesn't have access to SME or to the TPIDR2_EL0 register) + are already handled by this function (see [1] (8.1.3 and 8.1.2)). Reasoning + about other possible use cases would require making code inside clone() and + clone3() more complicated and it would defeat the point of trying to make + an optimisation of not calling __arm_za_disable(). + + Why can't the kernel do this instead? + + The handling of SME state by the kernel is described in [4]. In short, + kernel must not impose a specific ZA-interface onto a userspace function. + Interaction with the kernel happens (among other thing) via system calls. + In Glibc many of the system calls (notably, including SYS_clone and + SYS_clone3) are used via wrappers, and the kernel has no control of them + and, moreover, it cannot dictate how these wrappers should behave because + it is simply outside of the kernel's remit. + + However, in certain cases, the kernel may ensure that a "child" doesn't + start in an incorrect state. This is what is done by the recent change + included in 6.16 kernel [5]. This is not enough to ensure that code that + uses clone() and clone3() function conforms to [1] when it runs on a + system that provides SME, hence this change. + + [1]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst + [2]: https://inbox.sourceware.org/libc-alpha/20250522114828.2291047-1-yury.khrustalev@arm.com + [3]: https://inbox.sourceware.org/libc-alpha/20250609121407.3316070-1-yury.khrustalev@arm.com + [4]: https://www.kernel.org/doc/html/v6.16/arch/arm64/sme.html + [5]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cde5c32db55740659fca6d56c09b88800d88fd29 + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 27effb3d50424fb9634be77a2acd614b0386ff25) + (cherry picked from commit 256030b9842a10b1f22851b1de0c119761417544) + (cherry picked from commit 889ae4bdbb4a6fbf37c2303da8cdae3d18880d9e) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S +index 0e7ee24e68..4fb9f02792 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/clone.S ++++ b/sysdeps/unix/sysv/linux/aarch64/clone.S +@@ -51,6 +51,9 @@ ENTRY(__clone) + and x1, x1, -16 + cbz x1, .Lsyscall_error + ++ /* Clear ZA state of SME. */ ++ CALL_LIBC_ARM_ZA_DISABLE ++ + /* Do the system call. */ + /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid. */ + mov x0, x2 /* flags */ +diff --git a/sysdeps/unix/sysv/linux/aarch64/clone3.S b/sysdeps/unix/sysv/linux/aarch64/clone3.S +index e28aaa5083..17a40af916 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/clone3.S ++++ b/sysdeps/unix/sysv/linux/aarch64/clone3.S +@@ -50,6 +50,9 @@ ENTRY(__clone3) + cbz x10, .Lsyscall_error /* No NULL cl_args pointer. */ + cbz x2, .Lsyscall_error /* No NULL function pointer. */ + ++ /* Clear ZA state of SME. */ ++ CALL_LIBC_ARM_ZA_DISABLE ++ + /* Do the system call, the kernel expects: + x8: system call number + x0: cl_args +diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +index 966769a6d6..d1cf2de078 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h ++++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +@@ -246,6 +246,31 @@ + #undef HAVE_INTERNAL_BRK_ADDR_SYMBOL + #define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 + ++/* Clear ZA state of SME (C version). */ ++/* The __libc_arm_za_disable function has special calling convention ++ that allows to call it without stack manipulation and preserving ++ most of the registers. */ ++#define CALL_LIBC_ARM_ZA_DISABLE() \ ++({ \ ++ unsigned long int __tmp; \ ++ asm volatile ( \ ++ " mov %0, x30\n" \ ++ " .cfi_register x30, %0\n" \ ++ " bl __libc_arm_za_disable\n" \ ++ " mov x30, %0\n" \ ++ " .cfi_register %0, x30\n" \ ++ : "=r" (__tmp) \ ++ : \ ++ : "x14", "x15", "x16", "x17", "x18", "memory" ); \ ++}) ++ ++/* Do clear ZA state of SME before making normal clone syscall. */ ++#define INLINE_CLONE_SYSCALL(a0, a1, a2, a3, a4) \ ++({ \ ++ CALL_LIBC_ARM_ZA_DISABLE (); \ ++ INLINE_SYSCALL_CALL (clone, a0, a1, a2, a3, a4); \ ++}) ++ + #endif /* __ASSEMBLER__ */ + + #endif /* linux/aarch64/sysdep.h */ +diff --git a/sysdeps/unix/sysv/linux/aarch64/vfork.S b/sysdeps/unix/sysv/linux/aarch64/vfork.S +index e71e492da3..65fa85ae89 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/vfork.S ++++ b/sysdeps/unix/sysv/linux/aarch64/vfork.S +@@ -27,6 +27,9 @@ + + ENTRY (__vfork) + ++ /* Clear ZA state of SME. */ ++ CALL_LIBC_ARM_ZA_DISABLE ++ + mov x0, #0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ + mov x1, sp + DO_CALL (clone, 2) + +commit df3bcda9ac85eb720d27bbbc469cdc898cc9b02b +Author: Yury Khrustalev +Date: Fri Sep 26 10:03:45 2025 +0100 + + aarch64: tests for SME + + This commit adds tests for the following use cases relevant to handing of + the SME state: + + - fork() and vfork() + - clone() and clone3() + - signal handler + + While most cases are trivial, the case of clone3() is more complicated since + the clone3() symbol is not public in Glibc. + + To avoid having to check all possible ways clone3() may be called via other + public functions (e.g. vfork() or pthread_create()), we put together a test + that links directly with clone3.o. All the existing functions that have calls + to clone3() may not actually use it, in which case the outcome of such tests + would be unexpected. Having a direct call to the clone3() symbol in the test + allows to check precisely what we need to test: that the __arm_za_disable() + function is indeed called and has the desired effect. + + Linking to clone3.o also requires linking to __arm_za_disable.o that in + turn requires the _dl_hwcap2 hidden symbol which to provide in the test + and initialise it before using. + + Co-authored-by: Adhemerval Zanella Netto + Reviewed-by: Adhemerval Zanella + (cherry picked from commit ecb0fc2f0f839f36cd2a106283142c9df8ea8214) + (cherry picked from commit 71874f167aa5bb1538ff7e394beaacee28ebe65f) + (cherry picked from commit e4ffcf32b9213352917dcf7dc43adcaa0ff76503) + +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index 62ae97fab0..f205884fe1 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -75,8 +75,18 @@ sysdep_routines += \ + + tests += \ + tst-sme-jmp \ ++ tst-sme-signal \ + tst-sme-za-state \ + # tests ++tests-internal += \ ++ tst-sme-clone \ ++ tst-sme-clone3 \ ++ tst-sme-fork \ ++ tst-sme-vfork \ ++ # tests-internal ++ ++$(objpfx)tst-sme-clone3: $(objpfx)clone3.o $(objpfx)__arm_za_disable.o ++ + endif + + ifeq ($(subdir),malloc) +diff --git a/sysdeps/aarch64/tst-sme-clone.c b/sysdeps/aarch64/tst-sme-clone.c +new file mode 100644 +index 0000000000..7106ec7926 +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-clone.c +@@ -0,0 +1,53 @@ ++/* Test that ZA state of SME is cleared in both parent and child ++ when clone() syscall is used. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include "tst-sme-skeleton.c" ++ ++#include ++ ++static int ++fun (void * const arg) ++{ ++ printf ("in child: %s\n", (const char *)arg); ++ /* Check that ZA state of SME was disabled in child. */ ++ check_sme_za_state ("after clone in child", /* Clear. */ true); ++ return 0; ++} ++ ++static char __attribute__((aligned(16))) ++stack[1024 * 1024]; ++ ++static void ++run (struct blk *ptr) ++{ ++ char *syscall_name = (char *)"clone"; ++ printf ("in parent: before %s\n", syscall_name); ++ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (ptr); ++ check_sme_za_state ("before clone", /* Clear. */ false); ++ ++ pid_t pid = xclone (fun, syscall_name, stack, sizeof (stack), ++ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD); ++ ++ /* Check that ZA state of SME was disabled in parent. */ ++ check_sme_za_state ("after clone in parent", /* Clear. */ true); ++ ++ TEST_VERIFY (xwaitpid (pid, NULL, 0) == pid); ++} +diff --git a/sysdeps/aarch64/tst-sme-clone3.c b/sysdeps/aarch64/tst-sme-clone3.c +new file mode 100644 +index 0000000000..402b040cfd +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-clone3.c +@@ -0,0 +1,84 @@ ++/* Test that ZA state of SME is cleared in both parent and child ++ when clone3() syscall is used. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include "tst-sme-skeleton.c" ++ ++#include ++ ++#include ++#include ++#include ++ ++/* Since clone3 is not a public symbol, we link this test explicitly ++ with clone3.o and have to provide this declaration. */ ++int __clone3 (struct clone_args *cl_args, size_t size, ++ int (*func)(void *arg), void *arg); ++ ++static int ++fun (void * const arg) ++{ ++ printf ("in child: %s\n", (const char *)arg); ++ /* Check that ZA state of SME was disabled in child. */ ++ check_sme_za_state ("after clone3 in child", /* Clear. */ true); ++ return 0; ++} ++ ++static char __attribute__((aligned(16))) ++stack[1024 * 1024]; ++ ++/* Required by __arm_za_disable.o and provided by the startup code ++ as a hidden symbol. */ ++uint64_t _dl_hwcap2; ++ ++static void ++run (struct blk *ptr) ++{ ++ _dl_hwcap2 = getauxval (AT_HWCAP2); ++ ++ char *syscall_name = (char *)"clone3"; ++ struct clone_args args = { ++ .flags = CLONE_VM | CLONE_VFORK, ++ .exit_signal = SIGCHLD, ++ .stack = (uintptr_t) stack, ++ .stack_size = sizeof (stack), ++ }; ++ printf ("in parent: before %s\n", syscall_name); ++ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (ptr); ++ check_sme_za_state ("before clone3", /* Clear. */ false); ++ ++ pid_t pid = __clone3 (&args, sizeof (args), fun, syscall_name); ++ ++ /* Check that ZA state of SME was disabled in parent. */ ++ check_sme_za_state ("after clone3 in parent", /* Clear. */ true); ++ ++ printf ("%s child pid: %d\n", syscall_name, pid); ++ ++ xwaitpid (pid, NULL, 0); ++ printf ("in parent: after %s\n", syscall_name); ++} ++ ++/* Workaround to simplify linking with clone3.o. */ ++void __syscall_error(int code) ++{ ++ int err = -code; ++ fprintf (stderr, "syscall error %d (%s)\n", err, strerror (err)); ++ exit (err); ++} +diff --git a/sysdeps/aarch64/tst-sme-fork.c b/sysdeps/aarch64/tst-sme-fork.c +new file mode 100644 +index 0000000000..b003b08884 +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-fork.c +@@ -0,0 +1,43 @@ ++/* Test that ZA state of SME is cleared in both parent and child ++ when fork() function is used. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include "tst-sme-skeleton.c" ++ ++static void ++run (struct blk *blk) ++{ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (blk); ++ check_sme_za_state ("before fork", /* Clear. */ false); ++ fflush (stdout); ++ ++ pid_t pid = xfork (); ++ ++ if (pid == 0) ++ { ++ /* Check that ZA state of SME was disabled in child. */ ++ check_sme_za_state ("after fork in child", /* Clear. */ true); ++ exit (0); ++ } ++ ++ /* Check that ZA state of SME was disabled in parent. */ ++ check_sme_za_state ("after fork in parent", /* Clear. */ true); ++ ++ TEST_VERIFY (xwaitpid (pid, NULL, 0) == pid); ++} +diff --git a/sysdeps/aarch64/tst-sme-helper.h b/sysdeps/aarch64/tst-sme-helper.h +index f049416c2b..ab9c503e45 100644 +--- a/sysdeps/aarch64/tst-sme-helper.h ++++ b/sysdeps/aarch64/tst-sme-helper.h +@@ -16,9 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-/* Streaming SVE vector register size. */ +-static unsigned long svl; +- + struct blk { + void *za_save_buffer; + uint16_t num_za_save_slices; +@@ -68,10 +65,10 @@ start_za (void) + + /* Load data into ZA byte by byte from p. */ + static void __attribute__ ((noinline)) +-load_za (const void *p) ++load_za (const void *buf, unsigned long svl) + { + register unsigned long x15 asm ("x15") = 0; +- register unsigned long x16 asm ("x16") = (unsigned long)p; ++ register unsigned long x16 asm ("x16") = (unsigned long)buf; + register unsigned long x17 asm ("x17") = svl; + + asm volatile ( +diff --git a/sysdeps/aarch64/tst-sme-jmp.c b/sysdeps/aarch64/tst-sme-jmp.c +index b9638c6a71..0c1d1a4ff8 100644 +--- a/sysdeps/aarch64/tst-sme-jmp.c ++++ b/sysdeps/aarch64/tst-sme-jmp.c +@@ -29,6 +29,9 @@ + + #include "tst-sme-helper.h" + ++/* Streaming SVE vector register size. */ ++static unsigned long svl; ++ + static uint8_t *za_orig; + static uint8_t *za_dump; + static uint8_t *za_save; +@@ -82,7 +85,7 @@ longjmp_test (void) + FAIL_EXIT1 ("svcr != 0: %lu", svcr); + set_tpidr2 (&blk); + start_za (); +- load_za (za_orig); ++ load_za (za_orig, svl); + + print_data ("za save space", za_save); + p = get_tpidr2 (); +@@ -131,7 +134,7 @@ setcontext_test (void) + FAIL_EXIT1 ("svcr != 0: %lu", svcr); + set_tpidr2 (&blk); + start_za (); +- load_za (za_orig); ++ load_za (za_orig, svl); + + print_data ("za save space", za_save); + p = get_tpidr2 (); +diff --git a/sysdeps/aarch64/tst-sme-signal.c b/sysdeps/aarch64/tst-sme-signal.c +new file mode 100644 +index 0000000000..b4b07bcc44 +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-signal.c +@@ -0,0 +1,115 @@ ++/* Test handling of SME state in a signal handler. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include "tst-sme-skeleton.c" ++ ++#include ++ ++static struct _aarch64_ctx * ++extension (void *p) ++{ ++ return p; ++} ++ ++#ifndef TPIDR2_MAGIC ++#define TPIDR2_MAGIC 0x54504902 ++#endif ++ ++#ifndef ZA_MAGIC ++#define ZA_MAGIC 0x54366345 ++#endif ++ ++#ifndef ZT_MAGIC ++#define ZT_MAGIC 0x5a544e01 ++#endif ++ ++#ifndef EXTRA_MAGIC ++#define EXTRA_MAGIC 0x45585401 ++#endif ++ ++/* We use a pipe to make sure that the final check of the SME state ++ happens after signal handler finished. */ ++static int pipefd[2]; ++ ++#define WRITE(msg) xwrite (1, msg, sizeof (msg)); ++ ++static void ++handler (int signo, siginfo_t *si, void *ctx) ++{ ++ TEST_VERIFY (signo == SIGUSR1); ++ WRITE ("in the handler\n"); ++ check_sme_za_state ("during signal", true /* State is clear. */); ++ ucontext_t *uc = ctx; ++ void *p = uc->uc_mcontext.__reserved; ++ unsigned int found = 0; ++ uint32_t m; ++ while ((m = extension (p)->magic)) ++ { ++ if (m == TPIDR2_MAGIC) ++ { ++ WRITE ("found TPIDR2_MAGIC\n"); ++ found += 1; ++ } ++ if (m == ZA_MAGIC) ++ { ++ WRITE ("found ZA_MAGIC\n"); ++ found += 1; ++ } ++ if (m == ZT_MAGIC) ++ { ++ WRITE ("found ZT_MAGIC\n"); ++ found += 1; ++ } ++ if (m == EXTRA_MAGIC) ++ { ++ WRITE ("found EXTRA_MAGIC\n"); ++ struct { struct _aarch64_ctx h; uint64_t data; } *e = p; ++ p = (char *)e->data; ++ continue; ++ } ++ p = (char *)p + extension (p)->size; ++ } ++ TEST_COMPARE (found, 3); ++ ++ /* Signal that the wait is over (see below). */ ++ char message = '\0'; ++ xwrite (pipefd[1], &message, 1); ++} ++ ++static void ++run (struct blk *blk) ++{ ++ xpipe (pipefd); ++ ++ struct sigaction sigact; ++ sigemptyset (&sigact.sa_mask); ++ sigact.sa_flags = 0; ++ sigact.sa_flags |= SA_SIGINFO; ++ sigact.sa_sigaction = handler; ++ xsigaction (SIGUSR1, &sigact, NULL); ++ ++ enable_sme_za_state (blk); ++ check_sme_za_state ("before signal", false /* State is not clear. */); ++ xraise (SIGUSR1); ++ ++ /* Wait for signal handler to complete. */ ++ char response; ++ xread (pipefd[0], &response, 1); ++ ++ check_sme_za_state ("after signal", false /* State is not clear. */); ++} +diff --git a/sysdeps/aarch64/tst-sme-skeleton.c b/sysdeps/aarch64/tst-sme-skeleton.c +new file mode 100644 +index 0000000000..ba84dda1cb +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-skeleton.c +@@ -0,0 +1,101 @@ ++/* Template for SME tests. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "tst-sme-helper.h" ++ ++/* Streaming SVE vector register size. */ ++static unsigned long svl; ++ ++static uint8_t *state; ++ ++static void ++enable_sme_za_state (struct blk *blk) ++{ ++ start_za (); ++ set_tpidr2 (blk); ++ load_za (blk, svl); ++} ++ ++/* Check if SME state is disabled (when CLEAR is true) or ++ enabled (when CLEAR is false). */ ++static void ++check_sme_za_state (const char msg[], bool clear) ++{ ++ unsigned long svcr = get_svcr (); ++ void *tpidr2 = get_tpidr2 (); ++ printf ("[%s]\n", msg); ++ printf ("svcr = %016lx\n", svcr); ++ printf ("tpidr2 = %016lx\n", (unsigned long)tpidr2); ++ if (clear) ++ { ++ TEST_VERIFY (svcr == 0); ++ TEST_VERIFY (tpidr2 == NULL); ++ } ++ else ++ { ++ TEST_VERIFY (svcr != 0); ++ TEST_VERIFY (tpidr2 != NULL); ++ } ++} ++ ++/* Should be defined in actual test that includes this ++ skeleton file. */ ++static void ++run (struct blk *ptr); ++ ++static int ++do_test (void) ++{ ++ unsigned long hwcap2 = getauxval (AT_HWCAP2); ++ if ((hwcap2 & HWCAP2_SME) == 0) ++ return EXIT_UNSUPPORTED; ++ ++ /* Get current streaming SVE vector length in bytes. */ ++ svl = get_svl (); ++ printf ("svl: %lu\n", svl); ++ ++ TEST_VERIFY_EXIT (!(svl < 16 || svl % 16 != 0 || svl >= (1 << 16))); ++ ++ /* Initialise buffer for ZA state of SME. */ ++ state = xmalloc (svl * svl); ++ memset (state, 1, svl * svl); ++ struct blk blk = { ++ .za_save_buffer = state, ++ .num_za_save_slices = svl, ++ .__reserved = {0}, ++ }; ++ ++ run (&blk); ++ ++ free (state); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/aarch64/tst-sme-vfork.c b/sysdeps/aarch64/tst-sme-vfork.c +new file mode 100644 +index 0000000000..3feea065e5 +--- /dev/null ++++ b/sysdeps/aarch64/tst-sme-vfork.c +@@ -0,0 +1,43 @@ ++/* Test that ZA state of SME is cleared in both parent and child ++ when vfork() function is used. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include "tst-sme-skeleton.c" ++ ++static void ++run (struct blk *blk) ++{ ++ /* Enabled ZA state so that effect of disabling be observable. */ ++ enable_sme_za_state (blk); ++ check_sme_za_state ("before vfork", /* Clear. */ false); ++ fflush (stdout); ++ ++ pid_t pid = vfork (); ++ ++ if (pid == 0) ++ { ++ /* Check that ZA state of SME was disabled in child. */ ++ check_sme_za_state ("after vfork in child", /* Clear. */ true); ++ _exit (0); ++ } ++ ++ /* Check that ZA state of SME was disabled in parent. */ ++ check_sme_za_state ("after vfork in parent", /* Clear. */ true); ++ ++ TEST_VERIFY (xwaitpid (pid, NULL, 0) == pid); ++} +diff --git a/sysdeps/aarch64/tst-sme-za-state.c b/sysdeps/aarch64/tst-sme-za-state.c +index 63f6eebeb4..00118ef506 100644 +--- a/sysdeps/aarch64/tst-sme-za-state.c ++++ b/sysdeps/aarch64/tst-sme-za-state.c +@@ -16,47 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "tst-sme-helper.h" +- +-static uint8_t *state; +- +-static void +-enable_sme_za_state (struct blk *ptr) +-{ +- set_tpidr2 (ptr); +- start_za (); +- load_za (state); +-} ++#include "tst-sme-skeleton.c" + +-static void +-check_sme_za_state (const char msg[], bool clear) +-{ +- unsigned long svcr = get_svcr (); +- void *tpidr2 = get_tpidr2 (); +- printf ("[%s]\n", msg); +- printf ("svcr = %016lx\n", svcr); +- printf ("tpidr2 = %016lx\n", (unsigned long)tpidr2); +- if (clear) +- { +- TEST_VERIFY (svcr == 0); +- TEST_VERIFY (tpidr2 == NULL); +- } +- else +- { +- TEST_VERIFY (svcr != 0); +- TEST_VERIFY (tpidr2 != NULL); +- } +-} ++#include + + static void + run (struct blk *ptr) +@@ -88,32 +50,3 @@ run (struct blk *ptr) + TEST_COMPARE (ret, 42); + check_sme_za_state ("after longjmp", /* Clear. */ true); + } +- +-static int +-do_test (void) +-{ +- unsigned long hwcap2 = getauxval (AT_HWCAP2); +- if ((hwcap2 & HWCAP2_SME) == 0) +- return EXIT_UNSUPPORTED; +- +- /* Get current streaming SVE vector register size. */ +- svl = get_svl (); +- printf ("svl: %lu\n", svl); +- TEST_VERIFY_EXIT (!(svl < 16 || svl % 16 != 0 || svl >= (1 << 16))); +- +- /* Initialise buffer for ZA state of SME. */ +- state = xmalloc (svl * svl); +- memset (state, 1, svl * svl); +- struct blk blk = { +- .za_save_buffer = state, +- .num_za_save_slices = svl, +- .__reserved = {0}, +- }; +- +- run (&blk); +- +- free (state); +- return 0; +-} +- +-#include + +commit 1c0ad5ea63b2e5d39eb55f734b0e2bea7f766523 +Author: Yury Khrustalev +Date: Tue Oct 28 11:01:50 2025 +0000 + + aarch64: fix cfi directives around __libc_arm_za_disable + + Incorrect CFI directive corrupted call stack information + and prevented debuggers from correctly displaying call + stack information. + + Reviewed-by: Adhemerval Zanella + (cherry picked from commit 2f77aec043f61e8533487850b11941a640ae2dea) + (cherry picked from commit de1fe81f471496366580ad728b8986a3424b2fd7) + (cherry picked from commit 5bf8ee7ad559fd60bedd3f5ec831d0b12b5000b8) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/sysdep.h b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +index d1cf2de078..dd98242dad 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/sysdep.h ++++ b/sysdeps/unix/sysv/linux/aarch64/sysdep.h +@@ -155,11 +155,12 @@ + that allows to call it without stack manipulation and preserving + most of the registers. */ + .macro CALL_LIBC_ARM_ZA_DISABLE ++ cfi_remember_state + mov x13, x30 +- .cfi_register x30, x13 ++ cfi_register(x30, x13) + bl __libc_arm_za_disable + mov x30, x13 +- .cfi_register x13, x30 ++ cfi_restore_state + .endm + + #else /* not __ASSEMBLER__ */ +@@ -254,11 +255,12 @@ + ({ \ + unsigned long int __tmp; \ + asm volatile ( \ ++ " .cfi_remember_state\n" \ + " mov %0, x30\n" \ +- " .cfi_register x30, %0\n" \ ++ " .cfi_register x30, %0\n" \ + " bl __libc_arm_za_disable\n" \ + " mov x30, %0\n" \ +- " .cfi_register %0, x30\n" \ ++ " .cfi_restore_state\n" \ + : "=r" (__tmp) \ + : \ + : "x14", "x15", "x16", "x17", "x18", "memory" ); \ + +commit a66680adf3b2266c177f94f3f63e4b182e6362fe +Author: Yury Khrustalev +Date: Tue Nov 11 11:40:25 2025 +0000 + + aarch64: fix includes in SME tests + + Use the correct include for the SIGCHLD macro: signal.h + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit a9c426bcca59a9e228c4fbe75e75154217ec4ada) + (cherry picked from commit 17c3eab387c3ceb6972e57888a89b1480793f81a) + (cherry picked from commit 215e9155ea06064342151d05446ae51da16e0f65) + +diff --git a/sysdeps/aarch64/tst-sme-clone.c b/sysdeps/aarch64/tst-sme-clone.c +index 7106ec7926..b6ad54fa37 100644 +--- a/sysdeps/aarch64/tst-sme-clone.c ++++ b/sysdeps/aarch64/tst-sme-clone.c +@@ -19,6 +19,7 @@ + + #include "tst-sme-skeleton.c" + ++#include + #include + + static int +diff --git a/sysdeps/aarch64/tst-sme-clone3.c b/sysdeps/aarch64/tst-sme-clone3.c +index 402b040cfd..f420d5984d 100644 +--- a/sysdeps/aarch64/tst-sme-clone3.c ++++ b/sysdeps/aarch64/tst-sme-clone3.c +@@ -22,7 +22,7 @@ + #include + + #include +-#include ++#include + #include + + /* Since clone3 is not a public symbol, we link this test explicitly + +commit 303363922cf027713ed887241cd9b59cf705fe11 +Author: Joe Ramsay +Date: Thu Nov 6 15:36:03 2025 +0000 + + AArch64: Optimise SVE scalar callbacks + + Instead of using SVE instructions to marshall special results into the + correct lane, just write the entire vector (and the predicate) to + memory, then use cheaper scalar operations. + + Geomean speedup of 16% in special intervals on Neoverse with GCC 14. + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 5b82fb18827e962af9f080fdf3c1a69802783f67) + +diff --git a/sysdeps/aarch64/fpu/sv_math.h b/sysdeps/aarch64/fpu/sv_math.h +index 41a2013929..c2dae543a1 100644 +--- a/sysdeps/aarch64/fpu/sv_math.h ++++ b/sysdeps/aarch64/fpu/sv_math.h +@@ -24,11 +24,29 @@ + + #include "vecmath_config.h" + ++#if !defined(__ARM_FEATURE_SVE_BITS) || __ARM_FEATURE_SVE_BITS == 0 ++/* If not specified by -msve-vector-bits, assume maximum vector length. */ ++# define SVE_VECTOR_BYTES 256 ++#else ++# define SVE_VECTOR_BYTES (__ARM_FEATURE_SVE_BITS / 8) ++#endif ++#define SVE_NUM_FLTS (SVE_VECTOR_BYTES / sizeof (float)) ++#define SVE_NUM_DBLS (SVE_VECTOR_BYTES / sizeof (double)) ++/* Predicate is stored as one bit per byte of VL so requires VL / 64 bytes. */ ++#define SVE_NUM_PG_BYTES (SVE_VECTOR_BYTES / sizeof (uint64_t)) ++ + #define SV_NAME_F1(fun) _ZGVsMxv_##fun##f + #define SV_NAME_D1(fun) _ZGVsMxv_##fun + #define SV_NAME_F2(fun) _ZGVsMxvv_##fun##f + #define SV_NAME_D2(fun) _ZGVsMxvv_##fun + ++static inline void ++svstr_p (uint8_t *dst, svbool_t p) ++{ ++ /* Predicate STR does not currently have an intrinsic. */ ++ __asm__("str %0, [%x1]\n" : : "Upa"(p), "r"(dst) : "memory"); ++} ++ + /* Double precision. */ + static inline svint64_t + sv_s64 (int64_t x) +@@ -51,33 +69,35 @@ sv_f64 (double x) + static inline svfloat64_t + sv_call_f64 (double (*f) (double), svfloat64_t x, svfloat64_t y, svbool_t cmp) + { +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) ++ double tmp[SVE_NUM_DBLS]; ++ uint8_t pg_bits[SVE_NUM_PG_BYTES]; ++ svstr_p (pg_bits, cmp); ++ svst1 (svptrue_b64 (), tmp, svsel (cmp, x, y)); ++ ++ for (int i = 0; i < svcntd (); i++) + { +- double elem = svclastb_n_f64 (p, 0, x); +- elem = (*f) (elem); +- svfloat64_t y2 = svdup_n_f64 (elem); +- y = svsel_f64 (p, y2, y); +- p = svpnext_b64 (cmp, p); ++ if (pg_bits[i] & 1) ++ tmp[i] = f (tmp[i]); + } +- return y; ++ return svld1 (svptrue_b64 (), tmp); + } + + static inline svfloat64_t + sv_call2_f64 (double (*f) (double, double), svfloat64_t x1, svfloat64_t x2, + svfloat64_t y, svbool_t cmp) + { +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) ++ double tmp1[SVE_NUM_DBLS], tmp2[SVE_NUM_DBLS]; ++ uint8_t pg_bits[SVE_NUM_PG_BYTES]; ++ svstr_p (pg_bits, cmp); ++ svst1 (svptrue_b64 (), tmp1, svsel (cmp, x1, y)); ++ svst1 (cmp, tmp2, x2); ++ ++ for (int i = 0; i < svcntd (); i++) + { +- double elem1 = svclastb_n_f64 (p, 0, x1); +- double elem2 = svclastb_n_f64 (p, 0, x2); +- double ret = (*f) (elem1, elem2); +- svfloat64_t y2 = svdup_n_f64 (ret); +- y = svsel_f64 (p, y2, y); +- p = svpnext_b64 (cmp, p); ++ if (pg_bits[i] & 1) ++ tmp1[i] = f (tmp1[i], tmp2[i]); + } +- return y; ++ return svld1 (svptrue_b64 (), tmp1); + } + + static inline svuint64_t +@@ -109,33 +129,40 @@ sv_f32 (float x) + static inline svfloat32_t + sv_call_f32 (float (*f) (float), svfloat32_t x, svfloat32_t y, svbool_t cmp) + { +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) ++ float tmp[SVE_NUM_FLTS]; ++ uint8_t pg_bits[SVE_NUM_PG_BYTES]; ++ svstr_p (pg_bits, cmp); ++ svst1 (svptrue_b32 (), tmp, svsel (cmp, x, y)); ++ ++ for (int i = 0; i < svcntd (); i++) + { +- float elem = svclastb_n_f32 (p, 0, x); +- elem = f (elem); +- svfloat32_t y2 = svdup_n_f32 (elem); +- y = svsel_f32 (p, y2, y); +- p = svpnext_b32 (cmp, p); ++ uint8_t p = pg_bits[i]; ++ if (p & 1) ++ tmp[i * 2] = f (tmp[i * 2]); ++ if (p & (1 << 4)) ++ tmp[i * 2 + 1] = f (tmp[i * 2 + 1]); + } +- return y; ++ return svld1 (svptrue_b32 (), tmp); + } + + static inline svfloat32_t + sv_call2_f32 (float (*f) (float, float), svfloat32_t x1, svfloat32_t x2, + svfloat32_t y, svbool_t cmp) + { +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) ++ float tmp1[SVE_NUM_FLTS], tmp2[SVE_NUM_FLTS]; ++ uint8_t pg_bits[SVE_NUM_PG_BYTES]; ++ svstr_p (pg_bits, cmp); ++ svst1 (svptrue_b32 (), tmp1, svsel (cmp, x1, y)); ++ svst1 (cmp, tmp2, x2); ++ ++ for (int i = 0; i < svcntd (); i++) + { +- float elem1 = svclastb_n_f32 (p, 0, x1); +- float elem2 = svclastb_n_f32 (p, 0, x2); +- float ret = f (elem1, elem2); +- svfloat32_t y2 = svdup_n_f32 (ret); +- y = svsel_f32 (p, y2, y); +- p = svpnext_b32 (cmp, p); ++ uint8_t p = pg_bits[i]; ++ if (p & 1) ++ tmp1[i * 2] = f (tmp1[i * 2], tmp2[i * 2]); ++ if (p & (1 << 4)) ++ tmp1[i * 2 + 1] = f (tmp1[i * 2 + 1], tmp2[i * 2 + 1]); + } +- return y; ++ return svld1 (svptrue_b32 (), tmp1); + } +- + #endif + +commit b06fc96c20c30c28205725f3f60df4f5a7458bd3 +Author: Joe Ramsay +Date: Thu Nov 6 18:26:54 2025 +0000 + + AArch64: Fix instability in AdvSIMD tan + + Previously presence of special-cases in one lane could affect the + results in other lanes due to unconditional scalar fallback. The old + WANT_SIMD_EXCEPT option (which has never been enabled in libmvec) has + been removed from AOR, making it easier to spot and fix this. 4% + improvement in throughput with GCC 14 on Neoverse V1. This bug is + present as far back as 2.39 (where tan was first introduced). + + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 6c22823da57aa5218f717f569c04c9573c0448c5) + +diff --git a/sysdeps/aarch64/fpu/tan_advsimd.c b/sysdeps/aarch64/fpu/tan_advsimd.c +index d56a102dd1..c6a5a17126 100644 +--- a/sysdeps/aarch64/fpu/tan_advsimd.c ++++ b/sysdeps/aarch64/fpu/tan_advsimd.c +@@ -25,9 +25,7 @@ static const struct data + float64x2_t poly[9]; + double half_pi[2]; + float64x2_t two_over_pi, shift; +-#if !WANT_SIMD_EXCEPT + float64x2_t range_val; +-#endif + } data = { + /* Coefficients generated using FPMinimax. */ + .poly = { V2 (0x1.5555555555556p-2), V2 (0x1.1111111110a63p-3), +@@ -38,20 +36,17 @@ static const struct data + .half_pi = { 0x1.921fb54442d18p0, 0x1.1a62633145c07p-54 }, + .two_over_pi = V2 (0x1.45f306dc9c883p-1), + .shift = V2 (0x1.8p52), +-#if !WANT_SIMD_EXCEPT + .range_val = V2 (0x1p23), +-#endif + }; + + #define RangeVal 0x4160000000000000 /* asuint64(0x1p23). */ + #define TinyBound 0x3e50000000000000 /* asuint64(2^-26). */ +-#define Thresh 0x310000000000000 /* RangeVal - TinyBound. */ + + /* Special cases (fall back to scalar calls). */ + static float64x2_t VPCS_ATTR NOINLINE +-special_case (float64x2_t x) ++special_case (float64x2_t x, float64x2_t n, float64x2_t d, uint64x2_t special) + { +- return v_call_f64 (tan, x, x, v_u64 (-1)); ++ return v_call_f64 (tan, x, vdivq_f64 (n, d), special); + } + + /* Vector approximation for double-precision tan. +@@ -65,14 +60,6 @@ float64x2_t VPCS_ATTR V_NAME_D1 (tan) (float64x2_t x) + very large inputs. Fall back to scalar routine for all lanes if any are + too large, or Inf/NaN. If fenv exceptions are expected, also fall back for + tiny input to avoid underflow. */ +-#if WANT_SIMD_EXCEPT +- uint64x2_t iax = vreinterpretq_u64_f64 (vabsq_f64 (x)); +- /* iax - tiny_bound > range_val - tiny_bound. */ +- uint64x2_t special +- = vcgtq_u64 (vsubq_u64 (iax, v_u64 (TinyBound)), v_u64 (Thresh)); +- if (__glibc_unlikely (v_any_u64 (special))) +- return special_case (x); +-#endif + + /* q = nearest integer to 2 * x / pi. */ + float64x2_t q +@@ -81,9 +68,8 @@ float64x2_t VPCS_ATTR V_NAME_D1 (tan) (float64x2_t x) + + /* Use q to reduce x to r in [-pi/4, pi/4], by: + r = x - q * pi/2, in extended precision. */ +- float64x2_t r = x; + float64x2_t half_pi = vld1q_f64 (dat->half_pi); +- r = vfmsq_laneq_f64 (r, q, half_pi, 0); ++ float64x2_t r = vfmsq_laneq_f64 (x, q, half_pi, 0); + r = vfmsq_laneq_f64 (r, q, half_pi, 1); + /* Further reduce r to [-pi/8, pi/8], to be reconstructed using double angle + formula. */ +@@ -114,12 +100,13 @@ float64x2_t VPCS_ATTR V_NAME_D1 (tan) (float64x2_t x) + + uint64x2_t no_recip = vtstq_u64 (vreinterpretq_u64_s64 (qi), v_u64 (1)); + +-#if !WANT_SIMD_EXCEPT + uint64x2_t special = vcageq_f64 (x, dat->range_val); ++ float64x2_t swap = vbslq_f64 (no_recip, n, vnegq_f64 (d)); ++ d = vbslq_f64 (no_recip, d, n); ++ n = swap; ++ + if (__glibc_unlikely (v_any_u64 (special))) +- return special_case (x); +-#endif ++ return special_case (x, n, d, special); + +- return vdivq_f64 (vbslq_f64 (no_recip, n, vnegq_f64 (d)), +- vbslq_f64 (no_recip, d, n)); ++ return vdivq_f64 (n, d); + } + +commit a07f8630bf8b99ebc7f1df829e4c46b84a3ff4cc +Author: Pierre Blanchard +Date: Tue Nov 18 15:09:05 2025 +0000 + + AArch64: Fix and improve SVE pow(f) special cases + + powf: + + Update scalar special case function to best use new interface. + + pow: + + Make specialcase NOINLINE to prevent str/ldr leaking in fast path. + Remove depency in sv_call2, as new callback impl is not a + performance gain. + Replace with vectorised specialcase since structure of scalar + routine is fairly simple. + + Throughput gain of about 5-10% on V1 for large values and 25% for subnormal `x`. + + Reviewed-by: Wilco Dijkstra  + (cherry picked from commit bb6519de1e6fe73d79bc71588ec4e5668907f080) + +diff --git a/sysdeps/aarch64/fpu/pow_sve.c b/sysdeps/aarch64/fpu/pow_sve.c +index 4242d22a49..a34db23594 100644 +--- a/sysdeps/aarch64/fpu/pow_sve.c ++++ b/sysdeps/aarch64/fpu/pow_sve.c +@@ -31,8 +31,8 @@ + The SVE algorithm drops the tail in the exp computation at the price of + a lower accuracy, slightly above 1ULP. + The SVE algorithm also drops the special treatement of small (< 2^-65) and +- large (> 2^63) finite values of |y|, as they only affect non-round to nearest +- modes. ++ large (> 2^63) finite values of |y|, as they only affect non-round to ++ nearest modes. + + Maximum measured error is 1.04 ULPs: + SV_NAME_D2 (pow) (0x1.3d2d45bc848acp+63, -0x1.a48a38b40cd43p-12) +@@ -156,42 +156,22 @@ sv_zeroinfnan (svbool_t pg, svuint64_t i) + a double. (int32_t)KI is the k used in the argument reduction and exponent + adjustment of scale, positive k here means the result may overflow and + negative k means the result may underflow. */ +-static inline double +-specialcase (double tmp, uint64_t sbits, uint64_t ki) +-{ +- double scale; +- if ((ki & 0x80000000) == 0) +- { +- /* k > 0, the exponent of scale might have overflowed by <= 460. */ +- sbits -= 1009ull << 52; +- scale = asdouble (sbits); +- return 0x1p1009 * (scale + scale * tmp); +- } +- /* k < 0, need special care in the subnormal range. */ +- sbits += 1022ull << 52; +- /* Note: sbits is signed scale. */ +- scale = asdouble (sbits); +- double y = scale + scale * tmp; +- return 0x1p-1022 * y; +-} +- +-/* Scalar fallback for special cases of SVE pow's exp. */ + static inline svfloat64_t +-sv_call_specialcase (svfloat64_t x1, svuint64_t u1, svuint64_t u2, +- svfloat64_t y, svbool_t cmp) ++specialcase (svfloat64_t tmp, svuint64_t sbits, svuint64_t ki, svbool_t cmp) + { +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) +- { +- double sx1 = svclastb (p, 0, x1); +- uint64_t su1 = svclastb (p, 0, u1); +- uint64_t su2 = svclastb (p, 0, u2); +- double elem = specialcase (sx1, su1, su2); +- svfloat64_t y2 = sv_f64 (elem); +- y = svsel (p, y2, y); +- p = svpnext_b64 (cmp, p); +- } +- return y; ++ svbool_t p_pos = svcmpge_n_f64 (cmp, svreinterpret_f64_u64 (ki), 0.0); ++ ++ /* Scale up or down depending on sign of k. */ ++ svint64_t offset ++ = svsel_s64 (p_pos, sv_s64 (1009ull << 52), sv_s64 (-1022ull << 52)); ++ svfloat64_t factor ++ = svsel_f64 (p_pos, sv_f64 (0x1p1009), sv_f64 (0x1p-1022)); ++ ++ svuint64_t offset_sbits ++ = svsub_u64_x (cmp, sbits, svreinterpret_u64_s64 (offset)); ++ svfloat64_t scale = svreinterpret_f64_u64 (offset_sbits); ++ svfloat64_t res = svmad_f64_x (cmp, scale, tmp, scale); ++ return svmul_f64_x (cmp, res, factor); + } + + /* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about +@@ -214,8 +194,8 @@ sv_log_inline (svbool_t pg, svuint64_t ix, svfloat64_t *tail, + + /* log(x) = k*Ln2 + log(c) + log1p(z/c-1). */ + /* SVE lookup requires 3 separate lookup tables, as opposed to scalar version +- that uses array of structures. We also do the lookup earlier in the code to +- make sure it finishes as early as possible. */ ++ that uses array of structures. We also do the lookup earlier in the code ++ to make sure it finishes as early as possible. */ + svfloat64_t invc = svld1_gather_index (pg, __v_pow_log_data.invc, i); + svfloat64_t logc = svld1_gather_index (pg, __v_pow_log_data.logc, i); + svfloat64_t logctail = svld1_gather_index (pg, __v_pow_log_data.logctail, i); +@@ -325,14 +305,14 @@ sv_exp_inline (svbool_t pg, svfloat64_t x, svfloat64_t xtail, + svbool_t oflow = svcmpge (pg, abstop, HugeExp); + oflow = svand_z (pg, uoflow, svbic_z (pg, oflow, uflow)); + +- /* For large |x| values (512 < |x| < 1024) scale * (1 + TMP) can overflow +- or underflow. */ ++ /* Handle underflow and overlow in scale. ++ For large |x| values (512 < |x| < 1024), scale * (1 + TMP) can ++ overflow or underflow. */ + svbool_t special = svbic_z (pg, uoflow, svorr_z (pg, uflow, oflow)); ++ if (__glibc_unlikely (svptest_any (pg, special))) ++ z = svsel (special, specialcase (tmp, sbits, ki, special), z); + +- /* Update result with special and large cases. */ +- z = sv_call_specialcase (tmp, sbits, ki, z, special); +- +- /* Handle underflow and overflow. */ ++ /* Handle underflow and overflow in exp. */ + svbool_t x_is_neg = svcmplt (pg, x, 0); + svuint64_t sign_mask + = svlsl_x (pg, sign_bias, 52 - V_POW_EXP_TABLE_BITS); +@@ -353,7 +333,7 @@ sv_exp_inline (svbool_t pg, svfloat64_t x, svfloat64_t xtail, + } + + static inline double +-pow_sc (double x, double y) ++pow_specialcase (double x, double y) + { + uint64_t ix = asuint64 (x); + uint64_t iy = asuint64 (y); +@@ -382,6 +362,14 @@ pow_sc (double x, double y) + return x; + } + ++/* Scalar fallback for special case routines with custom signature. */ ++static svfloat64_t NOINLINE ++sv_pow_specialcase (svfloat64_t x1, svfloat64_t x2, svfloat64_t y, ++ svbool_t cmp) ++{ ++ return sv_call2_f64 (pow_specialcase, x1, x2, y, cmp); ++} ++ + svfloat64_t SV_NAME_D2 (pow) (svfloat64_t x, svfloat64_t y, const svbool_t pg) + { + const struct data *d = ptr_barrier (&data); +@@ -444,7 +432,7 @@ svfloat64_t SV_NAME_D2 (pow) (svfloat64_t x, svfloat64_t y, const svbool_t pg) + + /* Cases of zero/inf/nan x or y. */ + if (__glibc_unlikely (svptest_any (svptrue_b64 (), special))) +- vz = sv_call2_f64 (pow_sc, x, y, vz, special); ++ vz = sv_pow_specialcase (x, y, vz, special); + + return vz; + } +diff --git a/sysdeps/aarch64/fpu/powf_sve.c b/sysdeps/aarch64/fpu/powf_sve.c +index 33bba96054..8f6f85dca9 100644 +--- a/sysdeps/aarch64/fpu/powf_sve.c ++++ b/sysdeps/aarch64/fpu/powf_sve.c +@@ -116,11 +116,10 @@ zeroinfnan (uint32_t ix) + preamble of scalar powf except that we do not update ix and sign_bias. This + is done in the preamble of the SVE powf. */ + static inline float +-powf_specialcase (float x, float y, float z) ++powf_specialcase (float x, float y) + { + uint32_t ix = asuint (x); + uint32_t iy = asuint (y); +- /* Either (x < 0x1p-126 or inf or nan) or (y is 0 or inf or nan). */ + if (__glibc_unlikely (zeroinfnan (iy))) + { + if (2 * iy == 0) +@@ -142,32 +141,15 @@ powf_specialcase (float x, float y, float z) + x2 = -x2; + return iy & 0x80000000 ? 1 / x2 : x2; + } +- /* We need a return here in case x<0 and y is integer, but all other tests +- need to be run. */ +- return z; ++ /* Return x for convenience, but make sure result is never used. */ ++ return x; + } + + /* Scalar fallback for special case routines with custom signature. */ + static svfloat32_t NOINLINE +-sv_call_powf_sc (svfloat32_t x1, svfloat32_t x2, svfloat32_t y) ++sv_call_powf_sc (svfloat32_t x1, svfloat32_t x2, svfloat32_t y, svbool_t cmp) + { +- /* Special cases of x or y: zero, inf and nan. */ +- svbool_t xspecial = sv_zeroinfnan (svptrue_b32 (), svreinterpret_u32 (x1)); +- svbool_t yspecial = sv_zeroinfnan (svptrue_b32 (), svreinterpret_u32 (x2)); +- svbool_t cmp = svorr_z (svptrue_b32 (), xspecial, yspecial); +- +- svbool_t p = svpfirst (cmp, svpfalse ()); +- while (svptest_any (cmp, p)) +- { +- float sx1 = svclastb (p, 0, x1); +- float sx2 = svclastb (p, 0, x2); +- float elem = svclastb (p, 0, y); +- elem = powf_specialcase (sx1, sx2, elem); +- svfloat32_t y2 = sv_f32 (elem); +- y = svsel (p, y2, y); +- p = svpnext_b32 (cmp, p); +- } +- return y; ++ return sv_call2_f32 (powf_specialcase, x1, x2, y, cmp); + } + + /* Compute core for half of the lanes in double precision. */ +@@ -330,7 +312,7 @@ svfloat32_t SV_NAME_F2 (pow) (svfloat32_t x, svfloat32_t y, const svbool_t pg) + ret = svsel (yint_or_xpos, ret, sv_f32 (__builtin_nanf (""))); + + if (__glibc_unlikely (svptest_any (cmp, cmp))) +- return sv_call_powf_sc (x, y, ret); ++ return sv_call_powf_sc (x, y, ret, cmp); + + return ret; + } + +commit a460dc7bd9dee24a2a305d87b8646ba683cd57de +Author: Sachin Monga +Date: Tue Oct 7 03:17:00 2025 -0500 + + ppc64le: Restore optimized strcmp for power10 + + This patch addresses the actual cause of CVE-2025-5702 + + The vector non-volatile registers are not used anymore for + 32 byte load and comparison operation + + Additionally, the assembler workaround used earlier for the + instruction lxvp is replaced with actual instruction. + + Signed-off-by: Sachin Monga + Co-authored-by: Paul Murphy + (cherry picked from commit 9a40b1cda519cc4f532acb6d020390829df3d81b) + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/strcmp.S b/sysdeps/powerpc/powerpc64/le/power10/strcmp.S +new file mode 100644 +index 0000000000..0d4a53317c +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/strcmp.S +@@ -0,0 +1,185 @@ ++/* Optimized strcmp implementation for PowerPC64/POWER10. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++#include ++ ++#ifndef STRCMP ++# define STRCMP strcmp ++#endif ++ ++/* Implements the function ++ int [r3] strcmp (const char *s1 [r3], const char *s2 [r4]). */ ++ ++ ++#define COMPARE_16(vreg1,vreg2,offset) \ ++ lxv vreg1+32,offset(r3); \ ++ lxv vreg2+32,offset(r4); \ ++ vcmpnezb. v7,vreg1,vreg2; \ ++ bne cr6,L(different); \ ++ ++#define COMPARE_32(vreg1,vreg2,offset,label1,label2) \ ++ lxvp vreg1+32,offset(r3); \ ++ lxvp vreg2+32,offset(r4); \ ++ vcmpnezb. v7,vreg1+1,vreg2+1; \ ++ bne cr6,L(label1); \ ++ vcmpnezb. v7,vreg1,vreg2; \ ++ bne cr6,L(label2); \ ++ ++#define TAIL(vreg1,vreg2) \ ++ vctzlsbb r6,v7; \ ++ vextubrx r5,r6,vreg1; \ ++ vextubrx r4,r6,vreg2; \ ++ subf r3,r4,r5; \ ++ blr; \ ++ ++#define CHECK_N_BYTES(reg1,reg2,len_reg) \ ++ sldi r0,len_reg,56; \ ++ lxvl 32+v4,reg1,r0; \ ++ lxvl 32+v5,reg2,r0; \ ++ add reg1,reg1,len_reg; \ ++ add reg2,reg2,len_reg; \ ++ vcmpnezb. v7,v4,v5; \ ++ vctzlsbb r6,v7; \ ++ cmpld cr7,r6,len_reg; \ ++ blt cr7,L(different); \ ++ ++ ++ .machine power10 ++ENTRY_TOCLESS (STRCMP, 4) ++ li r11,16 ++ /* eq bit of cr1 used as swap status flag to indicate if ++ source pointers were swapped. */ ++ crclr 4*cr1+eq ++ andi. r7,r3,15 ++ sub r7,r11,r7 /* r7(nalign1) = 16 - (str1 & 15). */ ++ andi. r9,r4,15 ++ sub r5,r11,r9 /* r5(nalign2) = 16 - (str2 & 15). */ ++ cmpld cr7,r7,r5 ++ beq cr7,L(same_aligned) ++ blt cr7,L(nalign1_min) ++ /* Swap r3 and r4, and r7 and r5 such that r3 and r7 hold the ++ pointer which is closer to the next 16B boundary so that only ++ one CHECK_N_BYTES is needed before entering the loop below. */ ++ mr r8,r4 ++ mr r4,r3 ++ mr r3,r8 ++ mr r12,r7 ++ mr r7,r5 ++ mr r5,r12 ++ crset 4*cr1+eq /* Set bit on swapping source pointers. */ ++ ++ .p2align 5 ++L(nalign1_min): ++ CHECK_N_BYTES(r3,r4,r7) ++ ++ .p2align 5 ++L(s1_aligned): ++ /* r9 and r5 is number of bytes to be read after and before ++ page boundary correspondingly. */ ++ sub r5,r5,r7 ++ subfic r9,r5,16 ++ /* Now let r7 hold the count of quadwords which can be ++ checked without crossing a page boundary. quadword offset is ++ (str2>>4)&0xFF. */ ++ rlwinm r7,r4,28,0xFF ++ /* Below check is required only for first iteration. For second ++ iteration and beyond, the new loop counter is always 255. */ ++ cmpldi r7,255 ++ beq L(L3) ++ /* Get the initial loop count by 255-((str2>>4)&0xFF). */ ++ subfic r11,r7,255 ++ ++ .p2align 5 ++L(L1): ++ mtctr r11 ++ ++ .p2align 5 ++L(L2): ++ COMPARE_16(v4,v5,0) /* Load 16B blocks using lxv. */ ++ addi r3,r3,16 ++ addi r4,r4,16 ++ bdnz L(L2) ++ /* Cross the page boundary of s2, carefully. */ ++ ++ .p2align 5 ++L(L3): ++ CHECK_N_BYTES(r3,r4,r5) ++ CHECK_N_BYTES(r3,r4,r9) ++ li r11,255 /* Load the new loop counter. */ ++ b L(L1) ++ ++ .p2align 5 ++L(same_aligned): ++ CHECK_N_BYTES(r3,r4,r7) ++ /* Align s1 to 32B and adjust s2 address. ++ Use lxvp only if both s1 and s2 are 32B aligned. */ ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ COMPARE_16(v4,v5,48) ++ addi r3,r3,64 ++ addi r4,r4,64 ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ ++ clrldi r6,r3,59 ++ subfic r5,r6,32 ++ add r3,r3,r5 ++ add r4,r4,r5 ++ andi. r5,r4,0x1F ++ beq cr0,L(32B_aligned_loop) ++ ++ .p2align 5 ++L(16B_aligned_loop): ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ COMPARE_16(v4,v5,48) ++ addi r3,r3,64 ++ addi r4,r4,64 ++ b L(16B_aligned_loop) ++ ++ /* Calculate and return the difference. */ ++L(different): ++ vctzlsbb r6,v7 ++ vextubrx r5,r6,v4 ++ vextubrx r4,r6,v5 ++ bt 4*cr1+eq,L(swapped) ++ subf r3,r4,r5 ++ blr ++ ++ /* If src pointers were swapped, then swap the ++ indices and calculate the return value. */ ++L(swapped): ++ subf r3,r5,r4 ++ blr ++ ++ .p2align 5 ++L(32B_aligned_loop): ++ COMPARE_32(v14,v16,0,tail1,tail2) ++ COMPARE_32(v14,v16,32,tail1,tail2) ++ COMPARE_32(v14,v16,64,tail1,tail2) ++ COMPARE_32(v14,v16,96,tail1,tail2) ++ addi r3,r3,128 ++ addi r4,r4,128 ++ b L(32B_aligned_loop) ++ ++L(tail1): TAIL(v15,v17) ++L(tail2): TAIL(v14,v16) ++ ++END (STRCMP) ++libc_hidden_builtin_def (strcmp) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 9f15f3207f..fa1107dfd9 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,8 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += memcmp-power10 memcpy-power10 memmove-power10 memset-power10 \ + rawmemchr-power9 rawmemchr-power10 \ +- strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ ++ strcmp-power9 strcmp-power10 strncmp-power9 \ ++ strcpy-power9 stpcpy-power9 \ + strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 78443b7f34..9b3e617306 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -377,6 +377,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/strcmp.c. */ + IFUNC_IMPL (i, name, strcmp, + #ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strcmp, ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __strcmp_power10) + IFUNC_IMPL_ADD (array, i, strcmp, + hwcap2 & PPC_FEATURE2_ARCH_3_00 + && hwcap & PPC_FEATURE_HAS_ALTIVEC, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S +new file mode 100644 +index 0000000000..a4ee7fb53c +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power10.S +@@ -0,0 +1,26 @@ ++/* Optimized strcmp implementation for POWER10/PPC64. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) ++#define STRCMP __strcmp_power10 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#include ++#endif /* __LITTLE_ENDIAN__ && IS_IN (libc) */ +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c +index 06b9b4090f..ff32496fab 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c +@@ -29,12 +29,16 @@ extern __typeof (strcmp) __strcmp_power7 attribute_hidden; + extern __typeof (strcmp) __strcmp_power8 attribute_hidden; + # ifdef __LITTLE_ENDIAN__ + extern __typeof (strcmp) __strcmp_power9 attribute_hidden; ++extern __typeof (strcmp) __strcmp_power10 attribute_hidden; + # endif + + # undef strcmp + + libc_ifunc_redirected (__redirect_strcmp, strcmp, + # ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __strcmp_power10 : + (hwcap2 & PPC_FEATURE2_ARCH_3_00 + && hwcap & PPC_FEATURE_HAS_ALTIVEC) + ? __strcmp_power9 : + +commit 4bfd05e2b8f69a1178272c60c17961a61e4e09b3 +Author: Sachin Monga +Date: Fri Nov 21 01:39:50 2025 -0500 + + ppc64le: Restore optimized strncmp for power10 + + This patch addresses the actual cause of CVE-2025-5745 + + The vector non-volatile registers are not used anymore for + 32 byte load and comparison operation + + Additionally, the assembler workaround used earlier for the + instruction lxvp is replaced with actual instruction. + + Signed-off-by: Sachin Monga + Co-authored-by: Paul Murphy + (cherry picked from commit 2ea943f7d487d6a4166658b32af7c5365889fc34) + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/strncmp.S b/sysdeps/powerpc/powerpc64/le/power10/strncmp.S +new file mode 100644 +index 0000000000..6e09fcb7f2 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/strncmp.S +@@ -0,0 +1,252 @@ ++/* Optimized strncmp implementation for PowerPC64/POWER10. ++ Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++/* Implements the function ++ ++ int [r3] strncmp (const char *s1 [r3], const char *s2 [r4], size_t [r5] n) ++ ++ The implementation uses unaligned doubleword access to avoid specialized ++ code paths depending of data alignment for first 32 bytes and uses ++ vectorised loops after that. */ ++ ++#ifndef STRNCMP ++# define STRNCMP strncmp ++#endif ++ ++#define COMPARE_16(vreg1,vreg2,offset) \ ++ lxv vreg1+32,offset(r3); \ ++ lxv vreg2+32,offset(r4); \ ++ vcmpnezb. v7,vreg1,vreg2; \ ++ bne cr6,L(different); \ ++ cmpldi cr7,r5,16; \ ++ ble cr7,L(ret0); \ ++ addi r5,r5,-16; ++ ++#define COMPARE_32(vreg1,vreg2,offset,label1,label2) \ ++ lxvp vreg1+32,offset(r3); \ ++ lxvp vreg2+32,offset(r4); \ ++ vcmpnezb. v7,vreg1+1,vreg2+1; \ ++ bne cr6,L(label1); \ ++ vcmpnezb. v7,vreg1,vreg2; \ ++ bne cr6,L(label2); \ ++ cmpldi cr7,r5,32; \ ++ ble cr7,L(ret0); \ ++ addi r5,r5,-32; ++ ++#define TAIL_FIRST_16B(vreg1,vreg2) \ ++ vctzlsbb r6,v7; \ ++ cmpld cr7,r5,r6; \ ++ ble cr7,L(ret0); \ ++ vextubrx r5,r6,vreg1; \ ++ vextubrx r4,r6,vreg2; \ ++ subf r3,r4,r5; \ ++ blr; ++ ++#define TAIL_SECOND_16B(vreg1,vreg2) \ ++ vctzlsbb r6,v7; \ ++ addi r0,r6,16; \ ++ cmpld cr7,r5,r0; \ ++ ble cr7,L(ret0); \ ++ vextubrx r5,r6,vreg1; \ ++ vextubrx r4,r6,vreg2; \ ++ subf r3,r4,r5; \ ++ blr; ++ ++#define CHECK_N_BYTES(reg1,reg2,len_reg) \ ++ sldi r6,len_reg,56; \ ++ lxvl 32+v4,reg1,r6; \ ++ lxvl 32+v5,reg2,r6; \ ++ add reg1,reg1,len_reg; \ ++ add reg2,reg2,len_reg; \ ++ vcmpnezb v7,v4,v5; \ ++ vctzlsbb r6,v7; \ ++ cmpld cr7,r6,len_reg; \ ++ blt cr7,L(different); \ ++ cmpld cr7,r5,len_reg; \ ++ ble cr7,L(ret0); \ ++ sub r5,r5,len_reg; \ ++ ++ .machine power10 ++ENTRY_TOCLESS (STRNCMP, 4) ++ /* Check if size is 0. */ ++ cmpdi cr0,r5,0 ++ beq cr0,L(ret0) ++ andi. r7,r3,4095 ++ andi. r8,r4,4095 ++ cmpldi cr0,r7,4096-16 ++ cmpldi cr1,r8,4096-16 ++ bgt cr0,L(crosses) ++ bgt cr1,L(crosses) ++ COMPARE_16(v4,v5,0) ++ addi r3,r3,16 ++ addi r4,r4,16 ++ ++L(crosses): ++ andi. r7,r3,15 ++ subfic r7,r7,16 /* r7(nalign1) = 16 - (str1 & 15). */ ++ andi. r9,r4,15 ++ subfic r8,r9,16 /* r8(nalign2) = 16 - (str2 & 15). */ ++ cmpld cr7,r7,r8 ++ beq cr7,L(same_aligned) ++ blt cr7,L(nalign1_min) ++ ++ /* nalign2 is minimum and s2 pointer is aligned. */ ++ CHECK_N_BYTES(r3,r4,r8) ++ /* Are we on the 64B hunk which crosses a page? */ ++ andi. r10,r3,63 /* Determine offset into 64B hunk. */ ++ andi. r8,r3,15 /* The offset into the 16B hunk. */ ++ neg r7,r3 ++ andi. r9,r7,15 /* Number of bytes after a 16B cross. */ ++ rlwinm. r7,r7,26,0x3F /* ((r4-4096))>>6&63. */ ++ beq L(compare_64_pagecross) ++ mtctr r7 ++ b L(compare_64B_unaligned) ++ ++ /* nalign1 is minimum and s1 pointer is aligned. */ ++L(nalign1_min): ++ CHECK_N_BYTES(r3,r4,r7) ++ /* Are we on the 64B hunk which crosses a page? */ ++ andi. r10,r4,63 /* Determine offset into 64B hunk. */ ++ andi. r8,r4,15 /* The offset into the 16B hunk. */ ++ neg r7,r4 ++ andi. r9,r7,15 /* Number of bytes after a 16B cross. */ ++ rlwinm. r7,r7,26,0x3F /* ((r4-4096))>>6&63. */ ++ beq L(compare_64_pagecross) ++ mtctr r7 ++ ++ .p2align 5 ++L(compare_64B_unaligned): ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ COMPARE_16(v4,v5,48) ++ addi r3,r3,64 ++ addi r4,r4,64 ++ bdnz L(compare_64B_unaligned) ++ ++ /* Cross the page boundary of s2, carefully. Only for first ++ iteration we have to get the count of 64B blocks to be checked. ++ From second iteration and beyond, loop counter is always 63. */ ++L(compare_64_pagecross): ++ li r11, 63 ++ mtctr r11 ++ cmpldi r10,16 ++ ble L(cross_4) ++ cmpldi r10,32 ++ ble L(cross_3) ++ cmpldi r10,48 ++ ble L(cross_2) ++L(cross_1): ++ CHECK_N_BYTES(r3,r4,r9) ++ CHECK_N_BYTES(r3,r4,r8) ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ addi r3,r3,48 ++ addi r4,r4,48 ++ b L(compare_64B_unaligned) ++L(cross_2): ++ COMPARE_16(v4,v5,0) ++ addi r3,r3,16 ++ addi r4,r4,16 ++ CHECK_N_BYTES(r3,r4,r9) ++ CHECK_N_BYTES(r3,r4,r8) ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ addi r3,r3,32 ++ addi r4,r4,32 ++ b L(compare_64B_unaligned) ++L(cross_3): ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ addi r3,r3,32 ++ addi r4,r4,32 ++ CHECK_N_BYTES(r3,r4,r9) ++ CHECK_N_BYTES(r3,r4,r8) ++ COMPARE_16(v4,v5,0) ++ addi r3,r3,16 ++ addi r4,r4,16 ++ b L(compare_64B_unaligned) ++L(cross_4): ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ addi r3,r3,48 ++ addi r4,r4,48 ++ CHECK_N_BYTES(r3,r4,r9) ++ CHECK_N_BYTES(r3,r4,r8) ++ b L(compare_64B_unaligned) ++ ++L(same_aligned): ++ CHECK_N_BYTES(r3,r4,r7) ++ /* Align s1 to 32B and adjust s2 address. ++ Use lxvp only if both s1 and s2 are 32B aligned. */ ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ COMPARE_16(v4,v5,48) ++ addi r3,r3,64 ++ addi r4,r4,64 ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ addi r5,r5,32 ++ ++ clrldi r6,r3,59 ++ subfic r7,r6,32 ++ add r3,r3,r7 ++ add r4,r4,r7 ++ subf r5,r7,r5 ++ andi. r7,r4,0x1F ++ beq cr0,L(32B_aligned_loop) ++ ++ .p2align 5 ++L(16B_aligned_loop): ++ COMPARE_16(v4,v5,0) ++ COMPARE_16(v4,v5,16) ++ COMPARE_16(v4,v5,32) ++ COMPARE_16(v4,v5,48) ++ addi r3,r3,64 ++ addi r4,r4,64 ++ b L(16B_aligned_loop) ++ ++ /* Calculate and return the difference. */ ++L(different): ++ TAIL_FIRST_16B(v4,v5) ++ ++ .p2align 5 ++L(32B_aligned_loop): ++ COMPARE_32(v14,v16,0,tail1,tail2) ++ COMPARE_32(v14,v16,32,tail1,tail2) ++ COMPARE_32(v14,v16,64,tail1,tail2) ++ COMPARE_32(v14,v16,96,tail1,tail2) ++ addi r3,r3,128 ++ addi r4,r4,128 ++ b L(32B_aligned_loop) ++ ++L(tail1): TAIL_FIRST_16B(v15,v17) ++L(tail2): TAIL_SECOND_16B(v14,v16) ++ ++ .p2align 5 ++L(ret0): ++ li r3,0 ++ blr ++ ++END(STRNCMP) ++libc_hidden_builtin_def(strncmp) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index fa1107dfd9..9072b0d23a 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += memcmp-power10 memcpy-power10 memmove-power10 memset-power10 \ + rawmemchr-power9 rawmemchr-power10 \ +- strcmp-power9 strcmp-power10 strncmp-power9 \ ++ strcmp-power9 strcmp-power10 strncmp-power9 strncmp-power10 \ + strcpy-power9 stpcpy-power9 \ + strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10 + endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 9b3e617306..14aa642675 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -164,6 +164,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/strncmp.c. */ + IFUNC_IMPL (i, name, strncmp, + #ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap & PPC_FEATURE_HAS_VSX, ++ __strncmp_power10) + IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_00 + && hwcap & PPC_FEATURE_HAS_ALTIVEC, + __strncmp_power9) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S +new file mode 100644 +index 0000000000..bb25bc75b8 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power10.S +@@ -0,0 +1,25 @@ ++/* Copyright (C) 2025 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) ++#define STRNCMP __strncmp_power10 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +index 6178f4a432..a5ed67f766 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +@@ -29,6 +29,7 @@ extern __typeof (strncmp) __strncmp_ppc attribute_hidden; + extern __typeof (strncmp) __strncmp_power8 attribute_hidden; + # ifdef __LITTLE_ENDIAN__ + extern __typeof (strncmp) __strncmp_power9 attribute_hidden; ++extern __typeof (strncmp) __strncmp_power10 attribute_hidden; + # endif + # undef strncmp + +@@ -36,6 +37,9 @@ extern __typeof (strncmp) __strncmp_power9 attribute_hidden; + ifunc symbol properly. */ + libc_ifunc_redirected (__redirect_strncmp, strncmp, + # ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __strncmp_power10 : + (hwcap2 & PPC_FEATURE2_ARCH_3_00 + && hwcap & PPC_FEATURE_HAS_ALTIVEC) + ? __strncmp_power9 : + +commit 165497e8973f2bd960d8a3abcfa577720ee45bb4 +Author: Sachin Monga +Date: Thu Nov 27 10:58:19 2025 -0500 + + ppc64le: Power 10 rawmemchr clobbers v20 (bug #33091) + + Replace non-volatile(v20) by volatile(v17) + since v20 is not restored + + Reviewed-by: Peter Bergner + (cherry picked from commit b59799f14f97f697c3a36b4380bd4ce2fbe65f11) + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/strlen.S b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +index 0bd794540f..574a24b586 100644 +--- a/sysdeps/powerpc/powerpc64/le/power10/strlen.S ++++ b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +@@ -31,7 +31,7 @@ + # define FUNCNAME RAWMEMCHR + # endif + # define MCOUNT_NARGS 2 +-# define VREG_ZERO v20 ++# define VREG_ZERO v17 + # define OFF_START_LOOP 256 + # define RAWMEMCHR_SUBTRACT_VECTORS \ + vsububm v4,v4,v18; \ + +commit 183f600c802108897352ea3be27d43b8e2db846c +Author: H.J. Lu +Date: Tue Dec 17 15:18:36 2024 +0800 + + getaddrinfo.c: Avoid uninitialized pointer access [BZ #32465] + + Add valid_decimal_value to check valid decimal value in a string to + avoid uninitialized endp in add_prefixlist and gaiconf_init as reported + by Clang 19: + + ./getaddrinfo.c:1884:11: error: variable 'endp' is used uninitialized whenever '||' condition is true [-Werror,-Wsometimes-uninitialized] + 1884 | && (cp == NULL + | ^~~~~~~~~~ + ./getaddrinfo.c:1887:11: note: uninitialized use occurs here + 1887 | && *endp == '\0' + | ^~~~ + ./getaddrinfo.c:1884:11: note: remove the '||' if its condition is always false + 1884 | && (cp == NULL + | ^~~~~~~~~~ + 1885 | || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX + | ~~ + ./getaddrinfo.c:1875:13: note: initialize the variable 'endp' to silence this warning + 1875 | char *endp; + | ^ + | = NULL + + This fixes BZ #32465. + + Signed-off-by: H.J. Lu + Reviewed-by: Sam James + (cherry picked from commit 33aeb88c5bc9a0c6b1bd7190a0ead7570972b719) + +diff --git a/nss/getaddrinfo.c b/nss/getaddrinfo.c +index 3ccd3905fa..542b362af3 100644 +--- a/nss/getaddrinfo.c ++++ b/nss/getaddrinfo.c +@@ -1865,6 +1865,22 @@ scopecmp (const void *p1, const void *p2) + return 1; + } + ++/* Return true if PTR points to a valid decimal value string and ++ store the value in *VALUE_P. Otherwise, return false. */ ++ ++static bool ++valid_decimal_value (const char *str, unsigned long int *value_p) ++{ ++ char *endp; ++ unsigned long int value = strtoul (str, &endp, 10); ++ if (str == endp ++ || *endp != '\0' ++ || (value == ULONG_MAX && errno == ERANGE)) ++ return false; ++ *value_p = value; ++ return true; ++} ++ + static bool + add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp, + char *val1, char *val2, char **pos) +@@ -1872,7 +1888,6 @@ add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp, + struct in6_addr prefix; + unsigned long int bits; + unsigned long int val; +- char *endp; + + bits = 128; + __set_errno (0); +@@ -1881,14 +1896,9 @@ add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp, + *cp++ = '\0'; + *pos = cp; + if (inet_pton (AF_INET6, val1, &prefix) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && (cp == NULL || valid_decimal_value (cp, &bits)) + && bits <= 128 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && valid_decimal_value (val2, &val) + && val <= INT_MAX) + { + struct prefixlist *newp = malloc (sizeof (*newp)); +@@ -2031,7 +2041,6 @@ gaiconf_init (void) + struct in6_addr prefix; + unsigned long int bits; + unsigned long int val; +- char *endp; + + bits = 32; + __set_errno (0); +@@ -2042,15 +2051,10 @@ gaiconf_init (void) + { + bits = 128; + if (IN6_IS_ADDR_V4MAPPED (&prefix) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && (cp == NULL || valid_decimal_value (cp, &bits)) + && bits >= 96 + && bits <= 128 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && valid_decimal_value (val2, &val) + && val <= INT_MAX) + { + if (!add_scopelist (&scopelist, &nscopelist, +@@ -2064,14 +2068,9 @@ gaiconf_init (void) + } + } + else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3]) +- && (cp == NULL +- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && (cp == NULL || valid_decimal_value (cp, &bits)) + && bits <= 32 +- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX +- || errno != ERANGE) +- && *endp == '\0' ++ && valid_decimal_value (val2, &val) + && val <= INT_MAX) + { + if (!add_scopelist (&scopelist, &nscopelist, + +commit 0273c4d18ecbfe742439a45bb1df3fafaf1561c4 +Author: DJ Delorie +Date: Wed Oct 15 21:37:56 2025 -0400 + + sprof: check pread size and offset for overflow + + Add a bit of descriptive paranoia to the values we read from + the ELF headers and use to access data. + + Reviewed-by: Collin Funk + (cherry picked from commit 324084649b2da2f6840e3a1b84159a4e9a9e9a74) + +diff --git a/elf/sprof.c b/elf/sprof.c +index b19aca3292..0c687eab49 100644 +--- a/elf/sprof.c ++++ b/elf/sprof.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + /* Get libc version number. */ + #include "../version.h" +@@ -410,6 +411,7 @@ load_shobj (const char *name) + int fd; + ElfW(Shdr) *shdr; + size_t pagesize = getpagesize (); ++ struct stat st; + + /* Since we use dlopen() we must be prepared to work around the sometimes + strange lookup rules for the shared objects. If we have a file foo.so +@@ -553,14 +555,39 @@ load_shobj (const char *name) + error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"), + map->l_name); + ++ if (fstat (fd, &st) < 0) ++ error (EXIT_FAILURE, errno, _("stat(%s) failure"), map->l_name); ++ ++ /* We're depending on data that's being read from the file, so be a ++ bit paranoid here and make sure the requests are reasonable - ++ i.e. both size and offset are nonnegative and smaller than the ++ file size, as well as the offset of the end of the data. PREAD ++ would have failed anyway, but this is more robust and explains ++ what happened better. Note that SZ must be unsigned and OFF may ++ be signed or unsigned. */ ++#define PCHECK(sz1,off1) { \ ++ size_t sz = sz1, end_off; \ ++ off_t off = off1; \ ++ if (sz > st.st_size \ ++ || off < 0 || off > st.st_size \ ++ || INT_ADD_WRAPV (sz, off, &end_off) \ ++ || end_off > st.st_size) \ ++ error (EXIT_FAILURE, ERANGE, \ ++ _("read outside of file extents %zu + %zd > %zu"), \ ++ sz, off, st.st_size); \ ++ } ++ + /* Map the section header. */ + size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr)); + shdr = (ElfW(Shdr) *) alloca (size); ++ PCHECK (size, ehdr->e_shoff); + if (pread (fd, shdr, size, ehdr->e_shoff) != size) + error (EXIT_FAILURE, errno, _("reading of section headers failed")); + + /* Get the section header string table. */ + char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size); ++ PCHECK (shdr[ehdr->e_shstrndx].sh_size, ++ shdr[ehdr->e_shstrndx].sh_offset); + if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size, + shdr[ehdr->e_shstrndx].sh_offset) + != shdr[ehdr->e_shstrndx].sh_size) +@@ -588,6 +615,7 @@ load_shobj (const char *name) + size_t size = debuglink_entry->sh_size; + char *debuginfo_fname = (char *) alloca (size + 1); + debuginfo_fname[size] = '\0'; ++ PCHECK (size, debuglink_entry->sh_offset); + if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset) + != size) + { +@@ -641,21 +669,32 @@ load_shobj (const char *name) + if (fd2 != -1) + { + ElfW(Ehdr) ehdr2; ++ struct stat st; ++ ++ if (fstat (fd2, &st) < 0) ++ error (EXIT_FAILURE, errno, _("stat(%s) failure"), workbuf); + + /* Read the ELF header. */ ++ PCHECK (sizeof (ehdr2), 0); + if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2)) + error (EXIT_FAILURE, errno, + _("reading of ELF header failed")); + + /* Map the section header. */ +- size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr)); ++ size_t size; ++ if (INT_MULTIPLY_WRAPV (ehdr2.e_shnum, sizeof (ElfW(Shdr)), &size)) ++ error (EXIT_FAILURE, errno, _("too many section headers")); ++ + ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size); ++ PCHECK (size, ehdr2.e_shoff); + if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size) + error (EXIT_FAILURE, errno, + _("reading of section headers failed")); + + /* Get the section header string table. */ + shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size); ++ PCHECK (shdr2[ehdr2.e_shstrndx].sh_size, ++ shdr2[ehdr2.e_shstrndx].sh_offset); + if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size, + shdr2[ehdr2.e_shstrndx].sh_offset) + != shdr2[ehdr2.e_shstrndx].sh_size) + +commit 6a861d39464a8ff2a6a128fb54923f047f841927 +Author: Collin Funk +Date: Wed Oct 22 01:51:09 2025 -0700 + + sprof: fix -Wformat warnings on 32-bit hosts + + Reviewed-by: H.J. Lu + (cherry picked from commit 9681f645ba20fc3c18eb12ffebf94e3df1f888e3) + +diff --git a/elf/sprof.c b/elf/sprof.c +index 0c687eab49..1f5ab25ac3 100644 +--- a/elf/sprof.c ++++ b/elf/sprof.c +@@ -573,8 +573,8 @@ load_shobj (const char *name) + || INT_ADD_WRAPV (sz, off, &end_off) \ + || end_off > st.st_size) \ + error (EXIT_FAILURE, ERANGE, \ +- _("read outside of file extents %zu + %zd > %zu"), \ +- sz, off, st.st_size); \ ++ _("read outside of file extents %zu + %jd > %jd"), \ ++ sz, (intmax_t) off, (intmax_t) st.st_size); \ + } + + /* Map the section header. */ + +commit 9e2f52c5e08e605cf1aaa646a5398b7e5a04d4bb +Author: Florian Weimer +Date: Thu Nov 6 14:33:22 2025 +0100 + + support: Fix FILE * leak in check_for_unshare_hints in test-container + + The file opened via fopen is never closed. + + (cherry picked from commit 20a2a756089eacd7e7f4c02e381e82b5d0e40a2c) + +diff --git a/support/test-container.c b/support/test-container.c +index ebcc722da5..23fe31071c 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -705,6 +705,7 @@ check_for_unshare_hints (int require_pidns) + + val = -1; /* Sentinel. */ + int cnt = fscanf (f, "%d", &val); ++ fclose (f); + if (cnt == 1 && val != files[i].bad_value) + continue; + + +commit 468ca594f835d98857f78c6d3a7154fdc30db214 +Author: Florian Weimer +Date: Thu Nov 6 14:49:21 2025 +0100 + + support: Exit on consistency check failure in resolv_response_add_name + + Using TEST_VERIFY (crname_target != crname) instructs some analysis + tools that crname_target == crname might hold. Under this assumption, + they report a use-after-free for crname_target->offset below, caused + by the previous free (crname). + + Reviewed-by: Collin Funk + (cherry picked from commit b64335ff111c071fde61aec1c1a8460afb3d16d4) + +diff --git a/support/resolv_test.c b/support/resolv_test.c +index f1613bd255..d4cc26b4aa 100644 +--- a/support/resolv_test.c ++++ b/support/resolv_test.c +@@ -326,7 +326,7 @@ resolv_response_add_name (struct resolv_response_builder *b, + crname_target = *ptr; + else + crname_target = NULL; +- TEST_VERIFY (crname_target != crname); ++ TEST_VERIFY_EXIT (crname_target != crname); + /* Not added to the tree. */ + free (crname); + } + +commit d861635092a5ad3499baf18b2ff955b778734a0e +Author: Sunil K Pandey +Date: Tue Dec 9 08:57:44 2025 -0800 + + nptl: Optimize trylock for high cache contention workloads (BZ #33704) + + Check lock availability before acquisition to reduce cache line + bouncing. Significantly improves trylock throughput on multi-core + systems under heavy contention. + + Tested on x86_64. + + Fixes BZ #33704. + + Co-authored-by: Alex M Wells + Reviewed-by: Wilco Dijkstra + (cherry picked from commit 63716823dbad9482e09972907ae98e9cb00f9b86) + +diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c +index 720c103f3f..6cf47403dd 100644 +--- a/nptl/pthread_mutex_trylock.c ++++ b/nptl/pthread_mutex_trylock.c +@@ -48,7 +48,8 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex) + return 0; + } + +- if (lll_trylock (mutex->__data.__lock) == 0) ++ if (atomic_load_relaxed (&(mutex->__data.__lock)) == 0 ++ && lll_trylock (mutex->__data.__lock) == 0) + { + /* Record the ownership. */ + mutex->__data.__owner = id; +@@ -71,7 +72,10 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex) + /*FALL THROUGH*/ + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_ERRORCHECK_NP: +- if (lll_trylock (mutex->__data.__lock) != 0) ++ /* Mutex type is already loaded, lock check overhead should ++ be minimal. */ ++ if (atomic_load_relaxed (&(mutex->__data.__lock)) != 0 ++ || lll_trylock (mutex->__data.__lock) != 0) + break; + + /* Record the ownership. */ + +commit bfc4dd9e526eacf3017dd8864ba0848e9d045dd4 +Author: Siddhesh Poyarekar +Date: Thu Jan 15 06:06:40 2026 -0500 + + memalign: reinstate alignment overflow check (CVE-2026-0861) + + The change to cap valid sizes to PTRDIFF_MAX inadvertently dropped the + overflow check for alignment in memalign functions, _mid_memalign and + _int_memalign. Reinstate the overflow check in _int_memalign, aligned + with the PTRDIFF_MAX change since that is directly responsible for the + CVE. The missing _mid_memalign check is not relevant (and does not have + a security impact) and may need a different approach to fully resolve, + so it has been omitted. + + CVE-Id: CVE-2026-0861 + Vulnerable-Commit: 9bf8e29ca136094f73f69f725f15c51facc97206 + Reported-by: Igor Morgenstern, Aisle Research + Fixes: BZ #33796 + Reviewed-by: Wilco Dijkstra + Signed-off-by: Siddhesh Poyarekar + (cherry picked from commit c9188d333717d3ceb7e3020011651f424f749f93) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index bcb6e5b83c..e39354595e 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5049,7 +5049,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) + INTERNAL_SIZE_T size; + + nb = checked_request2size (bytes); +- if (nb == 0) ++ if (nb == 0 || alignment > PTRDIFF_MAX) + { + __set_errno (ENOMEM); + return NULL; +@@ -5065,7 +5065,10 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) + we don't find anything in those bins, the common malloc code will + scan starting at 2x. */ + +- /* Call malloc with worst case padding to hit alignment. */ ++ /* Call malloc with worst case padding to hit alignment. ALIGNMENT is a ++ power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of ++ space to add MINSIZE and whatever checked_request2size adds to BYTES to ++ get NB. Consequently, total below also does not overflow. */ + m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); + + if (m == 0) +diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c +index 2b91377e54..15b25cf01d 100644 +--- a/malloc/tst-malloc-too-large.c ++++ b/malloc/tst-malloc-too-large.c +@@ -152,7 +152,6 @@ test_large_allocations (size_t size) + } + + +-static long pagesize; + + /* This function tests the following aligned memory allocation functions + using several valid alignments and precedes each allocation test with a +@@ -171,8 +170,8 @@ test_large_aligned_allocations (size_t size) + + /* All aligned memory allocation functions expect an alignment that is a + power of 2. Given this, we test each of them with every valid +- alignment from 1 thru PAGESIZE. */ +- for (align = 1; align <= pagesize; align *= 2) ++ alignment for the type of ALIGN, i.e. until it wraps to 0. */ ++ for (align = 1; align > 0; align <<= 1) + { + test_setup (); + #if __GNUC_PREREQ (7, 0) +@@ -265,11 +264,6 @@ do_test (void) + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); + #endif + +- /* Aligned memory allocation functions need to be tested up to alignment +- size equivalent to page size, which should be a power of 2. */ +- pagesize = sysconf (_SC_PAGESIZE); +- TEST_VERIFY_EXIT (powerof2 (pagesize)); +- + /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. + in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. + + +commit 329c775788b2c9ff3da774ccf59fba7b6b8ff08e +Author: Carlos O'Donell +Date: Thu Jan 15 15:09:38 2026 -0500 + + resolv: Fix NSS DNS backend for getnetbyaddr (CVE-2026-0915) + + The default network value of zero for net was never tested for and + results in a DNS query constructed from uninitialized stack bytes. + The solution is to provide a default query for the case where net + is zero. + + Adding a test case for this was straight forward given the existence of + tst-resolv-network and if the test is added without the fix you observe + this failure: + + FAIL: resolv/tst-resolv-network + original exit status 1 + error: tst-resolv-network.c:174: invalid QNAME: \146\218\129\128 + error: 1 test failures + + With a random QNAME resulting from the use of uninitialized stack bytes. + + After the fix the test passes. + + Additionally verified using wireshark before and after to ensure + on-the-wire bytes for the DNS query were as expected. + + No regressions on x86_64. + + Reviewed-by: Florian Weimer + (cherry picked from commit e56ff82d5034ec66c6a78f517af6faa427f65b0b) + +diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c +index b32fd0fcab..71d67aa6f8 100644 +--- a/resolv/nss_dns/dns-network.c ++++ b/resolv/nss_dns/dns-network.c +@@ -207,6 +207,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, + sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2], + net_bytes[1], net_bytes[0]); + break; ++ default: ++ /* Default network (net is originally zero). */ ++ strcpy (qbuf, "0.0.0.0.in-addr.arpa"); ++ break; + } + + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); +diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c +index f40e6f926c..8d4f8badf3 100644 +--- a/resolv/tst-resolv-network.c ++++ b/resolv/tst-resolv-network.c +@@ -46,6 +46,9 @@ handle_code (const struct resolv_response_context *ctx, + { + switch (code) + { ++ case 0: ++ send_ptr (b, qname, qclass, qtype, "0.in-addr.arpa"); ++ break; + case 1: + send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa"); + break; +@@ -265,6 +268,9 @@ do_test (void) + "error: TRY_AGAIN\n"); + + /* Lookup by address, success cases. */ ++ check_reverse (0, ++ "name: 0.in-addr.arpa\n" ++ "net: 0x00000000\n"); + check_reverse (1, + "name: 1.in-addr.arpa\n" + "net: 0x00000001\n"); diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index 7e617c326996b..ea638e464c943 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -50,7 +50,7 @@ let version = "2.40"; - patchSuffix = "-66"; + patchSuffix = "-217"; sha256 = "sha256-GaiQF16SY9dI9ieZPeb0sa+c0h4D8IDkv7Oh+sECBaI="; in @@ -68,7 +68,7 @@ stdenv.mkDerivation ( /* No tarballs for stable upstream branch, only https://sourceware.org/git/glibc.git and using git would complicate bootstrapping. $ git fetch --all -p && git checkout origin/release/2.40/master && git describe - glibc-2.40-142-g2eb180377b + glibc-2.40-217-g329c775788 $ git show --minimal --reverse glibc-2.40.. ':!ADVISORIES' > 2.40-master.patch To compare the archive contents zdiff can be used. From b3e46e09431df52b6cabc14222ea08c3c1cc278c Mon Sep 17 00:00:00 2001 From: Jasi Date: Mon, 5 Jan 2026 23:20:26 -0500 Subject: [PATCH 31/74] libpng: 1.6.52 -> 1.6.53 - https://raw.githubusercontent.com/pnggroup/libpng/refs/tags/v1.6.53/CHANGES (cherry picked from commit 22d8a9fdc070c43054e9c2ca4051272ade33a056) --- pkgs/development/libraries/libpng/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/libraries/libpng/default.nix b/pkgs/development/libraries/libpng/default.nix index 7af29dedd1ac2..c16b6d4a17a23 100644 --- a/pkgs/development/libraries/libpng/default.nix +++ b/pkgs/development/libraries/libpng/default.nix @@ -20,11 +20,11 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "libpng" + whenPatched "-apng"; - version = "1.6.52"; + version = "1.6.53"; src = fetchurl { url = "mirror://sourceforge/libpng/libpng-${finalAttrs.version}.tar.xz"; - hash = "sha256-Nr1yYijsk6O2wi/bSelKZ7FvL+mzm3i3y2V3KWZmHMw="; + hash = "sha256-HT+4zMKTLQSqNmPiLvXvSQJENw9OVo14UBZQaHeNmNQ="; }; postPatch = whenPatched "gunzip < ${patch_src} | patch -Np1" From 6075009403e27e166a1572e0530ef624477e84df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Sat, 17 Jan 2026 08:46:17 +0100 Subject: [PATCH 32/74] libpng: 1.6.53 -> 1.6.54 And refresh the APNG patches, too. https://github.com/pnggroup/libpng/blob/02f2b4f4699f0ef9111a6534f093b53732df4452/ANNOUNCE Medium severity fixes: CVE-2026-22695 + CVE-2026-22801 (cherry picked from commit 6eb2c0976417d5311b4ede14818916c2b5169c1d) --- pkgs/development/libraries/libpng/default.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/development/libraries/libpng/default.nix b/pkgs/development/libraries/libpng/default.nix index c16b6d4a17a23..e548f82bdbb8f 100644 --- a/pkgs/development/libraries/libpng/default.nix +++ b/pkgs/development/libraries/libpng/default.nix @@ -10,21 +10,21 @@ assert zlib != null; let - patchVersion = "1.6.50"; + patchVersion = "1.6.54"; patch_src = fetchurl { url = "mirror://sourceforge/libpng-apng/libpng-${patchVersion}-apng.patch.gz"; - hash = "sha256-aH3cDHyxKKPqWOFZtRKSUlN8J+3gwyqT8R8DEn8MAWU="; + hash = "sha256-Vjj8RQDq9IRXtNfJ5VP9gqsB13MEpwB32DNoQp1E8bQ="; }; whenPatched = lib.optionalString apngSupport; in stdenv.mkDerivation (finalAttrs: { pname = "libpng" + whenPatched "-apng"; - version = "1.6.53"; + version = "1.6.54"; src = fetchurl { url = "mirror://sourceforge/libpng/libpng-${finalAttrs.version}.tar.xz"; - hash = "sha256-HT+4zMKTLQSqNmPiLvXvSQJENw9OVo14UBZQaHeNmNQ="; + hash = "sha256-AcnYowPJQewsURwUMSo7HTbO20Hi9RaMzaqF1TuIeAU="; }; postPatch = whenPatched "gunzip < ${patch_src} | patch -Np1" From a2a9a25fadb6ee6536df21b166135390a01359eb Mon Sep 17 00:00:00 2001 From: Michael Daniels Date: Sun, 11 Jan 2026 21:05:52 -0500 Subject: [PATCH 33/74] python3Packages.filelock: 3.20.1 -> 3.20.3 Changelog: https://github.com/tox-dev/py-filelock/releases/tag/3.20.3 (cherry picked from commit bd53fd2b50c36f9fb893a909821fea92cf50abb5) --- pkgs/development/python-modules/filelock/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/filelock/default.nix b/pkgs/development/python-modules/filelock/default.nix index 760286a19faf8..8b4baa9283689 100644 --- a/pkgs/development/python-modules/filelock/default.nix +++ b/pkgs/development/python-modules/filelock/default.nix @@ -12,12 +12,12 @@ buildPythonPackage rec { pname = "filelock"; - version = "3.20.1"; + version = "3.20.3"; pyproject = true; src = fetchPypi { inherit pname version; - hash = "sha256-uDYJSLNRuA9CCHjYUWUZoiBLB6783P0kkSpdMxJ/GIw="; + hash = "sha256-GMV+6RXH7GHP8Oz38Phpk2x8MBkbsM9AbxNBd40INOE="; }; build-system = [ From 29b651a5200ce48c76d877bd49abf316a4e52bd6 Mon Sep 17 00:00:00 2001 From: Stefan Visser Date: Tue, 20 Jan 2026 11:11:31 +0100 Subject: [PATCH 34/74] python3Packages.tinycss2: 1.4.0 -> 1.5.1 Release notes: https://github.com/Kozea/tinycss2/releases/tag/v1.5.1 Changelog: https://github.com/Kozea/tinycss2/compare/v1.4.0...v1.5.1 (cherry picked from commit d1ce5aaadfd4539bcedaa8542d6ec202458ca686) --- pkgs/development/python-modules/tinycss2/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/tinycss2/default.nix b/pkgs/development/python-modules/tinycss2/default.nix index 6a7129ad759e9..cc249b85ffde9 100644 --- a/pkgs/development/python-modules/tinycss2/default.nix +++ b/pkgs/development/python-modules/tinycss2/default.nix @@ -11,7 +11,7 @@ buildPythonPackage rec { pname = "tinycss2"; - version = "1.4.0"; + version = "1.5.1"; pyproject = true; disabled = pythonOlder "3.8"; @@ -22,7 +22,7 @@ buildPythonPackage rec { tag = "v${version}"; # for tests fetchSubmodules = true; - hash = "sha256-GVymUobWAE0YS65lti9dXRIIGpx0YkwF/vSb3y7cpYY="; + hash = "sha256-ZVmdHrqfF5fvBvHLaG2B4m1zek4wfEYArkntWzOqhfM="; }; build-system = [ flit-core ]; From ad255897fd63dc92fb39424cb54b5f7b3f36c0d1 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Fri, 2 Jan 2026 21:29:24 +0100 Subject: [PATCH 35/74] python3Packages.pillow: 12.0.0 -> 12.1.0 https://pillow.readthedocs.io/en/stable/releasenotes/12.1.0.html (cherry picked from commit 63bf1339ff574ea1edc78995b818d827dbbe4e8f) --- pkgs/development/python-modules/pillow/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pillow/default.nix b/pkgs/development/python-modules/pillow/default.nix index 3fc623ce4eb9f..3b301afdc59b0 100644 --- a/pkgs/development/python-modules/pillow/default.nix +++ b/pkgs/development/python-modules/pillow/default.nix @@ -44,14 +44,14 @@ buildPythonPackage rec { pname = "pillow"; - version = "12.0.0"; + version = "12.1.0"; pyproject = true; src = fetchFromGitHub { owner = "python-pillow"; repo = "pillow"; tag = version; - hash = "sha256-58mjwHErEZPkkGBVZznkkMQN5Zo4ZBBiXnhqVp1F81g="; + hash = "sha256-QGtuxKpkx2FScQHj9lH4mhEAo6jE+NAR2sR5/zvHUuA="; }; build-system = [ From a5e3f67d2a7850c51e2e0f49b22f3585d9b39532 Mon Sep 17 00:00:00 2001 From: Stefan Visser Date: Tue, 20 Jan 2026 10:39:13 +0100 Subject: [PATCH 36/74] python3Packages.weasyprint: 66.0 -> 68.0 Release notes: https://github.com/Kozea/WeasyPrint/releases/tag/v68.0 Changelog: https://github.com/Kozea/WeasyPrint/compare/v66.0...v68.0 (cherry picked from commit c6eda5ca8b0fa9a0254b43fdc8249afb797a80d5) --- .../python-modules/weasyprint/default.nix | 8 ++++++-- .../weasyprint/library-paths.patch | 18 +++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pkgs/development/python-modules/weasyprint/default.nix b/pkgs/development/python-modules/weasyprint/default.nix index 47c6a12e51fb5..74e63ac721029 100644 --- a/pkgs/development/python-modules/weasyprint/default.nix +++ b/pkgs/development/python-modules/weasyprint/default.nix @@ -32,7 +32,7 @@ buildPythonPackage rec { pname = "weasyprint"; - version = "66.0"; + version = "68.0"; pyproject = true; __darwinAllowLocalNetworking = true; @@ -41,7 +41,7 @@ buildPythonPackage rec { owner = "Kozea"; repo = "WeasyPrint"; tag = "v${version}"; - hash = "sha256-wmEDVEbikBpOQ5394IBPWQRjWZOLfMzEGxTtq4tt2Tw="; + hash = "sha256-kAJgSQz1RKrPwzO7I5xHXyXcXYJtvca9izjrAgTy3ek="; }; patches = [ @@ -98,6 +98,10 @@ buildPythonPackage rec { "test_visibility_3" "test_visibility_4" "test_woff_simple" + # AssertionError + "test_2d_transform" + # Reported upstream: https://github.com/Kozea/WeasyPrint/issues/2666 + "test_text_stroke" ]; FONTCONFIG_FILE = "${fontconfig.out}/etc/fonts/fonts.conf"; diff --git a/pkgs/development/python-modules/weasyprint/library-paths.patch b/pkgs/development/python-modules/weasyprint/library-paths.patch index dd2bbfe784e05..6053fbdc1ef0a 100644 --- a/pkgs/development/python-modules/weasyprint/library-paths.patch +++ b/pkgs/development/python-modules/weasyprint/library-paths.patch @@ -1,14 +1,14 @@ diff --git a/weasyprint/text/ffi.py b/weasyprint/text/ffi.py -index b5a9cf2..9380a79 100644 +index f57da3c..c50e41d 100644 --- a/weasyprint/text/ffi.py +++ b/weasyprint/text/ffi.py -@@ -444,25 +444,12 @@ if hasattr(os, 'add_dll_directory') and not hasattr(sys, 'frozen'): # pragma: n +@@ -473,25 +473,12 @@ if hasattr(os, 'add_dll_directory') and not hasattr(sys, 'frozen'): # pragma: n with suppress((OSError, FileNotFoundError)): os.add_dll_directory(dll_directory) -gobject = _dlopen( - ffi, 'libgobject-2.0-0', 'gobject-2.0-0', 'gobject-2.0', -- 'libgobject-2.0.so.0', 'libgobject-2.0.dylib', 'libgobject-2.0-0.dll') +- 'libgobject-2.0.so.0', 'libgobject-2.0.0.dylib', 'libgobject-2.0-0.dll') -pango = _dlopen( - ffi, 'libpango-1.0-0', 'pango-1.0-0', 'pango-1.0', 'libpango-1.0.so.0', - 'libpango-1.0.dylib', 'libpango-1.0-0.dll') @@ -25,12 +25,12 @@ index b5a9cf2..9380a79 100644 -pangoft2 = _dlopen( - ffi, 'libpangoft2-1.0-0', 'pangoft2-1.0-0', 'pangoft2-1.0', - 'libpangoft2-1.0.so.0', 'libpangoft2-1.0.dylib', 'libpangoft2-1.0-0.dll') -+gobject = _dlopen(ffi, "@gobject@") -+pango = _dlopen(ffi, "@pango@") -+harfbuzz = _dlopen(ffi, "@harfbuzz@") -+harfbuzz_subset = _dlopen(ffi, "@harfbuzz_subset@", allow_fail=True) -+fontconfig = _dlopen(ffi, "@fontconfig@") -+pangoft2 = _dlopen(ffi, "@pangoft2@") ++gobject = _dlopen(ffi, '@gobject@') ++pango = _dlopen(ffi, '@pango@') ++harfbuzz = _dlopen(ffi, '@harfbuzz@') ++harfbuzz_subset = _dlopen(ffi, '@harfbuzz_subset@', allow_fail=True) ++fontconfig = _dlopen(ffi, '@fontconfig@') ++pangoft2 = _dlopen(ffi, '@pangoft2@') gobject.g_type_init() From f602fcb9b43688d08fbe56e93da39ebf80ab6412 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Thu, 22 Jan 2026 09:46:45 +0100 Subject: [PATCH 37/74] glibc: 2.40-217 -> 2.40-218, fixes CVE-2025-15281 Fixes #482394 on 25.11. Seems like low-severity, given > There is no known application impact for this CVE, and the > feature is generally non-functional with the two flags. (from https://sourceware.org/bugzilla/show_bug.cgi?id=33814) --- .../libraries/glibc/2.40-master.patch | 180 ++++++++++++++++++ pkgs/development/libraries/glibc/common.nix | 4 +- 2 files changed, 182 insertions(+), 2 deletions(-) diff --git a/pkgs/development/libraries/glibc/2.40-master.patch b/pkgs/development/libraries/glibc/2.40-master.patch index 61b32239b03d0..664c2935d536f 100644 --- a/pkgs/development/libraries/glibc/2.40-master.patch +++ b/pkgs/development/libraries/glibc/2.40-master.patch @@ -57015,3 +57015,183 @@ index f40e6f926c..8d4f8badf3 100644 check_reverse (1, "name: 1.in-addr.arpa\n" "net: 0x00000001\n"); + +commit 9fe8576664d43b87ca19401fb6a975e217e47623 +Author: Adhemerval Zanella +Date: Thu Jan 15 10:32:19 2026 -0300 + + posix: Reset wordexp_t fields with WRDE_REUSE (CVE-2025-15281 / BZ 33814) + + The wordexp fails to properly initialize the input wordexp_t when + WRDE_REUSE is used. The wordexp_t struct is properly freed, but + reuses the old wc_wordc value and updates the we_wordv in the + wrong position. A later wordfree will then call free with an + invalid pointer. + + Checked on x86_64-linux-gnu and i686-linux-gnu. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit 80cc58ea2de214f85b0a1d902a3b668ad2ecb302) + +diff --git a/NEWS b/NEWS +index 595998fc6e..dd7673282a 100644 +--- a/NEWS ++++ b/NEWS +@@ -31,6 +31,8 @@ The following bugs are resolved with this release: + [33234] Use TLS initial-exec model for __libc_tsd_CTYPE_* thread variables + [33361] nss: Group merge does not react to ERANGE during merge + [33601] aarch64: Do not link conform tests with -Wl,-z,force-bti ++ [33814] glob: wordexp with WRDE_REUSE and WRDE_APPEND may return ++ uninitialized memory + + Version 2.40 + +diff --git a/posix/Makefile b/posix/Makefile +index 830278a423..0cd5572297 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -326,6 +326,7 @@ tests := \ + tst-wait4 \ + tst-waitid \ + tst-wordexp-nocmd \ ++ tst-wordexp-reuse \ + tstgetopt \ + # tests + +@@ -454,6 +455,8 @@ generated += \ + tst-rxspencer-no-utf8.mtrace \ + tst-vfork3-mem.out \ + tst-vfork3.mtrace \ ++ tst-wordexp-reuse-mem.out \ ++ tst-wordexp-reuse.mtrace \ + # generated + endif + endif +@@ -489,6 +492,7 @@ tests-special += \ + $(objpfx)tst-pcre-mem.out \ + $(objpfx)tst-rxspencer-no-utf8-mem.out \ + $(objpfx)tst-vfork3-mem.out \ ++ $(objpfx)tst-wordexp-reuse.out \ + # tests-special + endif + endif +@@ -772,3 +776,10 @@ $(objpfx)posix-conf-vars-def.h: $(..)scripts/gen-posix-conf-vars.awk \ + $(make-target-directory) + $(AWK) -f $(filter-out Makefile, $^) > $@.tmp + mv -f $@.tmp $@ ++ ++tst-wordexp-reuse-ENV += MALLOC_TRACE=$(objpfx)tst-wordexp-reuse.mtrace \ ++ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so ++ ++$(objpfx)tst-wordexp-reuse-mem.out: $(objpfx)tst-wordexp-reuse.out ++ $(common-objpfx)malloc/mtrace $(objpfx)tst-wordexp-reuse.mtrace > $@; \ ++ $(evaluate-test) +diff --git a/posix/tst-wordexp-reuse.c b/posix/tst-wordexp-reuse.c +new file mode 100644 +index 0000000000..3926b9f557 +--- /dev/null ++++ b/posix/tst-wordexp-reuse.c +@@ -0,0 +1,89 @@ ++/* Test for wordexp with WRDE_REUSE flag. ++ Copyright (C) 2026 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library 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. ++ ++ The GNU C Library 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 the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ ++ { ++ wordexp_t p = { 0 }; ++ TEST_COMPARE (wordexp ("one", &p, 0), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[0], "one"); ++ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[0], "two"); ++ wordfree (&p); ++ } ++ ++ { ++ wordexp_t p = { .we_offs = 2 }; ++ TEST_COMPARE (wordexp ("one", &p, 0), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[0], "one"); ++ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_DOOFFS), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two"); ++ wordfree (&p); ++ } ++ ++ { ++ wordexp_t p = { 0 }; ++ TEST_COMPARE (wordexp ("one", &p, 0), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[0], "one"); ++ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_APPEND), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[0], "two"); ++ wordfree (&p); ++ } ++ ++ { ++ wordexp_t p = { .we_offs = 2 }; ++ TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one"); ++ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE ++ | WRDE_DOOFFS), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two"); ++ wordfree (&p); ++ } ++ ++ { ++ wordexp_t p = { .we_offs = 2 }; ++ TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one"); ++ TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE ++ | WRDE_DOOFFS | WRDE_APPEND), 0); ++ TEST_COMPARE (p.we_wordc, 1); ++ TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two"); ++ wordfree (&p); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/posix/wordexp.c b/posix/wordexp.c +index a7362ef31b..4cd2364519 100644 +--- a/posix/wordexp.c ++++ b/posix/wordexp.c +@@ -2216,7 +2216,9 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) + { + /* Minimal implementation of WRDE_REUSE for now */ + wordfree (pwordexp); ++ old_word.we_wordc = 0; + old_word.we_wordv = NULL; ++ pwordexp->we_wordc = 0; + } + + if ((flags & WRDE_APPEND) == 0) diff --git a/pkgs/development/libraries/glibc/common.nix b/pkgs/development/libraries/glibc/common.nix index ea638e464c943..858806671d3c3 100644 --- a/pkgs/development/libraries/glibc/common.nix +++ b/pkgs/development/libraries/glibc/common.nix @@ -50,7 +50,7 @@ let version = "2.40"; - patchSuffix = "-217"; + patchSuffix = "-218"; sha256 = "sha256-GaiQF16SY9dI9ieZPeb0sa+c0h4D8IDkv7Oh+sECBaI="; in @@ -68,7 +68,7 @@ stdenv.mkDerivation ( /* No tarballs for stable upstream branch, only https://sourceware.org/git/glibc.git and using git would complicate bootstrapping. $ git fetch --all -p && git checkout origin/release/2.40/master && git describe - glibc-2.40-217-g329c775788 + glibc-2.40-218-g9fe8576664 $ git show --minimal --reverse glibc-2.40.. ':!ADVISORIES' > 2.40-master.patch To compare the archive contents zdiff can be used. From 86f9b236caf3092301264e8852096c67448230d3 Mon Sep 17 00:00:00 2001 From: kuflierl <41301536+kuflierl@users.noreply.github.com> Date: Thu, 22 Jan 2026 09:47:55 +0100 Subject: [PATCH 38/74] libheif: finalAttrs (cherry picked from commit 5d4fe5478b0529a90da1aaa963ff3c93699c1bf7) --- pkgs/by-name/li/libheif/package.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/li/libheif/package.nix b/pkgs/by-name/li/libheif/package.nix index c69af0dda7cd9..cf7295cbbd73b 100644 --- a/pkgs/by-name/li/libheif/package.nix +++ b/pkgs/by-name/li/libheif/package.nix @@ -22,7 +22,7 @@ vips, }: -stdenv.mkDerivation rec { +stdenv.mkDerivation (finalAttrs: { pname = "libheif"; version = "1.20.2"; @@ -37,7 +37,7 @@ stdenv.mkDerivation rec { src = fetchFromGitHub { owner = "strukturag"; repo = "libheif"; - rev = "v${version}"; + rev = "v${finalAttrs.version}"; hash = "sha256-PVfdX3/Oe3DXpYU5WMnCSi2p9X4fPszq2X3uuyh8RVU="; }; @@ -90,4 +90,4 @@ stdenv.mkDerivation rec { platforms = lib.platforms.unix; maintainers = with lib.maintainers; [ kuflierl ]; }; -} +}) From 1778575fa36df02ba5530f133bc07f3cd3ec6e36 Mon Sep 17 00:00:00 2001 From: kuflierl <41301536+kuflierl@users.noreply.github.com> Date: Thu, 22 Jan 2026 09:48:42 +0100 Subject: [PATCH 39/74] libheif: backport fix for CVE-2025-68431 (cherry picked from commit c12294290dad2c1b56f599292874c24da0701d6e) --- pkgs/by-name/li/libheif/package.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkgs/by-name/li/libheif/package.nix b/pkgs/by-name/li/libheif/package.nix index cf7295cbbd73b..f3c4804c1bbd7 100644 --- a/pkgs/by-name/li/libheif/package.nix +++ b/pkgs/by-name/li/libheif/package.nix @@ -2,6 +2,7 @@ lib, stdenv, fetchFromGitHub, + fetchpatch, cmake, pkg-config, dav1d, @@ -41,6 +42,15 @@ stdenv.mkDerivation (finalAttrs: { hash = "sha256-PVfdX3/Oe3DXpYU5WMnCSi2p9X4fPszq2X3uuyh8RVU="; }; + patches = [ + # CVE-2025-68431 (https://github.com/strukturag/libheif/security/advisories/GHSA-j87x-4gmq-cqfq) + (fetchpatch { + name = "001-fix-wrong-copy-width-in-overlay-images.patch"; + url = "https://github.com/strukturag/libheif/commit/b8c12a7b70f46c9516711a988483bed377b78d46.patch"; + hash = "sha256-PzGfcbdWAPdfExbSrPQwpk4v++TcNCXOhtwhgLGM13c="; + }) + ]; + nativeBuildInputs = [ pkg-config cmake From a08315ecb85f4bc13991de298fa238a33f1ed1a1 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Thu, 25 Dec 2025 16:13:57 +0000 Subject: [PATCH 40/74] libcdio: 2.2.0 -> 2.3.0 (cherry picked from commit 579d446b2a44f719e4196573365cffd4edfa903d) --- pkgs/by-name/li/libcdio/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/li/libcdio/package.nix b/pkgs/by-name/li/libcdio/package.nix index 483868b4ea99c..216b6c889f15c 100644 --- a/pkgs/by-name/li/libcdio/package.nix +++ b/pkgs/by-name/li/libcdio/package.nix @@ -16,13 +16,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "libcdio"; - version = "2.2.0"; + version = "2.3.0"; src = fetchFromGitHub { owner = "libcdio"; repo = "libcdio"; tag = finalAttrs.version; - hash = "sha256-izjZk2kz9PkLm9+INUdl1e7jMz3nUsQKdplKI9Io+CM="; + hash = "sha256-NZj6sMIhBORh2ZBs/WGI4BYri1REog4ovUug1t5p8Y8="; }; env = lib.optionalAttrs stdenv.hostPlatform.is32bit { From 363d1e7debd685b5862af35667a9b190e7484df8 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Sat, 17 Jan 2026 16:38:36 +0100 Subject: [PATCH 41/74] python3Packages.pyasn1: 0.6.1 -> 0.6.2 Fixes CVE-2026-23490. Fixes #481007. Changes: https://github.com/pyasn1/pyasn1/releases/tag/v0.6.2 (cherry picked from commit 1b8c827a5d930380d838f4bc873181dfc110d8d1) --- pkgs/development/python-modules/pyasn1/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pyasn1/default.nix b/pkgs/development/python-modules/pyasn1/default.nix index 727e107b15a5b..93c89ff6be20e 100644 --- a/pkgs/development/python-modules/pyasn1/default.nix +++ b/pkgs/development/python-modules/pyasn1/default.nix @@ -8,14 +8,14 @@ buildPythonPackage rec { pname = "pyasn1"; - version = "0.6.1"; + version = "0.6.2"; pyproject = true; disabled = pythonOlder "3.7"; src = fetchPypi { inherit pname version; - hash = "sha256-b1gNK92ENlOAgwrPRVUPJRFGn2c8tKWuOFejFwEosDQ="; + hash = "sha256-m1mislun5PgZfbdobAn7M+ZYuYM5+tuCbpUSYpAXgzs="; }; nativeBuildInputs = [ setuptools ]; From e614b136159320ea60150ed7ee57b1641b735e5d Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Wed, 21 Jan 2026 19:13:10 +0100 Subject: [PATCH 42/74] tcl: fix static builds The existing handling of static builds in this expression was insufficient for x86_64, where we can't even build shared libraries in a static environment. Avoid building such libraries, like we do for other packages. (cherry picked from commit 9b6e99f463039d115a29d4415c203bd83c5726a7) --- pkgs/development/interpreters/tcl/generic.nix | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkgs/development/interpreters/tcl/generic.nix b/pkgs/development/interpreters/tcl/generic.nix index 7ecc8250b9c24..9f2e781124e54 100644 --- a/pkgs/development/interpreters/tcl/generic.nix +++ b/pkgs/development/interpreters/tcl/generic.nix @@ -90,6 +90,18 @@ let ] ++ lib.optional stdenv.hostPlatform.is64bit "--enable-64bit"; + buildFlags = lib.optionals stdenv.hostPlatform.isStatic [ + # Don't use the default Make target for static, + # since it builds shared libraries for bundled packages. + "binaries" + "libraries" + "doc" + ]; + + makeFlags = lib.optionals stdenv.hostPlatform.isStatic [ + "INSTALL_PACKAGE_TARGETS=" + ]; + enableParallelBuilding = true; postInstall = From 53d609ef4bc7ab10417bf241f678b7ed8e9394d7 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Fri, 23 Jan 2026 21:21:48 +0000 Subject: [PATCH 43/74] javaPackages.compiler.openjdk21: 21.0.9+10 -> 21.0.10+7 (cherry picked from commit 23c804baa1f942ec0122466b395471d163e327d7) --- pkgs/development/compilers/openjdk/21/source.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/compilers/openjdk/21/source.json b/pkgs/development/compilers/openjdk/21/source.json index a43dec0d90665..5edd47f2b5762 100644 --- a/pkgs/development/compilers/openjdk/21/source.json +++ b/pkgs/development/compilers/openjdk/21/source.json @@ -1,6 +1,6 @@ { - "hash": "sha256-VYTitbgKgd9co9LXVnneaaKjMwAXFmscYp9McJV01Jg=", + "hash": "sha256-xaaYt63uvoB5zfwUxHjNR3HiBPzFTNc4xyQfuTC/7VU=", "owner": "openjdk", "repo": "jdk21u", - "rev": "refs/tags/jdk-21.0.9+10" + "rev": "refs/tags/jdk-21.0.10+7" } From d50d56f4969129f4f028704c1cab957b2a6b1552 Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Thu, 22 Jan 2026 00:39:49 +0100 Subject: [PATCH 44/74] inetutils: 2.6 -> 2.7, apply patches for CVE-2026-24061 https://lists.gnu.org/archive/html/bug-inetutils/2026-01/msg00004.html 2.7 release also seems to include another security fix: > syslogd: Fix a stack-based buffer overflow (CWE-121). Changes: https://codeberg.org/inetutils/inetutils/src/tag/v2.7/NEWS.md (cherry picked from commit b28f663543e73d26b8ba87685fc080885c97208f) --- pkgs/by-name/in/inetutils/package.nix | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/in/inetutils/package.nix b/pkgs/by-name/in/inetutils/package.nix index 05cdabb47d26c..ebbcb629359a3 100644 --- a/pkgs/by-name/in/inetutils/package.nix +++ b/pkgs/by-name/in/inetutils/package.nix @@ -2,6 +2,7 @@ stdenv, lib, fetchurl, + fetchpatch, ncurses, perl, help2man, @@ -12,11 +13,11 @@ stdenv.mkDerivation rec { pname = "inetutils"; - version = "2.6"; + version = "2.7"; src = fetchurl { - url = "mirror://gnu/${pname}/${pname}-${version}.tar.xz"; - hash = "sha256-aL7b/q9z99hr4qfZm8+9QJPYKfUncIk5Ga4XTAsjV8o="; + url = "mirror://gnu/${pname}/${pname}-${version}.tar.gz"; + hash = "sha256-oVa+HN48XA/+/CYhgNk2mmBIQIeQeqVUxieH0vQOwIY="; }; outputs = [ @@ -29,6 +30,17 @@ stdenv.mkDerivation rec { ./inetutils-1_9-PATH_PROCNET_DEV.patch ./tests-libls.sh.patch + + (fetchpatch { + name = "CVE-2026-24061_1.patch"; + url = "https://codeberg.org/inetutils/inetutils/commit/fd702c02497b2f398e739e3119bed0b23dd7aa7b.patch"; + hash = "sha256-d/FdQyLD0gYr+erFqKDr8Okf04DFXknFaN03ls2aonQ="; + }) + (fetchpatch { + name = "CVE-2026-24061_2.patch"; + url = "https://codeberg.org/inetutils/inetutils/commit/ccba9f748aa8d50a38d7748e2e60362edd6a32cc.patch"; + hash = "sha256-ws+ed5vb7kVMHEbqK7yj6FUT355pTv2RZEYuXs5M7Io="; + }) ]; strictDeps = true; From 534ba168e7e5553c31e8a4c3c39c4101f274340d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 00:16:07 +0100 Subject: [PATCH 45/74] libxml2_13: 2.13.8 -> 2.13.9 (cherry picked from commit ba124b47f5962a6e6d27e1beba8d33f5c175ac07) --- .../libraries/libxml2/CVE-2025-6021.patch | 40 ------- .../libraries/libxml2/CVE-2025-6170.patch | 112 ------------------ .../development/libraries/libxml2/default.nix | 22 +--- 3 files changed, 2 insertions(+), 172 deletions(-) delete mode 100644 pkgs/development/libraries/libxml2/CVE-2025-6021.patch delete mode 100644 pkgs/development/libraries/libxml2/CVE-2025-6170.patch diff --git a/pkgs/development/libraries/libxml2/CVE-2025-6021.patch b/pkgs/development/libraries/libxml2/CVE-2025-6021.patch deleted file mode 100644 index 7d20a17c70381..0000000000000 --- a/pkgs/development/libraries/libxml2/CVE-2025-6021.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/tree.c b/tree.c -index f097cf87..4d966ec9 100644 ---- a/tree.c -+++ b/tree.c -@@ -47,6 +47,10 @@ - #include "private/error.h" - #include "private/tree.h" - -+#ifndef SIZE_MAX -+ #define SIZE_MAX ((size_t) -1) -+#endif -+ - int __xmlRegisterCallbacks = 0; - - /************************************************************************ -@@ -167,10 +168,10 @@ xmlGetParameterEntityFromDtd(const xmlDtd *dtd, const xmlChar *name) { - xmlChar * - xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, - xmlChar *memory, int len) { -- int lenn, lenp; -+ size_t lenn, lenp; - xmlChar *ret; - -- if (ncname == NULL) return(NULL); -+ if ((ncname == NULL) || (len < 0)) return(NULL); - if (prefix == NULL) return((xmlChar *) ncname); - - #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -@@ -181,8 +182,10 @@ xmlBuildQName(const xmlChar *ncname, const xmlChar *prefix, - - lenn = strlen((char *) ncname); - lenp = strlen((char *) prefix); -+ if (lenn >= SIZE_MAX - lenp - 1) -+ return(NULL); - -- if ((memory == NULL) || (len < lenn + lenp + 2)) { -+ if ((memory == NULL) || ((size_t) len < lenn + lenp + 2)) { - ret = (xmlChar *) xmlMallocAtomic(lenn + lenp + 2); - if (ret == NULL) - return(NULL); diff --git a/pkgs/development/libraries/libxml2/CVE-2025-6170.patch b/pkgs/development/libraries/libxml2/CVE-2025-6170.patch deleted file mode 100644 index b66f24e305e0d..0000000000000 --- a/pkgs/development/libraries/libxml2/CVE-2025-6170.patch +++ /dev/null @@ -1,112 +0,0 @@ -diff --git a/result/scripts/long_command b/result/scripts/long_command -new file mode 100644 -index 000000000..e6f00708b ---- /dev/null -+++ b/result/scripts/long_command -@@ -0,0 +1,8 @@ -+/ > b > b > Object is a Node Set : -+Set contains 1 nodes: -+1 ELEMENT a:c -+b > Unknown command This_is_a_really_long_command_string_designed_to_test_the_limits_of_the_memory_that_stores_the_comm -+b > b > Unknown command ess_currents_of_time_and_existence -+b > -+Navigating_the_labyrinthine_corridors_of_human_cognition_one_often_encounters_the_perplexing_paradox_that_the_more_we_delve_into_the_intricate_dance_of_neural_pathways_and_synaptic_firings_the_further_we_seem_to_stray_from_a_truly_holistic_understanding_of_consciousness_a_phenomenon_that_remains_as_elusive_as_a_moonbeam_caught_in_a_spiderweb_yet_undeniably_shapes_every_fleeting_thought_every_prof -+b > -\ No newline at end of file -diff --git a/debugXML.c b/debugXML.c -index ed56b0f8..aeeea3c0 100644 ---- a/debugXML.c -+++ b/debugXML.c -@@ -2780,6 +2780,10 @@ xmlShellPwd(xmlShellCtxtPtr ctxt ATTRIBUTE_UNUSED, char *buffer, - return (0); - } - -+#define MAX_PROMPT_SIZE 500 -+#define MAX_ARG_SIZE 400 -+#define MAX_COMMAND_SIZE 100 -+ - /** - * xmlShell: - * @doc: the initial document -@@ -2795,10 +2795,10 @@ void - xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input, - FILE * output) - { -- char prompt[500] = "/ > "; -+ char prompt[MAX_PROMPT_SIZE] = "/ > "; - char *cmdline = NULL, *cur; -- char command[100]; -- char arg[400]; -+ char command[MAX_COMMAND_SIZE]; -+ char arg[MAX_ARG_SIZE]; - int i; - xmlShellCtxtPtr ctxt; - xmlXPathObjectPtr list; -@@ -2856,7 +2856,8 @@ xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input, - cur++; - i = 0; - while ((*cur != ' ') && (*cur != '\t') && -- (*cur != '\n') && (*cur != '\r')) { -+ (*cur != '\n') && (*cur != '\r') && -+ (i < (MAX_COMMAND_SIZE - 1))) { - if (*cur == 0) - break; - command[i++] = *cur++; -@@ -2871,7 +2872,7 @@ xmlShell(xmlDocPtr doc, const char *filename, xmlShellReadlineFunc input, - while ((*cur == ' ') || (*cur == '\t')) - cur++; - i = 0; -- while ((*cur != '\n') && (*cur != '\r') && (*cur != 0)) { -+ while ((*cur != '\n') && (*cur != '\r') && (*cur != 0) && (i < (MAX_ARG_SIZE-1))) { - if (*cur == 0) - break; - arg[i++] = *cur++; -diff --git a/xmllint.c b/xmllint.c -index c6273477..3d90272c 100644 ---- a/xmllint.c -+++ b/xmllint.c -@@ -724,6 +724,9 @@ xmlHTMLValidityWarning(void *ctx, const char *msg, ...) - ************************************************************************/ - #ifdef LIBXML_DEBUG_ENABLED - #ifdef LIBXML_XPATH_ENABLED -+ -+#define MAX_PROMPT_SIZE 500 -+ - /** - * xmlShellReadline: - * @prompt: the prompt value -@@ -754,9 +754,9 @@ xmlShellReadline(char *prompt) { - if (prompt != NULL) - fprintf(stdout, "%s", prompt); - fflush(stdout); -- if (!fgets(line_read, 500, stdin)) -+ if (!fgets(line_read, MAX_PROMPT_SIZE, stdin)) - return(NULL); -- line_read[500] = 0; -+ line_read[MAX_PROMPT_SIZE] = 0; - len = strlen(line_read); - ret = (char *) malloc(len + 1); - if (ret != NULL) { --- -diff --git a/test/scripts/long_command.script b/test/scripts/long_command.script -new file mode 100644 -index 000000000..00f6df09f ---- /dev/null -+++ b/test/scripts/long_command.script -@@ -0,0 +1,6 @@ -+cd a/b -+set -+xpath //*[namespace-uri()="foo"] -+This_is_a_really_long_command_string_designed_to_test_the_limits_of_the_memory_that_stores_the_command_please_dont_crash foo -+set Navigating_the_labyrinthine_corridors_of_human_cognition_one_often_encounters_the_perplexing_paradox_that_the_more_we_delve_into_the_intricate_dance_of_neural_pathways_and_synaptic_firings_the_further_we_seem_to_stray_from_a_truly_holistic_understanding_of_consciousness_a_phenomenon_that_remains_as_elusive_as_a_moonbeam_caught_in_a_spiderweb_yet_undeniably_shapes_every_fleeting_thought_every_profound_emotion_and_every_grand_aspiration_that_propels_our_species_ever_onward_through_the_relentless_currents_of_time_and_existence -+save - -diff --git a/test/scripts/long_command.xml b/test/scripts/long_command.xml -new file mode 100644 -index 000000000..1ba44016e ---- /dev/null -+++ b/test/scripts/long_command.xml -@@ -0,0 +1 @@ -+ --- -GitLab - diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index 41d2b1f953f0d..c459aafa171f7 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -8,33 +8,15 @@ let packages = { libxml2_13 = callPackage ./common.nix { - version = "2.13.8"; + version = "2.13.9"; src = fetchFromGitLab { domain = "gitlab.gnome.org"; owner = "GNOME"; repo = "libxml2"; tag = "v${packages.libxml2_13.version}"; - hash = "sha256-acemyYs1yRSTSLH7YCGxnQzrEDm8YPTK4HtisC36LsY="; + hash = "sha256-1qrgoMu702MglErNH9N2eCWFqxQnNHepR13m53GJb58="; }; extraPatches = [ - # same as upstream patch but fixed conflict and added required import: - # https://gitlab.gnome.org/GNOME/libxml2/-/commit/acbbeef9f5dcdcc901c5f3fa14d583ef8cfd22f0.diff - ./CVE-2025-6021.patch - (fetchpatch { - name = "CVE-2025-49794-49796.patch"; - url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/f7ebc65f05bffded58d1e1b2138eb124c2e44f21.patch"; - hash = "sha256-p5Vc/lkakHKsxuFNnCQtFczjqFJBeLnCwIwv2GnrQco="; - }) - (fetchpatch { - name = "CVE-2025-49795.patch"; - url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/c24909ba2601848825b49a60f988222da3019667.patch"; - hash = "sha256-vICVSb+X89TTE4QY92/v/6fRk77Hy9vzEWWsADHqMlk="; - excludes = [ "runtest.c" ]; # tests were rewritten in C and are on schematron for 2.13.x, meaning this does not apply - }) - # same as upstream, fixed conflicts - # https://gitlab.gnome.org/GNOME/libxml2/-/commit/c340e419505cf4bf1d9ed7019a87cc00ec200434 - ./CVE-2025-6170.patch - # Unmerged ABI-breaking patch required to fix the following security issues: # - https://gitlab.gnome.org/GNOME/libxslt/-/issues/139 # - https://gitlab.gnome.org/GNOME/libxslt/-/issues/140 From 8a2deccbc8ec26115483cc1123e292e3433eec9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 01:53:08 +0100 Subject: [PATCH 46/74] libxml2: fix CVE-2026-0990 (cherry picked from commit 11c38aaf923b3a15352a01196a25c95f8304379f) --- pkgs/development/libraries/libxml2/default.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index c459aafa171f7..7d685b1d9b74a 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -40,6 +40,13 @@ let tag = "v${packages.libxml2.version}"; hash = "sha256-FUfYMq5xT2i88JdIw9OtSofraUL3yjsyOVund+mfJKQ="; }; + extraPatches = [ + (fetchpatch { + name = "CVE-2026-0990.patch"; + url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/1961208e958ca22f80a0b4e4c9d71cfa050aa982.patch"; + hash = "sha256-Df2WLCTsP/ItSzgnVkNjRpLKkBP4xUOXEfCUV9o/Yks="; + }) + ]; extraMeta = { maintainers = with lib.maintainers; [ jtojnar From 531bb4b46dd0c40ed9ab1e27eeaf64670f47e4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 01:53:56 +0100 Subject: [PATCH 47/74] libxml2: fix CVE-2026-0992 (cherry picked from commit 071d4031249ac4f13e6446a34a588ce5b519a9cd) --- pkgs/development/libraries/libxml2/default.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index 7d685b1d9b74a..c2a0b8bb19dd0 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -46,6 +46,11 @@ let url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/1961208e958ca22f80a0b4e4c9d71cfa050aa982.patch"; hash = "sha256-Df2WLCTsP/ItSzgnVkNjRpLKkBP4xUOXEfCUV9o/Yks="; }) + (fetchpatch { + name = "CVE-2026-0992.patch"; + url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/f75abfcaa419a740a3191e56c60400f3ff18988d.patch"; + hash = "sha256-an/PpmsncNwim/pe/zsDx9P6jbuCqvr4QSgTokyDvzw="; + }) ]; extraMeta = { maintainers = with lib.maintainers; [ From edfa05a61938b8ed4c2841e9b522d7e7af06bc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 01:55:09 +0100 Subject: [PATCH 48/74] libxml2: fix CVE-2026-0989 (cherry picked from commit 7cc14c925e5f4151e6b94582594b8036473a3fa0) --- pkgs/development/libraries/libxml2/default.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index c2a0b8bb19dd0..77e3659f3df36 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -51,6 +51,11 @@ let url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/f75abfcaa419a740a3191e56c60400f3ff18988d.patch"; hash = "sha256-an/PpmsncNwim/pe/zsDx9P6jbuCqvr4QSgTokyDvzw="; }) + (fetchpatch { + name = "CVE-2026-0989.patch"; + url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/19549c61590c1873468c53e0026a2fbffae428ef.patch"; + hash = "sha256-YOF5cYdoFQuvsbcAezamglh/RKv8Zq6rm1nfo2/CLzo="; + }) ]; extraMeta = { maintainers = with lib.maintainers; [ From c05a51d8fe8740fefdd04ca6e1fd0c3274ee671a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 01:56:36 +0100 Subject: [PATCH 49/74] libxml2_13: fix CVE-2026-0990 (cherry picked from commit 41afd44087b55ecebe7608a0195f8f2352281aed) --- pkgs/development/libraries/libxml2/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index 77e3659f3df36..11ea63fddb01c 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -23,6 +23,12 @@ let # See also https://gitlab.gnome.org/GNOME/libxml2/-/issues/906 # Source: https://github.com/chromium/chromium/blob/4fb4ae8ce3daa399c3d8ca67f2dfb9deffcc7007/third_party/libxml/chromium/xml-attr-extra.patch ./xml-attr-extra.patch + + (fetchpatch { + name = "CVE-2026-0990.patch"; + url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/1961208e958ca22f80a0b4e4c9d71cfa050aa982.patch"; + hash = "sha256-Df2WLCTsP/ItSzgnVkNjRpLKkBP4xUOXEfCUV9o/Yks="; + }) ]; freezeUpdateScript = true; extraMeta = { From 32006857ee810dc6bec9b1e561b3e831360dde46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 02:16:29 +0100 Subject: [PATCH 50/74] libxml2_13: fix CVE-2026-0992 (cherry picked from commit ebb4591d1b1f605487ab28d15bd18e92b9b74f76) --- .../libxml2/2.13-CVE-2026-0992.patch | 49 +++++++++++++++++++ .../development/libraries/libxml2/default.nix | 4 ++ 2 files changed, 53 insertions(+) create mode 100644 pkgs/development/libraries/libxml2/2.13-CVE-2026-0992.patch diff --git a/pkgs/development/libraries/libxml2/2.13-CVE-2026-0992.patch b/pkgs/development/libraries/libxml2/2.13-CVE-2026-0992.patch new file mode 100644 index 0000000000000..95dde2b5017f6 --- /dev/null +++ b/pkgs/development/libraries/libxml2/2.13-CVE-2026-0992.patch @@ -0,0 +1,49 @@ +From f75abfcaa419a740a3191e56c60400f3ff18988d Mon Sep 17 00:00:00 2001 +From: Daniel Garcia Moreno +Date: Fri, 19 Dec 2025 11:02:18 +0100 +Subject: [PATCH] catalog: Ignore repeated nextCatalog entries + +This patch makes the catalog parsing to ignore repeated entries of +nextCatalog with the same value. + +Fix https://gitlab.gnome.org/GNOME/libxml2/-/issues/1019 +--- + catalog.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +diff --git a/catalog.c b/catalog.c +index 46b877e62..fa6d77ca1 100644 +--- a/catalog.c ++++ b/catalog.c +@@ -1223,9 +1223,27 @@ xmlParseXMLCatalogNode(xmlNodePtr cur, xmlCatalogPrefer prefer, + BAD_CAST "delegateURI", BAD_CAST "uriStartString", + BAD_CAST "catalog", prefer, cgroup); + } else if (xmlStrEqual(cur->name, BAD_CAST "nextCatalog")) { ++ xmlCatalogEntryPtr prev = parent->children; ++ + entry = xmlParseXMLCatalogOneNode(cur, XML_CATA_NEXT_CATALOG, + BAD_CAST "nextCatalog", NULL, + BAD_CAST "catalog", prefer, cgroup); ++ /* Avoid duplication of nextCatalog */ ++ while (prev != NULL) { ++ if ((prev->type == XML_CATA_NEXT_CATALOG) && ++ (xmlStrEqual (prev->URL, entry->URL)) && ++ (xmlStrEqual (prev->value, entry->value)) && ++ (prev->prefer == entry->prefer) && ++ (prev->group == entry->group)) { ++ if (xmlDebugCatalogs) ++ fprintf(stderr, ++ "Ignoring repeated nextCatalog %s\n", entry->URL); ++ xmlFreeCatalogEntry(entry, NULL); ++ entry = NULL; ++ break; ++ } ++ prev = prev->next; ++ } + } + if (entry != NULL) { + if (parent != NULL) { +-- +GitLab + + diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index 11ea63fddb01c..a997ece6f0a69 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -29,6 +29,10 @@ let url = "https://gitlab.gnome.org/GNOME/libxml2/-/commit/1961208e958ca22f80a0b4e4c9d71cfa050aa982.patch"; hash = "sha256-Df2WLCTsP/ItSzgnVkNjRpLKkBP4xUOXEfCUV9o/Yks="; }) + + # Based on https://gitlab.gnome.org/GNOME/libxml2/-/commit/f75abfcaa419a740a3191e56c60400f3ff18988d + # Vendored, because there is no xmlCatalogSetDebug in 2.13.9, use fprintf instead + ./2.13-CVE-2026-0992.patch ]; freezeUpdateScript = true; extraMeta = { From 056cdbaa57a356ed4a577bb2e80224c3797a5d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gutyina=20Gerg=C5=91?= Date: Sat, 17 Jan 2026 02:34:41 +0100 Subject: [PATCH 51/74] libxml2_13: fix CVE-2026-0989 (cherry picked from commit 607ad26f4ecf161efa50383e256f352aa7e221a6) --- .../libxml2/2.13-CVE-2026-0989.patch | 237 ++++++++++++++++++ .../development/libraries/libxml2/default.nix | 4 + 2 files changed, 241 insertions(+) create mode 100644 pkgs/development/libraries/libxml2/2.13-CVE-2026-0989.patch diff --git a/pkgs/development/libraries/libxml2/2.13-CVE-2026-0989.patch b/pkgs/development/libraries/libxml2/2.13-CVE-2026-0989.patch new file mode 100644 index 0000000000000..d3154c40d4614 --- /dev/null +++ b/pkgs/development/libraries/libxml2/2.13-CVE-2026-0989.patch @@ -0,0 +1,237 @@ +diff --git a/include/libxml/relaxng.h b/include/libxml/relaxng.h +index 079b7f12..78985e5e 100644 +--- a/include/libxml/relaxng.h ++++ b/include/libxml/relaxng.h +@@ -138,6 +138,10 @@ XMLPUBFUN int + xmlRelaxParserSetFlag (xmlRelaxNGParserCtxtPtr ctxt, + int flag); + ++XMLPUBFUN int ++ xmlRelaxParserSetIncLImit (xmlRelaxNGParserCtxt *ctxt, ++ int limit); ++ + XMLPUBFUN void + xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxtPtr ctxt); + XMLPUBFUN void +diff --git a/relaxng.c b/relaxng.c +index 24c3e510..eb0f2b36 100644 +--- a/relaxng.c ++++ b/relaxng.c +@@ -18,6 +18,8 @@ + + #ifdef LIBXML_SCHEMAS_ENABLED + ++#include ++#include + #include + #include + #include +@@ -44,6 +46,12 @@ + static const xmlChar *xmlRelaxNGNs = (const xmlChar *) + "http://relaxng.org/ns/structure/1.0"; + ++/* ++ * Default include limit, this can be override with RNG_INCLUDE_LIMIT ++ * env variable ++ */ ++static const int _xmlRelaxNGIncludeLimit = 1000; ++ + #define IS_RELAXNG(node, typ) \ + ((node != NULL) && (node->ns != NULL) && \ + (node->type == XML_ELEMENT_NODE) && \ +@@ -220,6 +228,7 @@ struct _xmlRelaxNGParserCtxt { + int incNr; /* Depth of the include parsing stack */ + int incMax; /* Max depth of the parsing stack */ + xmlRelaxNGIncludePtr *incTab; /* array of incs */ ++ int incLimit; /* Include limit, to avoid stack-overflow on parse */ + + int idref; /* requires idref checking */ + +@@ -1403,6 +1412,23 @@ xmlRelaxParserSetFlag(xmlRelaxNGParserCtxtPtr ctxt, int flags) + return(0); + } + ++/** ++ * Semi private function used to set the include recursion limit to a ++ * parser context. Set to 0 to use the default value. ++ * ++ * @param ctxt a RelaxNG parser context ++ * @param limit the new include depth limit ++ * @returns 0 if success and -1 in case of error ++ */ ++int ++xmlRelaxParserSetIncLImit(xmlRelaxNGParserCtxt *ctxt, int limit) ++{ ++ if (ctxt == NULL) return(-1); ++ if (limit < 0) return(-1); ++ ctxt->incLimit = limit; ++ return(0); ++} ++ + /************************************************************************ + * * + * Document functions * +@@ -1454,7 +1480,7 @@ xmlRelaxReadMemory(xmlRelaxNGParserCtxtPtr ctxt, const char *buf, int size) { + * + * Pushes a new include on top of the include stack + * +- * Returns 0 in case of error, the index in the stack otherwise ++ * Returns -1 in case of error, the index in the stack otherwise + */ + static int + xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, +@@ -1468,9 +1494,15 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, + sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlRngPErrMemory(ctxt); +- return (0); ++ return (-1); + } + } ++ if (ctxt->incNr >= ctxt->incLimit) { ++ xmlRngPErr(ctxt, (xmlNodePtr)value->doc, XML_RNGP_PARSE_ERROR, ++ "xmlRelaxNG: inclusion recursion limit reached\n", NULL, NULL); ++ return(-1); ++ } ++ + if (ctxt->incNr >= ctxt->incMax) { + ctxt->incMax *= 2; + ctxt->incTab = +@@ -1479,7 +1511,7 @@ xmlRelaxNGIncludePush(xmlRelaxNGParserCtxtPtr ctxt, + sizeof(ctxt->incTab[0])); + if (ctxt->incTab == NULL) { + xmlRngPErrMemory(ctxt); +- return (0); ++ return (-1); + } + } + ctxt->incTab[ctxt->incNr] = value; +@@ -1649,7 +1681,9 @@ xmlRelaxNGLoadInclude(xmlRelaxNGParserCtxtPtr ctxt, const xmlChar * URL, + /* + * push it on the stack + */ +- xmlRelaxNGIncludePush(ctxt, ret); ++ if (xmlRelaxNGIncludePush(ctxt, ret) < 0) { ++ return (NULL); ++ } + + /* + * Some preprocessing of the document content, this include recursing +@@ -7373,11 +7407,32 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt) + xmlDocPtr doc; + xmlNodePtr root; + ++ const char *include_limit_env = getenv("RNG_INCLUDE_LIMIT"); ++ + xmlRelaxNGInitTypes(); + + if (ctxt == NULL) + return (NULL); + ++ if (ctxt->incLimit == 0) { ++ ctxt->incLimit = _xmlRelaxNGIncludeLimit; ++ if (include_limit_env != NULL) { ++ char *strEnd; ++ unsigned long val = 0; ++ errno = 0; ++ val = strtoul(include_limit_env, &strEnd, 10); ++ if (errno != 0 || *strEnd != 0 || val > INT_MAX) { ++ xmlRngPErr(ctxt, NULL, XML_RNGP_PARSE_ERROR, ++ "xmlRelaxNGParse: invalid RNG_INCLUDE_LIMIT %s\n", ++ (const xmlChar*)include_limit_env, ++ NULL); ++ return(NULL); ++ } ++ if (val) ++ ctxt->incLimit = val; ++ } ++ } ++ + /* + * First step is to parse the input document into an DOM/Infoset + */ +diff --git a/runtest.c b/runtest.c +index 26681a3c..a41897dd 100644 +--- a/runtest.c ++++ b/runtest.c +@@ -3529,6 +3529,70 @@ rngTest(const char *filename, + return(ret); + } + ++/** ++ * Parse an RNG schemas with a custom RNG_INCLUDE_LIMIT ++ * ++ * @param filename the schemas file ++ * @param result the file with expected result ++ * @param err the file with error messages ++ * @returns 0 in case of success, an error code otherwise ++ */ ++static int ++rngIncludeTest(const char *filename, ++ const char *resul ATTRIBUTE_UNUSED, ++ const char *errr ATTRIBUTE_UNUSED, ++ int options ATTRIBUTE_UNUSED) { ++ xmlRelaxNGParserCtxtPtr ctxt; ++ xmlRelaxNGPtr schemas; ++ int ret = 0; ++ ++ /* first compile the schemas if possible */ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ ++ /* Should work */ ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas == NULL) { ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n", ++ filename); ++ ret = -1; ++ goto done; ++ } ++ xmlRelaxNGFree(schemas); ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ /* Should fail */ ++ xmlRelaxParserSetIncLImit(ctxt, 2); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas != NULL) { ++ ret = -1; ++ xmlRelaxNGFree(schemas); ++ } ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ ++ ctxt = xmlRelaxNGNewParserCtxt(filename); ++ /* Should work */ ++ xmlRelaxParserSetIncLImit(ctxt, 3); ++ xmlRelaxNGSetParserStructuredErrors(ctxt, testStructuredErrorHandler, ++ NULL); ++ schemas = xmlRelaxNGParse(ctxt); ++ if (schemas == NULL) { ++ testErrorHandler(NULL, "Relax-NG schema %s failed to compile\n", ++ filename); ++ ret = -1; ++ goto done; ++ } ++ xmlRelaxNGFree(schemas); ++ ++done: ++ xmlRelaxNGFreeParserCtxt(ctxt); ++ return(ret); ++} ++ + #ifdef LIBXML_READER_ENABLED + /** + * rngStreamTest: +@@ -4873,6 +4937,9 @@ testDesc testDescriptions[] = { + { "Relax-NG regression tests" , + rngTest, "./test/relaxng/*.rng", NULL, NULL, NULL, + XML_PARSE_DTDATTR | XML_PARSE_NOENT }, ++ { "Relax-NG include limit tests" , ++ rngIncludeTest, "./test/relaxng/include/include-limit.rng", NULL, NULL, NULL, ++ 0 }, + #ifdef LIBXML_READER_ENABLED + { "Relax-NG streaming regression tests" , + rngStreamTest, "./test/relaxng/*.rng", NULL, NULL, NULL, diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index a997ece6f0a69..c3626b71eeac4 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -33,6 +33,10 @@ let # Based on https://gitlab.gnome.org/GNOME/libxml2/-/commit/f75abfcaa419a740a3191e56c60400f3ff18988d # Vendored, because there is no xmlCatalogSetDebug in 2.13.9, use fprintf instead ./2.13-CVE-2026-0992.patch + + # Based on https://gitlab.gnome.org/GNOME/libxml2/-/commit/19549c61590c1873468c53e0026a2fbffae428ef.patch + # There are only whitespace differences from upstream. + ./2.13-CVE-2026-0989.patch ]; freezeUpdateScript = true; extraMeta = { From b13ff83b9609574fbfb6dd3c2f835de312cbca74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Sun, 25 Jan 2026 09:45:35 +0100 Subject: [PATCH 52/74] libxml2: fix a typo in comment (cherry picked from commit 74ff6c1f7b939b0e0e7f5aeb91e13f17816ac031) --- pkgs/development/libraries/libxml2/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/development/libraries/libxml2/default.nix b/pkgs/development/libraries/libxml2/default.nix index c3626b71eeac4..be187c33ffc4c 100644 --- a/pkgs/development/libraries/libxml2/default.nix +++ b/pkgs/development/libraries/libxml2/default.nix @@ -31,7 +31,7 @@ let }) # Based on https://gitlab.gnome.org/GNOME/libxml2/-/commit/f75abfcaa419a740a3191e56c60400f3ff18988d - # Vendored, because there is no xmlCatalogSetDebug in 2.13.9, use fprintf instead + # Vendored, because there is no xmlCatalogPrintDebug in 2.13.9, use fprintf instead ./2.13-CVE-2026-0992.patch # Based on https://gitlab.gnome.org/GNOME/libxml2/-/commit/19549c61590c1873468c53e0026a2fbffae428ef.patch From 61cdaea916537dd00b27584c1abaaa507c15bfac Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Wed, 19 Nov 2025 22:10:32 +0000 Subject: [PATCH 53/74] bind: 9.20.15 -> 9.20.16 Changes: https://downloads.isc.org/isc/bind9/cur/9.20/doc/arm/html/notes.html#notes-for-bind-9-20-16 (cherry picked from commit 26bddf9174100aed76a679b97377d1a88e39dbb7) --- pkgs/by-name/bi/bind/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/bi/bind/package.nix b/pkgs/by-name/bi/bind/package.nix index 68b0f8f4f81fd..208db30f4350f 100644 --- a/pkgs/by-name/bi/bind/package.nix +++ b/pkgs/by-name/bi/bind/package.nix @@ -29,11 +29,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "bind"; - version = "9.20.15"; + version = "9.20.16"; src = fetchurl { url = "https://downloads.isc.org/isc/bind9/${finalAttrs.version}/bind-${finalAttrs.version}.tar.xz"; - hash = "sha256-1is4+uSLqD/KYYERLQxxAY2LDyzihdx53GoDZ3Isyrs="; + hash = "sha256-A//Mek/LfDm4KzS+G6K1n2wZG8eVxZNVMNXr5jCjUtY="; }; outputs = [ From e672a4bc20d0fe4794904b12b1df347fafe62193 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Sat, 20 Dec 2025 09:38:47 +0000 Subject: [PATCH 54/74] bind: 9.20.16 -> 9.20.17 Changes: https://downloads.isc.org/isc/bind9/cur/9.20/doc/arm/html/notes.html#notes-for-bind-9-20-17 (cherry picked from commit 3ba8e8f94cd4b0231647e3552c8e71a474e2a5f4) --- pkgs/by-name/bi/bind/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/bi/bind/package.nix b/pkgs/by-name/bi/bind/package.nix index 208db30f4350f..6eb8f91e4c1de 100644 --- a/pkgs/by-name/bi/bind/package.nix +++ b/pkgs/by-name/bi/bind/package.nix @@ -29,11 +29,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "bind"; - version = "9.20.16"; + version = "9.20.17"; src = fetchurl { url = "https://downloads.isc.org/isc/bind9/${finalAttrs.version}/bind-${finalAttrs.version}.tar.xz"; - hash = "sha256-A//Mek/LfDm4KzS+G6K1n2wZG8eVxZNVMNXr5jCjUtY="; + hash = "sha256-XMiaCdoJF+sd32QMwHwXL/RPqbvzo0raS2ovfucP8cg="; }; outputs = [ From 52c3700532aae597bc450a18ccf87b11f923d70c Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Wed, 21 Jan 2026 23:58:05 +0100 Subject: [PATCH 55/74] bind: 9.20.17 -> 9.20.18 Fixes CVE-2025-13878. https://downloads.isc.org/isc/bind9/9.20.18/doc/arm/html/notes.html#notes-for-bind-9-20-18 (cherry picked from commit 6bd98c02c5f7e322ac5e32dfd8ab2eb3c722faab) --- pkgs/by-name/bi/bind/package.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/by-name/bi/bind/package.nix b/pkgs/by-name/bi/bind/package.nix index 6eb8f91e4c1de..c49ae029d7fa6 100644 --- a/pkgs/by-name/bi/bind/package.nix +++ b/pkgs/by-name/bi/bind/package.nix @@ -29,11 +29,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "bind"; - version = "9.20.17"; + version = "9.20.18"; src = fetchurl { url = "https://downloads.isc.org/isc/bind9/${finalAttrs.version}/bind-${finalAttrs.version}.tar.xz"; - hash = "sha256-XMiaCdoJF+sd32QMwHwXL/RPqbvzo0raS2ovfucP8cg="; + hash = "sha256-38VGyZCsRRVSnNRcTdmVhisYrootDLKSCOiJal0yUzE="; }; outputs = [ From 3381470ad007b3f53a42bb5025e9b5716a47dd73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Tue, 27 Jan 2026 19:06:32 +0100 Subject: [PATCH 56/74] openssl: 3.6.0 -> 3.6.1 The second item (severity: High) has possible unauthenticated RCE: https://www.openwall.com/lists/oss-security/2026/01/27/5 https://github.com/openssl/openssl/blob/openssl-3.6.1/CHANGES.md#openssl-36 The patches differ in whitespace only, as that's what upstream changed. (cherry picked from commit eab028a911ddc4c2f896647349dd56db72389456) --- .../openssl/3.5/use-etc-ssl-certs-darwin.patch | 13 ------------- .../libraries/openssl/3.5/use-etc-ssl-certs.patch | 13 ------------- .../openssl/3.6/use-etc-ssl-certs-darwin.patch | 13 +++++++++++++ .../libraries/openssl/3.6/use-etc-ssl-certs.patch | 13 +++++++++++++ pkgs/development/libraries/openssl/default.nix | 8 ++++---- 5 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch delete mode 100644 pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch create mode 100644 pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs-darwin.patch create mode 100644 pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs.patch diff --git a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch b/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch deleted file mode 100644 index e8b07b4ae5990..0000000000000 --- a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/include/internal/common.h b/include/internal/common.h -index 15666f1..d91e25b 100644 ---- a/include/internal/common.h -+++ b/include/internal/common.h -@@ -83,7 +83,7 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, - # ifndef OPENSSL_SYS_VMS - # define X509_CERT_AREA OPENSSLDIR - # define X509_CERT_DIR OPENSSLDIR "/certs" --# define X509_CERT_FILE OPENSSLDIR "/cert.pem" -+# define X509_CERT_FILE "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" - # define X509_PRIVATE_DIR OPENSSLDIR "/private" - # define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" - # else diff --git a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch b/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch deleted file mode 100644 index 13a36fbcd0314..0000000000000 --- a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/include/internal/common.h b/include/internal/common.h -index 15666f1..d91e25b 100644 ---- a/include/internal/common.h -+++ b/include/internal/common.h -@@ -83,7 +83,7 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, - # ifndef OPENSSL_SYS_VMS - # define X509_CERT_AREA OPENSSLDIR - # define X509_CERT_DIR OPENSSLDIR "/certs" --# define X509_CERT_FILE OPENSSLDIR "/cert.pem" -+# define X509_CERT_FILE "/etc/ssl/certs/ca-certificates.crt" - # define X509_PRIVATE_DIR OPENSSLDIR "/private" - # define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" - # else diff --git a/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs-darwin.patch b/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs-darwin.patch new file mode 100644 index 0000000000000..bb2d048542cba --- /dev/null +++ b/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs-darwin.patch @@ -0,0 +1,13 @@ +diff --git a/include/internal/common.h b/include/internal/common.h +index 15666f1..d91e25b 100644 +--- a/include/internal/common.h ++++ b/include/internal/common.h +@@ -83,7 +83,7 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, + #ifndef OPENSSL_SYS_VMS + #define X509_CERT_AREA OPENSSLDIR + #define X509_CERT_DIR OPENSSLDIR "/certs" +-#define X509_CERT_FILE OPENSSLDIR "/cert.pem" ++#define X509_CERT_FILE "/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" + #define X509_PRIVATE_DIR OPENSSLDIR "/private" + #define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" + #else diff --git a/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs.patch b/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs.patch new file mode 100644 index 0000000000000..e0fb994161deb --- /dev/null +++ b/pkgs/development/libraries/openssl/3.6/use-etc-ssl-certs.patch @@ -0,0 +1,13 @@ +diff --git a/include/internal/common.h b/include/internal/common.h +index 15666f1..d91e25b 100644 +--- a/include/internal/common.h ++++ b/include/internal/common.h +@@ -83,7 +83,7 @@ __owur static ossl_inline int ossl_assert_int(int expr, const char *exprstr, + #ifndef OPENSSL_SYS_VMS + #define X509_CERT_AREA OPENSSLDIR + #define X509_CERT_DIR OPENSSLDIR "/certs" +-#define X509_CERT_FILE OPENSSLDIR "/cert.pem" ++#define X509_CERT_FILE "/etc/ssl/certs/ca-certificates.crt" + #define X509_PRIVATE_DIR OPENSSLDIR "/private" + #define CTLOG_FILE OPENSSLDIR "/ct_log_list.cnf" + #else diff --git a/pkgs/development/libraries/openssl/default.nix b/pkgs/development/libraries/openssl/default.nix index d7f9a42511ad1..fb8f38ec805f1 100644 --- a/pkgs/development/libraries/openssl/default.nix +++ b/pkgs/development/libraries/openssl/default.nix @@ -449,8 +449,8 @@ in }; openssl_3_6 = common { - version = "3.6.0"; - hash = "sha256-tqX0S362nj+jXb8VUkQFtEg3pIHUPYHa3d4/8h/LuOk="; + version = "3.6.1"; + hash = "sha256-sb/tzVson/Iq7ofJ1gD1FXZ+v0X3cWjLbWTyMfUYqC4="; patches = [ # Support for NIX_SSL_CERT_FILE, motivation: @@ -464,9 +464,9 @@ in # Look up SSL certificates in /etc rather than the immutable installation directory ( if stdenv.hostPlatform.isDarwin then - ./3.5/use-etc-ssl-certs-darwin.patch + ./3.6/use-etc-ssl-certs-darwin.patch else - ./3.5/use-etc-ssl-certs.patch + ./3.6/use-etc-ssl-certs.patch ) ] ++ lib.optionals stdenv.hostPlatform.isMinGW [ From 8a376e916f36fce6ff69bc4cf9eb3e6103391151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Tue, 30 Dec 2025 14:45:51 -0800 Subject: [PATCH 57/74] imagemagick: 7.1.2-11 -> 7.1.2-12 Diff: https://github.com/ImageMagick/ImageMagick/compare/7.1.2-11...7.1.2-12 Changelog: https://github.com/ImageMagick/Website/blob/main/ChangeLog.md (cherry picked from commit 95f5d8c6a7831fae5522f75055f09c613dde561b) --- pkgs/applications/graphics/ImageMagick/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/applications/graphics/ImageMagick/default.nix b/pkgs/applications/graphics/ImageMagick/default.nix index 774b76f89fe05..0f4e87c9056ff 100644 --- a/pkgs/applications/graphics/ImageMagick/default.nix +++ b/pkgs/applications/graphics/ImageMagick/default.nix @@ -85,13 +85,13 @@ in stdenv.mkDerivation (finalAttrs: { pname = "imagemagick"; - version = "7.1.2-11"; + version = "7.1.2-12"; src = fetchFromGitHub { owner = "ImageMagick"; repo = "ImageMagick"; tag = finalAttrs.version; - hash = "sha256-RFiE23VW8AbVb7iglxjQMT6njDw+P7vLW6+nSKqN0p8="; + hash = "sha256-0X8Zpr4frknRbWzAu1nprok2ceScTHV8d4+ktnBpQF0="; }; outputs = [ From df93562690d7381547032372a9bb2b1551f5f56f Mon Sep 17 00:00:00 2001 From: faukah Date: Wed, 21 Jan 2026 20:53:21 +0100 Subject: [PATCH 58/74] imagemagick: 7.1.2-12 -> 7.1.2-13 (cherry picked from commit cfb11ceaa4d07f3b7ce3c8798bd2a8603a424c4d) --- pkgs/applications/graphics/ImageMagick/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/applications/graphics/ImageMagick/default.nix b/pkgs/applications/graphics/ImageMagick/default.nix index 0f4e87c9056ff..33dd080943a1a 100644 --- a/pkgs/applications/graphics/ImageMagick/default.nix +++ b/pkgs/applications/graphics/ImageMagick/default.nix @@ -85,13 +85,13 @@ in stdenv.mkDerivation (finalAttrs: { pname = "imagemagick"; - version = "7.1.2-12"; + version = "7.1.2-13"; src = fetchFromGitHub { owner = "ImageMagick"; repo = "ImageMagick"; tag = finalAttrs.version; - hash = "sha256-0X8Zpr4frknRbWzAu1nprok2ceScTHV8d4+ktnBpQF0="; + hash = "sha256-meADRjoV1c48laD35TuWAwuE95L90agROuuKBd++Kn8="; }; outputs = [ From 610f414ac25332dcc3f03aa4476a897ae62e8872 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 18 Dec 2025 01:32:20 +0100 Subject: [PATCH 59/74] python3Package.django_4: disable on 3.13 and newer Django 4.2.x does not support Python 3.13 and newer. (cherry picked from commit 652c49568846f7cc9bf354c6b25950efd9c7eb5f) --- pkgs/development/python-modules/django/4.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/development/python-modules/django/4.nix b/pkgs/development/python-modules/django/4.nix index 8438091346f9a..0a74f1350d763 100644 --- a/pkgs/development/python-modules/django/4.nix +++ b/pkgs/development/python-modules/django/4.nix @@ -48,7 +48,7 @@ buildPythonPackage rec { version = "4.2.27"; format = "pyproject"; - disabled = pythonOlder "3.8"; + disabled = pythonOlder "3.8" || pythonAtLeast "3.13"; src = fetchFromGitHub { owner = "django"; From 579e4391f1078ee6f6acfdabb2e6f39cbd6afb9a Mon Sep 17 00:00:00 2001 From: Thomas Gerbet Date: Wed, 19 Nov 2025 23:11:40 +0100 Subject: [PATCH 60/74] grub2: apply November security fixes https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00155.html Fixes CVE-2025-54770, CVE-2025-54771, CVE-2025-61661, CVE-2025-61662, CVE-2025-61663 and CVE-2025-61664. (cherry picked from commit e6066a2284d49cbd182ee190de1114ef25f098ef) --- pkgs/tools/misc/grub/default.nix | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/pkgs/tools/misc/grub/default.nix b/pkgs/tools/misc/grub/default.nix index 2cbdd44167842..51456e61b4c52 100644 --- a/pkgs/tools/misc/grub/default.nix +++ b/pkgs/tools/misc/grub/default.nix @@ -510,6 +510,47 @@ stdenv.mkDerivation rec { url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=c448f511e74cb7c776b314fcb7943f98d3f22b6d"; hash = "sha256-64gMhCEW0aYHt46crX/qN/3Hj8MgvWLazgQlVXqe8LE="; }) + # https://lists.gnu.org/archive/html/grub-devel/2025-11/msg00155.html + (fetchpatch { + name = "1_commands_test_fix_error_in_recursion_depth_calculation.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=cc9d621dd06bfa12eac511b37b4ceda5bd2f8246"; + hash = "sha256-GpLpqTKr2ke/YaxnZIO1Kh9wpde44h2mvwcODcAL/nk="; + }) + (fetchpatch { + name = "2_CVE-2025-54771.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=c4fb4cbc941981894a00ba8e75d634a41967a27f"; + hash = "sha256-yWowlAMVXdfIyC+BiB00IZvTwIybvaPhxAyz0MPjQuY="; + }) + (fetchpatch { + name = "3_CVE-2025-54770.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=10e58a14db20e17d1b6a39abe38df01fef98e29d"; + hash = "sha256-1ROc5n7sApw7aGr+y8gygFqVkifLdgOD3RPaW9b8aQQ="; + }) + (fetchpatch { + name = "4_CVE-2025-61662.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=8ed78fd9f0852ab218cc1f991c38e5a229e43807"; + hash = "sha256-mG+vcZHbF4duY2YoYAzPBQRHfWvp5Fvgtm0XBk7JqqM="; + }) + (fetchpatch { + name = "5_CVE-2025-61663_CVE-2025-61664.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=05d3698b8b03eccc49e53491bbd75dba15f40917"; + hash = "sha256-kgtXhZmAQpassEf8+RzqkghAzLrCcRoRMMnfunF/0J8="; + }) + (fetchpatch { + name = "6_tests_lib_functional_test_unregister_commands_on_module_unload.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=9df1e693e70c5a274b6d60dc76efe2694b89c2fc"; + hash = "sha256-UzyYkpP7vivx2jzxi7BMP9h9OB2yraswrMW4g9UWsbI="; + }) + (fetchpatch { + name = "7_CVE-2025-61661.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=549a9cc372fd0b96a4ccdfad0e12140476cc62a3"; + hash = "sha256-2mlDoVXY7Upwx4QBeAMOHUtoUlyx1MDDmabnrwK1gEY="; + }) + (fetchpatch { + name = "8_commands_usbtest_ensure_string_length_is_sufficient_in_usb_string_processing.patch"; + url = "https://git.savannah.gnu.org/cgit/grub.git/patch/?id=7debdce1e98907e65223a4b4c53a41345ac45e53"; + hash = "sha256-2ALvrmwxvpjQYjGNrQ0gyGotpk0kgmYlJXMF1xXrnEw="; + }) ]; postPatch = From 4ab1e6d005d1c1ae0f6d11817273ca888f14ff16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=BCtz?= Date: Fri, 21 Nov 2025 23:29:00 -0800 Subject: [PATCH 61/74] python3Packages.jupyter-server: 2.16.0 -> 2.17.0 Changelog: https://github.com/jupyter-server/jupyter_server/blob/v2.17.0/CHANGELOG.md (cherry picked from commit ba6a01e8a31a3e11f5882d2e05ccf0631589d0c5) Apparently this also fixes some test regressions: https://hydra.nixos.org/build/320662237/nixlog/1/tail --- pkgs/development/python-modules/jupyter-server/default.nix | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/development/python-modules/jupyter-server/default.nix b/pkgs/development/python-modules/jupyter-server/default.nix index ae7d77d47edac..41f803ad4ab96 100644 --- a/pkgs/development/python-modules/jupyter-server/default.nix +++ b/pkgs/development/python-modules/jupyter-server/default.nix @@ -1,6 +1,5 @@ { lib, - pythonOlder, stdenv, buildPythonPackage, fetchPypi, @@ -35,14 +34,13 @@ buildPythonPackage rec { pname = "jupyter-server"; - version = "2.16.0"; + version = "2.17.0"; pyproject = true; - disabled = pythonOlder "3.9"; src = fetchPypi { pname = "jupyter_server"; inherit version; - hash = "sha256-ZdS0T98ty73+CqGs5KhC1Kr3RqK3sWgTTVqu01Yht/Y="; + hash = "sha256-w46omFZpZMiItHcq4e1Y7KhFkuiCUdLPxNFx+B9+mdU="; }; build-system = [ From aefe04bfbf5e7ec45b5211fee1010d2028564dcb Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Fri, 21 Nov 2025 22:35:55 +0000 Subject: [PATCH 62/74] python3Packages.pypdf: 6.1.0 -> 6.3.0 (cherry picked from commit 29a4f3ee088e669737c8ed62a596d73c1b230560) --- pkgs/development/python-modules/pypdf/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pypdf/default.nix b/pkgs/development/python-modules/pypdf/default.nix index 7bfb42ce7e3ee..5e3c4b8f97d6a 100644 --- a/pkgs/development/python-modules/pypdf/default.nix +++ b/pkgs/development/python-modules/pypdf/default.nix @@ -27,7 +27,7 @@ buildPythonPackage rec { pname = "pypdf"; - version = "6.1.0"; + version = "6.3.0"; pyproject = true; disabled = pythonOlder "3.8"; @@ -38,7 +38,7 @@ buildPythonPackage rec { tag = version; # fetch sample files used in tests fetchSubmodules = true; - hash = "sha256-qfLN6g2+3j35E4m9vGcWXL1BLiFdDZEFmxYgnknlW3M="; + hash = "sha256-0cch0Je5se1FeHSXH78WhDpNiJQ3Qt0wqxRnv9lr8Qo="; }; outputs = [ From 1d4a8c3fbf4b9f1b10cb22dc2072a421950a8412 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Fri, 28 Nov 2025 10:16:02 +0000 Subject: [PATCH 63/74] python3Packages.pypdf: 6.3.0 -> 6.4.0 (cherry picked from commit 02522dab5a3b25b5f7d159f45a664d0cfdf19a44) --- pkgs/development/python-modules/pypdf/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pypdf/default.nix b/pkgs/development/python-modules/pypdf/default.nix index 5e3c4b8f97d6a..e95e1b7f81700 100644 --- a/pkgs/development/python-modules/pypdf/default.nix +++ b/pkgs/development/python-modules/pypdf/default.nix @@ -27,7 +27,7 @@ buildPythonPackage rec { pname = "pypdf"; - version = "6.3.0"; + version = "6.4.0"; pyproject = true; disabled = pythonOlder "3.8"; @@ -38,7 +38,7 @@ buildPythonPackage rec { tag = version; # fetch sample files used in tests fetchSubmodules = true; - hash = "sha256-0cch0Je5se1FeHSXH78WhDpNiJQ3Qt0wqxRnv9lr8Qo="; + hash = "sha256-QCMOB0qnxVPo8fGcf+TsEcBYYINXVbDCowrLUqNjojw="; }; outputs = [ From a5f62df057344c4888d08a92c39525e0873df2e1 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Wed, 17 Dec 2025 11:23:54 +0000 Subject: [PATCH 64/74] python3Packages.pypdf: 6.4.0 -> 6.4.2 (cherry picked from commit 85182a89d6d5ce2b2bd1f8060603176fec552b46) --- pkgs/development/python-modules/pypdf/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pypdf/default.nix b/pkgs/development/python-modules/pypdf/default.nix index e95e1b7f81700..8ef95974bdad1 100644 --- a/pkgs/development/python-modules/pypdf/default.nix +++ b/pkgs/development/python-modules/pypdf/default.nix @@ -27,7 +27,7 @@ buildPythonPackage rec { pname = "pypdf"; - version = "6.4.0"; + version = "6.4.2"; pyproject = true; disabled = pythonOlder "3.8"; @@ -38,7 +38,7 @@ buildPythonPackage rec { tag = version; # fetch sample files used in tests fetchSubmodules = true; - hash = "sha256-QCMOB0qnxVPo8fGcf+TsEcBYYINXVbDCowrLUqNjojw="; + hash = "sha256-GkCNw7XvDPvLIiIUAgXsTLQ2OBbqhpf3xHQZpB/f2ys="; }; outputs = [ From 1782ab4f2e4387077ba0f722630b339c9d5c0b51 Mon Sep 17 00:00:00 2001 From: "R. Ryantm" Date: Sun, 11 Jan 2026 23:38:38 +0000 Subject: [PATCH 65/74] python3Packages.pypdf: 6.4.2 -> 6.6.0 (cherry picked from commit ba007b6c8a39b6707281ce147b6d67407ef10bae) --- pkgs/development/python-modules/pypdf/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pypdf/default.nix b/pkgs/development/python-modules/pypdf/default.nix index 8ef95974bdad1..b112a45a363ac 100644 --- a/pkgs/development/python-modules/pypdf/default.nix +++ b/pkgs/development/python-modules/pypdf/default.nix @@ -27,7 +27,7 @@ buildPythonPackage rec { pname = "pypdf"; - version = "6.4.2"; + version = "6.6.0"; pyproject = true; disabled = pythonOlder "3.8"; @@ -38,7 +38,7 @@ buildPythonPackage rec { tag = version; # fetch sample files used in tests fetchSubmodules = true; - hash = "sha256-GkCNw7XvDPvLIiIUAgXsTLQ2OBbqhpf3xHQZpB/f2ys="; + hash = "sha256-C1ZFqqLFtxWOuLUT7KFSfWIE6a9xDPCFtOakzYP4NMY="; }; outputs = [ From 6b95051869f09dcbf39c6b63785c435a94751f89 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Fri, 30 Jan 2026 17:09:48 +0100 Subject: [PATCH 66/74] python3Packages.term-image: disable warnings The package is currently failing to build due to its pytest configuration erroring out on deprecation warnings. Override this behaviour by disabling the `warnings` plug-in entirely. (cherry picked from commit 744cdd3a3a0417f83cf27f97a253fa20d016086b) --- pkgs/development/python-modules/term-image/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/development/python-modules/term-image/default.nix b/pkgs/development/python-modules/term-image/default.nix index 04f5070108d4b..c69ac82809031 100644 --- a/pkgs/development/python-modules/term-image/default.nix +++ b/pkgs/development/python-modules/term-image/default.nix @@ -21,6 +21,12 @@ buildPythonPackage rec { hash = "sha256-uA04KHKLXW0lx1y5brpCDARLac4/C8VmVinVMkEtTdM="; }; + # Override the overly strict `tool.pytest.ini_options.filterwarnings` + postPatch = '' + substituteInPlace pyproject.toml \ + --replace-fail '"error"' '#"error"' + ''; + build-system = [ setuptools ]; From d36923f312bb8ed6e3a99cb6532337ebe57233a0 Mon Sep 17 00:00:00 2001 From: Marvin Preuss Date: Mon, 26 Jan 2026 10:01:34 +0100 Subject: [PATCH 67/74] python3Packages.pycdio: disables tests that have problems with python 3.13 (#482857) (cherry picked from commit f66647830db352eaefc15ad4235406618e5e4726) --- pkgs/development/python-modules/pycdio/default.nix | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkgs/development/python-modules/pycdio/default.nix b/pkgs/development/python-modules/pycdio/default.nix index fe191d948abd8..f9c34f0d49d49 100644 --- a/pkgs/development/python-modules/pycdio/default.nix +++ b/pkgs/development/python-modules/pycdio/default.nix @@ -43,6 +43,14 @@ buildPythonPackage rec { enabledTestPaths = [ "test/test-*.py" ]; + disabledTests = [ + # Test are depending on image files that are not there + "test_fs" + "test_bincue" + "test_read" + "test_cdda" + ]; + passthru.updateScript = nix-update-script { extraArgs = [ "--version=branch" ]; }; From ced0d238f56fd06d724d27be5a677df397003ad7 Mon Sep 17 00:00:00 2001 From: Sigmanificient Date: Mon, 26 Jan 2026 21:46:50 +0100 Subject: [PATCH 68/74] python3Packages.pycdio: fix test for fs,read (cherry picked from commit 0e66ce803b28d14c1e09b482f655e2876f0ce187) --- pkgs/development/python-modules/pycdio/default.nix | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/development/python-modules/pycdio/default.nix b/pkgs/development/python-modules/pycdio/default.nix index f9c34f0d49d49..c58f2ae568395 100644 --- a/pkgs/development/python-modules/pycdio/default.nix +++ b/pkgs/development/python-modules/pycdio/default.nix @@ -39,15 +39,18 @@ buildPythonPackage rec { libiconv ]; + postPatch = '' + substituteInPlace {data,test}/isofs-m1.cue \ + --replace-fail "ISOFS-M1.BIN" "isofs-m1.bin" + ''; + nativeCheckInputs = [ pytestCheckHook ]; enabledTestPaths = [ "test/test-*.py" ]; disabledTests = [ # Test are depending on image files that are not there - "test_fs" "test_bincue" - "test_read" "test_cdda" ]; From 3b615f97e29180e05cc7eecd6c4c4700fc74acea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Tue, 3 Feb 2026 12:04:06 +0100 Subject: [PATCH 69/74] knot-resolver-manager_6: 6.1.0 -> 6.2.0 https://gitlab.nic.cz/knot/knot-resolver/-/releases/v6.2.0 The enablement of DoQ costs us only 48 KiB of runtime closure increase, thanks to sharing the costs with knot-dns libs. (cherry picked from commit 9a49c1ff889b95542895547690292156cb8e5c32) --- pkgs/by-name/kn/knot-resolver_6/package.nix | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkgs/by-name/kn/knot-resolver_6/package.nix b/pkgs/by-name/kn/knot-resolver_6/package.nix index d767d3b7223ab..14021cc706795 100644 --- a/pkgs/by-name/kn/knot-resolver_6/package.nix +++ b/pkgs/by-name/kn/knot-resolver_6/package.nix @@ -15,13 +15,15 @@ libuv, gnutls, lmdb, + # optionals, in principle jemalloc, systemdMinimal, libcap_ng, dns-root-data, - nghttp2, # optionals, in principle + nghttp2, + ngtcp2-gnutls, fstrm, - protobufc, # more optionals + protobufc, # test-only deps. cmocka, which, @@ -34,11 +36,11 @@ let # TODO: we could cut the `let` short here, but it would de-indent everything. unwrapped = stdenv.mkDerivation (finalAttrs: { pname = "knot-resolver_6"; - version = "6.1.0"; + version = "6.2.0"; src = fetchurl { url = "https://secure.nic.cz/files/knot-resolver/knot-resolver-${finalAttrs.version}.tar.xz"; - hash = "sha256-eSHfdQcobZBXS79a5mSopTeAXOQLX6ixX10NM+LEONA="; + hash = "sha256-tEYzvIQxgMC8fHfPexX+VxJDrpkrTdt0r97kz6gDcBs="; }; outputs = [ @@ -92,6 +94,7 @@ let ++ [ jemalloc nghttp2 + ngtcp2-gnutls # dnstap support fstrm protobufc From be7ab8701d032c02bec320fddd05b2d39a72e609 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Wed, 4 Feb 2026 21:16:40 +0100 Subject: [PATCH 70/74] Revert "python3Package.django_4: disable on 3.13 and newer" This reverts commit 610f414ac25332dcc3f03aa4476a897ae62e8872. While it is not supported on 3.13 I'm doing everything to keep it alive because by accident it is the default Django on the default Python version. --- pkgs/development/python-modules/django/4.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/development/python-modules/django/4.nix b/pkgs/development/python-modules/django/4.nix index 0a74f1350d763..8438091346f9a 100644 --- a/pkgs/development/python-modules/django/4.nix +++ b/pkgs/development/python-modules/django/4.nix @@ -48,7 +48,7 @@ buildPythonPackage rec { version = "4.2.27"; format = "pyproject"; - disabled = pythonOlder "3.8" || pythonAtLeast "3.13"; + disabled = pythonOlder "3.8"; src = fetchFromGitHub { owner = "django"; From 857330ddff49131345908f26071d955522a81a5f Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Tue, 3 Feb 2026 18:03:24 +0100 Subject: [PATCH 71/74] python3Packages.django_4: 4.2.27 -> 4.2.28 https://docs.djangoproject.com/en/4.2/releases/4.2.28/ https://www.djangoproject.com/weblog/2026/feb/03/security-releases/ Fixes: CVE-2025-13473, CVE-2025-14550, CVE-2026-1207, CVE-2026-1285, CVE-2026-1287, CVE-2026-1312 (cherry picked from commit 154cebd52aaddd791c4ab34186f02746419d7476) --- pkgs/development/python-modules/django/4.nix | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/development/python-modules/django/4.nix b/pkgs/development/python-modules/django/4.nix index 8438091346f9a..0688f35b9855c 100644 --- a/pkgs/development/python-modules/django/4.nix +++ b/pkgs/development/python-modules/django/4.nix @@ -45,16 +45,16 @@ buildPythonPackage rec { pname = "django"; - version = "4.2.27"; - format = "pyproject"; + version = "4.2.28"; + pyproject = true; disabled = pythonOlder "3.8"; src = fetchFromGitHub { owner = "django"; repo = "django"; - rev = "refs/tags/${version}"; - hash = "sha256-vdY85Ib2knRFLPmZZ6ojiD5R9diuvpVut1+nOVXSp0Y="; + tag = version; + hash = "sha256-dxlTonT8zFIFGFrrOW4GFKOy5b0chcESxt9i9xHO8h4="; }; patches = [ From 4bb246e2bd8a2b0e673cf2f045477a16ace2b4e9 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 5 Feb 2026 11:14:26 +0100 Subject: [PATCH 72/74] python3Packages.bleach: relax tinycss2 constraint While this is an optional dependency and it doesn't block bleach itself it does block notebook, which uses a stricter transitive dependency constraint validation. --- pkgs/development/python-modules/bleach/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/development/python-modules/bleach/default.nix b/pkgs/development/python-modules/bleach/default.nix index b9f3dd18cf7e6..4c7c9a8a55a70 100644 --- a/pkgs/development/python-modules/bleach/default.nix +++ b/pkgs/development/python-modules/bleach/default.nix @@ -29,6 +29,8 @@ buildPythonPackage rec { webencodings ]; + pythonRelaxDeps = [ "tinycss2" ]; + optional-dependencies = { css = [ tinycss2 ]; }; From 1e6c61a5a47393b104fe214ef641bfd111136ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Fri, 6 Feb 2026 12:24:30 +0100 Subject: [PATCH 73/74] texlive: force rebuild of core binaries on aarch64-darwin It's a successful build on Hydra but it's got broken binaries, and thus it's breaking other builds, e.g.: https://hydra.nixos.org/build/320614180/nixlog/4/tail --- pkgs/tools/typesetting/tex/texlive/bin.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/tools/typesetting/tex/texlive/bin.nix b/pkgs/tools/typesetting/tex/texlive/bin.nix index 48b22d07c1447..7608cdd8e7134 100644 --- a/pkgs/tools/typesetting/tex/texlive/bin.nix +++ b/pkgs/tools/typesetting/tex/texlive/bin.nix @@ -346,6 +346,9 @@ rec { + '' rm "$out"/bin/{eptex,ptex,uptex} rm "${placeholder "ptex"}"/bin/{pbibtex,pdvitype,ppltotf,ptftopl} + '' + + lib.optionalString (stdenv.system == "aarch64-darwin") '' + # TMP: just cause a rebuild ''; passthru = { inherit version buildInputs; }; From 157d6f9df2e098548c57946af757118cd510037a Mon Sep 17 00:00:00 2001 From: Arian van Putten Date: Wed, 21 Jan 2026 21:51:12 +0100 Subject: [PATCH 74/74] amazon-ssm-agent: stop running tests there are many and the codebase is a mess. I don't feel like dealing with this. If someone feels strongly they can re-enable but I prefer we ship updates again. wore maintainers needed. (cherry picked from commit 197277f730b0f76462e62bd3a4b8abe4aab5ff3b) https://hydra.nixos.org/build/320496536#tabs-buildsteps --- pkgs/by-name/am/amazon-ssm-agent/package.nix | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkgs/by-name/am/amazon-ssm-agent/package.nix b/pkgs/by-name/am/amazon-ssm-agent/package.nix index 2bcdd3b50dc18..225676459aa20 100644 --- a/pkgs/by-name/am/amazon-ssm-agent/package.nix +++ b/pkgs/by-name/am/amazon-ssm-agent/package.nix @@ -107,10 +107,6 @@ buildGoModule rec { ''; preBuild = '' - # Note: if this step fails, please patch the code to fix it! Please only skip - # tests if it is not feasible for the test to pass in a sandbox. - make quick-integtest - make pre-release make pre-build ''; @@ -143,11 +139,7 @@ buildGoModule rec { runHook postInstall ''; - checkFlags = [ - # Skip time dependent/flaky test - "-skip=TestSendStreamDataMessageWithStreamDataSequenceNumberMutexLocked" - "-skip=TestParallelAccessOfQueue" - ]; + doCheck = false; postFixup = '' wrapProgram $out/bin/amazon-ssm-agent \