add new patches for release 100
Signed-off-by: Toshaan Bharvani <toshaan@powerel.org>master
parent
7fc01014c3
commit
e90f7c0dfe
SOURCES
Binary file not shown.
|
@ -0,0 +1,432 @@
|
|||
From e4ca6de1bc5e4ba3f94cf0c501a293c5bc827b10 Mon Sep 17 00:00:00 2001
|
||||
From: Anton Blanchard <anton@ozlabs.org>
|
||||
Date: Tue, 27 Jul 2021 15:47:49 +1000
|
||||
Subject: powerpc64: Replace some PPC_FEATURE_HAS_VSX with
|
||||
PPC_FEATURE_ARCH_2_06
|
||||
|
||||
We use PPC_FEATURE_HAS_VSX to select a number of POWER7 optimised
|
||||
functions. These functions don't use any VSX instructions, so
|
||||
PPC_FEATURE_ARCH_2_06 seems like a better fit.
|
||||
|
||||
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
index 0acdf22ba3..32564c8f1f 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
@@ -95,7 +95,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memset_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memset_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_05,
|
||||
__memset_power6)
|
||||
@@ -139,7 +139,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strlen_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, strlen, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strlen_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strlen, 1,
|
||||
__strlen_ppc))
|
||||
@@ -152,7 +152,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strncmp_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strncmp_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_POWER4,
|
||||
__strncmp_power4)
|
||||
@@ -165,7 +165,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strchr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strchr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strchr, 1,
|
||||
__strchr_ppc))
|
||||
@@ -176,7 +176,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strchrnul_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strchrnul,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strchrnul_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strchrnul, 1,
|
||||
__strchrnul_ppc))
|
||||
@@ -192,7 +192,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memcmp_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memcmp_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_POWER4,
|
||||
__memcmp_power4)
|
||||
@@ -244,7 +244,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memchr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memchr, 1,
|
||||
__memchr_ppc))
|
||||
@@ -255,7 +255,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__memrchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memrchr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr, 1,
|
||||
__memrchr_ppc))
|
||||
@@ -272,7 +272,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
__rawmemchr_power9)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__rawmemchr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr, 1,
|
||||
__rawmemchr_ppc))
|
||||
@@ -282,7 +282,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL_ADD (array, i, strnlen,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strnlen_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, strnlen, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, strnlen, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strnlen_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strnlen, 1,
|
||||
__strnlen_ppc))
|
||||
@@ -293,14 +293,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strcasecmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strcasecmp_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp, 1, __strcasecmp_ppc))
|
||||
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcasecmp_l.c. */
|
||||
IFUNC_IMPL (i, name, strcasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp_l,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strcasecmp_l_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp_l, 1,
|
||||
__strcasecmp_l_ppc))
|
||||
@@ -311,14 +311,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strncasecmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strncasecmp_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp, 1, __strncasecmp_ppc))
|
||||
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strncase_l.c. */
|
||||
IFUNC_IMPL (i, name, strncasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp_l,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strncasecmp_l_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp_l, 1,
|
||||
__strncasecmp_l_ppc))
|
||||
@@ -329,7 +329,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strrchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strrchr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr, 1,
|
||||
__strrchr_ppc))
|
||||
@@ -357,7 +357,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strncpy_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strncpy,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strncpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strncpy, 1,
|
||||
__strncpy_ppc))
|
||||
@@ -374,7 +374,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__stpncpy_power8)
|
||||
IFUNC_IMPL_ADD (array, i, stpncpy,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__stpncpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, stpncpy, 1,
|
||||
__stpncpy_ppc))
|
||||
@@ -390,7 +390,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
__strcmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strcmp_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp, 1,
|
||||
__strcmp_ppc))
|
||||
@@ -425,7 +425,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strstr.c. */
|
||||
IFUNC_IMPL (i, name, strstr,
|
||||
IFUNC_IMPL_ADD (array, i, strstr,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strstr_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strstr, 1,
|
||||
__strstr_ppc))
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memchr.c b/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
index 0c718d4f15..c24186689e 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
@@ -30,7 +30,7 @@ extern __typeof (__memchr) __memchr_power8 attribute_hidden;
|
||||
libc_ifunc (__memchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memchr_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memchr_power7
|
||||
: __memchr_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
index 4fd089aba7..99559bce26 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
@@ -40,7 +40,7 @@ libc_ifunc_redirected (__redirect_memcmp, memcmp,
|
||||
#endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memcmp_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memcmp_power7
|
||||
: (hwcap & PPC_FEATURE_POWER4)
|
||||
? __memcmp_power4
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memrchr.c b/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
index e06d6468b8..16bb6f0042 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
@@ -30,7 +30,7 @@ extern __typeof (__memrchr) __memrchr_power8 attribute_hidden;
|
||||
libc_ifunc (__memrchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memrchr_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memrchr_power7
|
||||
: __memrchr_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset.c b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
index 5994bf02e6..c1aa143f60 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
@@ -48,7 +48,7 @@ libc_ifunc (__libc_memset,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __memset_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memset_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
? __memset_power6 :
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
index c0ffea2b93..b5d2d3a635 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
@@ -41,7 +41,7 @@ libc_ifunc_redirected (__redirect___rawmemchr, __rawmemchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
? __rawmemchr_power9 :
|
||||
# endif
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __rawmemchr_power7
|
||||
: __rawmemchr_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c b/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c
|
||||
index bebd377fd9..e7035761a7 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c
|
||||
@@ -40,7 +40,7 @@ libc_ifunc_redirected (__redirect___stpncpy, __stpncpy,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __stpncpy_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __stpncpy_power7
|
||||
: __stpncpy_ppc);
|
||||
weak_alias (__stpncpy, stpncpy)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
index dcd7774403..55ca6c85c4 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
@@ -29,7 +29,7 @@ extern __typeof (__strcasecmp) __strcasecmp_power8 attribute_hidden;
|
||||
libc_ifunc (__libc_strcasecmp,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strcasecmp_power8:
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strcasecmp_power7
|
||||
: __strcasecmp_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp_l.c b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp_l.c
|
||||
index 96a70b8b11..1afee5d7fd 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp_l.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp_l.c
|
||||
@@ -32,7 +32,7 @@ extern __typeof (__strcasecmp_l) __strcasecmp_l_power7 attribute_hidden;
|
||||
|
||||
extern __typeof (__strcasecmp_l) __libc_strcasecmp_l;
|
||||
libc_ifunc (__libc_strcasecmp_l,
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strcasecmp_l_power7
|
||||
: __strcasecmp_l_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strchr.c b/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
index ea9ac1134f..27c794c6b7 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
@@ -35,7 +35,7 @@ extern __typeof (strchr) __strchr_power8 attribute_hidden;
|
||||
libc_ifunc_redirected (__redirect_strchr, strchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strchr_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strchr_power7
|
||||
: __strchr_ppc);
|
||||
weak_alias (strchr, index)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c b/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
index 4688e7c3f0..4a07b4a242 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
@@ -30,7 +30,7 @@ extern __typeof (__strchrnul) __strchrnul_power8 attribute_hidden;
|
||||
libc_ifunc (__strchrnul,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strchrnul_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strchrnul_power7
|
||||
: __strchrnul_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
index 72f9a639bf..4b0b25fff6 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
@@ -40,7 +40,7 @@ libc_ifunc_redirected (__redirect_strcmp, strcmp,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strcmp_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strcmp_power7
|
||||
: __strcmp_ppc);
|
||||
#endif
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen.c b/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
index 109c8a90bd..0cd1c6faff 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
@@ -42,7 +42,7 @@ libc_ifunc (__libc_strlen,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strlen_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strlen_power7
|
||||
: __strlen_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncase.c b/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
index 2013a5d75a..644046bd74 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
@@ -29,7 +29,7 @@ extern __typeof (__strncasecmp) __strncasecmp_power8 attribute_hidden;
|
||||
libc_ifunc (__libc_strncasecmp,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strncasecmp_power8:
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strncasecmp_power7
|
||||
: __strncasecmp_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncase_l.c b/sysdeps/powerpc/powerpc64/multiarch/strncase_l.c
|
||||
index cad6da302d..d2d761af72 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncase_l.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncase_l.c
|
||||
@@ -34,7 +34,7 @@ extern __typeof (__strncasecmp_l) __strncasecmp_l_power7 attribute_hidden;
|
||||
ifunc symbol properly. */
|
||||
extern __typeof (__strncasecmp_l) __libc_strncasecmp_l;
|
||||
libc_ifunc (__libc_strncasecmp_l,
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strncasecmp_l_power7
|
||||
: __strncasecmp_l_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
index eef524ddfb..1f689e5c05 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
@@ -43,7 +43,7 @@ libc_ifunc_redirected (__redirect_strncmp, strncmp,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strncmp_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strncmp_power7
|
||||
: (hwcap & PPC_FEATURE_POWER4)
|
||||
? __strncmp_power4
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncpy.c b/sysdeps/powerpc/powerpc64/multiarch/strncpy.c
|
||||
index 7da9def358..d4d3463bd1 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncpy.c
|
||||
@@ -43,7 +43,7 @@ libc_ifunc_redirected (__redirect_strncpy, strncpy,
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strncpy_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strncpy_power7
|
||||
: __strncpy_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strnlen.c b/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
index 264b7a752d..baf375a75a 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
@@ -31,7 +31,7 @@ extern __typeof (__strnlen) __strnlen_power8 attribute_hidden;
|
||||
libc_ifunc_redirected (__redirect___strnlen, __strnlen,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strnlen_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strnlen_power7
|
||||
: __strnlen_ppc);
|
||||
weak_alias (__strnlen, strnlen)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strrchr.c b/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
index bb06b93d19..1c9eea1817 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
@@ -33,7 +33,7 @@ extern __typeof (strrchr) __strrchr_power8 attribute_hidden;
|
||||
libc_ifunc_redirected (__redirect_strrchr, strrchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
? __strrchr_power8 :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strrchr_power7
|
||||
: __strrchr_ppc);
|
||||
weak_alias (strrchr, rindex)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strstr.c b/sysdeps/powerpc/powerpc64/multiarch/strstr.c
|
||||
index bb0588844e..6582798dda 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strstr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strstr.c
|
||||
@@ -30,7 +30,7 @@ extern __typeof (strstr) __strstr_power7 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect_strstr, strstr,
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strstr_power7
|
||||
: __strstr_ppc);
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
From f2a15dd668913c5a1388ba7e1131b25162b2ea75 Mon Sep 17 00:00:00 2001
|
||||
From: Anton Blanchard <anton@ozlabs.org>
|
||||
Date: Tue, 27 Jul 2021 15:47:50 +1000
|
||||
Subject: powerpc64: Check cacheline size before using optimised memset
|
||||
routines
|
||||
|
||||
A number of optimised memset routines assume the cacheline size is 128B,
|
||||
so we better check before using them.
|
||||
|
||||
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
index 32564c8f1f..a3fdcd43bd 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
@@ -35,6 +35,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
|
||||
unsigned long int hwcap = GLRO(dl_hwcap);
|
||||
unsigned long int hwcap2 = GLRO(dl_hwcap2);
|
||||
+#ifdef SHARED
|
||||
+ int cacheline_size = GLRO(dl_cache_line_size);
|
||||
+#endif
|
||||
|
||||
/* hwcap contains only the latest supported ISA, the code checks which is
|
||||
and fills the previous supported ones. */
|
||||
@@ -90,16 +93,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL_ADD (array, i, memset,
|
||||
hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
&& hwcap2 & PPC_FEATURE2_HAS_ISEL
|
||||
- && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX
|
||||
+ && cacheline_size == 128,
|
||||
__memset_power10)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && cacheline_size == 128,
|
||||
__memset_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && cacheline_size == 128,
|
||||
__memset_power7)
|
||||
- IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_05,
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_05
|
||||
+ && cacheline_size == 128,
|
||||
__memset_power6)
|
||||
- IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_POWER4,
|
||||
+ IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_POWER4
|
||||
+ && cacheline_size == 128,
|
||||
__memset_power4)
|
||||
IFUNC_IMPL_ADD (array, i, memset, 1, __memset_ppc))
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset.c b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
index c1aa143f60..056e911699 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
@@ -43,16 +43,21 @@ libc_ifunc (__libc_memset,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
&& hwcap2 & PPC_FEATURE2_HAS_ISEL
|
||||
- && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX
|
||||
+ && GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power10 :
|
||||
# endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power8 :
|
||||
- (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power7 :
|
||||
- (hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_05
|
||||
+ && GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power6 :
|
||||
- (hwcap & PPC_FEATURE_POWER4)
|
||||
+ (hwcap & PPC_FEATURE_POWER4
|
||||
+ && GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power4
|
||||
: __memset_ppc);
|
||||
|
|
@ -0,0 +1,703 @@
|
|||
From 60b4dd25790342b40e8942e3a4115f511a6b6911 Mon Sep 17 00:00:00 2001
|
||||
From: Anton Blanchard <anton@ozlabs.org>
|
||||
Date: Tue, 27 Jul 2021 15:47:51 +1000
|
||||
Subject: powerpc64: Add checks for Altivec and VSX in ifunc selection
|
||||
|
||||
We'd like to support processors without Altivec or VSX, so check
|
||||
the relevant hwcap bits before selecting them.
|
||||
|
||||
Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/bzero.c b/sysdeps/powerpc/powerpc64/multiarch/bzero.c
|
||||
index 660d7dc686..c8ffbea01c 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/bzero.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/bzero.c
|
||||
@@ -38,11 +38,13 @@ libc_ifunc (__bzero,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __bzero_power10 :
|
||||
# endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __bzero_power8 :
|
||||
(hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __bzero_power7 :
|
||||
- (hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_05
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __bzero_power6 :
|
||||
(hwcap & PPC_FEATURE_POWER4)
|
||||
? __bzero_power4
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
index a3fdcd43bd..c3e25c5981 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
@@ -60,9 +60,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__memcpy_power10)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, memcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, memcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memcpy_power8_cached)
|
||||
- IFUNC_IMPL_ADD (array, i, memcpy, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, memcpy, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memcpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memcpy, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memcpy_a2)
|
||||
@@ -83,7 +85,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__memmove_power10)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, memmove, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, memmove, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memmove_power7)
|
||||
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_ppc))
|
||||
|
||||
@@ -98,6 +101,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
__memset_power10)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC
|
||||
&& cacheline_size == 128,
|
||||
__memset_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
@@ -114,12 +118,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcpy.c. */
|
||||
IFUNC_IMPL (i, name, strcpy,
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
- IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00,
|
||||
+ IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strcpy_power9)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strcpy_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, strcpy, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, strcpy, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strcpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strcpy, 1,
|
||||
__strcpy_ppc))
|
||||
@@ -127,12 +134,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/stpcpy.c. */
|
||||
IFUNC_IMPL (i, name, stpcpy,
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
- IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00,
|
||||
+ IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__stpcpy_power9)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__stpcpy_power8)
|
||||
- IFUNC_IMPL_ADD (array, i, stpcpy, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ IFUNC_IMPL_ADD (array, i, stpcpy, hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__stpcpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, stpcpy, 1,
|
||||
__stpcpy_ppc))
|
||||
@@ -140,12 +150,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strlen.c. */
|
||||
IFUNC_IMPL (i, name, strlen,
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
- IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_1,
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strlen_power10)
|
||||
- IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_00,
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strlen_power9)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strlen_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strlen, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strlen_power7)
|
||||
@@ -155,7 +168,8 @@ __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_00,
|
||||
+ IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strncmp_power9)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
@@ -170,7 +184,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strchr.c. */
|
||||
IFUNC_IMPL (i, name, strchr,
|
||||
IFUNC_IMPL_ADD (array, i, strchr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strchr,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -181,7 +196,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strchrnul.c. */
|
||||
IFUNC_IMPL (i, name, strchrnul,
|
||||
IFUNC_IMPL_ADD (array, i, strchrnul,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strchrnul_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strchrnul,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -198,7 +214,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__memcmp_power10)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, memcmp, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, memcmp, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memcmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__memcmp_power7)
|
||||
@@ -215,11 +232,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__bzero_power10)
|
||||
#endif
|
||||
- IFUNC_IMPL_ADD (array, i, bzero, hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ IFUNC_IMPL_ADD (array, i, bzero, hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__bzero_power8)
|
||||
IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__bzero_power7)
|
||||
- IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_ARCH_2_05,
|
||||
+ IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_ARCH_2_05
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__bzero_power6)
|
||||
IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_POWER4,
|
||||
__bzero_power4)
|
||||
@@ -241,7 +260,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/mempcpy.c. */
|
||||
IFUNC_IMPL (i, name, mempcpy,
|
||||
IFUNC_IMPL_ADD (array, i, mempcpy,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__mempcpy_power7)
|
||||
IFUNC_IMPL_ADD (array, i, mempcpy, 1,
|
||||
__mempcpy_ppc))
|
||||
@@ -249,7 +269,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/memchr.c. */
|
||||
IFUNC_IMPL (i, name, memchr,
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -260,7 +281,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/memrchr.c. */
|
||||
IFUNC_IMPL (i, name, memrchr,
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__memrchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -276,7 +298,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
&& (hwcap & PPC_FEATURE_HAS_VSX),
|
||||
__rawmemchr_power10)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_3_00,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__rawmemchr_power9)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
@@ -288,7 +311,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strnlen.c. */
|
||||
IFUNC_IMPL (i, name, strnlen,
|
||||
IFUNC_IMPL_ADD (array, i, strnlen,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strnlen_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strnlen, hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
__strnlen_power7)
|
||||
@@ -298,7 +322,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c. */
|
||||
IFUNC_IMPL (i, name, strcasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strcasecmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -316,7 +341,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strncase.c. */
|
||||
IFUNC_IMPL (i, name, strncasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strncasecmp_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -334,7 +360,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strrchr.c. */
|
||||
IFUNC_IMPL (i, name, strrchr,
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strrchr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
hwcap & PPC_FEATURE_ARCH_2_06,
|
||||
@@ -345,10 +372,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strncat.c. */
|
||||
IFUNC_IMPL (i, name, strncat,
|
||||
IFUNC_IMPL_ADD (array, i, strncat,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strncat_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strncat,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strncat_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strncat, 1,
|
||||
__strncat_ppc))
|
||||
@@ -391,7 +420,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strcmp,
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_3_00,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strcmp_power9)
|
||||
#endif
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
@@ -406,10 +436,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcat.c. */
|
||||
IFUNC_IMPL (i, name, strcat,
|
||||
IFUNC_IMPL_ADD (array, i, strcat,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strcat_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcat,
|
||||
- hwcap & PPC_FEATURE_HAS_VSX,
|
||||
+ hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strcat_power7)
|
||||
IFUNC_IMPL_ADD (array, i, strcat, 1,
|
||||
__strcat_ppc))
|
||||
@@ -417,7 +449,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strspn.c. */
|
||||
IFUNC_IMPL (i, name, strspn,
|
||||
IFUNC_IMPL_ADD (array, i, strspn,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strspn_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strspn, 1,
|
||||
__strspn_ppc))
|
||||
@@ -425,7 +458,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcspn.c. */
|
||||
IFUNC_IMPL (i, name, strcspn,
|
||||
IFUNC_IMPL_ADD (array, i, strcspn,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX,
|
||||
__strcspn_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcspn, 1,
|
||||
__strcspn_ppc))
|
||||
@@ -442,7 +476,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/powerpc/powerpc64/multiarch/strcasestr.c. */
|
||||
IFUNC_IMPL (i, name, strcasestr,
|
||||
IFUNC_IMPL_ADD (array, i, strcasestr,
|
||||
- hwcap2 & PPC_FEATURE2_ARCH_2_07,
|
||||
+ hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC,
|
||||
__strcasestr_power8)
|
||||
IFUNC_IMPL_ADD (array, i, strcasestr, 1,
|
||||
__strcasestr_ppc))
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memchr.c b/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
index c24186689e..f40013e061 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memchr.c
|
||||
@@ -28,7 +28,8 @@ extern __typeof (__memchr) __memchr_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc (__memchr,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __memchr_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memchr_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
index 99559bce26..89b56c103b 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
|
||||
@@ -38,7 +38,8 @@ libc_ifunc_redirected (__redirect_memcmp, memcmp,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __memcmp_power10 :
|
||||
#endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __memcmp_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memcmp_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcpy.c b/sysdeps/powerpc/powerpc64/multiarch/memcpy.c
|
||||
index 53ab32ef26..684ee064f2 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memcpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memcpy.c
|
||||
@@ -45,9 +45,12 @@ libc_ifunc (__libc_memcpy,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_3_1 && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __memcpy_power10 :
|
||||
# endif
|
||||
- ((hwcap2 & PPC_FEATURE2_ARCH_2_07) && use_cached_memopt)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC
|
||||
+ && use_cached_memopt)
|
||||
? __memcpy_power8_cached :
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __memcpy_power7 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memcpy_a2 :
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memmove.c b/sysdeps/powerpc/powerpc64/multiarch/memmove.c
|
||||
index 637b2cbf7f..50253b4554 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memmove.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memmove.c
|
||||
@@ -41,7 +41,8 @@ libc_ifunc (__libc_memmove,
|
||||
&& hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __memmove_power10 :
|
||||
#endif
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __memmove_power7
|
||||
: __memmove_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/mempcpy.c b/sysdeps/powerpc/powerpc64/multiarch/mempcpy.c
|
||||
index b37e0f35b5..563095a5ec 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/mempcpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/mempcpy.c
|
||||
@@ -33,7 +33,8 @@ extern __typeof (__mempcpy) __mempcpy_power7 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect___mempcpy, __mempcpy,
|
||||
- (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __mempcpy_power7
|
||||
: __mempcpy_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memrchr.c b/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
index 16bb6f0042..a8b985b06a 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memrchr.c
|
||||
@@ -28,7 +28,8 @@ extern __typeof (__memrchr) __memrchr_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc (__memrchr,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __memrchr_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __memrchr_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset.c b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
index 056e911699..a2bc223bcc 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/memset.c
|
||||
@@ -48,6 +48,7 @@ libc_ifunc (__libc_memset,
|
||||
? __memset_power10 :
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC
|
||||
&& GLRO(dl_cache_line_size) == 128)
|
||||
? __memset_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
index b5d2d3a635..43eb459e02 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c
|
||||
@@ -38,7 +38,8 @@ libc_ifunc_redirected (__redirect___rawmemchr, __rawmemchr,
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_3_1)
|
||||
&& (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __rawmemchr_power10 :
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __rawmemchr_power9 :
|
||||
# endif
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c b/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c
|
||||
index d4eb4285fc..5be413405e 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c
|
||||
@@ -32,12 +32,15 @@ extern __typeof (__stpcpy) __stpcpy_power9 attribute_hidden;
|
||||
|
||||
libc_ifunc_hidden (__stpcpy, __stpcpy,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __stpcpy_power9 :
|
||||
# endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __stpcpy_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __stpcpy_power7
|
||||
: __stpcpy_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
index 55ca6c85c4..21ce2d279b 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcasecmp.c
|
||||
@@ -27,7 +27,8 @@ extern __typeof (__strcasecmp) __strcasecmp_power7 attribute_hidden;
|
||||
extern __typeof (__strcasecmp) __strcasecmp_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_strcasecmp,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strcasecmp_power8:
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strcasecmp_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcasestr.c b/sysdeps/powerpc/powerpc64/multiarch/strcasestr.c
|
||||
index 7e4bd3b5ac..5bb3016022 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcasestr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcasestr.c
|
||||
@@ -27,7 +27,8 @@ extern __typeof (__strcasestr) __strcasestr_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc (__strcasestr,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strcasestr_power8
|
||||
: __strcasestr_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcat.c b/sysdeps/powerpc/powerpc64/multiarch/strcat.c
|
||||
index 6d342324c4..d8d9870824 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcat.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcat.c
|
||||
@@ -28,9 +28,11 @@ extern __typeof (strcat) __strcat_power8 attribute_hidden;
|
||||
# undef strcat
|
||||
|
||||
libc_ifunc_redirected (__redirect_strcat, strcat,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strcat_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strcat_power7
|
||||
: __strcat_ppc);
|
||||
#endif
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strchr.c b/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
index 27c794c6b7..62b202baf9 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strchr.c
|
||||
@@ -33,7 +33,8 @@ extern __typeof (strchr) __strchr_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect_strchr, strchr,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strchr_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strchr_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c b/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
index 4a07b4a242..40e529b9d9 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strchrnul.c
|
||||
@@ -28,7 +28,8 @@ extern __typeof (__strchrnul) __strchrnul_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc (__strchrnul,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strchrnul_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strchrnul_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
index 4b0b25fff6..8132682a99 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c
|
||||
@@ -35,7 +35,8 @@ extern __typeof (strcmp) __strcmp_power9 attribute_hidden;
|
||||
|
||||
libc_ifunc_redirected (__redirect_strcmp, strcmp,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strcmp_power9 :
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcpy.c b/sysdeps/powerpc/powerpc64/multiarch/strcpy.c
|
||||
index b733fa5a23..5af1d45cc1 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcpy.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcpy.c
|
||||
@@ -32,12 +32,15 @@ extern __typeof (strcpy) __strcpy_power9 attribute_hidden;
|
||||
|
||||
libc_ifunc_redirected (__redirect_strcpy, strcpy,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strcpy_power9 :
|
||||
# endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strcpy_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strcpy_power7
|
||||
: __strcpy_ppc);
|
||||
#endif
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcspn.c b/sysdeps/powerpc/powerpc64/multiarch/strcspn.c
|
||||
index 683aa104d7..8ba01c13b1 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strcspn.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strcspn.c
|
||||
@@ -27,7 +27,8 @@ extern __typeof (strcspn) __strcspn_ppc attribute_hidden;
|
||||
extern __typeof (strcspn) __strcspn_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_strcspn,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strcspn_power8
|
||||
: __strcspn_ppc);
|
||||
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen.c b/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
index 0cd1c6faff..f1e28414e0 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strlen.c
|
||||
@@ -35,12 +35,15 @@ extern __typeof (__redirect_strlen) __strlen_power10 attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_strlen,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_1)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_1
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strlen_power10 :
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strlen_power9 :
|
||||
# endif
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strlen_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strlen_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncase.c b/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
index 644046bd74..2802cf2c3f 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncase.c
|
||||
@@ -27,7 +27,8 @@ extern __typeof (__strncasecmp) __strncasecmp_power7 attribute_hidden;
|
||||
extern __typeof (__strncasecmp) __strncasecmp_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_strncasecmp,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strncasecmp_power8:
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strncasecmp_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncat.c b/sysdeps/powerpc/powerpc64/multiarch/strncat.c
|
||||
index 0036fca91a..9ea294a72d 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncat.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncat.c
|
||||
@@ -26,9 +26,11 @@ extern __typeof (strncat) __strncat_power7 attribute_hidden;
|
||||
extern __typeof (strncat) __strncat_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (strncat,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strncat_power8
|
||||
- : (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ : (hwcap & PPC_FEATURE_ARCH_2_06
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strncat_power7
|
||||
: __strncat_ppc);
|
||||
#endif
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
index 1f689e5c05..2d21122854 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c
|
||||
@@ -38,7 +38,8 @@ extern __typeof (strncmp) __strncmp_power9 attribute_hidden;
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect_strncmp, strncmp,
|
||||
# ifdef __LITTLE_ENDIAN__
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_3_00)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_3_00
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strncmp_power9 :
|
||||
# endif
|
||||
(hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strnlen.c b/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
index baf375a75a..e68e9d9f88 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strnlen.c
|
||||
@@ -29,7 +29,8 @@ extern __typeof (__strnlen) __strnlen_power8 attribute_hidden;
|
||||
# undef strnlen
|
||||
# undef __strnlen
|
||||
libc_ifunc_redirected (__redirect___strnlen, __strnlen,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strnlen_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strnlen_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strrchr.c b/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
index 1c9eea1817..7f0cf2a1b7 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strrchr.c
|
||||
@@ -31,7 +31,8 @@ extern __typeof (strrchr) __strrchr_power8 attribute_hidden;
|
||||
/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
|
||||
ifunc symbol properly. */
|
||||
libc_ifunc_redirected (__redirect_strrchr, strrchr,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_ALTIVEC)
|
||||
? __strrchr_power8 :
|
||||
(hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
? __strrchr_power7
|
||||
diff --git a/sysdeps/powerpc/powerpc64/multiarch/strspn.c b/sysdeps/powerpc/powerpc64/multiarch/strspn.c
|
||||
index 70167a176b..7613ab3d55 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/strspn.c
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/strspn.c
|
||||
@@ -27,7 +27,8 @@ extern __typeof (strspn) __strspn_ppc attribute_hidden;
|
||||
extern __typeof (strspn) __strspn_power8 attribute_hidden;
|
||||
|
||||
libc_ifunc (__libc_strspn,
|
||||
- (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ (hwcap2 & PPC_FEATURE2_ARCH_2_07
|
||||
+ && hwcap & PPC_FEATURE_HAS_VSX)
|
||||
? __strspn_power8
|
||||
: __strspn_ppc);
|
||||
|
|
@ -0,0 +1,652 @@
|
|||
From 21841f0d562f0e944c4d267a28cc3ebd19c847e9 Mon Sep 17 00:00:00 2001
|
||||
From: Mahesh Bodapati <bmahi496@linux.ibm.com>
|
||||
Date: Tue, 1 Aug 2023 07:41:17 -0500
|
||||
Subject: PowerPC: Influence cpu/arch hwcap features via GLIBC_TUNABLES
|
||||
|
||||
This patch enables the option to influence hwcaps used by PowerPC.
|
||||
The environment variable, GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz....,
|
||||
can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature xxx
|
||||
and zzz, where the feature name is case-sensitive and has to match the ones
|
||||
mentioned in the file{sysdeps/powerpc/dl-procinfo.c}.
|
||||
|
||||
Note that the hwcap tunables only used in the IFUNC selection.
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
[rebased to c9s by DJ]
|
||||
|
||||
diff -rupN a/manual/tunables.texi b/manual/tunables.texi
|
||||
--- a/manual/tunables.texi 2023-09-13 01:16:19.979884270 -0400
|
||||
+++ b/manual/tunables.texi 2023-09-13 01:17:19.217179994 -0400
|
||||
@@ -476,7 +476,10 @@ On s390x, the supported HWCAP and STFLE
|
||||
@code{sysdeps/s390/cpu-features.c}. In addition the user can also set
|
||||
a CPU arch-level like @code{z13} instead of single HWCAP and STFLE features.
|
||||
|
||||
-This tunable is specific to i386, x86-64 and s390x.
|
||||
+On powerpc, the supported HWCAP and HWCAP2 features can be found in
|
||||
+@code{sysdeps/powerpc/dl-procinfo.c}.
|
||||
+
|
||||
+This tunable is specific to i386, x86-64, s390x and powerpc.
|
||||
@end deftp
|
||||
|
||||
@deftp Tunable glibc.cpu.cached_memopt
|
||||
diff -rupN a/sysdeps/powerpc/cpu-features.c b/sysdeps/powerpc/cpu-features.c
|
||||
--- a/sysdeps/powerpc/cpu-features.c 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/cpu-features.c 1969-12-31 19:00:00.000000000 -0500
|
||||
@@ -1,39 +0,0 @@
|
||||
-/* Initialize cpu feature data. PowerPC version.
|
||||
- Copyright (C) 2017-2021 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
|
||||
- <https://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-#include <stdint.h>
|
||||
-#include <cpu-features.h>
|
||||
-
|
||||
-#if HAVE_TUNABLES
|
||||
-# include <elf/dl-tunables.h>
|
||||
-#endif
|
||||
-
|
||||
-static inline void
|
||||
-init_cpu_features (struct cpu_features *cpu_features)
|
||||
-{
|
||||
- /* Default is to use aligned memory access on optimized function unless
|
||||
- tunables is enable, since for this case user can explicit disable
|
||||
- unaligned optimizations. */
|
||||
-#if HAVE_TUNABLES
|
||||
- int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t,
|
||||
- NULL);
|
||||
- cpu_features->use_cached_memopt = (cached_memfunc > 0);
|
||||
-#else
|
||||
- cpu_features->use_cached_memopt = false;
|
||||
-#endif
|
||||
-}
|
||||
diff -rupN a/sysdeps/powerpc/cpu-features.h b/sysdeps/powerpc/cpu-features.h
|
||||
--- a/sysdeps/powerpc/cpu-features.h 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/cpu-features.h 1969-12-31 19:00:00.000000000 -0500
|
||||
@@ -1,28 +0,0 @@
|
||||
-/* Initialize cpu feature data. PowerPC version.
|
||||
- Copyright (C) 2017-2021 Free Software Foundation, Inc.
|
||||
-
|
||||
- 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
|
||||
- <https://www.gnu.org/licenses/>. */
|
||||
-
|
||||
-#ifndef __CPU_FEATURES_POWERPC_H
|
||||
-# define __CPU_FEATURES_POWERPC_H
|
||||
-
|
||||
-#include <stdbool.h>
|
||||
-
|
||||
-struct cpu_features
|
||||
-{
|
||||
- bool use_cached_memopt;
|
||||
-};
|
||||
-
|
||||
-#endif /* __CPU_FEATURES_H */
|
||||
diff -rupN a/sysdeps/powerpc/dl-tunables.list b/sysdeps/powerpc/dl-tunables.list
|
||||
--- a/sysdeps/powerpc/dl-tunables.list 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/dl-tunables.list 2023-09-13 01:17:19.226180343 -0400
|
||||
@@ -24,5 +24,8 @@ glibc {
|
||||
maxval: 1
|
||||
default: 0
|
||||
}
|
||||
+ hwcaps {
|
||||
+ type: STRING
|
||||
+ }
|
||||
}
|
||||
}
|
||||
diff -rupN a/sysdeps/powerpc/hwcapinfo.c b/sysdeps/powerpc/hwcapinfo.c
|
||||
--- a/sysdeps/powerpc/hwcapinfo.c 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/hwcapinfo.c 2023-09-13 01:17:19.229180459 -0400
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <unistd.h>
|
||||
#include <shlib-compat.h>
|
||||
#include <dl-procinfo.h>
|
||||
+#include <cpu-features.c>
|
||||
|
||||
uint64_t __tcb_hwcap __attribute__ ((visibility ("hidden")));
|
||||
uint32_t __tcb_platform __attribute__ ((visibility ("hidden")));
|
||||
@@ -64,6 +65,9 @@ __tcb_parse_hwcap_and_convert_at_platfor
|
||||
else if (h1 & PPC_FEATURE_POWER5)
|
||||
h1 |= PPC_FEATURE_POWER4;
|
||||
|
||||
+ uint64_t array_hwcaps[] = { h1, h2 };
|
||||
+ init_cpu_features (&GLRO(dl_powerpc_cpu_features), array_hwcaps);
|
||||
+
|
||||
/* Consolidate both HWCAP and HWCAP2 into a single doubleword so that
|
||||
we can read both in a single load later. */
|
||||
__tcb_hwcap = h2;
|
||||
diff -rupN a/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c
|
||||
--- a/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/powerpc32/power4/multiarch/ifunc-impl-list.c 2023-09-13 01:17:19.232180575 -0400
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <wchar.h>
|
||||
#include <ldsodefs.h>
|
||||
#include <ifunc-impl-list.h>
|
||||
+#include <cpu-features.h>
|
||||
|
||||
/* Maximum number of IFUNC implementations. */
|
||||
#define MAX_IFUNC 6
|
||||
@@ -33,7 +34,8 @@ __libc_ifunc_impl_list (const char *name
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
- unsigned long int hwcap = GLRO(dl_hwcap);
|
||||
+ const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features);
|
||||
+ unsigned long int hwcap = features->hwcap;
|
||||
/* hwcap contains only the latest supported ISA, the code checks which is
|
||||
and fills the previous supported ones. */
|
||||
if (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
diff -rupN a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h
|
||||
--- a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h 2023-09-13 01:17:19.232180575 -0400
|
||||
@@ -16,6 +16,7 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <ldsodefs.h>
|
||||
+#include <cpu-features.h>
|
||||
|
||||
/* The code checks if _rtld_global_ro was realocated before trying to access
|
||||
the dl_hwcap field. The assembly is to make the compiler not optimize the
|
||||
@@ -32,11 +33,12 @@
|
||||
# define __GLRO(value) GLRO(value)
|
||||
#endif
|
||||
|
||||
-/* dl_hwcap contains only the latest supported ISA, the macro checks which is
|
||||
- and fills the previous ones. */
|
||||
+/* Get the hardware information post the tunables set, the macro checks
|
||||
+ it and fills the previous ones. */
|
||||
#define INIT_ARCH() \
|
||||
- unsigned long int hwcap = __GLRO(dl_hwcap); \
|
||||
- unsigned long int __attribute__((unused)) hwcap2 = __GLRO(dl_hwcap2); \
|
||||
+ const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features); \
|
||||
+ unsigned long int hwcap = features->hwcap; \
|
||||
+ unsigned long int __attribute__((unused)) hwcap2 = features->hwcap2; \
|
||||
bool __attribute__((unused)) use_cached_memopt = \
|
||||
__GLRO(dl_powerpc_cpu_features.use_cached_memopt); \
|
||||
if (hwcap & PPC_FEATURE_ARCH_2_06) \
|
||||
diff -rupN a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
|
||||
--- a/sysdeps/powerpc/powerpc64/dl-machine.h 2023-09-13 01:16:17.582791395 -0400
|
||||
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h 2023-09-13 01:17:19.236180730 -0400
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <dl-tls.h>
|
||||
#include <sysdep.h>
|
||||
#include <hwcapinfo.h>
|
||||
-#include <cpu-features.c>
|
||||
#include <dl-static-tls.h>
|
||||
#include <dl-funcdesc.h>
|
||||
#include <dl-machine-rel.h>
|
||||
@@ -293,7 +292,6 @@ static inline void __attribute__ ((unuse
|
||||
dl_platform_init (void)
|
||||
{
|
||||
__tcb_parse_hwcap_and_convert_at_platform ();
|
||||
- init_cpu_features (&GLRO(dl_powerpc_cpu_features));
|
||||
}
|
||||
#endif
|
||||
|
||||
diff -rupN a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
|
||||
--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c 2023-09-13 01:16:20.219893569 -0400
|
||||
+++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c 2023-09-13 01:19:17.169756083 -0400
|
||||
@@ -17,6 +17,7 @@
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
+#include <cpu-features.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <ldsodefs.h>
|
||||
@@ -32,9 +33,9 @@ __libc_ifunc_impl_list (const char *name
|
||||
assert (max >= MAX_IFUNC);
|
||||
|
||||
size_t i = 0;
|
||||
-
|
||||
- unsigned long int hwcap = GLRO(dl_hwcap);
|
||||
- unsigned long int hwcap2 = GLRO(dl_hwcap2);
|
||||
+ const struct cpu_features *features = &GLRO(dl_powerpc_cpu_features);
|
||||
+ unsigned long int hwcap = features->hwcap;
|
||||
+ unsigned long int hwcap2 = features->hwcap2;
|
||||
#ifdef SHARED
|
||||
int cacheline_size = GLRO(dl_cache_line_size);
|
||||
#endif
|
||||
diff -rupN a/sysdeps/unix/sysv/linux/powerpc/Makefile b/sysdeps/unix/sysv/linux/powerpc/Makefile
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/Makefile 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/Makefile 2023-09-13 01:17:19.243181002 -0400
|
||||
@@ -21,7 +21,12 @@ ifeq ($(subdir),misc)
|
||||
sysdep_headers += bits/ppc.h
|
||||
sysdep_routines += get_timebase_freq
|
||||
tests-static += test-gettimebasefreq-static
|
||||
-tests += $(tests-static)
|
||||
-tests += test-gettimebasefreq
|
||||
-tests += test-powerpc-linux-sysconf
|
||||
+tests += \
|
||||
+ $(tests-static) \
|
||||
+ test-gettimebasefreq \
|
||||
+ test-powerpc-linux-sysconf \
|
||||
+ tst-hwcap-tunables \
|
||||
+ # tests
|
||||
+
|
||||
+tst-hwcap-tunables-ARGS = -- $(host-test-program-cmd)
|
||||
endif
|
||||
diff -rupN a/sysdeps/unix/sysv/linux/powerpc/cpu-features.c b/sysdeps/unix/sysv/linux/powerpc/cpu-features.c
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/cpu-features.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/cpu-features.c 2023-09-13 01:17:19.247181157 -0400
|
||||
@@ -0,0 +1,124 @@
|
||||
+/* Initialize cpu feature data. PowerPC version.
|
||||
+ Copyright (C) 2017-2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <array_length.h>
|
||||
+#include <stdint.h>
|
||||
+#include <cpu-features.h>
|
||||
+#include <elf/dl-tunables.h>
|
||||
+#include <unistd.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+static void
|
||||
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
|
||||
+{
|
||||
+ /* The current IFUNC selection is always using the most recent
|
||||
+ features which are available via AT_HWCAP or AT_HWCAP2. But in
|
||||
+ some scenarios it is useful to adjust this selection.
|
||||
+
|
||||
+ The environment variable:
|
||||
+
|
||||
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,....
|
||||
+
|
||||
+ Can be used to enable HWCAP/HWCAP2 feature yyy, disable HWCAP/HWCAP2
|
||||
+ feature xxx, where the feature name is case-sensitive and has to match
|
||||
+ the ones mentioned in the file{sysdeps/powerpc/dl-procinfo.c}. */
|
||||
+
|
||||
+ /* Copy the features from dl_powerpc_cpu_features, which contains the
|
||||
+ features provided by AT_HWCAP and AT_HWCAP2. */
|
||||
+ struct cpu_features *cpu_features = &GLRO(dl_powerpc_cpu_features);
|
||||
+ unsigned long int tcbv_hwcap = cpu_features->hwcap;
|
||||
+ unsigned long int tcbv_hwcap2 = cpu_features->hwcap2;
|
||||
+ const char *token = valp->strval;
|
||||
+ do
|
||||
+ {
|
||||
+ const char *token_end, *feature;
|
||||
+ bool disable;
|
||||
+ size_t token_len, i, feature_len, offset = 0;
|
||||
+ /* Find token separator or end of string. */
|
||||
+ for (token_end = token; *token_end != ','; token_end++)
|
||||
+ if (*token_end == '\0')
|
||||
+ break;
|
||||
+
|
||||
+ /* Determine feature. */
|
||||
+ token_len = token_end - token;
|
||||
+ if (*token == '-')
|
||||
+ {
|
||||
+ disable = true;
|
||||
+ feature = token + 1;
|
||||
+ feature_len = token_len - 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ disable = false;
|
||||
+ feature = token;
|
||||
+ feature_len = token_len;
|
||||
+ }
|
||||
+ for (i = 0; i < array_length (hwcap_tunables); ++i)
|
||||
+ {
|
||||
+ const char *hwcap_name = hwcap_names + offset;
|
||||
+ size_t hwcap_name_len = strlen (hwcap_name);
|
||||
+ /* Check the tunable name on the supported list. */
|
||||
+ if (hwcap_name_len == feature_len
|
||||
+ && memcmp (feature, hwcap_name, feature_len) == 0)
|
||||
+ {
|
||||
+ /* Update the hwcap and hwcap2 bits. */
|
||||
+ if (disable)
|
||||
+ {
|
||||
+ /* Id is 1 for hwcap2 tunable. */
|
||||
+ if (hwcap_tunables[i].id)
|
||||
+ cpu_features->hwcap2 &= ~(hwcap_tunables[i].mask);
|
||||
+ else
|
||||
+ cpu_features->hwcap &= ~(hwcap_tunables[i].mask);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Enable the features and also check that no unsupported
|
||||
+ features were enabled by user. */
|
||||
+ if (hwcap_tunables[i].id)
|
||||
+ cpu_features->hwcap2 |= (tcbv_hwcap2 & hwcap_tunables[i].mask);
|
||||
+ else
|
||||
+ cpu_features->hwcap |= (tcbv_hwcap & hwcap_tunables[i].mask);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ offset += hwcap_name_len + 1;
|
||||
+ }
|
||||
+ token += token_len;
|
||||
+ /* ... and skip token separator for next round. */
|
||||
+ if (*token == ',')
|
||||
+ token++;
|
||||
+ }
|
||||
+ while (*token != '\0');
|
||||
+}
|
||||
+
|
||||
+static inline void
|
||||
+init_cpu_features (struct cpu_features *cpu_features, uint64_t hwcaps[])
|
||||
+{
|
||||
+ /* Fill the cpu_features with the supported hwcaps
|
||||
+ which are set by __tcb_parse_hwcap_and_convert_at_platform. */
|
||||
+ cpu_features->hwcap = hwcaps[0];
|
||||
+ cpu_features->hwcap2 = hwcaps[1];
|
||||
+ /* Default is to use aligned memory access on optimized function unless
|
||||
+ tunables is enable, since for this case user can explicit disable
|
||||
+ unaligned optimizations. */
|
||||
+ int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t,
|
||||
+ NULL);
|
||||
+ cpu_features->use_cached_memopt = (cached_memfunc > 0);
|
||||
+ TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *,
|
||||
+ TUNABLE_CALLBACK (set_hwcaps));
|
||||
+}
|
||||
diff -rupN a/sysdeps/unix/sysv/linux/powerpc/cpu-features.h b/sysdeps/unix/sysv/linux/powerpc/cpu-features.h
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/cpu-features.h 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/cpu-features.h 2023-09-13 01:17:19.251181312 -0400
|
||||
@@ -0,0 +1,130 @@
|
||||
+/* Initialize cpu feature data. PowerPC version.
|
||||
+ Copyright (C) 2017-2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef __CPU_FEATURES_POWERPC_H
|
||||
+# define __CPU_FEATURES_POWERPC_H
|
||||
+
|
||||
+#include <stdbool.h>
|
||||
+#include <sys/auxv.h>
|
||||
+
|
||||
+struct cpu_features
|
||||
+{
|
||||
+ bool use_cached_memopt;
|
||||
+ unsigned long int hwcap;
|
||||
+ unsigned long int hwcap2;
|
||||
+};
|
||||
+
|
||||
+static const char hwcap_names[] = {
|
||||
+ "4xxmac\0"
|
||||
+ "altivec\0"
|
||||
+ "arch_2_05\0"
|
||||
+ "arch_2_06\0"
|
||||
+ "archpmu\0"
|
||||
+ "booke\0"
|
||||
+ "cellbe\0"
|
||||
+ "dfp\0"
|
||||
+ "efpdouble\0"
|
||||
+ "efpsingle\0"
|
||||
+ "fpu\0"
|
||||
+ "ic_snoop\0"
|
||||
+ "mmu\0"
|
||||
+ "notb\0"
|
||||
+ "pa6t\0"
|
||||
+ "power4\0"
|
||||
+ "power5\0"
|
||||
+ "power5+\0"
|
||||
+ "power6x\0"
|
||||
+ "ppc32\0"
|
||||
+ "ppc601\0"
|
||||
+ "ppc64\0"
|
||||
+ "ppcle\0"
|
||||
+ "smt\0"
|
||||
+ "spe\0"
|
||||
+ "true_le\0"
|
||||
+ "ucache\0"
|
||||
+ "vsx\0"
|
||||
+ "arch_2_07\0"
|
||||
+ "dscr\0"
|
||||
+ "ebb\0"
|
||||
+ "htm\0"
|
||||
+ "htm-nosc\0"
|
||||
+ "htm-no-suspend\0"
|
||||
+ "isel\0"
|
||||
+ "tar\0"
|
||||
+ "vcrypto\0"
|
||||
+ "arch_3_00\0"
|
||||
+ "ieee128\0"
|
||||
+ "darn\0"
|
||||
+ "scv\0"
|
||||
+ "arch_3_1\0"
|
||||
+ "mma\0"
|
||||
+};
|
||||
+
|
||||
+static const struct
|
||||
+{
|
||||
+ unsigned int mask;
|
||||
+ bool id;
|
||||
+} hwcap_tunables[] = {
|
||||
+ /* AT_HWCAP tunable masks. */
|
||||
+ { PPC_FEATURE_HAS_4xxMAC, 0 },
|
||||
+ { PPC_FEATURE_HAS_ALTIVEC, 0 },
|
||||
+ { PPC_FEATURE_ARCH_2_05, 0 },
|
||||
+ { PPC_FEATURE_ARCH_2_06, 0 },
|
||||
+ { PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0 },
|
||||
+ { PPC_FEATURE_BOOKE, 0 },
|
||||
+ { PPC_FEATURE_CELL_BE, 0 },
|
||||
+ { PPC_FEATURE_HAS_DFP, 0 },
|
||||
+ { PPC_FEATURE_HAS_EFP_DOUBLE, 0 },
|
||||
+ { PPC_FEATURE_HAS_EFP_SINGLE, 0 },
|
||||
+ { PPC_FEATURE_HAS_FPU, 0 },
|
||||
+ { PPC_FEATURE_ICACHE_SNOOP, 0 },
|
||||
+ { PPC_FEATURE_HAS_MMU, 0 },
|
||||
+ { PPC_FEATURE_NO_TB, 0 },
|
||||
+ { PPC_FEATURE_PA6T, 0 },
|
||||
+ { PPC_FEATURE_POWER4, 0 },
|
||||
+ { PPC_FEATURE_POWER5, 0 },
|
||||
+ { PPC_FEATURE_POWER5_PLUS, 0 },
|
||||
+ { PPC_FEATURE_POWER6_EXT, 0 },
|
||||
+ { PPC_FEATURE_32, 0 },
|
||||
+ { PPC_FEATURE_601_INSTR, 0 },
|
||||
+ { PPC_FEATURE_64, 0 },
|
||||
+ { PPC_FEATURE_PPC_LE, 0 },
|
||||
+ { PPC_FEATURE_SMT, 0 },
|
||||
+ { PPC_FEATURE_HAS_SPE, 0 },
|
||||
+ { PPC_FEATURE_TRUE_LE, 0 },
|
||||
+ { PPC_FEATURE_UNIFIED_CACHE, 0 },
|
||||
+ { PPC_FEATURE_HAS_VSX, 0 },
|
||||
+
|
||||
+ /* AT_HWCAP2 tunable masks. */
|
||||
+ { PPC_FEATURE2_ARCH_2_07, 1 },
|
||||
+ { PPC_FEATURE2_HAS_DSCR, 1 },
|
||||
+ { PPC_FEATURE2_HAS_EBB, 1 },
|
||||
+ { PPC_FEATURE2_HAS_HTM, 1 },
|
||||
+ { PPC_FEATURE2_HTM_NOSC, 1 },
|
||||
+ { PPC_FEATURE2_HTM_NO_SUSPEND, 1 },
|
||||
+ { PPC_FEATURE2_HAS_ISEL, 1 },
|
||||
+ { PPC_FEATURE2_HAS_TAR, 1 },
|
||||
+ { PPC_FEATURE2_HAS_VEC_CRYPTO, 1 },
|
||||
+ { PPC_FEATURE2_ARCH_3_00, 1 },
|
||||
+ { PPC_FEATURE2_HAS_IEEE128, 1 },
|
||||
+ { PPC_FEATURE2_DARN, 1 },
|
||||
+ { PPC_FEATURE2_SCV, 1 },
|
||||
+ { PPC_FEATURE2_ARCH_3_1, 1 },
|
||||
+ { PPC_FEATURE2_MMA, 1 },
|
||||
+};
|
||||
+
|
||||
+#endif /* __CPU_FEATURES_H */
|
||||
diff -rupN a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list 2023-09-13 01:16:19.989884657 -0400
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list 2023-09-13 01:17:19.254181428 -0400
|
||||
@@ -28,3 +28,4 @@
|
||||
@order glibc.malloc.check
|
||||
@order glibc.gmon.minarcs
|
||||
@order glibc.gmon.maxarcs
|
||||
+@order glibc.cpu.hwcaps
|
||||
diff -rupN a/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c b/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/tst-hwcap-tunables.c 2023-09-13 01:17:19.258181583 -0400
|
||||
@@ -0,0 +1,128 @@
|
||||
+/* Tests for powerpc GLIBC_TUNABLES=glibc.cpu.hwcaps filter.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <array_length.h>
|
||||
+#include <getopt.h>
|
||||
+#include <ifunc-impl-list.h>
|
||||
+#include <spawn.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <sys/auxv.h>
|
||||
+#include <sys/wait.h>
|
||||
+
|
||||
+/* Nonzero if the program gets called via `exec'. */
|
||||
+#define CMDLINE_OPTIONS \
|
||||
+ { "restart", no_argument, &restart, 1 },
|
||||
+static int restart;
|
||||
+
|
||||
+/* Hold the four initial argument used to respawn the process, plus the extra
|
||||
+ '--direct', '--restart', and the function to check */
|
||||
+static char *spargs[8];
|
||||
+static int fc;
|
||||
+
|
||||
+/* Called on process re-execution. */
|
||||
+_Noreturn static void
|
||||
+handle_restart (int argc, char *argv[])
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (argc == 1);
|
||||
+ const char *funcname = argv[0];
|
||||
+
|
||||
+ struct libc_ifunc_impl impls[32];
|
||||
+ int cnt = __libc_ifunc_impl_list ("memcpy", impls, array_length (impls));
|
||||
+ if (cnt == 0)
|
||||
+ _exit (EXIT_SUCCESS);
|
||||
+ TEST_VERIFY_EXIT (cnt >= 1);
|
||||
+ for (int i = 0; i < cnt; i++) {
|
||||
+ if (strcmp (impls[i].name, funcname) == 0)
|
||||
+ {
|
||||
+ TEST_COMPARE (impls[i].usable, false);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ _exit (EXIT_SUCCESS);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+run_test (const char *filter, const char *funcname)
|
||||
+{
|
||||
+ printf ("info: checking filter %s (expect %s ifunc selection to be removed)\n",
|
||||
+ filter, funcname);
|
||||
+ char *tunable = xasprintf ("GLIBC_TUNABLES=glibc.cpu.hwcaps=%s", filter);
|
||||
+ char *const newenvs[] = { (char*) tunable, NULL };
|
||||
+ spargs[fc] = (char *) funcname;
|
||||
+
|
||||
+ pid_t pid;
|
||||
+ TEST_COMPARE (posix_spawn (&pid, spargs[0], NULL, NULL, spargs, newenvs), 0);
|
||||
+ int status;
|
||||
+ TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
|
||||
+ TEST_VERIFY (WIFEXITED (status));
|
||||
+ TEST_VERIFY (!WIFSIGNALED (status));
|
||||
+ TEST_COMPARE (WEXITSTATUS (status), 0);
|
||||
+
|
||||
+ free (tunable);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (int argc, char *argv[])
|
||||
+{
|
||||
+ if (restart)
|
||||
+ handle_restart (argc - 1, &argv[1]);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (argc == 2 || argc == 5);
|
||||
+
|
||||
+ int i;
|
||||
+ for (i = 0; i < argc - 1; i++)
|
||||
+ spargs[i] = argv[i + 1];
|
||||
+ spargs[i++] = (char *) "--direct";
|
||||
+ spargs[i++] = (char *) "--restart";
|
||||
+ fc = i++;
|
||||
+ spargs[i] = NULL;
|
||||
+
|
||||
+ unsigned long int hwcap = getauxval (AT_HWCAP);
|
||||
+ unsigned long int hwcap2 = getauxval (AT_HWCAP2);
|
||||
+ if (__WORDSIZE == 64)
|
||||
+ {
|
||||
+ if (hwcap2 & PPC_FEATURE2_ARCH_3_1)
|
||||
+ run_test ("-arch_3_1", "__memcpy_power10");
|
||||
+ if (hwcap2 & PPC_FEATURE2_ARCH_2_07)
|
||||
+ run_test ("-arch_2_07", "__memcpy_power8_cached");
|
||||
+ if (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
+ run_test ("-arch_2_06", "__memcpy_power7");
|
||||
+ if (hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
+ run_test ("-arch_2_06,-arch_2_05","__memcpy_power6");
|
||||
+ run_test ("-arch_2_06,-arch_2_05,-power5+,-power5,-power4", "__memcpy_power4");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (hwcap & PPC_FEATURE_HAS_VSX)
|
||||
+ run_test ("-vsx", "__memcpy_power7");
|
||||
+ if (hwcap & PPC_FEATURE_ARCH_2_06)
|
||||
+ run_test ("-arch_2_06", "__memcpy_a2");
|
||||
+ if (hwcap & PPC_FEATURE_ARCH_2_05)
|
||||
+ run_test ("-arch_2_05", "__memcpy_power6");
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION_ARGV do_test
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,69 @@
|
|||
commit 1493622f4f9048ffede3fbedb64695efa49d662a
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Mon Aug 28 12:08:14 2023 -0700
|
||||
|
||||
x86: Check the lower byte of EAX of CPUID leaf 2 [BZ #30643]
|
||||
|
||||
The old Intel software developer manual specified that the low byte of
|
||||
EAX of CPUID leaf 2 returned 1 which indicated the number of rounds of
|
||||
CPUDID leaf 2 was needed to retrieve the complete cache information. The
|
||||
newer Intel manual has been changed to that it should always return 1
|
||||
and be ignored. If the lower byte isn't 1, CPUID leaf 2 can't be used.
|
||||
In this case, we ignore CPUID leaf 2 and use CPUID leaf 4 instead. If
|
||||
CPUID leaf 4 doesn't contain the cache information, cache information
|
||||
isn't available at all. This addresses BZ #30643.
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index f950e488cfbe42dd..bd2f2b65f78056ca 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -187,7 +187,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2,
|
||||
++round;
|
||||
}
|
||||
/* There is no other cache information anywhere else. */
|
||||
- break;
|
||||
+ return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -257,28 +257,23 @@ handle_intel (int name, const struct cpu_features *cpu_features)
|
||||
|
||||
/* OK, we can use the CPUID instruction to get all info about the
|
||||
caches. */
|
||||
- unsigned int cnt = 0;
|
||||
- unsigned int max = 1;
|
||||
long int result = 0;
|
||||
bool no_level_2_or_3 = false;
|
||||
bool has_level_2 = false;
|
||||
+ unsigned int eax;
|
||||
+ unsigned int ebx;
|
||||
+ unsigned int ecx;
|
||||
+ unsigned int edx;
|
||||
+ __cpuid (2, eax, ebx, ecx, edx);
|
||||
|
||||
- while (cnt++ < max)
|
||||
+ /* The low byte of EAX of CPUID leaf 2 should always return 1 and it
|
||||
+ should be ignored. If it isn't 1, use CPUID leaf 4 instead. */
|
||||
+ if ((eax & 0xff) != 1)
|
||||
+ return intel_check_word (name, 0xff, &has_level_2, &no_level_2_or_3,
|
||||
+ cpu_features);
|
||||
+ else
|
||||
{
|
||||
- unsigned int eax;
|
||||
- unsigned int ebx;
|
||||
- unsigned int ecx;
|
||||
- unsigned int edx;
|
||||
- __cpuid (2, eax, ebx, ecx, edx);
|
||||
-
|
||||
- /* The low byte of EAX in the first round contain the number of
|
||||
- rounds we have to make. At least one, the one we are already
|
||||
- doing. */
|
||||
- if (cnt == 1)
|
||||
- {
|
||||
- max = eax & 0xff;
|
||||
- eax &= 0xffffff00;
|
||||
- }
|
||||
+ eax &= 0xffffff00;
|
||||
|
||||
/* Process the individual registers' value. */
|
||||
result = intel_check_word (name, eax, &has_level_2,
|
|
@ -0,0 +1,72 @@
|
|||
commit 2aa0974d2573441bffd596b07bff8698b1f2f18c
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Oct 20 14:29:50 2023 +0200
|
||||
|
||||
elf: ldconfig should skip temporary files created by package managers
|
||||
|
||||
This avoids crashes due to partially written files, after a package
|
||||
update is interrupted.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
elf/ldconfig.c
|
||||
(missing alloca removal downstream)
|
||||
|
||||
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||
index be47ad8c2d7f89f3..f0c811001965cc46 100644
|
||||
--- a/elf/ldconfig.c
|
||||
+++ b/elf/ldconfig.c
|
||||
@@ -778,6 +778,31 @@ struct dlib_entry
|
||||
struct dlib_entry *next;
|
||||
};
|
||||
|
||||
+/* Skip some temporary DSO files. These files may be partially written
|
||||
+ and lead to ldconfig crashes when examined. */
|
||||
+static bool
|
||||
+skip_dso_based_on_name (const char *name, size_t len)
|
||||
+{
|
||||
+ /* Skip temporary files created by the prelink program. Files with
|
||||
+ names like these are never really DSOs we want to look at. */
|
||||
+ if (len >= sizeof (".#prelink#") - 1)
|
||||
+ {
|
||||
+ if (strcmp (name + len - sizeof (".#prelink#") + 1,
|
||||
+ ".#prelink#") == 0)
|
||||
+ return true;
|
||||
+ if (len >= sizeof (".#prelink#.XXXXXX") - 1
|
||||
+ && memcmp (name + len - sizeof (".#prelink#.XXXXXX")
|
||||
+ + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
|
||||
+ return true;
|
||||
+ }
|
||||
+ /* Skip temporary files created by RPM. */
|
||||
+ if (memchr (name, len, ';') != NULL)
|
||||
+ return true;
|
||||
+ /* Skip temporary files created by dpkg. */
|
||||
+ if (len > 4 && memcmp (name + len - 4, ".tmp", 4) == 0)
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
|
||||
static void
|
||||
search_dir (const struct dir_entry *entry)
|
||||
@@ -854,18 +879,8 @@ search_dir (const struct dir_entry *entry)
|
||||
continue;
|
||||
|
||||
size_t len = strlen (direntry->d_name);
|
||||
- /* Skip temporary files created by the prelink program. Files with
|
||||
- names like these are never really DSOs we want to look at. */
|
||||
- if (len >= sizeof (".#prelink#") - 1)
|
||||
- {
|
||||
- if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1,
|
||||
- ".#prelink#") == 0)
|
||||
- continue;
|
||||
- if (len >= sizeof (".#prelink#.XXXXXX") - 1
|
||||
- && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
|
||||
- + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
|
||||
- continue;
|
||||
- }
|
||||
+ if (skip_dso_based_on_name (direntry->d_name, len))
|
||||
+ continue;
|
||||
len += strlen (entry->path) + 2;
|
||||
if (len > file_name_len)
|
||||
{
|
|
@ -0,0 +1,61 @@
|
|||
commit cfb5a97a93ea656e3b2263e42142a4032986d9ba
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Oct 23 12:53:16 2023 +0200
|
||||
|
||||
ldconfig: Fixes for skipping temporary files.
|
||||
|
||||
Arguments to a memchr call were swapped, causing incorrect skipping
|
||||
of files.
|
||||
|
||||
Files related to dpkg have different names: they actually end in
|
||||
.dpkg-new and .dpkg-tmp, not .tmp as I mistakenly assumed.
|
||||
|
||||
Fixes commit 2aa0974d2573441bffd59 ("elf: ldconfig should skip
|
||||
temporary files created by package managers").
|
||||
|
||||
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||
index f0c811001965cc46..4a96c409994d96c8 100644
|
||||
--- a/elf/ldconfig.c
|
||||
+++ b/elf/ldconfig.c
|
||||
@@ -778,6 +778,17 @@ struct dlib_entry
|
||||
struct dlib_entry *next;
|
||||
};
|
||||
|
||||
+/* Return true if the N bytes at NAME end with with the characters in
|
||||
+ the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
|
||||
+ Expected to be called with a string literal for SUFFIX. */
|
||||
+static inline bool
|
||||
+endswithn (const char *name, size_t n, const char *suffix)
|
||||
+{
|
||||
+ return (n >= strlen (suffix)
|
||||
+ && memcmp (name + n - strlen (suffix), suffix,
|
||||
+ strlen (suffix)) == 0);
|
||||
+}
|
||||
+
|
||||
/* Skip some temporary DSO files. These files may be partially written
|
||||
and lead to ldconfig crashes when examined. */
|
||||
static bool
|
||||
@@ -787,8 +798,7 @@ skip_dso_based_on_name (const char *name, size_t len)
|
||||
names like these are never really DSOs we want to look at. */
|
||||
if (len >= sizeof (".#prelink#") - 1)
|
||||
{
|
||||
- if (strcmp (name + len - sizeof (".#prelink#") + 1,
|
||||
- ".#prelink#") == 0)
|
||||
+ if (endswithn (name, len, ".#prelink#"))
|
||||
return true;
|
||||
if (len >= sizeof (".#prelink#.XXXXXX") - 1
|
||||
&& memcmp (name + len - sizeof (".#prelink#.XXXXXX")
|
||||
@@ -796,10 +806,11 @@ skip_dso_based_on_name (const char *name, size_t len)
|
||||
return true;
|
||||
}
|
||||
/* Skip temporary files created by RPM. */
|
||||
- if (memchr (name, len, ';') != NULL)
|
||||
+ if (memchr (name, ';', len) != NULL)
|
||||
return true;
|
||||
/* Skip temporary files created by dpkg. */
|
||||
- if (len > 4 && memcmp (name + len - 4, ".tmp", 4) == 0)
|
||||
+ if (endswithn (name, len, ".dpkg-new")
|
||||
+ || endswithn (name, len, ".dpkg-tmp"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
commit 1626d8a521c7c771d4118b1328421fea113cab64
|
||||
Author: Joe Simmons-Talbott <josimmon@redhat.com>
|
||||
Date: Fri Apr 21 09:24:22 2023 -0400
|
||||
|
||||
string: Allow use of test-string.h for non-ifunc implementations.
|
||||
|
||||
Mark two variables as unused to silence warning when using
|
||||
test-string.h for non-ifunc implementations.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/string/test-string.h b/string/test-string.h
|
||||
index 41de973479..8bcb8afd0a 100644
|
||||
--- a/string/test-string.h
|
||||
+++ b/string/test-string.h
|
||||
@@ -130,8 +130,8 @@ cmdline_process_function (int c)
|
||||
/* Increase size of FUNC_LIST if assert is triggered at run-time. */
|
||||
static struct libc_ifunc_impl func_list[32];
|
||||
static int func_count;
|
||||
-static int impl_count = -1;
|
||||
-static impl_t *impl_array;
|
||||
+static int impl_count __attribute__ ((unused)) = -1;
|
||||
+static impl_t *impl_array __attribute__ ((unused));
|
||||
|
||||
# define FOR_EACH_IMPL(impl, notall) \
|
||||
impl_t *impl; \
|
|
@ -0,0 +1,233 @@
|
|||
commit eaaad78db41724e5a18a42becb238bfc4e683998
|
||||
Author: Joe Simmons-Talbott <josimmon@redhat.com>
|
||||
Date: Fri Apr 21 09:24:23 2023 -0400
|
||||
|
||||
string: Add tests for strdup (BZ #30266)
|
||||
|
||||
Copy strcpy tests for strdup. Covers some basic testcases with random
|
||||
strings. Add a zero-length string testcase.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Conflicts:
|
||||
string/Makefile
|
||||
(different test backport order)
|
||||
|
||||
|
||||
diff -Nrup a/string/Makefile b/string/Makefile
|
||||
--- a/string/Makefile 2023-11-30 10:59:16.400251685 -0500
|
||||
+++ b/string/Makefile 2023-11-30 11:16:42.829613344 -0500
|
||||
@@ -63,7 +63,8 @@ tests := tester inl-tester noinl-tester
|
||||
tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt \
|
||||
test-endian-types test-endian-file-scope \
|
||||
test-endian-sign-conversion tst-memmove-overflow \
|
||||
- test-sig_np tst-strerror-fail
|
||||
+ test-sig_np tst-strerror-fail \
|
||||
+ test-strdup
|
||||
|
||||
# Both tests require the .mo translation files generated by msgfmt.
|
||||
tests-translation := tst-strsignal \
|
||||
diff -Nrup a/string/test-strdup.c b/string/test-strdup.c
|
||||
--- a/string/test-strdup.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/string/test-strdup.c 2023-11-30 11:11:32.850447614 -0500
|
||||
@@ -0,0 +1,201 @@
|
||||
+/* Test and measure strdup functions.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+#ifdef WIDE
|
||||
+# include <wchar.h>
|
||||
+# define CHAR wchar_t
|
||||
+# define sfmt "ls"
|
||||
+# define BIG_CHAR WCHAR_MAX
|
||||
+# define SMALL_CHAR 1273
|
||||
+# define STRCMP wcscmp
|
||||
+# define MEMCMP wmemcmp
|
||||
+# define MEMSET wmemset
|
||||
+# define TCS TEST_COMPARE_STRING_WIDE
|
||||
+#else
|
||||
+# define CHAR char
|
||||
+# define sfmt "s"
|
||||
+# define BIG_CHAR CHAR_MAX
|
||||
+# define SMALL_CHAR 127
|
||||
+# define STRCMP strcmp
|
||||
+# define MEMCMP memcmp
|
||||
+# define MEMSET memset
|
||||
+# define TCS TEST_COMPARE_STRING
|
||||
+#endif
|
||||
+
|
||||
+#ifndef STRDUP_RESULT
|
||||
+# define STRDUP_RESULT(dst, len) dst
|
||||
+# define TEST_MAIN
|
||||
+# ifndef WIDE
|
||||
+# define TEST_NAME "strdup"
|
||||
+# else
|
||||
+# define TEST_NAME "wcsdup"
|
||||
+# endif
|
||||
+# include "test-string.h"
|
||||
+# ifndef WIDE
|
||||
+# define STRDUP strdup
|
||||
+# else
|
||||
+# define STRDUP wcsdup
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
+typedef CHAR *(*proto_t) (const CHAR *);
|
||||
+
|
||||
+static void
|
||||
+do_zero_len_test (void)
|
||||
+{
|
||||
+ CHAR src[1] = { '\0' };
|
||||
+ CHAR *dst = STRDUP (src);
|
||||
+
|
||||
+ TCS (dst, src);
|
||||
+ free (dst);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_one_test (const CHAR *src,
|
||||
+ size_t len __attribute__((unused)))
|
||||
+{
|
||||
+ CHAR *dst = STRDUP (src);
|
||||
+
|
||||
+ if (STRCMP (dst, src) != 0)
|
||||
+ {
|
||||
+ error (0, 0,
|
||||
+ "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"",
|
||||
+ TEST_NAME, dst, src);
|
||||
+ ret = 1;
|
||||
+ free (dst);
|
||||
+ return;
|
||||
+ }
|
||||
+ free (dst);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_test (size_t align1, size_t align2, size_t len, int max_char)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ CHAR *s1;
|
||||
+/* For wcsdup: align1 and align2 here mean alignment not in bytes,
|
||||
+ but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t))
|
||||
+ len for wcschr here isn't in bytes but it's number of wchar_t symbols. */
|
||||
+ align1 &= 7;
|
||||
+ if ((align1 + len) * sizeof (CHAR) >= page_size)
|
||||
+ return;
|
||||
+
|
||||
+ align2 &= 7;
|
||||
+ if ((align2 + len) * sizeof (CHAR) >= page_size)
|
||||
+ return;
|
||||
+
|
||||
+ s1 = (CHAR *) (buf1) + align1;
|
||||
+
|
||||
+ for (i = 0; i < len; i++)
|
||||
+ s1[i] = 32 + 23 * i % (max_char - 32);
|
||||
+ s1[len] = 0;
|
||||
+
|
||||
+ do_one_test (s1, len);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_random_tests (void)
|
||||
+{
|
||||
+ size_t i, j, n, align1, align2, len;
|
||||
+ CHAR *p1 = (CHAR *)(buf1 + page_size) - 512;
|
||||
+ CHAR *res;
|
||||
+
|
||||
+ for (n = 0; n < ITERATIONS; n++)
|
||||
+ {
|
||||
+ /* align1 and align2 are expressed as wchar_t and not in bytes for wide
|
||||
+ char test, and thus it will be equal to align times wchar_t size.
|
||||
+
|
||||
+ For non wide version we need to check all alignments from 0 to 63
|
||||
+ since some assembly implementations have separate prolog for alignments
|
||||
+ more 48. */
|
||||
+
|
||||
+ align1 = random () & (63 / sizeof (CHAR));
|
||||
+ if (random () & 1)
|
||||
+ align2 = random () & (63 / sizeof (CHAR));
|
||||
+ else
|
||||
+ align2 = align1 + (random () & 24);
|
||||
+ len = random () & 511;
|
||||
+ j = align1;
|
||||
+ if (align2 > j)
|
||||
+ j = align2;
|
||||
+ if (len + j >= 511)
|
||||
+ len = 510 - j - (random () & 7);
|
||||
+ j = len + align1 + 64;
|
||||
+ if (j > 512)
|
||||
+ j = 512;
|
||||
+ for (i = 0; i < j; i++)
|
||||
+ {
|
||||
+ if (i == len + align1)
|
||||
+ p1[i] = 0;
|
||||
+ else
|
||||
+ {
|
||||
+ p1[i] = random () & BIG_CHAR;
|
||||
+ if (i >= align1 && i < len + align1 && !p1[i])
|
||||
+ p1[i] = (random () & SMALL_CHAR) + 3;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ res = STRDUP(p1 + align1);
|
||||
+ TCS (res, (p1 + align1));
|
||||
+ free (res);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int
|
||||
+test_main (void)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ test_init ();
|
||||
+
|
||||
+ printf ("%23s", "");
|
||||
+ printf ("\t%s", TEST_NAME);
|
||||
+ putchar ('\n');
|
||||
+
|
||||
+ for (i = 0; i < 16; ++i)
|
||||
+ {
|
||||
+ do_test (0, 0, i, SMALL_CHAR);
|
||||
+ do_test (0, 0, i, BIG_CHAR);
|
||||
+ do_test (0, i, i, SMALL_CHAR);
|
||||
+ do_test (i, 0, i, BIG_CHAR);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 1; i < 8; ++i)
|
||||
+ {
|
||||
+ do_test (0, 0, 8 << i, SMALL_CHAR);
|
||||
+ do_test (8 - i, 2 * i, 8 << i, SMALL_CHAR);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 1; i < 8; ++i)
|
||||
+ {
|
||||
+ do_test (i, 2 * i, 8 << i, SMALL_CHAR);
|
||||
+ do_test (2 * i, i, 8 << i, BIG_CHAR);
|
||||
+ do_test (i, i, 8 << i, SMALL_CHAR);
|
||||
+ do_test (i, i, 8 << i, BIG_CHAR);
|
||||
+ }
|
||||
+
|
||||
+ do_zero_len_test ();
|
||||
+ do_random_tests ();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,232 @@
|
|||
commit 0c48aa0551151ea201f7f528492e89a0b08a6890
|
||||
Author: Joe Simmons-Talbott <josimmon@redhat.com>
|
||||
Date: Fri Apr 21 09:24:24 2023 -0400
|
||||
|
||||
string: Add tests for strndup (BZ #30266)
|
||||
|
||||
Copy strncpy tests for strndup. Covers some basic testcases with random
|
||||
strings. Remove tests that set the destination's bytes and checked the
|
||||
resulting buffer's bytes. Remove wide character test support since
|
||||
wcsndup() doesn't exist.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Conflicts:
|
||||
string/Makefile
|
||||
(different test backport order)
|
||||
|
||||
diff -Nrup a/string/Makefile b/string/Makefile
|
||||
--- a/string/Makefile 2023-11-30 11:55:02.263010916 -0500
|
||||
+++ b/string/Makefile 2023-11-30 11:58:29.238954539 -0500
|
||||
@@ -64,7 +64,7 @@ tests := tester inl-tester noinl-tester
|
||||
test-endian-types test-endian-file-scope \
|
||||
test-endian-sign-conversion tst-memmove-overflow \
|
||||
test-sig_np tst-strerror-fail \
|
||||
- test-strdup
|
||||
+ test-strdup test-strndup
|
||||
|
||||
# Both tests require the .mo translation files generated by msgfmt.
|
||||
tests-translation := tst-strsignal \
|
||||
diff -Nrup a/string/test-strndup.c b/string/test-strndup.c
|
||||
--- a/string/test-strndup.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/string/test-strndup.c 2023-11-30 11:56:24.986388053 -0500
|
||||
@@ -0,0 +1,200 @@
|
||||
+/* Test strndup functions.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+#define TEST_MAIN
|
||||
+#include "test-string.h"
|
||||
+
|
||||
+static void
|
||||
+do_one_test (const char *src, size_t len, size_t n)
|
||||
+{
|
||||
+ char *dst = strndup (src, n);
|
||||
+ size_t s = (len > n ? n: len) * sizeof (char);
|
||||
+
|
||||
+ TEST_COMPARE_BLOB (dst, s, src, s);
|
||||
+
|
||||
+ free (dst);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char)
|
||||
+{
|
||||
+ size_t i;
|
||||
+ char *s1;
|
||||
+
|
||||
+ align1 &= 7;
|
||||
+ if ((align1 + len) * sizeof (char) >= page_size)
|
||||
+ return;
|
||||
+
|
||||
+ align2 &= 7;
|
||||
+ if ((align2 + len) * sizeof (char) >= page_size)
|
||||
+ return;
|
||||
+
|
||||
+ s1 = (char *) (buf1) + align1;
|
||||
+
|
||||
+ for (i = 0; i < len; ++i)
|
||||
+ s1[i] = 32 + 23 * i % (max_char - 32);
|
||||
+ s1[len] = 0;
|
||||
+ for (i = len + 1; (i + align1) * sizeof (char) < page_size && i < len + 64;
|
||||
+ ++i)
|
||||
+ s1[i] = 32 + 32 * i % (max_char - 32);
|
||||
+
|
||||
+ do_one_test (s1, len, n);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_page_tests (void)
|
||||
+{
|
||||
+ char *s1;
|
||||
+ const size_t maxoffset = 64;
|
||||
+
|
||||
+ /* Put s1 at the maxoffset from the edge of buf1's last page. */
|
||||
+ s1 = (char *) buf1 + BUF1PAGES * page_size / sizeof (char) - maxoffset;
|
||||
+
|
||||
+ memset (s1, 'a', maxoffset - 1);
|
||||
+ s1[maxoffset - 1] = '\0';
|
||||
+
|
||||
+ /* Both strings are bounded to a page with read/write access and the next
|
||||
+ page is protected with PROT_NONE (meaning that any access outside of the
|
||||
+ page regions will trigger an invalid memory access).
|
||||
+
|
||||
+ The loop copies the string s1 for all possible offsets up to maxoffset
|
||||
+ for both inputs with a size larger than s1 (so memory access outside the
|
||||
+ expected memory regions might trigger invalid access). */
|
||||
+
|
||||
+ for (size_t off1 = 0; off1 < maxoffset; off1++)
|
||||
+ for (size_t off2 = 0; off2 < maxoffset; off2++)
|
||||
+ do_one_test (s1 + off1, maxoffset - off1 - 1,
|
||||
+ maxoffset + (maxoffset - off2));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_random_tests (void)
|
||||
+{
|
||||
+ size_t i, j, n, align1, align2, len, size, mode;
|
||||
+ char *p1 = (char *) (buf1 + page_size) - 512;
|
||||
+ char *res;
|
||||
+
|
||||
+ for (n = 0; n < ITERATIONS; n++)
|
||||
+ {
|
||||
+ mode = random ();
|
||||
+ if (mode & 1)
|
||||
+ {
|
||||
+ size = random () & 255;
|
||||
+ align1 = 512 - size - (random () & 15);
|
||||
+ if (mode & 2)
|
||||
+ align2 = align1 - (random () & 24);
|
||||
+ else
|
||||
+ align2 = align1 - (random () & 31);
|
||||
+ if (mode & 4)
|
||||
+ {
|
||||
+ j = align1;
|
||||
+ align1 = align2;
|
||||
+ align2 = j;
|
||||
+ }
|
||||
+ if (mode & 8)
|
||||
+ len = size - (random () & 31);
|
||||
+ else
|
||||
+ len = 512;
|
||||
+ if (len >= 512)
|
||||
+ len = random () & 511;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ align1 = random () & 31;
|
||||
+ if (mode & 2)
|
||||
+ align2 = random () & 31;
|
||||
+ else
|
||||
+ align2 = align1 + (random () & 24);
|
||||
+ len = random () & 511;
|
||||
+ j = align1;
|
||||
+ if (align2 > j)
|
||||
+ j = align2;
|
||||
+ if (mode & 4)
|
||||
+ {
|
||||
+ size = random () & 511;
|
||||
+ if (size + j > 512)
|
||||
+ size = 512 - j - (random () & 31);
|
||||
+ }
|
||||
+ else
|
||||
+ size = 512 - j;
|
||||
+ if ((mode & 8) && len + j >= 512)
|
||||
+ len = 512 - j - (random () & 7);
|
||||
+ }
|
||||
+ j = len + align1 + 64;
|
||||
+ if (j > 512)
|
||||
+ j = 512;
|
||||
+ for (i = 0; i < j; i++)
|
||||
+ {
|
||||
+ if (i == len + align1)
|
||||
+ p1[i] = 0;
|
||||
+ else
|
||||
+ {
|
||||
+ p1[i] = random () & CHAR_MAX;
|
||||
+ if (i >= align1 && i < len + align1 && !p1[i])
|
||||
+ p1[i] = (random () & 127) + 3;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ res = (char *) strndup ((char *) (p1 + align1), size);
|
||||
+ j = len + 1;
|
||||
+ if (size < j)
|
||||
+ j = size;
|
||||
+ TEST_COMPARE_BLOB (res, j, (char *) (p1 + align1), j);
|
||||
+ free (res);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+test_main (void)
|
||||
+{
|
||||
+ size_t i;
|
||||
+
|
||||
+ test_init ();
|
||||
+
|
||||
+ printf ("%28s", "");
|
||||
+ printf ("\t%s", "strndup");
|
||||
+ putchar ('\n');
|
||||
+
|
||||
+ for (i = 1; i < 8; ++i)
|
||||
+ {
|
||||
+ do_test (i, i, 16, 16, 127);
|
||||
+ do_test (i, i, 16, 16, CHAR_MAX);
|
||||
+ do_test (i, 2 * i, 16, 16, 127);
|
||||
+ do_test (2 * i, i, 16, 16, CHAR_MAX);
|
||||
+ do_test (8 - i, 2 * i, 1 << i, 2 << i, 127);
|
||||
+ do_test (2 * i, 8 - i, 2 << i, 1 << i, 127);
|
||||
+ do_test (8 - i, 2 * i, 1 << i, 2 << i, CHAR_MAX);
|
||||
+ do_test (2 * i, 8 - i, 2 << i, 1 << i, CHAR_MAX);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 1; i < 8; ++i)
|
||||
+ {
|
||||
+ do_test (0, 0, 4 << i, 8 << i, 127);
|
||||
+ do_test (0, 0, 16 << i, 8 << i, 127);
|
||||
+ do_test (8 - i, 2 * i, 4 << i, 8 << i, 127);
|
||||
+ do_test (8 - i, 2 * i, 16 << i, 8 << i, 127);
|
||||
+ }
|
||||
+
|
||||
+ do_random_tests ();
|
||||
+ do_page_tests ();
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,33 @@
|
|||
commit 0aa5b28a504c6f1f17b387d8147715d1496fff62
|
||||
Author: Joe Simmons-Talbott <josimmon@redhat.com>
|
||||
Date: Fri Apr 21 09:24:25 2023 -0400
|
||||
|
||||
wcsmbs: Add wcsdup() tests. (BZ #30266)
|
||||
|
||||
Enable wide character testcases for wcsdup().
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Conflicts:
|
||||
wcsmbs/Makefile
|
||||
(different test backport order)
|
||||
|
||||
|
||||
diff -Nrup a/wcsmbs/Makefile b/wcsmbs/Makefile
|
||||
--- a/wcsmbs/Makefile 2023-11-30 14:14:18.755010508 -0500
|
||||
+++ b/wcsmbs/Makefile 2023-11-30 14:38:18.511131851 -0500
|
||||
@@ -53,7 +53,8 @@ tests := tst-wcstof wcsmbs-tst1 tst-wcsn
|
||||
tst-c16c32-1 wcsatcliff tst-wcstol-locale tst-wcstod-nan-locale \
|
||||
tst-wcstod-round test-char-types tst-fgetwc-after-eof \
|
||||
tst-wcstod-nan-sign tst-c16-surrogate tst-c32-state \
|
||||
- $(addprefix test-,$(strop-tests)) tst-mbstowcs
|
||||
+ $(addprefix test-,$(strop-tests)) tst-mbstowcs \
|
||||
+ test-wcsdup
|
||||
|
||||
include ../Rules
|
||||
|
||||
diff -Nrup a/wcsmbs/test-wcsdup.c b/wcsmbs/test-wcsdup.c
|
||||
--- a/wcsmbs/test-wcsdup.c 1969-12-31 19:00:00.000000000 -0500
|
||||
+++ b/wcsmbs/test-wcsdup.c 2023-11-30 14:14:48.869138712 -0500
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define WIDE 1
|
||||
+#include "../string/test-strdup.c"
|
|
@ -0,0 +1,26 @@
|
|||
commit 919b9bfaa969c9517fe86c753c001b96ee4ea840
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Wed Oct 5 14:33:14 2022 +0000
|
||||
|
||||
Update syscall lists for Linux 6.0
|
||||
|
||||
Linux 6.0 has no new syscalls. Update the version number in
|
||||
syscall-names.list to reflect that it is still current for 6.0.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 028ad3107a..4a78258646 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 5.19.
|
||||
-kernel 5.19
|
||||
+# The list of system calls is current as of Linux 6.0.
|
||||
+kernel 6.0
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
|
@ -0,0 +1,24 @@
|
|||
commit 5ab9b2c92411eb52f7b7a8e6074f0740d9bd727b
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Tue Dec 20 15:24:29 2022 +0000
|
||||
|
||||
Update syscall lists for Linux 6.1
|
||||
|
||||
Linux 6.1 has no new syscalls. Update the version number in
|
||||
syscall-names.list to reflect that it is still current for 6.1.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 4a78258646..1274d9cd4a 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.0.
|
||||
-kernel 6.0
|
||||
+# The list of system calls is current as of Linux 6.1.
|
||||
+kernel 6.1
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
|
@ -0,0 +1,26 @@
|
|||
commit f8e8effa2629c74769a3552aba33175746b710bb
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Thu Feb 23 22:53:17 2023 +0000
|
||||
|
||||
Update syscall lists for Linux 6.2
|
||||
|
||||
Linux 6.2 has no new syscalls. Update the version number in
|
||||
syscall-names.list to reflect that it is still current for 6.2.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 822498d3e3..5d27b5279c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.1.
|
||||
-kernel 6.1
|
||||
+# The list of system calls is current as of Linux 6.2.
|
||||
+kernel 6.2
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
|
@ -0,0 +1,26 @@
|
|||
commit eeef96f56ce399f2c3fc1d93c0ba1dde34f3ae41
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon May 15 22:26:56 2023 +0000
|
||||
|
||||
Update syscall lists for Linux 6.3
|
||||
|
||||
Linux 6.3 has no new syscalls. Update the version number in
|
||||
syscall-names.list to reflect that it is still current for 6.3.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 5d27b5279c..72fe1d5efe 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.2.
|
||||
-kernel 6.2
|
||||
+# The list of system calls is current as of Linux 6.3.
|
||||
+kernel 6.3
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
|
@ -0,0 +1,83 @@
|
|||
commit 1a21693e16a3f3d10f41c486b97fbecb53dd2087
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Wed Jun 28 21:22:14 2023 +0000
|
||||
|
||||
Update syscall lists for Linux 6.4
|
||||
|
||||
Linux 6.4 adds the riscv_hwprobe syscall on riscv and enables
|
||||
memfd_secret on s390. Update syscall-names.list and regenerate the
|
||||
arch-syscall.h headers with build-many-glibcs.py update-syscalls.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
index 202520ee25..2416e041c8 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
@@ -198,6 +198,7 @@
|
||||
#define __NR_request_key 218
|
||||
#define __NR_restart_syscall 128
|
||||
#define __NR_riscv_flush_icache 259
|
||||
+#define __NR_riscv_hwprobe 258
|
||||
#define __NR_rseq 293
|
||||
#define __NR_rt_sigaction 134
|
||||
#define __NR_rt_sigpending 136
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
index 4e65f337d4..a32bc82f60 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
@@ -205,6 +205,7 @@
|
||||
#define __NR_request_key 218
|
||||
#define __NR_restart_syscall 128
|
||||
#define __NR_riscv_flush_icache 259
|
||||
+#define __NR_riscv_hwprobe 258
|
||||
#define __NR_rseq 293
|
||||
#define __NR_rt_sigaction 134
|
||||
#define __NR_rt_sigpending 136
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
index 57025107e8..2288f20e45 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
@@ -178,6 +178,7 @@
|
||||
#define __NR_mbind 268
|
||||
#define __NR_membarrier 356
|
||||
#define __NR_memfd_create 350
|
||||
+#define __NR_memfd_secret 447
|
||||
#define __NR_migrate_pages 287
|
||||
#define __NR_mincore 218
|
||||
#define __NR_mkdir 39
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
index 72e19c6d56..05e6d8428e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
@@ -152,6 +152,7 @@
|
||||
#define __NR_mbind 268
|
||||
#define __NR_membarrier 356
|
||||
#define __NR_memfd_create 350
|
||||
+#define __NR_memfd_secret 447
|
||||
#define __NR_migrate_pages 287
|
||||
#define __NR_mincore 218
|
||||
#define __NR_mkdir 39
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 72fe1d5efe..5b69106434 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.3.
|
||||
-kernel 6.3
|
||||
+# The list of system calls is current as of Linux 6.4.
|
||||
+kernel 6.4
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
||||
@@ -477,6 +477,7 @@ renameat2
|
||||
request_key
|
||||
restart_syscall
|
||||
riscv_flush_icache
|
||||
+riscv_hwprobe
|
||||
rmdir
|
||||
rseq
|
||||
rt_sigaction
|
|
@ -0,0 +1,338 @@
|
|||
commit 72511f539cc34681ec61c6a0dc2fe6d684760ffe
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Tue Sep 12 14:08:53 2023 +0000
|
||||
|
||||
Update syscall lists for Linux 6.5
|
||||
|
||||
Linux 6.5 has one new syscall, cachestat, and also enables the
|
||||
cacheflush syscall for hppa. Update syscall-names.list and regenerate
|
||||
the arch-syscall.h headers with build-many-glibcs.py update-syscalls.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
Conflicts: Removed loongarch, or1k
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
index 4fcb6da80a..8f21ee66a0 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __NR_bind 200
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
index 0cf74c1a96..c5802a5fec 100644
|
||||
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
@@ -11,6 +11,7 @@
|
||||
#define __NR_bind 104
|
||||
#define __NR_bpf 515
|
||||
#define __NR_brk 17
|
||||
+#define __NR_cachestat 561
|
||||
#define __NR_capget 368
|
||||
#define __NR_capset 369
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
index c1207aaa12..f23f9e1154 100644
|
||||
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
@@ -11,6 +11,7 @@
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
#define __NR_cacheflush 244
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
index e7ba04c106..7edf574899 100644
|
||||
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 386
|
||||
#define __NR_brk 45
|
||||
#define __NR_cacheflush 983042
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
index dc9383758e..d74a06e063 100644
|
||||
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
#define __NR_cacheflush 245
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
index 767f1287a3..5568b94cd3 100644
|
||||
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
@@ -13,6 +13,8 @@
|
||||
#define __NR_bind 22
|
||||
#define __NR_bpf 341
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cacheflush 356
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 106
|
||||
#define __NR_capset 107
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
index 1998f0d76a..3af21a15cb 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 357
|
||||
#define __NR_break 17
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
index b2eab1b93d..39b270e642 100644
|
||||
--- a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
@@ -11,6 +11,7 @@
|
||||
#define __NR_bind 1191
|
||||
#define __NR_bpf 1341
|
||||
#define __NR_brk 1060
|
||||
+#define __NR_cachestat 1475
|
||||
#define __NR_capget 1185
|
||||
#define __NR_capset 1186
|
||||
#define __NR_chdir 1034
|
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
index 5fc3723772..315e49cd33 100644
|
||||
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 354
|
||||
#define __NR_brk 45
|
||||
#define __NR_cacheflush 123
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
index b6e9b007e4..54af12780c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 387
|
||||
#define __NR_break 17
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
index b3a3871f8a..a2aa1ffa1b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
@@ -17,6 +17,7 @@
|
||||
#define __NR_brk 4045
|
||||
#define __NR_cachectl 4148
|
||||
#define __NR_cacheflush 4147
|
||||
+#define __NR_cachestat 4451
|
||||
#define __NR_capget 4204
|
||||
#define __NR_capset 4205
|
||||
#define __NR_chdir 4012
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
index b462182723..5bec858040 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#define __NR_brk 6012
|
||||
#define __NR_cachectl 6198
|
||||
#define __NR_cacheflush 6197
|
||||
+#define __NR_cachestat 6451
|
||||
#define __NR_capget 6123
|
||||
#define __NR_capset 6124
|
||||
#define __NR_chdir 6078
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
index a9d6b94572..0166371ee2 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#define __NR_brk 5012
|
||||
#define __NR_cachectl 5198
|
||||
#define __NR_cacheflush 5197
|
||||
+#define __NR_cachestat 5451
|
||||
#define __NR_capget 5123
|
||||
#define __NR_capset 5124
|
||||
#define __NR_chdir 5078
|
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
index 809a219ef3..29a4cfa988 100644
|
||||
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
@@ -8,6 +8,7 @@
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
#define __NR_cacheflush 244
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
index 627831ebae..3a212a0269 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 361
|
||||
#define __NR_break 17
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 183
|
||||
#define __NR_capset 184
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
index bae597199d..1038ead227 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#define __NR_bpf 361
|
||||
#define __NR_break 17
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 183
|
||||
#define __NR_capset 184
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
index 2416e041c8..57b043ffb5 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define __NR_bind 200
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
index a32bc82f60..1041a0f8c9 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __NR_bind 200
|
||||
#define __NR_bpf 280
|
||||
#define __NR_brk 214
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 90
|
||||
#define __NR_capset 91
|
||||
#define __NR_chdir 49
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
index 2288f20e45..70d4c6782e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
@@ -13,6 +13,7 @@
|
||||
#define __NR_bind 361
|
||||
#define __NR_bpf 351
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
index 05e6d8428e..65a8a9e316 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
@@ -11,6 +11,7 @@
|
||||
#define __NR_bind 361
|
||||
#define __NR_bpf 351
|
||||
#define __NR_brk 45
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
index d52b522d9c..94aad0f119 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#define __NR_bpf 375
|
||||
#define __NR_brk 45
|
||||
#define __NR_cacheflush 123
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 184
|
||||
#define __NR_capset 185
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
index d3f4d8aa3e..d630306c75 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#define __NR_bind 353
|
||||
#define __NR_bpf 349
|
||||
#define __NR_brk 17
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 21
|
||||
#define __NR_capset 22
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
index 2cc03d7a24..930f29b4d2 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
@@ -14,6 +14,7 @@
|
||||
#define __NR_bind 353
|
||||
#define __NR_bpf 349
|
||||
#define __NR_brk 17
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 21
|
||||
#define __NR_capset 22
|
||||
#define __NR_chdir 12
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 5b69106434..cf6f70ecd9 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.4.
|
||||
-kernel 6.4
|
||||
+# The list of system calls is current as of Linux 6.5.
|
||||
+kernel 6.5
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
||||
@@ -58,6 +58,7 @@ breakpoint
|
||||
brk
|
||||
cachectl
|
||||
cacheflush
|
||||
+cachestat
|
||||
capget
|
||||
capset
|
||||
chdir
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
index b4ab892ec1..58646cf0bd 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
@@ -12,6 +12,7 @@
|
||||
#define __NR_bind 49
|
||||
#define __NR_bpf 321
|
||||
#define __NR_brk 12
|
||||
+#define __NR_cachestat 451
|
||||
#define __NR_capget 125
|
||||
#define __NR_capset 126
|
||||
#define __NR_chdir 80
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
index 772559c87b..604bcdfa5b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
@@ -11,6 +11,7 @@
|
||||
#define __NR_bind 1073741873
|
||||
#define __NR_bpf 1073742145
|
||||
#define __NR_brk 1073741836
|
||||
+#define __NR_cachestat 1073742275
|
||||
#define __NR_capget 1073741949
|
||||
#define __NR_capset 1073741950
|
||||
#define __NR_chdir 1073741904
|
|
@ -0,0 +1,350 @@
|
|||
commit 582383b37d95b133c1ee6855ffaa2b1f5cb3d3b8
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue Oct 31 13:32:33 2023 -0300
|
||||
|
||||
Update syscall lists for Linux 6.6
|
||||
|
||||
Linux 6.6 has one new syscall for all architectures, fchmodat2, and
|
||||
the map_shadow_stack on x86_64.
|
||||
|
||||
Conflicts: Removed loongarch, or1k
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
index 8f21ee66a0..746991aa2f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h
|
||||
@@ -44,6 +44,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
index c5802a5fec..32efe51267 100644
|
||||
--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h
|
||||
@@ -56,6 +56,7 @@
|
||||
#define __NR_fchdir 13
|
||||
#define __NR_fchmod 124
|
||||
#define __NR_fchmodat 461
|
||||
+#define __NR_fchmodat2 562
|
||||
#define __NR_fchown 123
|
||||
#define __NR_fchownat 453
|
||||
#define __NR_fcntl 92
|
||||
diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
index f23f9e1154..1d2879e877 100644
|
||||
--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h
|
||||
@@ -48,6 +48,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl64 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
index 7edf574899..6711981e78 100644
|
||||
--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h
|
||||
@@ -64,6 +64,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 333
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 325
|
||||
diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
index d74a06e063..92d9a703ea 100644
|
||||
--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h
|
||||
@@ -50,6 +50,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl64 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
index 5568b94cd3..fbac124b70 100644
|
||||
--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h
|
||||
@@ -63,6 +63,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 286
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchownat 278
|
||||
#define __NR_fcntl 55
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
index 3af21a15cb..8961788a96 100644
|
||||
--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h
|
||||
@@ -67,6 +67,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 306
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 298
|
||||
diff --git a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
index 39b270e642..1ef762d693 100644
|
||||
--- a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h
|
||||
@@ -55,6 +55,7 @@
|
||||
#define __NR_fchdir 1035
|
||||
#define __NR_fchmod 1099
|
||||
#define __NR_fchmodat 1292
|
||||
+#define __NR_fchmodat2 1476
|
||||
#define __NR_fchown 1100
|
||||
#define __NR_fchownat 1284
|
||||
#define __NR_fcntl 1066
|
||||
diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
index 315e49cd33..2053d5d392 100644
|
||||
--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h
|
||||
@@ -67,6 +67,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 299
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 291
|
||||
diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
index 54af12780c..6865b1693c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h
|
||||
@@ -67,6 +67,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 306
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 298
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
index a2aa1ffa1b..b13ace8e1c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h
|
||||
@@ -67,6 +67,7 @@
|
||||
#define __NR_fchdir 4133
|
||||
#define __NR_fchmod 4094
|
||||
#define __NR_fchmodat 4299
|
||||
+#define __NR_fchmodat2 4452
|
||||
#define __NR_fchown 4095
|
||||
#define __NR_fchownat 4291
|
||||
#define __NR_fcntl 4055
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
index 5bec858040..b7a7c0dfa7 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h
|
||||
@@ -64,6 +64,7 @@
|
||||
#define __NR_fchdir 6079
|
||||
#define __NR_fchmod 6089
|
||||
#define __NR_fchmodat 6262
|
||||
+#define __NR_fchmodat2 6452
|
||||
#define __NR_fchown 6091
|
||||
#define __NR_fchownat 6254
|
||||
#define __NR_fcntl 6070
|
||||
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
index 0166371ee2..e5d7f91f48 100644
|
||||
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h
|
||||
@@ -59,6 +59,7 @@
|
||||
#define __NR_fchdir 5079
|
||||
#define __NR_fchmod 5089
|
||||
#define __NR_fchmodat 5258
|
||||
+#define __NR_fchmodat2 5452
|
||||
#define __NR_fchown 5091
|
||||
#define __NR_fchownat 5250
|
||||
#define __NR_fcntl 5070
|
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
index 29a4cfa988..89950cc33a 100644
|
||||
--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h
|
||||
@@ -49,6 +49,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl64 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
index 3a212a0269..64683bcb76 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h
|
||||
@@ -66,6 +66,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 297
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchownat 289
|
||||
#define __NR_fcntl 55
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
index 1038ead227..af1bbf32e8 100644
|
||||
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h
|
||||
@@ -60,6 +60,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 297
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchownat 289
|
||||
#define __NR_fcntl 55
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
index 57b043ffb5..56e3088cbf 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
@@ -43,6 +43,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl64 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
index 1041a0f8c9..508161b47a 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
@@ -44,6 +44,7 @@
|
||||
#define __NR_fchdir 50
|
||||
#define __NR_fchmod 52
|
||||
#define __NR_fchmodat 53
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 55
|
||||
#define __NR_fchownat 54
|
||||
#define __NR_fcntl 25
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
index 70d4c6782e..1498ebf42e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h
|
||||
@@ -65,6 +65,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 299
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 291
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
index 65a8a9e316..624d71b56d 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h
|
||||
@@ -56,6 +56,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 299
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 207
|
||||
#define __NR_fchownat 291
|
||||
#define __NR_fcntl 55
|
||||
diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
index 94aad0f119..37211f5f8c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h
|
||||
@@ -64,6 +64,7 @@
|
||||
#define __NR_fchdir 133
|
||||
#define __NR_fchmod 94
|
||||
#define __NR_fchmodat 306
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 95
|
||||
#define __NR_fchown32 207
|
||||
#define __NR_fchownat 298
|
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
index d630306c75..8093abcc9c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h
|
||||
@@ -66,6 +66,7 @@
|
||||
#define __NR_fchdir 176
|
||||
#define __NR_fchmod 124
|
||||
#define __NR_fchmodat 295
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 123
|
||||
#define __NR_fchown32 32
|
||||
#define __NR_fchownat 287
|
||||
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
index 930f29b4d2..d25ccfb571 100644
|
||||
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h
|
||||
@@ -60,6 +60,7 @@
|
||||
#define __NR_fchdir 176
|
||||
#define __NR_fchmod 124
|
||||
#define __NR_fchmodat 295
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 123
|
||||
#define __NR_fchownat 287
|
||||
#define __NR_fcntl 92
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index cf6f70ecd9..c3627fcd7f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 6.5.
|
||||
-kernel 6.5
|
||||
+# The list of system calls is current as of Linux 6.6.
|
||||
+kernel 6.6
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
||||
@@ -117,6 +117,7 @@ fanotify_mark
|
||||
fchdir
|
||||
fchmod
|
||||
fchmodat
|
||||
+fchmodat2
|
||||
fchown
|
||||
fchown32
|
||||
fchownat
|
||||
@@ -246,6 +247,7 @@ lsetxattr
|
||||
lstat
|
||||
lstat64
|
||||
madvise
|
||||
+map_shadow_stack
|
||||
mbind
|
||||
membarrier
|
||||
memfd_create
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
index 58646cf0bd..5e4c9e901c 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h
|
||||
@@ -59,6 +59,7 @@
|
||||
#define __NR_fchdir 81
|
||||
#define __NR_fchmod 91
|
||||
#define __NR_fchmodat 268
|
||||
+#define __NR_fchmodat2 452
|
||||
#define __NR_fchown 93
|
||||
#define __NR_fchownat 260
|
||||
#define __NR_fcntl 72
|
||||
@@ -153,6 +154,7 @@
|
||||
#define __NR_lsetxattr 189
|
||||
#define __NR_lstat 6
|
||||
#define __NR_madvise 28
|
||||
+#define __NR_map_shadow_stack 453
|
||||
#define __NR_mbind 237
|
||||
#define __NR_membarrier 324
|
||||
#define __NR_memfd_create 319
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
index 604bcdfa5b..dd5e196272 100644
|
||||
--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h
|
||||
@@ -55,6 +55,7 @@
|
||||
#define __NR_fchdir 1073741905
|
||||
#define __NR_fchmod 1073741915
|
||||
#define __NR_fchmodat 1073742092
|
||||
+#define __NR_fchmodat2 1073742276
|
||||
#define __NR_fchown 1073741917
|
||||
#define __NR_fchownat 1073742084
|
||||
#define __NR_fcntl 1073741896
|
|
@ -0,0 +1,16 @@
|
|||
Downstream-only patch to refer to /run instead of the legacy /var/run
|
||||
directory in the downstream nscd systemd socket file.
|
||||
|
||||
diff --git a/nscd/nscd.socket b/nscd/nscd.socket
|
||||
index 7e512d5339fa1136..52a67608c7c55475 100644
|
||||
--- a/nscd/nscd.socket
|
||||
+++ b/nscd/nscd.socket
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Name Service Cache Daemon Socket
|
||||
|
||||
[Socket]
|
||||
-ListenDatagram=/var/run/nscd/socket
|
||||
+ListenDatagram=/run/nscd/socket
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
|
@ -0,0 +1,211 @@
|
|||
commit 06890c7ba553e82393413c59bb3131db5815a337
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Jul 27 22:49:53 2021 +0530
|
||||
|
||||
gaiconf_init: Refactor some bits for readability
|
||||
|
||||
Split out line processing for `label`, `precedence` and `scopev4` into
|
||||
separate functions instead of the gotos.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index d6046a707f1d742a..3bf9a8bae16a5b02 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1858,6 +1858,66 @@ scopecmp (const void *p1, const void *p2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static bool
|
||||
+add_prefixlist (struct prefixlist **listp, size_t *lenp, bool *nullbitsp,
|
||||
+ char *val1, char *val2, char **pos)
|
||||
+{
|
||||
+ struct in6_addr prefix;
|
||||
+ unsigned long int bits;
|
||||
+ unsigned long int val;
|
||||
+ char *endp;
|
||||
+
|
||||
+ bits = 128;
|
||||
+ __set_errno (0);
|
||||
+ char *cp = strchr (val1, '/');
|
||||
+ if (cp != NULL)
|
||||
+ *cp++ = '\0';
|
||||
+ *pos = cp;
|
||||
+ if (inet_pton (AF_INET6, val1, &prefix)
|
||||
+ && (cp == NULL
|
||||
+ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && bits <= 128
|
||||
+ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && val <= INT_MAX)
|
||||
+ {
|
||||
+ struct prefixlist *newp = malloc (sizeof (*newp));
|
||||
+ if (newp == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
|
||||
+ newp->entry.bits = bits;
|
||||
+ newp->entry.val = val;
|
||||
+ newp->next = *listp;
|
||||
+ *listp = newp;
|
||||
+ ++*lenp;
|
||||
+ *nullbitsp |= bits == 0;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool
|
||||
+add_scopelist (struct scopelist **listp, size_t *lenp, bool *nullbitsp,
|
||||
+ const struct in6_addr *prefixp, unsigned long int bits,
|
||||
+ unsigned long int val)
|
||||
+{
|
||||
+ struct scopelist *newp = malloc (sizeof (*newp));
|
||||
+ if (newp == NULL)
|
||||
+ return false;
|
||||
+
|
||||
+ newp->entry.netmask = htonl (bits != 96 ? (0xffffffff << (128 - bits)) : 0);
|
||||
+ newp->entry.addr32 = (prefixp->s6_addr32[3] & newp->entry.netmask);
|
||||
+ newp->entry.scope = val;
|
||||
+ newp->next = *listp;
|
||||
+ *listp = newp;
|
||||
+ ++*lenp;
|
||||
+ *nullbitsp |= bits == 96;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
static void
|
||||
gaiconf_init (void)
|
||||
@@ -1933,55 +1993,17 @@ gaiconf_init (void)
|
||||
/* Ignore the rest of the line. */
|
||||
*cp = '\0';
|
||||
|
||||
- struct prefixlist **listp;
|
||||
- size_t *lenp;
|
||||
- bool *nullbitsp;
|
||||
switch (cmdlen)
|
||||
{
|
||||
case 5:
|
||||
if (strcmp (cmd, "label") == 0)
|
||||
{
|
||||
- struct in6_addr prefix;
|
||||
- unsigned long int bits;
|
||||
- unsigned long int val;
|
||||
- char *endp;
|
||||
-
|
||||
- listp = &labellist;
|
||||
- lenp = &nlabellist;
|
||||
- nullbitsp = &labellist_nullbits;
|
||||
-
|
||||
- new_elem:
|
||||
- bits = 128;
|
||||
- __set_errno (0);
|
||||
- cp = strchr (val1, '/');
|
||||
- if (cp != NULL)
|
||||
- *cp++ = '\0';
|
||||
- if (inet_pton (AF_INET6, val1, &prefix)
|
||||
- && (cp == NULL
|
||||
- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && bits <= 128
|
||||
- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && val <= INT_MAX)
|
||||
+ if (!add_prefixlist (&labellist, &nlabellist,
|
||||
+ &labellist_nullbits, val1, val2, &cp))
|
||||
{
|
||||
- struct prefixlist *newp = malloc (sizeof (*newp));
|
||||
- if (newp == NULL)
|
||||
- {
|
||||
- free (line);
|
||||
- fclose (fp);
|
||||
- goto no_file;
|
||||
- }
|
||||
-
|
||||
- memcpy (&newp->entry.prefix, &prefix, sizeof (prefix));
|
||||
- newp->entry.bits = bits;
|
||||
- newp->entry.val = val;
|
||||
- newp->next = *listp;
|
||||
- *listp = newp;
|
||||
- ++*lenp;
|
||||
- *nullbitsp |= bits == 0;
|
||||
+ free (line);
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2023,27 +2045,14 @@ gaiconf_init (void)
|
||||
&& *endp == '\0'
|
||||
&& val <= INT_MAX)
|
||||
{
|
||||
- struct scopelist *newp;
|
||||
- new_scope:
|
||||
- newp = malloc (sizeof (*newp));
|
||||
- if (newp == NULL)
|
||||
+ if (!add_scopelist (&scopelist, &nscopelist,
|
||||
+ &scopelist_nullbits, &prefix,
|
||||
+ bits, val))
|
||||
{
|
||||
free (line);
|
||||
fclose (fp);
|
||||
goto no_file;
|
||||
}
|
||||
-
|
||||
- newp->entry.netmask = htonl (bits != 96
|
||||
- ? (0xffffffff
|
||||
- << (128 - bits))
|
||||
- : 0);
|
||||
- newp->entry.addr32 = (prefix.s6_addr32[3]
|
||||
- & newp->entry.netmask);
|
||||
- newp->entry.scope = val;
|
||||
- newp->next = scopelist;
|
||||
- scopelist = newp;
|
||||
- ++nscopelist;
|
||||
- scopelist_nullbits |= bits == 96;
|
||||
}
|
||||
}
|
||||
else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
|
||||
@@ -2057,8 +2066,14 @@ gaiconf_init (void)
|
||||
&& *endp == '\0'
|
||||
&& val <= INT_MAX)
|
||||
{
|
||||
- bits += 96;
|
||||
- goto new_scope;
|
||||
+ if (!add_scopelist (&scopelist, &nscopelist,
|
||||
+ &scopelist_nullbits, &prefix,
|
||||
+ bits + 96, val))
|
||||
+ {
|
||||
+ free (line);
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2066,10 +2081,14 @@ gaiconf_init (void)
|
||||
case 10:
|
||||
if (strcmp (cmd, "precedence") == 0)
|
||||
{
|
||||
- listp = &precedencelist;
|
||||
- lenp = &nprecedencelist;
|
||||
- nullbitsp = &precedencelist_nullbits;
|
||||
- goto new_elem;
|
||||
+ if (!add_prefixlist (&precedencelist, &nprecedencelist,
|
||||
+ &precedencelist_nullbits, val1, val2,
|
||||
+ &cp))
|
||||
+ {
|
||||
+ free (line);
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
+ }
|
||||
}
|
||||
break;
|
||||
}
|
|
@ -0,0 +1,584 @@
|
|||
commit bc0d18d873abf2cda6842ad8bb4df2a31dc0fbac
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Aug 3 21:29:23 2021 +0530
|
||||
|
||||
gai_init: Avoid jumping from if condition to its else counterpart
|
||||
|
||||
Clean up another antipattern where code flows from an if condition to
|
||||
its else counterpart with a goto.
|
||||
|
||||
Most of the change in this patch is whitespace-only; a `git diff -b`
|
||||
ought to show the actual logic changes.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 3bf9a8bae16a5b02..1635a09837351068 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1933,142 +1933,122 @@ gaiconf_init (void)
|
||||
bool scopelist_nullbits = false;
|
||||
|
||||
FILE *fp = fopen (GAICONF_FNAME, "rce");
|
||||
- if (fp != NULL)
|
||||
+ if (fp == NULL)
|
||||
+ goto no_file;
|
||||
+
|
||||
+ struct __stat64_t64 st;
|
||||
+ if (__fstat64_time64 (fileno (fp), &st) != 0)
|
||||
{
|
||||
- struct __stat64_t64 st;
|
||||
- if (__fstat64_time64 (fileno (fp), &st) != 0)
|
||||
- {
|
||||
- fclose (fp);
|
||||
- goto no_file;
|
||||
- }
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
+ }
|
||||
|
||||
- char *line = NULL;
|
||||
- size_t linelen = 0;
|
||||
+ char *line = NULL;
|
||||
+ size_t linelen = 0;
|
||||
|
||||
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
|
||||
|
||||
- while (!feof_unlocked (fp))
|
||||
- {
|
||||
- ssize_t n = __getline (&line, &linelen, fp);
|
||||
- if (n <= 0)
|
||||
- break;
|
||||
+ while (!feof_unlocked (fp))
|
||||
+ {
|
||||
+ ssize_t n = __getline (&line, &linelen, fp);
|
||||
+ if (n <= 0)
|
||||
+ break;
|
||||
|
||||
- /* Handle comments. No escaping possible so this is easy. */
|
||||
- char *cp = strchr (line, '#');
|
||||
- if (cp != NULL)
|
||||
- *cp = '\0';
|
||||
+ /* Handle comments. No escaping possible so this is easy. */
|
||||
+ char *cp = strchr (line, '#');
|
||||
+ if (cp != NULL)
|
||||
+ *cp = '\0';
|
||||
|
||||
- cp = line;
|
||||
- while (isspace (*cp))
|
||||
- ++cp;
|
||||
+ cp = line;
|
||||
+ while (isspace (*cp))
|
||||
+ ++cp;
|
||||
|
||||
- char *cmd = cp;
|
||||
- while (*cp != '\0' && !isspace (*cp))
|
||||
- ++cp;
|
||||
- size_t cmdlen = cp - cmd;
|
||||
+ char *cmd = cp;
|
||||
+ while (*cp != '\0' && !isspace (*cp))
|
||||
+ ++cp;
|
||||
+ size_t cmdlen = cp - cmd;
|
||||
|
||||
- if (*cp != '\0')
|
||||
- *cp++ = '\0';
|
||||
- while (isspace (*cp))
|
||||
- ++cp;
|
||||
+ if (*cp != '\0')
|
||||
+ *cp++ = '\0';
|
||||
+ while (isspace (*cp))
|
||||
+ ++cp;
|
||||
|
||||
- char *val1 = cp;
|
||||
- while (*cp != '\0' && !isspace (*cp))
|
||||
- ++cp;
|
||||
- size_t val1len = cp - cmd;
|
||||
+ char *val1 = cp;
|
||||
+ while (*cp != '\0' && !isspace (*cp))
|
||||
+ ++cp;
|
||||
+ size_t val1len = cp - cmd;
|
||||
|
||||
- /* We always need at least two values. */
|
||||
- if (val1len == 0)
|
||||
- continue;
|
||||
+ /* We always need at least two values. */
|
||||
+ if (val1len == 0)
|
||||
+ continue;
|
||||
|
||||
- if (*cp != '\0')
|
||||
- *cp++ = '\0';
|
||||
- while (isspace (*cp))
|
||||
- ++cp;
|
||||
+ if (*cp != '\0')
|
||||
+ *cp++ = '\0';
|
||||
+ while (isspace (*cp))
|
||||
+ ++cp;
|
||||
|
||||
- char *val2 = cp;
|
||||
- while (*cp != '\0' && !isspace (*cp))
|
||||
- ++cp;
|
||||
+ char *val2 = cp;
|
||||
+ while (*cp != '\0' && !isspace (*cp))
|
||||
+ ++cp;
|
||||
|
||||
- /* Ignore the rest of the line. */
|
||||
- *cp = '\0';
|
||||
+ /* Ignore the rest of the line. */
|
||||
+ *cp = '\0';
|
||||
|
||||
- switch (cmdlen)
|
||||
+ switch (cmdlen)
|
||||
+ {
|
||||
+ case 5:
|
||||
+ if (strcmp (cmd, "label") == 0)
|
||||
{
|
||||
- case 5:
|
||||
- if (strcmp (cmd, "label") == 0)
|
||||
+ if (!add_prefixlist (&labellist, &nlabellist,
|
||||
+ &labellist_nullbits, val1, val2, &cp))
|
||||
{
|
||||
- if (!add_prefixlist (&labellist, &nlabellist,
|
||||
- &labellist_nullbits, val1, val2, &cp))
|
||||
- {
|
||||
- free (line);
|
||||
- fclose (fp);
|
||||
- goto no_file;
|
||||
- }
|
||||
+ free (line);
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
}
|
||||
- break;
|
||||
+ }
|
||||
+ break;
|
||||
|
||||
- case 6:
|
||||
- if (strcmp (cmd, "reload") == 0)
|
||||
- {
|
||||
- gaiconf_reload_flag = strcmp (val1, "yes") == 0;
|
||||
- if (gaiconf_reload_flag)
|
||||
- gaiconf_reload_flag_ever_set = 1;
|
||||
- }
|
||||
- break;
|
||||
+ case 6:
|
||||
+ if (strcmp (cmd, "reload") == 0)
|
||||
+ {
|
||||
+ gaiconf_reload_flag = strcmp (val1, "yes") == 0;
|
||||
+ if (gaiconf_reload_flag)
|
||||
+ gaiconf_reload_flag_ever_set = 1;
|
||||
+ }
|
||||
+ break;
|
||||
|
||||
- case 7:
|
||||
- if (strcmp (cmd, "scopev4") == 0)
|
||||
+ case 7:
|
||||
+ if (strcmp (cmd, "scopev4") == 0)
|
||||
+ {
|
||||
+ struct in6_addr prefix;
|
||||
+ unsigned long int bits;
|
||||
+ unsigned long int val;
|
||||
+ char *endp;
|
||||
+
|
||||
+ bits = 32;
|
||||
+ __set_errno (0);
|
||||
+ cp = strchr (val1, '/');
|
||||
+ if (cp != NULL)
|
||||
+ *cp++ = '\0';
|
||||
+ if (inet_pton (AF_INET6, val1, &prefix))
|
||||
{
|
||||
- struct in6_addr prefix;
|
||||
- unsigned long int bits;
|
||||
- unsigned long int val;
|
||||
- char *endp;
|
||||
-
|
||||
- bits = 32;
|
||||
- __set_errno (0);
|
||||
- cp = strchr (val1, '/');
|
||||
- if (cp != NULL)
|
||||
- *cp++ = '\0';
|
||||
- if (inet_pton (AF_INET6, val1, &prefix))
|
||||
- {
|
||||
- bits = 128;
|
||||
- if (IN6_IS_ADDR_V4MAPPED (&prefix)
|
||||
- && (cp == NULL
|
||||
- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && bits >= 96
|
||||
- && bits <= 128
|
||||
- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && val <= INT_MAX)
|
||||
- {
|
||||
- if (!add_scopelist (&scopelist, &nscopelist,
|
||||
- &scopelist_nullbits, &prefix,
|
||||
- bits, val))
|
||||
- {
|
||||
- free (line);
|
||||
- fclose (fp);
|
||||
- goto no_file;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
|
||||
- && (cp == NULL
|
||||
- || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && bits <= 32
|
||||
- && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
- || errno != ERANGE)
|
||||
- && *endp == '\0'
|
||||
- && val <= INT_MAX)
|
||||
+ bits = 128;
|
||||
+ if (IN6_IS_ADDR_V4MAPPED (&prefix)
|
||||
+ && (cp == NULL
|
||||
+ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && bits >= 96
|
||||
+ && bits <= 128
|
||||
+ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && val <= INT_MAX)
|
||||
{
|
||||
if (!add_scopelist (&scopelist, &nscopelist,
|
||||
&scopelist_nullbits, &prefix,
|
||||
- bits + 96, val))
|
||||
+ bits, val))
|
||||
{
|
||||
free (line);
|
||||
fclose (fp);
|
||||
@@ -2076,173 +2056,191 @@ gaiconf_init (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
- break;
|
||||
-
|
||||
- case 10:
|
||||
- if (strcmp (cmd, "precedence") == 0)
|
||||
+ else if (inet_pton (AF_INET, val1, &prefix.s6_addr32[3])
|
||||
+ && (cp == NULL
|
||||
+ || (bits = strtoul (cp, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && bits <= 32
|
||||
+ && ((val = strtoul (val2, &endp, 10)) != ULONG_MAX
|
||||
+ || errno != ERANGE)
|
||||
+ && *endp == '\0'
|
||||
+ && val <= INT_MAX)
|
||||
{
|
||||
- if (!add_prefixlist (&precedencelist, &nprecedencelist,
|
||||
- &precedencelist_nullbits, val1, val2,
|
||||
- &cp))
|
||||
+ if (!add_scopelist (&scopelist, &nscopelist,
|
||||
+ &scopelist_nullbits, &prefix,
|
||||
+ bits + 96, val))
|
||||
{
|
||||
free (line);
|
||||
fclose (fp);
|
||||
goto no_file;
|
||||
}
|
||||
}
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- free (line);
|
||||
-
|
||||
- fclose (fp);
|
||||
-
|
||||
- /* Create the array for the labels. */
|
||||
- struct prefixentry *new_labels;
|
||||
- if (nlabellist > 0)
|
||||
- {
|
||||
- if (!labellist_nullbits)
|
||||
- ++nlabellist;
|
||||
- new_labels = malloc (nlabellist * sizeof (*new_labels));
|
||||
- if (new_labels == NULL)
|
||||
- goto no_file;
|
||||
-
|
||||
- int i = nlabellist;
|
||||
- if (!labellist_nullbits)
|
||||
- {
|
||||
- --i;
|
||||
- memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
|
||||
- new_labels[i].bits = 0;
|
||||
- new_labels[i].val = 1;
|
||||
}
|
||||
+ break;
|
||||
|
||||
- struct prefixlist *l = labellist;
|
||||
- while (i-- > 0)
|
||||
+ case 10:
|
||||
+ if (strcmp (cmd, "precedence") == 0)
|
||||
{
|
||||
- new_labels[i] = l->entry;
|
||||
- l = l->next;
|
||||
+ if (!add_prefixlist (&precedencelist, &nprecedencelist,
|
||||
+ &precedencelist_nullbits, val1, val2,
|
||||
+ &cp))
|
||||
+ {
|
||||
+ free (line);
|
||||
+ fclose (fp);
|
||||
+ goto no_file;
|
||||
+ }
|
||||
}
|
||||
- free_prefixlist (labellist);
|
||||
- labellist = NULL;
|
||||
-
|
||||
- /* Sort the entries so that the most specific ones are at
|
||||
- the beginning. */
|
||||
- qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
|
||||
+ break;
|
||||
}
|
||||
- else
|
||||
- new_labels = (struct prefixentry *) default_labels;
|
||||
-
|
||||
- struct prefixentry *new_precedence;
|
||||
- if (nprecedencelist > 0)
|
||||
- {
|
||||
- if (!precedencelist_nullbits)
|
||||
- ++nprecedencelist;
|
||||
- new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
|
||||
- if (new_precedence == NULL)
|
||||
- {
|
||||
- if (new_labels != default_labels)
|
||||
- free (new_labels);
|
||||
- goto no_file;
|
||||
- }
|
||||
+ }
|
||||
|
||||
- int i = nprecedencelist;
|
||||
- if (!precedencelist_nullbits)
|
||||
- {
|
||||
- --i;
|
||||
- memset (&new_precedence[i].prefix, '\0',
|
||||
- sizeof (struct in6_addr));
|
||||
- new_precedence[i].bits = 0;
|
||||
- new_precedence[i].val = 40;
|
||||
- }
|
||||
+ free (line);
|
||||
|
||||
- struct prefixlist *l = precedencelist;
|
||||
- while (i-- > 0)
|
||||
- {
|
||||
- new_precedence[i] = l->entry;
|
||||
- l = l->next;
|
||||
- }
|
||||
- free_prefixlist (precedencelist);
|
||||
- precedencelist = NULL;
|
||||
+ fclose (fp);
|
||||
|
||||
- /* Sort the entries so that the most specific ones are at
|
||||
- the beginning. */
|
||||
- qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
|
||||
- prefixcmp);
|
||||
+ /* Create the array for the labels. */
|
||||
+ struct prefixentry *new_labels;
|
||||
+ if (nlabellist > 0)
|
||||
+ {
|
||||
+ if (!labellist_nullbits)
|
||||
+ ++nlabellist;
|
||||
+ new_labels = malloc (nlabellist * sizeof (*new_labels));
|
||||
+ if (new_labels == NULL)
|
||||
+ goto no_file;
|
||||
+
|
||||
+ int i = nlabellist;
|
||||
+ if (!labellist_nullbits)
|
||||
+ {
|
||||
+ --i;
|
||||
+ memset (&new_labels[i].prefix, '\0', sizeof (struct in6_addr));
|
||||
+ new_labels[i].bits = 0;
|
||||
+ new_labels[i].val = 1;
|
||||
}
|
||||
- else
|
||||
- new_precedence = (struct prefixentry *) default_precedence;
|
||||
|
||||
- struct scopeentry *new_scopes;
|
||||
- if (nscopelist > 0)
|
||||
+ struct prefixlist *l = labellist;
|
||||
+ while (i-- > 0)
|
||||
{
|
||||
- if (!scopelist_nullbits)
|
||||
- ++nscopelist;
|
||||
- new_scopes = malloc (nscopelist * sizeof (*new_scopes));
|
||||
- if (new_scopes == NULL)
|
||||
- {
|
||||
- if (new_labels != default_labels)
|
||||
- free (new_labels);
|
||||
- if (new_precedence != default_precedence)
|
||||
- free (new_precedence);
|
||||
- goto no_file;
|
||||
- }
|
||||
-
|
||||
- int i = nscopelist;
|
||||
- if (!scopelist_nullbits)
|
||||
- {
|
||||
- --i;
|
||||
- new_scopes[i].addr32 = 0;
|
||||
- new_scopes[i].netmask = 0;
|
||||
- new_scopes[i].scope = 14;
|
||||
- }
|
||||
+ new_labels[i] = l->entry;
|
||||
+ l = l->next;
|
||||
+ }
|
||||
+ free_prefixlist (labellist);
|
||||
+ labellist = NULL;
|
||||
|
||||
- struct scopelist *l = scopelist;
|
||||
- while (i-- > 0)
|
||||
- {
|
||||
- new_scopes[i] = l->entry;
|
||||
- l = l->next;
|
||||
- }
|
||||
- free_scopelist (scopelist);
|
||||
+ /* Sort the entries so that the most specific ones are at
|
||||
+ the beginning. */
|
||||
+ qsort (new_labels, nlabellist, sizeof (*new_labels), prefixcmp);
|
||||
+ }
|
||||
+ else
|
||||
+ new_labels = (struct prefixentry *) default_labels;
|
||||
|
||||
- /* Sort the entries so that the most specific ones are at
|
||||
- the beginning. */
|
||||
- qsort (new_scopes, nscopelist, sizeof (*new_scopes),
|
||||
- scopecmp);
|
||||
+ struct prefixentry *new_precedence;
|
||||
+ if (nprecedencelist > 0)
|
||||
+ {
|
||||
+ if (!precedencelist_nullbits)
|
||||
+ ++nprecedencelist;
|
||||
+ new_precedence = malloc (nprecedencelist * sizeof (*new_precedence));
|
||||
+ if (new_precedence == NULL)
|
||||
+ {
|
||||
+ if (new_labels != default_labels)
|
||||
+ free (new_labels);
|
||||
+ goto no_file;
|
||||
}
|
||||
- else
|
||||
- new_scopes = (struct scopeentry *) default_scopes;
|
||||
-
|
||||
- /* Now we are ready to replace the values. */
|
||||
- const struct prefixentry *old = labels;
|
||||
- labels = new_labels;
|
||||
- if (old != default_labels)
|
||||
- free ((void *) old);
|
||||
|
||||
- old = precedence;
|
||||
- precedence = new_precedence;
|
||||
- if (old != default_precedence)
|
||||
- free ((void *) old);
|
||||
+ int i = nprecedencelist;
|
||||
+ if (!precedencelist_nullbits)
|
||||
+ {
|
||||
+ --i;
|
||||
+ memset (&new_precedence[i].prefix, '\0',
|
||||
+ sizeof (struct in6_addr));
|
||||
+ new_precedence[i].bits = 0;
|
||||
+ new_precedence[i].val = 40;
|
||||
+ }
|
||||
|
||||
- const struct scopeentry *oldscope = scopes;
|
||||
- scopes = new_scopes;
|
||||
- if (oldscope != default_scopes)
|
||||
- free ((void *) oldscope);
|
||||
+ struct prefixlist *l = precedencelist;
|
||||
+ while (i-- > 0)
|
||||
+ {
|
||||
+ new_precedence[i] = l->entry;
|
||||
+ l = l->next;
|
||||
+ }
|
||||
+ free_prefixlist (precedencelist);
|
||||
+ precedencelist = NULL;
|
||||
|
||||
- save_gaiconf_mtime (&st);
|
||||
+ /* Sort the entries so that the most specific ones are at
|
||||
+ the beginning. */
|
||||
+ qsort (new_precedence, nprecedencelist, sizeof (*new_precedence),
|
||||
+ prefixcmp);
|
||||
}
|
||||
else
|
||||
+ new_precedence = (struct prefixentry *) default_precedence;
|
||||
+
|
||||
+ struct scopeentry *new_scopes;
|
||||
+ if (nscopelist > 0)
|
||||
{
|
||||
- no_file:
|
||||
- free_prefixlist (labellist);
|
||||
- free_prefixlist (precedencelist);
|
||||
+ if (!scopelist_nullbits)
|
||||
+ ++nscopelist;
|
||||
+ new_scopes = malloc (nscopelist * sizeof (*new_scopes));
|
||||
+ if (new_scopes == NULL)
|
||||
+ {
|
||||
+ if (new_labels != default_labels)
|
||||
+ free (new_labels);
|
||||
+ if (new_precedence != default_precedence)
|
||||
+ free (new_precedence);
|
||||
+ goto no_file;
|
||||
+ }
|
||||
+
|
||||
+ int i = nscopelist;
|
||||
+ if (!scopelist_nullbits)
|
||||
+ {
|
||||
+ --i;
|
||||
+ new_scopes[i].addr32 = 0;
|
||||
+ new_scopes[i].netmask = 0;
|
||||
+ new_scopes[i].scope = 14;
|
||||
+ }
|
||||
+
|
||||
+ struct scopelist *l = scopelist;
|
||||
+ while (i-- > 0)
|
||||
+ {
|
||||
+ new_scopes[i] = l->entry;
|
||||
+ l = l->next;
|
||||
+ }
|
||||
free_scopelist (scopelist);
|
||||
|
||||
- /* If we previously read the file but it is gone now, free the
|
||||
- old data and use the builtin one. Leave the reload flag
|
||||
- alone. */
|
||||
- fini ();
|
||||
+ /* Sort the entries so that the most specific ones are at
|
||||
+ the beginning. */
|
||||
+ qsort (new_scopes, nscopelist, sizeof (*new_scopes),
|
||||
+ scopecmp);
|
||||
}
|
||||
+ else
|
||||
+ new_scopes = (struct scopeentry *) default_scopes;
|
||||
+
|
||||
+ /* Now we are ready to replace the values. */
|
||||
+ const struct prefixentry *old = labels;
|
||||
+ labels = new_labels;
|
||||
+ if (old != default_labels)
|
||||
+ free ((void *) old);
|
||||
+
|
||||
+ old = precedence;
|
||||
+ precedence = new_precedence;
|
||||
+ if (old != default_precedence)
|
||||
+ free ((void *) old);
|
||||
+
|
||||
+ const struct scopeentry *oldscope = scopes;
|
||||
+ scopes = new_scopes;
|
||||
+ if (oldscope != default_scopes)
|
||||
+ free ((void *) oldscope);
|
||||
+
|
||||
+ save_gaiconf_mtime (&st);
|
||||
+ return;
|
||||
+
|
||||
+no_file:
|
||||
+ free_prefixlist (labellist);
|
||||
+ free_prefixlist (precedencelist);
|
||||
+ free_scopelist (scopelist);
|
||||
+
|
||||
+ /* If we previously read the file but it is gone now, free the old data and
|
||||
+ use the builtin one. Leave the reload flag alone. */
|
||||
+ fini ();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
commit d3f2c2c8b57bdf9d963db8fa2372d6c1b86a337e
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Mar 22 22:40:05 2022 +0530
|
||||
|
||||
getaddrinfo: Refactor code for readability
|
||||
|
||||
The close_retry goto jump is confusing and clumsy to read, so refactor
|
||||
the code a bit to make it easier to follow.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 1635a09837351068..5e9bd17eb949974c 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -2253,6 +2253,36 @@ gaiconf_reload (void)
|
||||
gaiconf_init ();
|
||||
}
|
||||
|
||||
+static bool
|
||||
+try_connect (int *fdp, int *afp, struct sockaddr_in6 *source_addrp,
|
||||
+ const struct sockaddr *addr, socklen_t addrlen, int family)
|
||||
+{
|
||||
+ int fd = *fdp;
|
||||
+ int af = *afp;
|
||||
+ socklen_t sl = sizeof (*source_addrp);
|
||||
+
|
||||
+ while (true)
|
||||
+ {
|
||||
+ if (fd != -1 && __connect (fd, addr, addrlen) == 0
|
||||
+ && __getsockname (fd, (struct sockaddr *) source_addrp, &sl) == 0)
|
||||
+ return true;
|
||||
+
|
||||
+ if (errno == EAFNOSUPPORT && af == AF_INET6 && family == AF_INET)
|
||||
+ {
|
||||
+ /* This could mean IPv6 sockets are IPv6-only. */
|
||||
+ if (fd != -1)
|
||||
+ __close_nocancel_nostatus (fd);
|
||||
+ *afp = af = AF_INET;
|
||||
+ *fdp = fd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC,
|
||||
+ IPPROTO_IP);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ __builtin_unreachable ();
|
||||
+}
|
||||
|
||||
int
|
||||
getaddrinfo (const char *name, const char *service,
|
||||
@@ -2443,7 +2473,6 @@ getaddrinfo (const char *name, const char *service,
|
||||
if (fd == -1 || (af == AF_INET && q->ai_family == AF_INET6))
|
||||
{
|
||||
if (fd != -1)
|
||||
- close_retry:
|
||||
__close_nocancel_nostatus (fd);
|
||||
af = q->ai_family;
|
||||
fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
|
||||
@@ -2455,14 +2484,10 @@ getaddrinfo (const char *name, const char *service,
|
||||
__connect (fd, &sa, sizeof (sa));
|
||||
}
|
||||
|
||||
- socklen_t sl = sizeof (results[i].source_addr);
|
||||
- if (fd != -1
|
||||
- && __connect (fd, q->ai_addr, q->ai_addrlen) == 0
|
||||
- && __getsockname (fd,
|
||||
- (struct sockaddr *) &results[i].source_addr,
|
||||
- &sl) == 0)
|
||||
+ if (try_connect (&fd, &af, &results[i].source_addr, q->ai_addr,
|
||||
+ q->ai_addrlen, q->ai_family))
|
||||
{
|
||||
- results[i].source_addr_len = sl;
|
||||
+ results[i].source_addr_len = sizeof (results[i].source_addr);
|
||||
results[i].got_source_addr = true;
|
||||
|
||||
if (in6ai != NULL)
|
||||
@@ -2527,10 +2552,6 @@ getaddrinfo (const char *name, const char *service,
|
||||
results[i].source_addr_len = sizeof (struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
- else if (errno == EAFNOSUPPORT && af == AF_INET6
|
||||
- && q->ai_family == AF_INET)
|
||||
- /* This could mean IPv6 sockets are IPv6-only. */
|
||||
- goto close_retry;
|
||||
else
|
||||
/* Just make sure that if we have to process the same
|
||||
address again we do not copy any memory. */
|
|
@ -0,0 +1,32 @@
|
|||
commit c9226c03da0276593a0918eaa9a14835183343e8
|
||||
Author: Jörg Sonnenberger <joerg@bec.de>
|
||||
Date: Mon Sep 26 13:59:16 2022 -0400
|
||||
|
||||
get_nscd_addresses: Fix subscript typos [BZ #29605]
|
||||
|
||||
Fix the subscript on air->family, which was accidentally set to COUNT
|
||||
when it should have remained as I.
|
||||
|
||||
Resolves: BZ #29605
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 5e9bd17eb949974c..40a32a3de30cb294 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -549,11 +549,11 @@ get_nscd_addresses (const char *name, const struct addrinfo *req,
|
||||
at[count].addr[2] = htonl (0xffff);
|
||||
}
|
||||
else if (req->ai_family == AF_UNSPEC
|
||||
- || air->family[count] == req->ai_family)
|
||||
+ || air->family[i] == req->ai_family)
|
||||
{
|
||||
- at[count].family = air->family[count];
|
||||
+ at[count].family = air->family[i];
|
||||
memcpy (at[count].addr, addrs, size);
|
||||
- if (air->family[count] == AF_INET6)
|
||||
+ if (air->family[i] == AF_INET6)
|
||||
res->got_ipv6 = true;
|
||||
}
|
||||
at[count].next = at + count + 1;
|
|
@ -0,0 +1,25 @@
|
|||
commit 3bf7bab88b0da01d4f5ef20afbbb45203185501e
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Sep 5 17:04:05 2023 -0400
|
||||
|
||||
getcanonname: Fix a typo
|
||||
|
||||
This code is generally unused in practice since there don't seem to be
|
||||
any NSS modules that only implement _nss_MOD_gethostbyname2_r and not
|
||||
_nss_MOD_gethostbyname3_r.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 40a32a3de30cb294..e9f47aea358a3351 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -346,7 +346,7 @@ getcanonname (nss_action_list nip, const char *hname, const char *name)
|
||||
string. */
|
||||
s = (char *) name;
|
||||
}
|
||||
- return __strdup (name);
|
||||
+ return __strdup (s);
|
||||
}
|
||||
|
||||
/* Process looked up canonical name and if necessary, decode to IDNA. Result
|
|
@ -0,0 +1,23 @@
|
|||
commit 61bac1a9d2ab80ebcbc51484722e6ea43414bec7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Dec 20 16:14:33 2023 +0100
|
||||
|
||||
nss: Remove unused allocation from get_nscd_addresses in getaddrinfo
|
||||
|
||||
No bug because this is not visible if glibc is built with
|
||||
optimization. Otherwise this would be a critical resource leak.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index e9f47aea358a3351..321a6679d46494a3 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -514,7 +514,6 @@ get_nscd_addresses (const char *name, const struct addrinfo *req,
|
||||
int result = 0;
|
||||
char *addrs = air->addrs;
|
||||
|
||||
- struct gaih_addrtuple *addrfree = calloc (air->naddrs, sizeof (*addrfree));
|
||||
struct gaih_addrtuple *at = calloc (air->naddrs, sizeof (*at));
|
||||
if (at == NULL)
|
||||
{
|
|
@ -0,0 +1,35 @@
|
|||
commit b893410be304ddcea0bd43f537a13e8b18d37cf2
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 27 11:28:07 2023 +0100
|
||||
|
||||
elf: In _dl_relocate_object, skip processing if object is relocated
|
||||
|
||||
This is just a minor optimization. It also makes it more obvious that
|
||||
_dl_relocate_object can be called multiple times.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
|
||||
index be3e09e36835ed23..0254e589c06fbf4c 100644
|
||||
--- a/elf/dl-reloc.c
|
||||
+++ b/elf/dl-reloc.c
|
||||
@@ -192,6 +192,9 @@ void
|
||||
_dl_relocate_object (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;
|
||||
@@ -229,9 +232,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||
# define consider_symbind 0
|
||||
#endif
|
||||
|
||||
- if (l->l_relocated)
|
||||
- return;
|
||||
-
|
||||
/* If DT_BIND_NOW is set relocate all references in this object. We
|
||||
do not do this if we are profiling, of course. */
|
||||
// XXX Correct for auditing?
|
|
@ -0,0 +1,121 @@
|
|||
commit a74c2e1cbc8673dd7e97aae2f2705392e2ccc3f6
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 27 11:28:10 2023 +0100
|
||||
|
||||
elf: Introduce the _dl_open_relocate_one_object function
|
||||
|
||||
It is extracted from dl_open_worker_begin.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index c8a5d88161441031..cf3baccccb461878 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -467,6 +467,50 @@ activate_nodelete (struct link_map *new)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Relocate the object L. *RELOCATION_IN_PROGRESS controls whether
|
||||
+ the debugger is notified of the start of relocation processing. */
|
||||
+static void
|
||||
+_dl_open_relocate_one_object (struct dl_open_args *args, struct r_debug *r,
|
||||
+ struct link_map *l, int reloc_mode,
|
||||
+ bool *relocation_in_progress)
|
||||
+{
|
||||
+ if (l->l_real->l_relocated)
|
||||
+ return;
|
||||
+
|
||||
+ if (!*relocation_in_progress)
|
||||
+ {
|
||||
+ /* Notify the debugger that relocations are about to happen. */
|
||||
+ LIBC_PROBE (reloc_start, 2, args->nsid, r);
|
||||
+ *relocation_in_progress = true;
|
||||
+ }
|
||||
+
|
||||
+#ifdef SHARED
|
||||
+ if (__glibc_unlikely (GLRO(dl_profile) != NULL))
|
||||
+ {
|
||||
+ /* If this here is the shared object which we want to profile
|
||||
+ make sure the profile is started. We can find out whether
|
||||
+ this is necessary or not by observing the `_dl_profile_map'
|
||||
+ variable. If it was NULL but is not NULL afterwards we must
|
||||
+ start the profiling. */
|
||||
+ struct link_map *old_profile_map = GL(dl_profile_map);
|
||||
+
|
||||
+ _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
|
||||
+
|
||||
+ if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
|
||||
+ {
|
||||
+ /* We must prepare the profiling. */
|
||||
+ _dl_start_profile ();
|
||||
+
|
||||
+ /* Prevent unloading the object. */
|
||||
+ GL(dl_profile_map)->l_nodelete_active = true;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+#endif
|
||||
+ _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* struct dl_init_args and call_dl_init are used to call _dl_init with
|
||||
exception handling disabled. */
|
||||
struct dl_init_args
|
||||
@@ -651,7 +695,7 @@ dl_open_worker_begin (void *a)
|
||||
}
|
||||
while (l != NULL);
|
||||
|
||||
- int relocation_in_progress = 0;
|
||||
+ bool relocation_in_progress = false;
|
||||
|
||||
/* Perform relocation. This can trigger lazy binding in IFUNC
|
||||
resolvers. For NODELETE mappings, these dependencies are not
|
||||
@@ -662,44 +706,8 @@ dl_open_worker_begin (void *a)
|
||||
are undefined anyway, so this is not a problem. */
|
||||
|
||||
for (unsigned int i = last; i-- > first; )
|
||||
- {
|
||||
- l = new->l_initfini[i];
|
||||
-
|
||||
- if (l->l_real->l_relocated)
|
||||
- continue;
|
||||
-
|
||||
- if (! relocation_in_progress)
|
||||
- {
|
||||
- /* Notify the debugger that relocations are about to happen. */
|
||||
- LIBC_PROBE (reloc_start, 2, args->nsid, r);
|
||||
- relocation_in_progress = 1;
|
||||
- }
|
||||
-
|
||||
-#ifdef SHARED
|
||||
- if (__glibc_unlikely (GLRO(dl_profile) != NULL))
|
||||
- {
|
||||
- /* If this here is the shared object which we want to profile
|
||||
- make sure the profile is started. We can find out whether
|
||||
- this is necessary or not by observing the `_dl_profile_map'
|
||||
- variable. If it was NULL but is not NULL afterwards we must
|
||||
- start the profiling. */
|
||||
- struct link_map *old_profile_map = GL(dl_profile_map);
|
||||
-
|
||||
- _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
|
||||
-
|
||||
- if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
|
||||
- {
|
||||
- /* We must prepare the profiling. */
|
||||
- _dl_start_profile ();
|
||||
-
|
||||
- /* Prevent unloading the object. */
|
||||
- GL(dl_profile_map)->l_nodelete_active = true;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
-#endif
|
||||
- _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
|
||||
- }
|
||||
+ _dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode,
|
||||
+ &relocation_in_progress);
|
||||
|
||||
/* This only performs the memory allocations. The actual update of
|
||||
the scopes happens below, after failure is impossible. */
|
|
@ -0,0 +1,224 @@
|
|||
commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Nov 27 11:28:13 2023 +0100
|
||||
|
||||
elf: Relocate libc.so early during startup and dlmopen (bug 31083)
|
||||
|
||||
This makes it more likely that objects without dependencies can
|
||||
use IFUNC resolvers in libc.so.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(test backport differences)
|
||||
elf/rtld.c
|
||||
(prelink support was removed upstream)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 8e1f91bcd917fd4e..7b7c6c171ce23247 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -419,6 +419,8 @@ tests += \
|
||||
tst-nodelete2 \
|
||||
tst-nodelete-dlclose \
|
||||
tst-nodelete-opened \
|
||||
+ tst-nodeps1 \
|
||||
+ tst-nodeps2 \
|
||||
tst-noload \
|
||||
tst-null-argv \
|
||||
tst-relsort1 \
|
||||
@@ -777,6 +779,8 @@ modules-names = \
|
||||
tst-nodelete-dlclose-dso \
|
||||
tst-nodelete-dlclose-plugin \
|
||||
tst-nodelete-opened-lib \
|
||||
+ tst-nodeps1-mod \
|
||||
+ tst-nodeps2-mod \
|
||||
tst-null-argv-lib \
|
||||
tst-relsort1mod1 \
|
||||
tst-relsort1mod2 \
|
||||
@@ -931,8 +935,15 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
|
||||
|
||||
# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special
|
||||
# rules.
|
||||
-modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod \
|
||||
- tst-audit24bmod1 tst-audit24bmod2
|
||||
+modules-names-nobuild += \
|
||||
+ filtmod1 \
|
||||
+ tst-audit24bmod1 \
|
||||
+ tst-audit24bmod2 \
|
||||
+ tst-big-note-lib \
|
||||
+ tst-nodeps1-mod \
|
||||
+ tst-nodeps2-mod \
|
||||
+ tst-ro-dynamic-mod \
|
||||
+ # modules-names-nobuild
|
||||
|
||||
tests += $(tests-static)
|
||||
|
||||
@@ -2684,3 +2695,18 @@ LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed
|
||||
$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so
|
||||
$(objpfx)tst-dlclose-lazy.out: \
|
||||
$(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
|
||||
+
|
||||
+# The object tst-nodeps1-mod.so has no explicit dependencies on libc.so.
|
||||
+$(objpfx)tst-nodeps1-mod.so: $(objpfx)tst-nodeps1-mod.os
|
||||
+ $(LINK.o) -nostartfiles -nostdlib -shared -o $@ $^
|
||||
+tst-nodeps1.so-no-z-defs = yes
|
||||
+# Link libc.so before the test module with the IFUNC resolver reference.
|
||||
+LDFLAGS-tst-nodeps1 = $(common-objpfx)libc.so $(objpfx)tst-nodeps1-mod.so
|
||||
+$(objpfx)tst-nodeps1: $(objpfx)tst-nodeps1-mod.so
|
||||
+# Reuse the tst-nodeps1 module. Link libc.so before the test module
|
||||
+# with the IFUNC resolver reference.
|
||||
+$(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \
|
||||
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.os
|
||||
+ $(LINK.o) -Wl,--no-as-needed -nostartfiles -nostdlib -shared -o $@ $^
|
||||
+$(objpfx)tst-nodeps2.out: \
|
||||
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index cf3baccccb461878..4b58bdd668634130 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -705,6 +705,17 @@ dl_open_worker_begin (void *a)
|
||||
them. However, such relocation dependencies in IFUNC resolvers
|
||||
are undefined anyway, so this is not a problem. */
|
||||
|
||||
+ /* Ensure that libc is relocated first. This helps with the
|
||||
+ execution of IFUNC resolvers in libc, and matters only to newly
|
||||
+ 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. */
|
||||
+#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,
|
||||
+ reloc_mode, &relocation_in_progress);
|
||||
+#endif
|
||||
+
|
||||
for (unsigned int i = last; i-- > first; )
|
||||
_dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode,
|
||||
&relocation_in_progress);
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index 9de53ccaed420a57..a638d14e77745baa 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -2421,11 +2421,17 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
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 relocs (we
|
||||
- know that because it is self-contained). */
|
||||
+ 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. */
|
||||
|
||||
int consider_profiling = GLRO(dl_profile) != NULL;
|
||||
|
||||
+ 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);
|
||||
+
|
||||
/* If we are profiling we also must do lazy reloaction. */
|
||||
GLRO(dl_lazy) |= consider_profiling;
|
||||
|
||||
diff --git a/elf/tst-nodeps1-mod.c b/elf/tst-nodeps1-mod.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..45c8e3c631251a89
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-nodeps1-mod.c
|
||||
@@ -0,0 +1,25 @@
|
||||
+/* Test module with no libc.so dependency and string function references.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <string.h>
|
||||
+
|
||||
+/* Some references to libc symbols which are likely to have IFUNC
|
||||
+ resolvers. If they do not, this module does not exercise bug 31083. */
|
||||
+void *memcpy_pointer = memcpy;
|
||||
+void *memmove_pointer = memmove;
|
||||
+void *memset_pointer = memset;
|
||||
diff --git a/elf/tst-nodeps1.c b/elf/tst-nodeps1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1a8bde36cdb71446
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-nodeps1.c
|
||||
@@ -0,0 +1,23 @@
|
||||
+/* Test initially loaded module with implicit libc.so dependency (bug 31083).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Testing happens before main. */
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+}
|
||||
diff --git a/elf/tst-nodeps2-mod.c b/elf/tst-nodeps2-mod.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..4913feee9b56e0e1
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-nodeps2-mod.c
|
||||
@@ -0,0 +1 @@
|
||||
+/* Empty test module which depends on tst-nodeps1-mod.so. */
|
||||
diff --git a/elf/tst-nodeps2.c b/elf/tst-nodeps2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0bdc8eeb8cba3a99
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-nodeps2.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* Test dlmopen with implicit libc.so dependency (bug 31083).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/xdlfcn.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-nodeps2-mod.so", RTLD_NOW);
|
||||
+ xdlclose (handle);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,41 @@
|
|||
commit b3bee76c5f59498b9c189608f0a3132e2013fa1a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Dec 8 09:51:34 2023 +0100
|
||||
|
||||
elf: Initialize GLRO(dl_lazy) before relocating libc in dynamic startup
|
||||
|
||||
GLRO(dl_lazy) is used to set the parameters for the early
|
||||
_dl_relocate_object call, so the consider_profiling setting has to
|
||||
be applied before the call.
|
||||
|
||||
Fixes commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec ("elf: Relocate
|
||||
libc.so early during startup and dlmopen (bug 31083)").
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/rtld.c
|
||||
(prelink was removed upstream)
|
||||
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index a638d14e77745baa..d973c385b312ea16 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -2427,14 +2427,14 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||
|
||||
int consider_profiling = GLRO(dl_profile) != NULL;
|
||||
|
||||
+ /* If we are profiling we also must do lazy reloaction. */
|
||||
+ GLRO(dl_lazy) |= consider_profiling;
|
||||
+
|
||||
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);
|
||||
|
||||
- /* If we are profiling we also must do lazy reloaction. */
|
||||
- GLRO(dl_lazy) |= consider_profiling;
|
||||
-
|
||||
RTLD_TIMING_VAR (start);
|
||||
rtld_timer_start (&start);
|
||||
unsigned i = main_map->l_searchlist.r_nlist;
|
|
@ -0,0 +1,47 @@
|
|||
commit 3921c5b40f293c57cb326f58713c924b0662ef59
|
||||
Author: Hector Martin <marcan@marcan.st>
|
||||
Date: Tue Nov 28 15:23:07 2023 +0900
|
||||
|
||||
elf: Fix TLS modid reuse generation assignment (BZ 29039)
|
||||
|
||||
_dl_assign_tls_modid() assigns a slotinfo entry for a new module, but
|
||||
does *not* do anything to the generation counter. The first time this
|
||||
happens, the generation is zero and map_generation() returns the current
|
||||
generation to be used during relocation processing. However, if
|
||||
a slotinfo entry is later reused, it will already have a generation
|
||||
assigned. If this generation has fallen behind the current global max
|
||||
generation, then this causes an obsolete generation to be assigned
|
||||
during relocation processing, as map_generation() returns this
|
||||
generation if nonzero. _dl_add_to_slotinfo() eventually resets the
|
||||
generation, but by then it is too late. This causes DTV updates to be
|
||||
skipped, leading to NULL or broken TLS slot pointers and segfaults.
|
||||
|
||||
Fix this by resetting the generation to zero in _dl_assign_tls_modid(),
|
||||
so it behaves the same as the first time a slot is assigned.
|
||||
_dl_add_to_slotinfo() will still assign the correct static generation
|
||||
later during module load, but relocation processing will no longer use
|
||||
an obsolete generation.
|
||||
|
||||
Note that slotinfo entry (aka modid) reuse typically happens after a
|
||||
dlclose and only TLS access via dynamic tlsdesc is affected. Because
|
||||
tlsdesc is optimized to use the optional part of static TLS, dynamic
|
||||
tlsdesc can be avoided by increasing the glibc.rtld.optional_static_tls
|
||||
tunable to a large enough value, or by LD_PRELOAD-ing the affected
|
||||
modules.
|
||||
|
||||
Fixes bug 29039.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index b8ada16f1637c910..b9dc56e81a3b43db 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -160,6 +160,7 @@ _dl_assign_tls_modid (struct link_map *l)
|
||||
{
|
||||
/* Mark the entry as used, so any dependency see it. */
|
||||
atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
|
||||
+ atomic_store_relaxed (&runp->slotinfo[result - disp].gen, 0);
|
||||
break;
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
commit 980450f12685326729d63ff72e93a996113bf073
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Wed Nov 29 11:31:37 2023 +0000
|
||||
|
||||
elf: Add TLS modid reuse test for bug 29039
|
||||
|
||||
This is a minimal regression test for bug 29039 which only affects
|
||||
targets with TLSDESC and a reproducer requires that
|
||||
|
||||
1) Have modid gaps (closed modules) with old generation.
|
||||
2) Update a DTV to a newer generation (needs a newer dlopen).
|
||||
3) But do not update the closed gap entry in that DTV.
|
||||
4) Reuse the modid gap for a new module (another dlopen).
|
||||
5) Use dynamic TLSDESC in that new module with old generation (bug).
|
||||
6) Access TLS via this TLSDESC and the now outdated DTV.
|
||||
|
||||
However step (3) in practice rarely happens: during DTV update the
|
||||
entries for closed modids are initialized to "unallocated" and then
|
||||
dynamic TLSDESC calls __tls_get_addr independently of its generation.
|
||||
The only exception to this is DTV setup at thread creation (gaps are
|
||||
initialized to NULL instead of unallocated) or DTV resize where the
|
||||
gap entries are outside the previous DTV array (again NULL instead
|
||||
of unallocated, and this requires loading > DTV_SURPLUS modules).
|
||||
|
||||
So the bug can only cause NULL (+ offset) dereference, not use after
|
||||
free. And the easiest way to get (3) is via thread creation.
|
||||
|
||||
Note that step (5) requires that the newly loaded module has larger
|
||||
TLS than the remaining optional static TLS. And for (6) there cannot
|
||||
be other TLS access or dlopen in the thread that updates the DTV.
|
||||
|
||||
Tested on aarch64-linux-gnu.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(Resolve test case ordering conflict.)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 7b7c6c171ce23247..7d55e68a55b54bd6 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -447,6 +447,7 @@ tests += \
|
||||
tst-tls5 \
|
||||
tst-tlsalign \
|
||||
tst-tlsalign-extern \
|
||||
+ tst-tlsgap \
|
||||
tst-tls-dlinfo \
|
||||
tst-tls-ie \
|
||||
tst-tls-ie-dlmopen \
|
||||
@@ -798,6 +799,9 @@ modules-names = \
|
||||
tst-tls20mod-bad \
|
||||
tst-tls21mod \
|
||||
tst-tlsalign-lib \
|
||||
+ tst-tlsgap-mod0 \
|
||||
+ tst-tlsgap-mod1 \
|
||||
+ tst-tlsgap-mod2 \
|
||||
tst-tls-ie-mod0 \
|
||||
tst-tls-ie-mod1 \
|
||||
tst-tls-ie-mod2 \
|
||||
@@ -2710,3 +2714,14 @@ $(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \
|
||||
$(LINK.o) -Wl,--no-as-needed -nostartfiles -nostdlib -shared -o $@ $^
|
||||
$(objpfx)tst-nodeps2.out: \
|
||||
$(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so
|
||||
+
|
||||
+$(objpfx)tst-tlsgap: $(shared-thread-library)
|
||||
+$(objpfx)tst-tlsgap.out: \
|
||||
+ $(objpfx)tst-tlsgap-mod0.so \
|
||||
+ $(objpfx)tst-tlsgap-mod1.so \
|
||||
+ $(objpfx)tst-tlsgap-mod2.so
|
||||
+ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||
+CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
|
||||
+CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
|
||||
+CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
|
||||
+endif
|
||||
diff --git a/elf/tst-tlsgap-mod0.c b/elf/tst-tlsgap-mod0.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1478b0beac5faf98
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tlsgap-mod0.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+int __thread tls0;
|
||||
+int *f0(void) { return &tls0; }
|
||||
diff --git a/elf/tst-tlsgap-mod1.c b/elf/tst-tlsgap-mod1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b10fc3702c43e478
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tlsgap-mod1.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+int __thread tls1[100]; /* Size > glibc.rtld.optional_static_tls / 2. */
|
||||
+int *f1(void) { return tls1; }
|
||||
diff --git a/elf/tst-tlsgap-mod2.c b/elf/tst-tlsgap-mod2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..166c27d7f3fac252
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tlsgap-mod2.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+int __thread tls2;
|
||||
+int *f2(void) { return &tls2; }
|
||||
diff --git a/elf/tst-tlsgap.c b/elf/tst-tlsgap.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..49328850769c5609
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-tlsgap.c
|
||||
@@ -0,0 +1,92 @@
|
||||
+/* TLS modid gap reuse regression test for bug 29039.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <http://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <dlfcn.h>
|
||||
+#include <pthread.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static void *mod[3];
|
||||
+#define MOD(i) "tst-tlsgap-mod" #i ".so"
|
||||
+static const char *modname[3] = { MOD(0), MOD(1), MOD(2) };
|
||||
+#undef MOD
|
||||
+
|
||||
+static void
|
||||
+open_mod (int i)
|
||||
+{
|
||||
+ mod[i] = xdlopen (modname[i], RTLD_LAZY);
|
||||
+ printf ("open %s\n", modname[i]);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+close_mod (int i)
|
||||
+{
|
||||
+ xdlclose (mod[i]);
|
||||
+ mod[i] = NULL;
|
||||
+ printf ("close %s\n", modname[i]);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+access_mod (int i, const char *sym)
|
||||
+{
|
||||
+ int *(*f) (void) = xdlsym (mod[i], sym);
|
||||
+ int *p = f ();
|
||||
+ printf ("access %s: %s() = %p\n", modname[i], sym, p);
|
||||
+ TEST_VERIFY_EXIT (p != NULL);
|
||||
+ ++*p;
|
||||
+}
|
||||
+
|
||||
+static void *
|
||||
+start (void *arg)
|
||||
+{
|
||||
+ /* The DTV generation is at the last dlopen of mod0 and the
|
||||
+ entry for mod1 is NULL. */
|
||||
+
|
||||
+ open_mod (1); /* Reuse modid of mod1. Uses dynamic TLS. */
|
||||
+
|
||||
+ /* DTV is unchanged: dlopen only updates the DTV to the latest
|
||||
+ generation if static TLS is allocated for a loaded module.
|
||||
+
|
||||
+ With bug 29039, the TLSDESC relocation in mod1 uses the old
|
||||
+ dlclose generation of mod1 instead of the new dlopen one so
|
||||
+ DTV is not updated on TLS access. */
|
||||
+
|
||||
+ access_mod (1, "f1");
|
||||
+
|
||||
+ return arg;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ open_mod (0);
|
||||
+ open_mod (1);
|
||||
+ open_mod (2);
|
||||
+ close_mod (0);
|
||||
+ close_mod (1); /* Create modid gap at mod1. */
|
||||
+ open_mod (0); /* Reuse modid of mod0, bump generation count. */
|
||||
+
|
||||
+ /* Create a thread where DTV of mod1 is NULL. */
|
||||
+ pthread_t t = xpthread_create (NULL, start, NULL);
|
||||
+ xpthread_join (t);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,29 @@
|
|||
commit 5eabdb6a6ac1599d23dd5966a37417215950245f
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Wed Dec 6 14:48:22 2023 +0100
|
||||
|
||||
getaddrinfo: translate ENOMEM to EAI_MEMORY (bug 31163)
|
||||
|
||||
When __resolv_context_get returns NULL due to out of memory, translate it
|
||||
to a return value of EAI_MEMORY.
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 321a6679d46494a3..8fe879c5420337a4 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -615,7 +615,14 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
|
||||
function variant. */
|
||||
res_ctx = __resolv_context_get ();
|
||||
if (res_ctx == NULL)
|
||||
- no_more = 1;
|
||||
+ {
|
||||
+ if (errno == ENOMEM)
|
||||
+ {
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ no_more = 1;
|
||||
+ }
|
||||
|
||||
while (!no_more)
|
||||
{
|
|
@ -0,0 +1,27 @@
|
|||
commit ecc7c3deb9f347649c2078fcc0f94d4cedf92d60
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Jan 2 14:36:17 2024 +0100
|
||||
|
||||
libio: Check remaining buffer size in _IO_wdo_write (bug 31183)
|
||||
|
||||
The multibyte character needs to fit into the remaining buffer space,
|
||||
not the already-written buffer space. Without the fix, we were never
|
||||
moving the write pointer from the start of the buffer, always using
|
||||
the single-character fallback buffer.
|
||||
|
||||
Fixes commit 04b76b5aa8b2d1d19066e42dd1 ("Don't error out writing
|
||||
a multibyte character to an unbuffered stream (bug 17522)").
|
||||
|
||||
diff --git a/libio/wfileops.c b/libio/wfileops.c
|
||||
index 37f44780f811bd38..6cbc3c7c968f9136 100644
|
||||
--- a/libio/wfileops.c
|
||||
+++ b/libio/wfileops.c
|
||||
@@ -57,7 +57,7 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do)
|
||||
char mb_buf[MB_LEN_MAX];
|
||||
char *write_base, *write_ptr, *buf_end;
|
||||
|
||||
- if (fp->_IO_write_ptr - fp->_IO_write_base < sizeof (mb_buf))
|
||||
+ if (fp->_IO_buf_end - fp->_IO_write_ptr < sizeof (mb_buf))
|
||||
{
|
||||
/* Make sure we have room for at least one multibyte
|
||||
character. */
|
|
@ -0,0 +1,317 @@
|
|||
commit d2123d68275acc0f061e73d5f86ca504e0d5a344
|
||||
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
Date: Tue Feb 16 12:55:13 2021 +0000
|
||||
|
||||
elf: Fix slow tls access after dlopen [BZ #19924]
|
||||
|
||||
In short: __tls_get_addr checks the global generation counter and if
|
||||
the current dtv is older then _dl_update_slotinfo updates dtv up to the
|
||||
generation of the accessed module. So if the global generation is newer
|
||||
than generation of the module then __tls_get_addr keeps hitting the
|
||||
slow dtv update path. The dtv update path includes a number of checks
|
||||
to see if any update is needed and this already causes measurable tls
|
||||
access slow down after dlopen.
|
||||
|
||||
It may be possible to detect up-to-date dtv faster. But if there are
|
||||
many modules loaded (> TLS_SLOTINFO_SURPLUS) then this requires at
|
||||
least walking the slotinfo list.
|
||||
|
||||
This patch tries to update the dtv to the global generation instead, so
|
||||
after a dlopen the tls access slow path is only hit once. The modules
|
||||
with larger generation than the accessed one were not necessarily
|
||||
synchronized before, so additional synchronization is needed.
|
||||
|
||||
This patch uses acquire/release synchronization when accessing the
|
||||
generation counter.
|
||||
|
||||
Note: in the x86_64 version of dl-tls.c the generation is only loaded
|
||||
once, since relaxed mo is not faster than acquire mo load.
|
||||
|
||||
I have not benchmarked this. Tested by Adhemerval Zanella on aarch64,
|
||||
powerpc, sparc, x86 who reported that it fixes the performance issue
|
||||
of bug 19924.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 985cd4e2821436af..95a03c9616c6a786 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -739,7 +739,7 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
if (__glibc_unlikely (newgen == 0))
|
||||
_dl_fatal_printf ("TLS generation counter wrapped! Please report as described in "REPORT_BUGS_TO".\n");
|
||||
/* Can be read concurrently. */
|
||||
- atomic_store_relaxed (&GL(dl_tls_generation), newgen);
|
||||
+ atomic_store_release (&GL(dl_tls_generation), newgen);
|
||||
|
||||
if (tls_free_end == GL(dl_tls_static_used))
|
||||
GL(dl_tls_static_used) = tls_free_start;
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index 633b047ad2497296..c8a5d88161441031 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -404,7 +404,7 @@ update_tls_slotinfo (struct link_map *new)
|
||||
_dl_fatal_printf (N_("\
|
||||
TLS generation counter wrapped! Please report this."));
|
||||
/* Can be read concurrently. */
|
||||
- atomic_store_relaxed (&GL(dl_tls_generation), newgen);
|
||||
+ atomic_store_release (&GL(dl_tls_generation), newgen);
|
||||
|
||||
/* We need a second pass for static tls data, because
|
||||
_dl_update_slotinfo must not be run while calls to
|
||||
@@ -421,8 +421,8 @@ TLS generation counter wrapped! Please report this."));
|
||||
now, but we can delay updating the DTV. */
|
||||
imap->l_need_tls_init = 0;
|
||||
#ifdef SHARED
|
||||
- /* Update the slot information data for at least the
|
||||
- generation of the DSO we are allocating data for. */
|
||||
+ /* Update the slot information data for the current
|
||||
+ generation. */
|
||||
|
||||
/* FIXME: This can terminate the process on memory
|
||||
allocation failure. It is not possible to raise
|
||||
@@ -430,7 +430,7 @@ TLS generation counter wrapped! Please report this."));
|
||||
_dl_update_slotinfo would have to be split into two
|
||||
operations, similar to resize_scopes and update_scopes
|
||||
above. This is related to bug 16134. */
|
||||
- _dl_update_slotinfo (imap->l_tls_modid);
|
||||
+ _dl_update_slotinfo (imap->l_tls_modid, newgen);
|
||||
#endif
|
||||
|
||||
dl_init_static_tls (imap);
|
||||
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
|
||||
index 5b69321bda1f2b27..be3e09e36835ed23 100644
|
||||
--- a/elf/dl-reloc.c
|
||||
+++ b/elf/dl-reloc.c
|
||||
@@ -111,11 +111,11 @@ _dl_try_allocate_static_tls (struct link_map *map, bool optional)
|
||||
if (map->l_real->l_relocated)
|
||||
{
|
||||
#ifdef SHARED
|
||||
+ /* Update the DTV of the current thread. Note: GL(dl_load_tls_lock)
|
||||
+ is held here so normal load of the generation counter is valid. */
|
||||
if (__builtin_expect (THREAD_DTV()[0].counter != GL(dl_tls_generation),
|
||||
0))
|
||||
- /* Update the slot information data for at least the generation of
|
||||
- the DSO we are allocating data for. */
|
||||
- (void) _dl_update_slotinfo (map->l_tls_modid);
|
||||
+ (void) _dl_update_slotinfo (map->l_tls_modid, GL(dl_tls_generation));
|
||||
#endif
|
||||
|
||||
dl_init_static_tls (map);
|
||||
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
||||
index fab6546e2d31edd4..b8ada16f1637c910 100644
|
||||
--- a/elf/dl-tls.c
|
||||
+++ b/elf/dl-tls.c
|
||||
@@ -721,57 +721,57 @@ allocate_and_init (struct link_map *map)
|
||||
|
||||
|
||||
struct link_map *
|
||||
-_dl_update_slotinfo (unsigned long int req_modid)
|
||||
+_dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
|
||||
{
|
||||
struct link_map *the_map = NULL;
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
- /* The global dl_tls_dtv_slotinfo array contains for each module
|
||||
- index the generation counter current when the entry was created.
|
||||
+ /* CONCURRENCY NOTES:
|
||||
+
|
||||
+ The global dl_tls_dtv_slotinfo_list array contains for each module
|
||||
+ index the generation counter current when that entry was updated.
|
||||
This array never shrinks so that all module indices which were
|
||||
- valid at some time can be used to access it. Before the first
|
||||
- use of a new module index in this function the array was extended
|
||||
- appropriately. Access also does not have to be guarded against
|
||||
- modifications of the array. It is assumed that pointer-size
|
||||
- values can be read atomically even in SMP environments. It is
|
||||
- possible that other threads at the same time dynamically load
|
||||
- code and therefore add to the slotinfo list. This is a problem
|
||||
- since we must not pick up any information about incomplete work.
|
||||
- The solution to this is to ignore all dtv slots which were
|
||||
- created after the one we are currently interested. We know that
|
||||
- dynamic loading for this module is completed and this is the last
|
||||
- load operation we know finished. */
|
||||
- unsigned long int idx = req_modid;
|
||||
+ valid at some time can be used to access it. Concurrent loading
|
||||
+ and unloading of modules can update slotinfo entries or extend
|
||||
+ the array. The updates happen under the GL(dl_load_tls_lock) and
|
||||
+ finish with the release store of the generation counter to
|
||||
+ GL(dl_tls_generation) which is synchronized with the load of
|
||||
+ new_gen in the caller. So updates up to new_gen are synchronized
|
||||
+ but updates for later generations may not be.
|
||||
+
|
||||
+ Here we update the thread dtv from old_gen (== dtv[0].counter) to
|
||||
+ new_gen generation. For this, each dtv[i] entry is either set to
|
||||
+ an unallocated state (set), or left unmodified (nop). Where (set)
|
||||
+ may resize the dtv first if modid i >= dtv[-1].counter. The rules
|
||||
+ for the decision between (set) and (nop) are
|
||||
+
|
||||
+ (1) If slotinfo entry i is concurrently updated then either (set)
|
||||
+ or (nop) is valid: TLS access cannot use dtv[i] unless it is
|
||||
+ synchronized with a generation > new_gen.
|
||||
+
|
||||
+ Otherwise, if the generation of slotinfo entry i is gen and the
|
||||
+ loaded module for this entry is map then
|
||||
+
|
||||
+ (2) If gen <= old_gen then do (nop).
|
||||
+
|
||||
+ (3) If old_gen < gen <= new_gen then
|
||||
+ (3.1) if map != 0 then (set)
|
||||
+ (3.2) if map == 0 then either (set) or (nop).
|
||||
+
|
||||
+ Note that (1) cannot be reliably detected, but since both actions
|
||||
+ are valid it does not have to be. Only (2) and (3.1) cases need
|
||||
+ to be distinguished for which relaxed mo access of gen and map is
|
||||
+ enough: their value is synchronized when it matters.
|
||||
+
|
||||
+ Note that a relaxed mo load may give an out-of-thin-air value since
|
||||
+ it is used in decisions that can affect concurrent stores. But this
|
||||
+ should only happen if the OOTA value causes UB that justifies the
|
||||
+ concurrent store of the value. This is not expected to be an issue
|
||||
+ in practice. */
|
||||
struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
|
||||
|
||||
- while (idx >= listp->len)
|
||||
+ if (dtv[0].counter < new_gen)
|
||||
{
|
||||
- idx -= listp->len;
|
||||
- listp = listp->next;
|
||||
- }
|
||||
-
|
||||
- if (dtv[0].counter < listp->slotinfo[idx].gen)
|
||||
- {
|
||||
- /* CONCURRENCY NOTES:
|
||||
-
|
||||
- Here the dtv needs to be updated to new_gen generation count.
|
||||
-
|
||||
- This code may be called during TLS access when GL(dl_load_tls_lock)
|
||||
- is not held. In that case the user code has to synchronize with
|
||||
- dlopen and dlclose calls of relevant modules. A module m is
|
||||
- relevant if the generation of m <= new_gen and dlclose of m is
|
||||
- synchronized: a memory access here happens after the dlopen and
|
||||
- before the dlclose of relevant modules. The dtv entries for
|
||||
- relevant modules need to be updated, other entries can be
|
||||
- arbitrary.
|
||||
-
|
||||
- This e.g. means that the first part of the slotinfo list can be
|
||||
- accessed race free, but the tail may be concurrently extended.
|
||||
- Similarly relevant slotinfo entries can be read race free, but
|
||||
- other entries are racy. However updating a non-relevant dtv
|
||||
- entry does not affect correctness. For a relevant module m,
|
||||
- max_modid >= modid of m. */
|
||||
- size_t new_gen = listp->slotinfo[idx].gen;
|
||||
size_t total = 0;
|
||||
size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
|
||||
assert (max_modid >= req_modid);
|
||||
@@ -784,31 +784,33 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
{
|
||||
size_t modid = total + cnt;
|
||||
|
||||
- /* Later entries are not relevant. */
|
||||
+ /* Case (1) for all later modids. */
|
||||
if (modid > max_modid)
|
||||
break;
|
||||
|
||||
size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen);
|
||||
|
||||
+ /* Case (1). */
|
||||
if (gen > new_gen)
|
||||
- /* Not relevant. */
|
||||
continue;
|
||||
|
||||
- /* If the entry is older than the current dtv layout we
|
||||
- know we don't have to handle it. */
|
||||
+ /* Case (2) or (1). */
|
||||
if (gen <= dtv[0].counter)
|
||||
continue;
|
||||
|
||||
+ /* Case (3) or (1). */
|
||||
+
|
||||
/* If there is no map this means the entry is empty. */
|
||||
struct link_map *map
|
||||
= atomic_load_relaxed (&listp->slotinfo[cnt].map);
|
||||
/* Check whether the current dtv array is large enough. */
|
||||
if (dtv[-1].counter < modid)
|
||||
{
|
||||
+ /* Case (3.2) or (1). */
|
||||
if (map == NULL)
|
||||
continue;
|
||||
|
||||
- /* Resize the dtv. */
|
||||
+ /* Resizing the dtv aborts on failure: bug 16134. */
|
||||
dtv = _dl_resize_dtv (dtv, max_modid);
|
||||
|
||||
assert (modid <= dtv[-1].counter);
|
||||
@@ -819,7 +821,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
|
||||
}
|
||||
|
||||
/* If there is currently memory allocate for this
|
||||
- dtv entry free it. */
|
||||
+ dtv entry free it. Note: this is not AS-safe. */
|
||||
/* XXX Ideally we will at some point create a memory
|
||||
pool. */
|
||||
free (dtv[modid].pointer.to_free);
|
||||
@@ -914,9 +916,9 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
|
||||
|
||||
static struct link_map *
|
||||
__attribute_noinline__
|
||||
-update_get_addr (GET_ADDR_ARGS)
|
||||
+update_get_addr (GET_ADDR_ARGS, size_t gen)
|
||||
{
|
||||
- struct link_map *the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
|
||||
+ struct link_map *the_map = _dl_update_slotinfo (GET_ADDR_MODULE, gen);
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
void *p = dtv[GET_ADDR_MODULE].pointer.val;
|
||||
@@ -946,12 +948,17 @@ __tls_get_addr (GET_ADDR_ARGS)
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
/* Update is needed if dtv[0].counter < the generation of the accessed
|
||||
- module. The global generation counter is used here as it is easier
|
||||
- to check. Synchronization for the relaxed MO access is guaranteed
|
||||
- by user code, see CONCURRENCY NOTES in _dl_update_slotinfo. */
|
||||
+ module, but the global generation counter is easier to check (which
|
||||
+ must be synchronized up to the generation of the accessed module by
|
||||
+ user code doing the TLS access so relaxed mo read is enough). */
|
||||
size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
- return update_get_addr (GET_ADDR_PARAM);
|
||||
+ {
|
||||
+ /* Update DTV up to the global generation, see CONCURRENCY NOTES
|
||||
+ in _dl_update_slotinfo. */
|
||||
+ gen = atomic_load_acquire (&GL(dl_tls_generation));
|
||||
+ return update_get_addr (GET_ADDR_PARAM, gen);
|
||||
+ }
|
||||
|
||||
void *p = dtv[GET_ADDR_MODULE].pointer.val;
|
||||
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||
index 8c0fe98f69a88f1e..7964e133e4930e88 100644
|
||||
--- a/sysdeps/generic/ldsodefs.h
|
||||
+++ b/sysdeps/generic/ldsodefs.h
|
||||
@@ -1304,7 +1304,8 @@ extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add)
|
||||
|
||||
/* Update slot information data for at least the generation of the
|
||||
module with the given index. */
|
||||
-extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid)
|
||||
+extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid,
|
||||
+ size_t gen)
|
||||
attribute_hidden;
|
||||
|
||||
/* Look up the module's TLS block as for __tls_get_addr,
|
||||
diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
|
||||
index 24ef560b718275a2..4ded8dd6b94edc81 100644
|
||||
--- a/sysdeps/x86_64/dl-tls.c
|
||||
+++ b/sysdeps/x86_64/dl-tls.c
|
||||
@@ -40,9 +40,9 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
|
||||
{
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
|
||||
- size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
|
||||
+ size_t gen = atomic_load_acquire (&GL(dl_tls_generation));
|
||||
if (__glibc_unlikely (dtv[0].counter != gen))
|
||||
- return update_get_addr (GET_ADDR_PARAM);
|
||||
+ return update_get_addr (GET_ADDR_PARAM, gen);
|
||||
|
||||
return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
commit c06c8aeb61708249d8eb0b17a676d16771ea640b
|
||||
Author: Dennis Brendel <dbrendel@redhat.com>
|
||||
Date: Mon Jan 15 09:55:37 2024 +0100
|
||||
|
||||
manual: fix order of arguments of memalign and aligned_alloc (Bug 27547)
|
||||
|
||||
On the summary page the order of the function arguments was reversed, but it is
|
||||
in correct order in the other places of the manual.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/manual/memory.texi b/manual/memory.texi
|
||||
index fb875f4c3c..3710d7ec66 100644
|
||||
--- a/manual/memory.texi
|
||||
+++ b/manual/memory.texi
|
||||
@@ -1502,7 +1502,7 @@ Space}.
|
||||
Allocate a block of @var{size} bytes, starting on a page boundary.
|
||||
@xref{Aligned Memory Blocks}.
|
||||
|
||||
-@item void *aligned_alloc (size_t @var{size}, size_t @var{alignment})
|
||||
+@item void *aligned_alloc (size_t @var{alignment}, size_t @var{size})
|
||||
Allocate a block of @var{size} bytes, starting on an address that is a
|
||||
multiple of @var{alignment}. @xref{Aligned Memory Blocks}.
|
||||
|
||||
@@ -1510,7 +1510,7 @@ multiple of @var{alignment}. @xref{Aligned Memory Blocks}.
|
||||
Allocate a block of @var{size} bytes, starting on an address that is a
|
||||
multiple of @var{alignment}. @xref{Aligned Memory Blocks}.
|
||||
|
||||
-@item void *memalign (size_t @var{size}, size_t @var{boundary})
|
||||
+@item void *memalign (size_t @var{boundary}, size_t @var{size})
|
||||
Allocate a block of @var{size} bytes, starting on an address that is a
|
||||
multiple of @var{boundary}. @xref{Aligned Memory Blocks}.
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
commit c3b023a7822185c9176cfb96eeca4ada3d662c4b
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Nov 24 12:57:57 2021 -0300
|
||||
|
||||
linux: Only build fstatat fallback if required
|
||||
|
||||
For 32-bit architecture with __ASSUME_STATX there is no need to
|
||||
build fstatat64_time64_stat.
|
||||
|
||||
Checked on i686-linux-gnu.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
index f968e4ef0594852e..50ae5ad74832efe1 100644
|
||||
--- a/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
@@ -74,6 +74,17 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
return r;
|
||||
}
|
||||
|
||||
+#if (__WORDSIZE == 32 \
|
||||
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
+ || defined STAT_HAS_TIME32
|
||||
+# define FSTATAT_USE_STATX 1
|
||||
+#else
|
||||
+# define FSTATAT_USE_STATX 0
|
||||
+#endif
|
||||
+
|
||||
+/* Only statx supports 64-bit timestamps for 32-bit architectures with
|
||||
+ __ASSUME_STATX, so there is no point in building the fallback. */
|
||||
+#if !FSTATAT_USE_STATX || (FSTATAT_USE_STATX && !defined __ASSUME_STATX)
|
||||
static inline int
|
||||
fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
int flag)
|
||||
@@ -134,13 +145,6 @@ fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
|
||||
return r;
|
||||
}
|
||||
-
|
||||
-#if (__WORDSIZE == 32 \
|
||||
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
- || defined STAT_HAS_TIME32
|
||||
-# define FSTATAT_USE_STATX 1
|
||||
-#else
|
||||
-# define FSTATAT_USE_STATX 0
|
||||
#endif
|
||||
|
||||
int
|
|
@ -0,0 +1,36 @@
|
|||
commit c7f05bd5342517f3f751e6ea8dec1916b80bee8a
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Mar 9 18:35:39 2022 -0300
|
||||
|
||||
Fix ununsed fstatat64_time64_statx
|
||||
|
||||
It is only called for legacy ABIs.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
index 50ae5ad74832efe1..45221bbdf901fa47 100644
|
||||
--- a/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
@@ -40,6 +40,11 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
|
||||
"__blkcnt_t and __blkcnt64_t must match");
|
||||
#endif
|
||||
|
||||
+#if (__WORDSIZE == 32 \
|
||||
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
+ || defined STAT_HAS_TIME32
|
||||
+# define FSTATAT_USE_STATX 1
|
||||
+
|
||||
static inline int
|
||||
fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
int flag)
|
||||
@@ -73,11 +78,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
|
||||
return r;
|
||||
}
|
||||
-
|
||||
-#if (__WORDSIZE == 32 \
|
||||
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
- || defined STAT_HAS_TIME32
|
||||
-# define FSTATAT_USE_STATX 1
|
||||
#else
|
||||
# define FSTATAT_USE_STATX 0
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
commit e6547d635b991651600fab31f788ed5facd77610
|
||||
Author: WANG Xuerui <git@xen0n.name>
|
||||
Date: Wed Jun 1 10:12:28 2022 +0800
|
||||
|
||||
linux: use statx for fstat if neither newfstatat nor fstatat64 is present
|
||||
|
||||
LoongArch is going to be the first architecture supported by Linux that
|
||||
has neither fstat* nor newfstatat [1], instead exclusively relying on
|
||||
statx. So in fstatat64's implementation, we need to also enable statx
|
||||
usage if neither fstatat64 nor newfstatat is present, to prepare for
|
||||
this new case of kernel ABI.
|
||||
|
||||
[1]: https://lore.kernel.org/all/20220518092619.1269111-1-chenhuacai@loongson.cn/
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
index 45221bbdf901fa47..ded431257bf3450f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
@@ -42,7 +42,8 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
|
||||
|
||||
#if (__WORDSIZE == 32 \
|
||||
&& (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
- || defined STAT_HAS_TIME32
|
||||
+ || defined STAT_HAS_TIME32 \
|
||||
+ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
|
||||
# define FSTATAT_USE_STATX 1
|
||||
|
||||
static inline int
|
|
@ -0,0 +1,157 @@
|
|||
commit 551101e8240b7514fc646d1722f8b79c90362b8f
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Mon Sep 11 10:25:48 2023 -0300
|
||||
|
||||
io: Do not implement fstat with fstatat
|
||||
|
||||
AT_EMPTY_PATH is a requirement to implement fstat over fstatat,
|
||||
however it does not prevent the kernel to read the path argument.
|
||||
It is not an issue, but on x86-64 with SMAP-capable CPUs the kernel is
|
||||
forced to perform expensive user memory access. After that regular
|
||||
lookup is performed which adds even more overhead.
|
||||
|
||||
Instead, issue the fstat syscall directly on LFS fstat implementation
|
||||
(32 bit architectures will still continue to use statx, which is
|
||||
required to have 64 bit time_t support). it should be even a
|
||||
small performance gain on non x86_64, since there is no need
|
||||
to handle the path argument.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c
|
||||
index 46de80b663b9c1c4..fe4f57065f8713d2 100644
|
||||
--- a/sysdeps/unix/sysv/linux/fstat64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/fstat64.c
|
||||
@@ -19,20 +19,53 @@
|
||||
#define __fstat __redirect___fstat
|
||||
#define fstat __redirect_fstat
|
||||
#include <sys/stat.h>
|
||||
+#undef __fstat
|
||||
+#undef fstat
|
||||
#include <fcntl.h>
|
||||
-#include <kernel_stat.h>
|
||||
-#include <stat_t64_cp.h>
|
||||
+#include <internal-stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
__fstat64_time64 (int fd, struct __stat64_t64 *buf)
|
||||
{
|
||||
+#if !FSTATAT_USE_STATX
|
||||
+# if XSTAT_IS_XSTAT64
|
||||
+# ifdef __NR_fstat
|
||||
+ /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and
|
||||
+ x86_64. */
|
||||
+ return INLINE_SYSCALL_CALL (fstat, fd, buf);
|
||||
+# elif defined __NR_fstat64
|
||||
+# if STAT64_IS_KERNEL_STAT64
|
||||
+ /* 64-bit kABI outlier, e.g. alpha */
|
||||
+ return INLINE_SYSCALL_CALL (fstat64, fd, buf);
|
||||
+# else
|
||||
+ /* 64-bit kABI outlier, e.g. sparc64. */
|
||||
+ struct kernel_stat64 kst64;
|
||||
+ int r = INLINE_SYSCALL_CALL (fstat64, fd, &kst64);
|
||||
+ if (r == 0)
|
||||
+ __cp_stat64_kstat64 (buf, &kst64);
|
||||
+ return r;
|
||||
+# endif /* STAT64_IS_KERNEL_STAT64 */
|
||||
+# endif
|
||||
+# else /* XSTAT_IS_XSTAT64 */
|
||||
+ /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */
|
||||
+ struct kernel_stat kst;
|
||||
+ int r = INLINE_SYSCALL_CALL (fstat, fd, &kst);
|
||||
+ if (r == 0)
|
||||
+ __cp_kstat_stat64_t64 (&kst, buf);
|
||||
+ return r;
|
||||
+# endif
|
||||
+#else /* !FSTATAT_USE_STATX */
|
||||
+ /* All kABIs with non-LFS support and with old 32-bit time_t support
|
||||
+ e.g. arm, csky, i386, hppa, m68k, microblaze, nios2, sh, powerpc32,
|
||||
+ and sparc32. */
|
||||
if (fd < 0)
|
||||
{
|
||||
__set_errno (EBADF);
|
||||
return -1;
|
||||
}
|
||||
return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH);
|
||||
+#endif
|
||||
}
|
||||
#if __TIMESIZE != 64
|
||||
hidden_def (__fstat64_time64)
|
||||
diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
index ded431257bf3450f..8e9db7b11f0e1cf3 100644
|
||||
--- a/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
+++ b/sysdeps/unix/sysv/linux/fstatat64.c
|
||||
@@ -21,12 +21,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
-#include <kernel_stat.h>
|
||||
#include <sysdep.h>
|
||||
#include <time.h>
|
||||
-#include <kstat_cp.h>
|
||||
-#include <stat_t64_cp.h>
|
||||
#include <sys/sysmacros.h>
|
||||
+#include <internal-stat.h>
|
||||
|
||||
#if __TIMESIZE == 64 \
|
||||
&& (__WORDSIZE == 32 \
|
||||
@@ -40,11 +38,7 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
|
||||
"__blkcnt_t and __blkcnt64_t must match");
|
||||
#endif
|
||||
|
||||
-#if (__WORDSIZE == 32 \
|
||||
- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
- || defined STAT_HAS_TIME32 \
|
||||
- || (!defined __NR_newfstatat && !defined __NR_fstatat64)
|
||||
-# define FSTATAT_USE_STATX 1
|
||||
+#if FSTATAT_USE_STATX
|
||||
|
||||
static inline int
|
||||
fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
@@ -79,8 +73,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
|
||||
|
||||
return r;
|
||||
}
|
||||
-#else
|
||||
-# define FSTATAT_USE_STATX 0
|
||||
#endif
|
||||
|
||||
/* Only statx supports 64-bit timestamps for 32-bit architectures with
|
||||
diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e3b05698532fb185
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/internal-stat.h
|
||||
@@ -0,0 +1,31 @@
|
||||
+/* Internal stat definitions.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <sysdep.h>
|
||||
+#include <stat_t64_cp.h>
|
||||
+#include <kernel_stat.h>
|
||||
+#include <kstat_cp.h>
|
||||
+
|
||||
+#if (__WORDSIZE == 32 \
|
||||
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
|
||||
+ || defined STAT_HAS_TIME32 \
|
||||
+ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
|
||||
+# define FSTATAT_USE_STATX 1
|
||||
+#else
|
||||
+# define FSTATAT_USE_STATX 0
|
||||
+#endif
|
|
@ -0,0 +1,41 @@
|
|||
commit 01671608a3bddde369cdd42aed12e1c019b87158
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Wed Aug 4 02:21:01 2021 +0530
|
||||
|
||||
gethosts: Remove unused argument _type
|
||||
|
||||
The generated code is unchanged.
|
||||
|
||||
(cherry picked from commit b17e842a60819098d2a203ecc8b8371b7e1d6c65)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index f391dc0a59849aab..702d8a50e0c218d2 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -239,7 +239,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
return true;
|
||||
}
|
||||
|
||||
-#define gethosts(_family, _type) \
|
||||
+#define gethosts(_family) \
|
||||
{ \
|
||||
struct hostent th; \
|
||||
char *localcanon = NULL; \
|
||||
@@ -864,7 +864,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (req->ai_family == AF_INET6
|
||||
|| req->ai_family == AF_UNSPEC)
|
||||
{
|
||||
- gethosts (AF_INET6, struct in6_addr);
|
||||
+ gethosts (AF_INET6);
|
||||
no_inet6_data = no_data;
|
||||
inet6_status = status;
|
||||
}
|
||||
@@ -876,7 +876,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
know we are not going to need them. */
|
||||
&& ((req->ai_flags & AI_ALL) || !got_ipv6)))
|
||||
{
|
||||
- gethosts (AF_INET, struct in_addr);
|
||||
+ gethosts (AF_INET);
|
||||
|
||||
if (req->ai_family == AF_INET)
|
||||
{
|
|
@ -0,0 +1,178 @@
|
|||
commit 6e3fed9d20d6b7ef4b69dd7cfcdd7bbaf1c9a9cb
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 20:24:37 2022 +0530
|
||||
|
||||
gaih_inet: split loopback lookup into its own function
|
||||
|
||||
Flatten the condition nesting and replace the alloca for RET.AT/ATR with
|
||||
a single array LOCAL_AT[2]. This gets rid of alloca and alloca
|
||||
accounting.
|
||||
|
||||
`git diff -b` is probably the best way to view this change since much of
|
||||
the diff is whitespace changes.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 657472b2a50f67b12e5bbe5827582c9c2bb82dc3)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 6be109d07f7fcce0..827c43b369836de9 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1004,6 +1004,32 @@ try_simple_gethostbyname (const char *name, const struct addrinfo *req,
|
||||
return -EAI_NODATA;
|
||||
}
|
||||
|
||||
+/* Add local address information into RES. RES->AT is assumed to have enough
|
||||
+ space for two tuples and is zeroed out. */
|
||||
+
|
||||
+static void
|
||||
+get_local_addresses (const struct addrinfo *req, struct gaih_result *res)
|
||||
+{
|
||||
+ struct gaih_addrtuple *atr = res->at;
|
||||
+ if (req->ai_family == AF_UNSPEC)
|
||||
+ res->at->next = res->at + 1;
|
||||
+
|
||||
+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||||
+ {
|
||||
+ res->at->family = AF_INET6;
|
||||
+ if ((req->ai_flags & AI_PASSIVE) == 0)
|
||||
+ memcpy (res->at->addr, &in6addr_loopback, sizeof (struct in6_addr));
|
||||
+ atr = res->at->next;
|
||||
+ }
|
||||
+
|
||||
+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
|
||||
+ {
|
||||
+ atr->family = AF_INET;
|
||||
+ if ((req->ai_flags & AI_PASSIVE) == 0)
|
||||
+ atr->addr[0] = htonl (INADDR_LOOPBACK);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int
|
||||
gaih_inet (const char *name, const struct gaih_service *service,
|
||||
const struct addrinfo *req, struct addrinfo **pai,
|
||||
@@ -1014,10 +1040,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
const char *orig_name = name;
|
||||
|
||||
- /* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
- function. */
|
||||
- size_t alloca_used = sizeof (struct scratch_buffer);
|
||||
-
|
||||
int rc;
|
||||
if ((rc = get_servtuples (service, req, st, tmpbuf)) != 0)
|
||||
return rc;
|
||||
@@ -1027,76 +1049,51 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
int result = 0;
|
||||
|
||||
struct gaih_result res = {0};
|
||||
- if (name != NULL)
|
||||
+ struct gaih_addrtuple local_at[2] = {0};
|
||||
+
|
||||
+ res.at = local_at;
|
||||
+
|
||||
+ if (__glibc_unlikely (name == NULL))
|
||||
{
|
||||
- if (req->ai_flags & AI_IDN)
|
||||
- {
|
||||
- char *out;
|
||||
- result = __idna_to_dns_encoding (name, &out);
|
||||
- if (result != 0)
|
||||
- return -result;
|
||||
- name = out;
|
||||
- malloc_name = true;
|
||||
- }
|
||||
+ get_local_addresses (req, &res);
|
||||
+ goto process_list;
|
||||
+ }
|
||||
|
||||
- res.at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||||
- res.at->scopeid = 0;
|
||||
- res.at->next = NULL;
|
||||
+ if (req->ai_flags & AI_IDN)
|
||||
+ {
|
||||
+ char *out;
|
||||
+ result = __idna_to_dns_encoding (name, &out);
|
||||
+ if (result != 0)
|
||||
+ return -result;
|
||||
+ name = out;
|
||||
+ malloc_name = true;
|
||||
+ }
|
||||
|
||||
- if ((result = text_to_binary_address (name, req, &res)) != 0)
|
||||
- goto free_and_return;
|
||||
- else if (res.at != NULL)
|
||||
- goto process_list;
|
||||
+ if ((result = text_to_binary_address (name, req, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
|
||||
- if ((result = try_simple_gethostbyname (name, req, tmpbuf, &res)) != 0)
|
||||
- goto free_and_return;
|
||||
- else if (res.at != NULL)
|
||||
- goto process_list;
|
||||
+ if ((result = try_simple_gethostbyname (name, req, tmpbuf, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
|
||||
#ifdef USE_NSCD
|
||||
- if ((result = get_nscd_addresses (name, req, &res)) != 0)
|
||||
- goto free_and_return;
|
||||
- else if (res.at != NULL)
|
||||
- goto process_list;
|
||||
+ if ((result = get_nscd_addresses (name, req, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
#endif
|
||||
|
||||
- if ((result = get_nss_addresses (name, req, tmpbuf, &res)) != 0)
|
||||
- goto free_and_return;
|
||||
- else if (res.at != NULL)
|
||||
- goto process_list;
|
||||
-
|
||||
- /* None of the lookups worked, so name not found. */
|
||||
- result = -EAI_NONAME;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- struct gaih_addrtuple *atr;
|
||||
- atr = res.at = alloca_account (sizeof (struct gaih_addrtuple),
|
||||
- alloca_used);
|
||||
- memset (res.at, '\0', sizeof (struct gaih_addrtuple));
|
||||
-
|
||||
- if (req->ai_family == AF_UNSPEC)
|
||||
- {
|
||||
- res.at->next = __alloca (sizeof (struct gaih_addrtuple));
|
||||
- memset (res.at->next, '\0', sizeof (struct gaih_addrtuple));
|
||||
- }
|
||||
-
|
||||
- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||||
- {
|
||||
- res.at->family = AF_INET6;
|
||||
- if ((req->ai_flags & AI_PASSIVE) == 0)
|
||||
- memcpy (res.at->addr, &in6addr_loopback, sizeof (struct in6_addr));
|
||||
- atr = res.at->next;
|
||||
- }
|
||||
+ if ((result = get_nss_addresses (name, req, tmpbuf, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
|
||||
- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
|
||||
- {
|
||||
- atr->family = AF_INET;
|
||||
- if ((req->ai_flags & AI_PASSIVE) == 0)
|
||||
- atr->addr[0] = htonl (INADDR_LOOPBACK);
|
||||
- }
|
||||
- }
|
||||
+ /* None of the lookups worked, so name not found. */
|
||||
+ result = -EAI_NONAME;
|
||||
+ goto free_and_return;
|
||||
|
||||
process_list:
|
||||
{
|
|
@ -0,0 +1,208 @@
|
|||
commit 92478a808f477480adbc5ca3d9a4a1bc27fc13ae
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 20:38:31 2022 +0530
|
||||
|
||||
gaih_inet: Split result generation into its own function
|
||||
|
||||
Simplify the loop a wee bit and clean up variable names too.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit ac4653ef503d1e87893d1a6714748a1cdf4bf7ad)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 827c43b369836de9..1008f247365ea009 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1030,6 +1030,87 @@ get_local_addresses (const struct addrinfo *req, struct gaih_result *res)
|
||||
}
|
||||
}
|
||||
|
||||
+/* Generate results in PAI and its count in NADDRS. Return 0 on success or an
|
||||
+ error code on failure. */
|
||||
+
|
||||
+static int
|
||||
+generate_addrinfo (const struct addrinfo *req, struct gaih_result *res,
|
||||
+ const struct gaih_servtuple *st, struct addrinfo **pai,
|
||||
+ unsigned int *naddrs)
|
||||
+{
|
||||
+ size_t socklen;
|
||||
+ sa_family_t family;
|
||||
+
|
||||
+ /* Buffer is the size of an unformatted IPv6 address in printable format. */
|
||||
+ for (struct gaih_addrtuple *at = res->at; at != NULL; at = at->next)
|
||||
+ {
|
||||
+ family = at->family;
|
||||
+ if (family == AF_INET6)
|
||||
+ {
|
||||
+ socklen = sizeof (struct sockaddr_in6);
|
||||
+
|
||||
+ /* If we looked up IPv4 mapped address discard them here if
|
||||
+ the caller isn't interested in all address and we have
|
||||
+ found at least one IPv6 address. */
|
||||
+ if (res->got_ipv6
|
||||
+ && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
|
||||
+ && IN6_IS_ADDR_V4MAPPED (at->addr))
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ socklen = sizeof (struct sockaddr_in);
|
||||
+
|
||||
+ for (int i = 0; st[i].set; i++)
|
||||
+ {
|
||||
+ struct addrinfo *ai;
|
||||
+ ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
|
||||
+ if (ai == NULL)
|
||||
+ return -EAI_MEMORY;
|
||||
+
|
||||
+ ai->ai_flags = req->ai_flags;
|
||||
+ ai->ai_family = family;
|
||||
+ ai->ai_socktype = st[i].socktype;
|
||||
+ ai->ai_protocol = st[i].protocol;
|
||||
+ ai->ai_addrlen = socklen;
|
||||
+ ai->ai_addr = (void *) (ai + 1);
|
||||
+
|
||||
+ /* We only add the canonical name once. */
|
||||
+ ai->ai_canonname = res->canon;
|
||||
+ res->canon = NULL;
|
||||
+
|
||||
+#ifdef _HAVE_SA_LEN
|
||||
+ ai->ai_addr->sa_len = socklen;
|
||||
+#endif /* _HAVE_SA_LEN */
|
||||
+ ai->ai_addr->sa_family = family;
|
||||
+
|
||||
+ /* In case of an allocation error the list must be NULL
|
||||
+ terminated. */
|
||||
+ ai->ai_next = NULL;
|
||||
+
|
||||
+ if (family == AF_INET6)
|
||||
+ {
|
||||
+ struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) ai->ai_addr;
|
||||
+ sin6p->sin6_port = st[i].port;
|
||||
+ sin6p->sin6_flowinfo = 0;
|
||||
+ memcpy (&sin6p->sin6_addr, at->addr, sizeof (struct in6_addr));
|
||||
+ sin6p->sin6_scope_id = at->scopeid;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ struct sockaddr_in *sinp = (struct sockaddr_in *) ai->ai_addr;
|
||||
+ sinp->sin_port = st[i].port;
|
||||
+ memcpy (&sinp->sin_addr, at->addr, sizeof (struct in_addr));
|
||||
+ memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
|
||||
+ }
|
||||
+
|
||||
+ pai = &(ai->ai_next);
|
||||
+ }
|
||||
+
|
||||
+ ++*naddrs;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
gaih_inet (const char *name, const struct gaih_service *service,
|
||||
const struct addrinfo *req, struct addrinfo **pai,
|
||||
@@ -1096,98 +1177,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
goto free_and_return;
|
||||
|
||||
process_list:
|
||||
- {
|
||||
- /* Set up the canonical name if we need it. */
|
||||
- if ((result = process_canonname (req, orig_name, &res)) != 0)
|
||||
- goto free_and_return;
|
||||
-
|
||||
- struct gaih_addrtuple *at2 = res.at;
|
||||
- size_t socklen;
|
||||
- sa_family_t family;
|
||||
-
|
||||
- /*
|
||||
- buffer is the size of an unformatted IPv6 address in printable format.
|
||||
- */
|
||||
- while (at2 != NULL)
|
||||
- {
|
||||
- family = at2->family;
|
||||
- if (family == AF_INET6)
|
||||
- {
|
||||
- socklen = sizeof (struct sockaddr_in6);
|
||||
-
|
||||
- /* If we looked up IPv4 mapped address discard them here if
|
||||
- the caller isn't interested in all address and we have
|
||||
- found at least one IPv6 address. */
|
||||
- if (res.got_ipv6
|
||||
- && (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
|
||||
- && IN6_IS_ADDR_V4MAPPED (at2->addr))
|
||||
- goto ignore;
|
||||
- }
|
||||
- else
|
||||
- socklen = sizeof (struct sockaddr_in);
|
||||
-
|
||||
- for (int i = 0; st[i].set; i++)
|
||||
- {
|
||||
- struct addrinfo *ai;
|
||||
- ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
|
||||
- if (ai == NULL)
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
- ai->ai_flags = req->ai_flags;
|
||||
- ai->ai_family = family;
|
||||
- ai->ai_socktype = st[i].socktype;
|
||||
- ai->ai_protocol = st[i].protocol;
|
||||
- ai->ai_addrlen = socklen;
|
||||
- ai->ai_addr = (void *) (ai + 1);
|
||||
-
|
||||
- /* We only add the canonical name once. */
|
||||
- ai->ai_canonname = res.canon;
|
||||
- res.canon = NULL;
|
||||
-
|
||||
-#ifdef _HAVE_SA_LEN
|
||||
- ai->ai_addr->sa_len = socklen;
|
||||
-#endif /* _HAVE_SA_LEN */
|
||||
- ai->ai_addr->sa_family = family;
|
||||
-
|
||||
- /* In case of an allocation error the list must be NULL
|
||||
- terminated. */
|
||||
- ai->ai_next = NULL;
|
||||
-
|
||||
- if (family == AF_INET6)
|
||||
- {
|
||||
- struct sockaddr_in6 *sin6p =
|
||||
- (struct sockaddr_in6 *) ai->ai_addr;
|
||||
-
|
||||
- sin6p->sin6_port = st[i].port;
|
||||
- sin6p->sin6_flowinfo = 0;
|
||||
- memcpy (&sin6p->sin6_addr,
|
||||
- at2->addr, sizeof (struct in6_addr));
|
||||
- sin6p->sin6_scope_id = at2->scopeid;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- struct sockaddr_in *sinp =
|
||||
- (struct sockaddr_in *) ai->ai_addr;
|
||||
- sinp->sin_port = st[i].port;
|
||||
- memcpy (&sinp->sin_addr,
|
||||
- at2->addr, sizeof (struct in_addr));
|
||||
- memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
|
||||
- }
|
||||
-
|
||||
- pai = &(ai->ai_next);
|
||||
- }
|
||||
-
|
||||
- ++*naddrs;
|
||||
+ /* Set up the canonical name if we need it. */
|
||||
+ if ((result = process_canonname (req, orig_name, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
|
||||
- ignore:
|
||||
- at2 = at2->next;
|
||||
- }
|
||||
- }
|
||||
+ result = generate_addrinfo (req, &res, st, pai, naddrs);
|
||||
|
||||
- free_and_return:
|
||||
+free_and_return:
|
||||
if (malloc_name)
|
||||
free ((char *) name);
|
||||
free (addrmem);
|
|
@ -0,0 +1,34 @@
|
|||
commit cc4544ef8069a14c67a46b7e8e28eff1dc102050
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Wed Mar 2 11:45:29 2022 +0530
|
||||
|
||||
gethosts: Return EAI_MEMORY on allocation failure
|
||||
|
||||
All other cases of failures due to lack of memory return EAI_MEMORY, so
|
||||
it seems wrong to return EAI_SYSTEM here. The only reason
|
||||
convert_hostent_to_gaih_addrtuple could fail is on calloc failure.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit b587456c0e7b59dcfdbd2d44db000a3bc8244e57)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 1008f247365ea009..37260d6e6f292186 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -303,13 +303,13 @@ gethosts (nss_gethostbyname3_r fct, int family, const char *name,
|
||||
else if (status == NSS_STATUS_SUCCESS)
|
||||
{
|
||||
if (!convert_hostent_to_gaih_addrtuple (req, family, &th, res))
|
||||
- return -EAI_SYSTEM;
|
||||
+ return -EAI_MEMORY;
|
||||
|
||||
if (localcanon != NULL && res->canon == NULL)
|
||||
{
|
||||
char *canonbuf = __strdup (localcanon);
|
||||
if (canonbuf == NULL)
|
||||
- return -EAI_SYSTEM;
|
||||
+ return -EAI_MEMORY;
|
||||
res->canon = canonbuf;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,316 @@
|
|||
commit e09ee267c03e3150c2c9ba28625ab130705a485e
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri Sep 15 13:51:12 2023 -0400
|
||||
|
||||
getaddrinfo: Fix use after free in getcanonname (CVE-2023-4806)
|
||||
|
||||
When an NSS plugin only implements the _gethostbyname2_r and
|
||||
_getcanonname_r callbacks, getaddrinfo could use memory that was freed
|
||||
during tmpbuf resizing, through h_name in a previous query response.
|
||||
|
||||
The backing store for res->at->name when doing a query with
|
||||
gethostbyname3_r or gethostbyname2_r is tmpbuf, which is reallocated in
|
||||
gethosts during the query. For AF_INET6 lookup with AI_ALL |
|
||||
AI_V4MAPPED, gethosts gets called twice, once for a v6 lookup and second
|
||||
for a v4 lookup. In this case, if the first call reallocates tmpbuf
|
||||
enough number of times, resulting in a malloc, th->h_name (that
|
||||
res->at->name refers to) ends up on a heap allocated storage in tmpbuf.
|
||||
Now if the second call to gethosts also causes the plugin callback to
|
||||
return NSS_STATUS_TRYAGAIN, tmpbuf will get freed, resulting in a UAF
|
||||
reference in res->at->name. This then gets dereferenced in the
|
||||
getcanonname_r plugin call, resulting in the use after free.
|
||||
|
||||
Fix this by copying h_name over and freeing it at the end. This
|
||||
resolves BZ #30843, which is assigned CVE-2023-4806.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 333edb1588ede881..64b29745131d3cf5 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -81,6 +81,7 @@ tests-container := \
|
||||
tst-nss-test3 \
|
||||
tst-reload1 \
|
||||
tst-reload2 \
|
||||
+ tst-nss-gai-hv2-canonname \
|
||||
# tests-container
|
||||
|
||||
# Tests which need libdl
|
||||
@@ -144,7 +145,8 @@ libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
ifeq ($(build-static-nss),yes)
|
||||
tests-static += tst-nss-static
|
||||
endif
|
||||
-extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os
|
||||
+extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os \
|
||||
+ nss_test_gai_hv2_canonname.os
|
||||
|
||||
include ../Rules
|
||||
|
||||
@@ -179,12 +181,16 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver
|
||||
libof-nss_test1 = extramodules
|
||||
libof-nss_test2 = extramodules
|
||||
libof-nss_test_errno = extramodules
|
||||
+libof-nss_test_gai_hv2_canonname = extramodules
|
||||
$(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps)
|
||||
$(build-module)
|
||||
$(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps)
|
||||
$(build-module)
|
||||
$(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps)
|
||||
$(build-module)
|
||||
+$(objpfx)/libnss_test_gai_hv2_canonname.so: \
|
||||
+ $(objpfx)nss_test_gai_hv2_canonname.os $(link-libc-deps)
|
||||
+ $(build-module)
|
||||
$(objpfx)nss_test2.os : nss_test1.c
|
||||
# Use the nss_files suffix for these objects as well.
|
||||
$(objpfx)/libnss_test1.so$(libnss_files.so-version): $(objpfx)/libnss_test1.so
|
||||
@@ -194,10 +200,14 @@ $(objpfx)/libnss_test2.so$(libnss_files.so-version): $(objpfx)/libnss_test2.so
|
||||
$(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \
|
||||
$(objpfx)/libnss_test_errno.so
|
||||
$(make-link)
|
||||
+$(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version): \
|
||||
+ $(objpfx)/libnss_test_gai_hv2_canonname.so
|
||||
+ $(make-link)
|
||||
$(patsubst %,$(objpfx)%.out,$(tests) $(tests-container)) : \
|
||||
$(objpfx)/libnss_test1.so$(libnss_files.so-version) \
|
||||
$(objpfx)/libnss_test2.so$(libnss_files.so-version) \
|
||||
- $(objpfx)/libnss_test_errno.so$(libnss_files.so-version)
|
||||
+ $(objpfx)/libnss_test_errno.so$(libnss_files.so-version) \
|
||||
+ $(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version)
|
||||
|
||||
ifeq (yes,$(have-thread-library))
|
||||
$(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library)
|
||||
diff --git a/nss/nss_test_gai_hv2_canonname.c b/nss/nss_test_gai_hv2_canonname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..4439c83c9f40cf43
|
||||
--- /dev/null
|
||||
+++ b/nss/nss_test_gai_hv2_canonname.c
|
||||
@@ -0,0 +1,56 @@
|
||||
+/* NSS service provider that only provides gethostbyname2_r.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <nss.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include "nss/tst-nss-gai-hv2-canonname.h"
|
||||
+
|
||||
+/* Catch misnamed and functions. */
|
||||
+#pragma GCC diagnostic error "-Wmissing-prototypes"
|
||||
+NSS_DECLARE_MODULE_FUNCTIONS (test_gai_hv2_canonname)
|
||||
+
|
||||
+extern enum nss_status _nss_files_gethostbyname2_r (const char *, int,
|
||||
+ struct hostent *, char *,
|
||||
+ size_t, int *, int *);
|
||||
+
|
||||
+enum nss_status
|
||||
+_nss_test_gai_hv2_canonname_gethostbyname2_r (const char *name, int af,
|
||||
+ struct hostent *result,
|
||||
+ char *buffer, size_t buflen,
|
||||
+ int *errnop, int *herrnop)
|
||||
+{
|
||||
+ return _nss_files_gethostbyname2_r (name, af, result, buffer, buflen, errnop,
|
||||
+ herrnop);
|
||||
+}
|
||||
+
|
||||
+enum nss_status
|
||||
+_nss_test_gai_hv2_canonname_getcanonname_r (const char *name, char *buffer,
|
||||
+ size_t buflen, char **result,
|
||||
+ int *errnop, int *h_errnop)
|
||||
+{
|
||||
+ /* We expect QUERYNAME, which is a small enough string that it shouldn't fail
|
||||
+ the test. */
|
||||
+ if (memcmp (QUERYNAME, name, sizeof (QUERYNAME))
|
||||
+ || buflen < sizeof (QUERYNAME))
|
||||
+ abort ();
|
||||
+
|
||||
+ strncpy (buffer, name, buflen);
|
||||
+ *result = buffer;
|
||||
+ return NSS_STATUS_SUCCESS;
|
||||
+}
|
||||
diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d5f10c07d6a90773
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-hv2-canonname.c
|
||||
@@ -0,0 +1,63 @@
|
||||
+/* Test NSS query path for plugins that only implement gethostbyname2
|
||||
+ (#30843).
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <nss.h>
|
||||
+#include <netdb.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include "nss/tst-nss-gai-hv2-canonname.h"
|
||||
+
|
||||
+#define PREPARE do_prepare
|
||||
+
|
||||
+static void do_prepare (int a, char **av)
|
||||
+{
|
||||
+ FILE *hosts = xfopen ("/etc/hosts", "w");
|
||||
+ for (unsigned i = 2; i < 255; i++)
|
||||
+ {
|
||||
+ fprintf (hosts, "ff01::ff02:ff03:%u:2\ttest.example.com\n", i);
|
||||
+ fprintf (hosts, "192.168.0.%u\ttest.example.com\n", i);
|
||||
+ }
|
||||
+ xfclose (hosts);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ __nss_configure_lookup ("hosts", "test_gai_hv2_canonname");
|
||||
+
|
||||
+ struct addrinfo hints = {};
|
||||
+ struct addrinfo *result = NULL;
|
||||
+
|
||||
+ hints.ai_family = AF_INET6;
|
||||
+ hints.ai_flags = AI_ALL | AI_V4MAPPED | AI_CANONNAME;
|
||||
+
|
||||
+ int ret = getaddrinfo (QUERYNAME, NULL, &hints, &result);
|
||||
+
|
||||
+ if (ret != 0)
|
||||
+ FAIL_EXIT1 ("getaddrinfo failed: %s\n", gai_strerror (ret));
|
||||
+
|
||||
+ TEST_COMPARE_STRING (result->ai_canonname, QUERYNAME);
|
||||
+
|
||||
+ freeaddrinfo(result);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nss/tst-nss-gai-hv2-canonname.h b/nss/tst-nss-gai-hv2-canonname.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..14f2a9cb0867dff9
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-hv2-canonname.h
|
||||
@@ -0,0 +1 @@
|
||||
+#define QUERYNAME "test.example.com"
|
||||
diff --git a/nss/tst-nss-gai-hv2-canonname.root/postclean.req b/nss/tst-nss-gai-hv2-canonname.root/postclean.req
|
||||
new file mode 100644
|
||||
index 0000000000000000..e69de29bb2d1d643
|
||||
diff --git a/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script b/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script
|
||||
new file mode 100644
|
||||
index 0000000000000000..31848b4a28524af6
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script
|
||||
@@ -0,0 +1,2 @@
|
||||
+cp $B/nss/libnss_test_gai_hv2_canonname.so $L/libnss_test_gai_hv2_canonname.so.2
|
||||
+su
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 37260d6e6f292186..10dc63542f337693 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -120,6 +120,7 @@ struct gaih_result
|
||||
{
|
||||
struct gaih_addrtuple *at;
|
||||
char *canon;
|
||||
+ char *h_name;
|
||||
bool free_at;
|
||||
bool got_ipv6;
|
||||
};
|
||||
@@ -165,6 +166,7 @@ gaih_result_reset (struct gaih_result *res)
|
||||
if (res->free_at)
|
||||
free (res->at);
|
||||
free (res->canon);
|
||||
+ free (res->h_name);
|
||||
memset (res, 0, sizeof (*res));
|
||||
}
|
||||
|
||||
@@ -203,9 +205,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name
|
||||
- is not copied, and the struct hostent object must not be deallocated
|
||||
- prematurely. The new addresses are appended to the tuple array in RES. */
|
||||
+/* Convert struct hostent to a list of struct gaih_addrtuple objects. The new
|
||||
+ addresses are appended to the tuple array in RES. */
|
||||
static bool
|
||||
convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
|
||||
struct hostent *h, struct gaih_result *res)
|
||||
@@ -238,6 +239,15 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
|
||||
res->at = array;
|
||||
res->free_at = true;
|
||||
|
||||
+ /* Duplicate h_name because it may get reclaimed when the underlying storage
|
||||
+ is freed. */
|
||||
+ if (res->h_name == NULL)
|
||||
+ {
|
||||
+ res->h_name = __strdup (h->h_name);
|
||||
+ if (res->h_name == NULL)
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/* Update the next pointers on reallocation. */
|
||||
for (size_t i = 0; i < old; i++)
|
||||
array[i].next = array + i + 1;
|
||||
@@ -262,7 +272,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
|
||||
}
|
||||
array[i].next = array + i + 1;
|
||||
}
|
||||
- array[0].name = h->h_name;
|
||||
array[count - 1].next = NULL;
|
||||
|
||||
return true;
|
||||
@@ -324,15 +333,15 @@ gethosts (nss_gethostbyname3_r fct, int family, const char *name,
|
||||
memory allocation failure. The returned string is allocated on the
|
||||
heap; the caller has to free it. */
|
||||
static char *
|
||||
-getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
|
||||
+getcanonname (nss_action_list nip, const char *hname, const char *name)
|
||||
{
|
||||
nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
|
||||
char *s = (char *) name;
|
||||
if (cfct != NULL)
|
||||
{
|
||||
char buf[256];
|
||||
- if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
|
||||
- &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS)
|
||||
+ if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno,
|
||||
+ &h_errno)) != NSS_STATUS_SUCCESS)
|
||||
/* If the canonical name cannot be determined, use the passed
|
||||
string. */
|
||||
s = (char *) name;
|
||||
@@ -771,7 +780,7 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
|
||||
if ((req->ai_flags & AI_CANONNAME) != 0
|
||||
&& res->canon == NULL)
|
||||
{
|
||||
- char *canonbuf = getcanonname (nip, res->at, name);
|
||||
+ char *canonbuf = getcanonname (nip, res->h_name, name);
|
||||
if (canonbuf == NULL)
|
||||
{
|
||||
__resolv_context_put (res_ctx);
|
|
@ -0,0 +1,37 @@
|
|||
commit 57e349b1b0df1aee2dcd19dae1f324bde25ff8f0
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Wed Dec 8 07:02:27 2021 -0800
|
||||
|
||||
Disable DT_RUNPATH on NSS tests [BZ #28455]
|
||||
|
||||
The glibc internal NSS functions should always load NSS modules from
|
||||
the system. For testing purpose, disable DT_RUNPATH on NSS tests so
|
||||
that the glibc internal NSS functions can load testing NSS modules
|
||||
via DT_RPATH.
|
||||
|
||||
This partially fixes BZ #28455.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
nss/Makefile
|
||||
(different test backport order)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 64b29745131d3cf5..9af46fb3a8195809 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -215,3 +215,13 @@ endif
|
||||
|
||||
$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so
|
||||
$(objpfx)tst-nss-files-alias-truncated.out: $(objpfx)/libnss_files.so
|
||||
+
|
||||
+# Disable DT_RUNPATH on NSS tests so that the glibc internal NSS
|
||||
+# functions can load testing NSS modules via DT_RPATH.
|
||||
+LDFLAGS-tst-nss-test1 = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test2 = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test3 = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test4 = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test5 = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test_errno = -Wl,--disable-new-dtags
|
||||
+LDFLAGS-tst-nss-test_gai_hv2_canonname = -Wl,--disable-new-dtags
|
|
@ -0,0 +1,84 @@
|
|||
commit ec6b95c3303c700eb89eebeda2d7264cc184a796
|
||||
Author: Romain Geissler <romain.geissler@amadeus.com>
|
||||
Date: Mon Sep 25 01:21:51 2023 +0100
|
||||
|
||||
Fix leak in getaddrinfo introduced by the fix for CVE-2023-4806 [BZ #30843]
|
||||
|
||||
This patch fixes a very recently added leak in getaddrinfo.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 9af46fb3a8195809..62a68880198c243c 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -148,6 +148,15 @@ endif
|
||||
extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os \
|
||||
nss_test_gai_hv2_canonname.os
|
||||
|
||||
+ifeq ($(run-built-tests),yes)
|
||||
+ifneq (no,$(PERL))
|
||||
+tests-special += $(objpfx)mtrace-tst-nss-gai-hv2-canonname.out
|
||||
+endif
|
||||
+endif
|
||||
+
|
||||
+generated += mtrace-tst-nss-gai-hv2-canonname.out \
|
||||
+ tst-nss-gai-hv2-canonname.mtrace
|
||||
+
|
||||
include ../Rules
|
||||
|
||||
ifeq (yes,$(have-selinux))
|
||||
@@ -216,6 +225,17 @@ endif
|
||||
$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so
|
||||
$(objpfx)tst-nss-files-alias-truncated.out: $(objpfx)/libnss_files.so
|
||||
|
||||
+tst-nss-gai-hv2-canonname-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-nss-gai-hv2-canonname.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
|
||||
+$(objpfx)mtrace-tst-nss-gai-hv2-canonname.out: \
|
||||
+ $(objpfx)tst-nss-gai-hv2-canonname.out
|
||||
+ { test -r $(objpfx)tst-nss-gai-hv2-canonname.mtrace \
|
||||
+ || ( echo "tst-nss-gai-hv2-canonname.mtrace does not exist"; exit 77; ) \
|
||||
+ && $(common-objpfx)malloc/mtrace \
|
||||
+ $(objpfx)tst-nss-gai-hv2-canonname.mtrace; } > $@; \
|
||||
+ $(evaluate-test)
|
||||
+
|
||||
# Disable DT_RUNPATH on NSS tests so that the glibc internal NSS
|
||||
# functions can load testing NSS modules via DT_RPATH.
|
||||
LDFLAGS-tst-nss-test1 = -Wl,--disable-new-dtags
|
||||
diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c
|
||||
index d5f10c07d6a90773..7db53cf09da8dcb6 100644
|
||||
--- a/nss/tst-nss-gai-hv2-canonname.c
|
||||
+++ b/nss/tst-nss-gai-hv2-canonname.c
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
+#include <mcheck.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xstdio.h>
|
||||
#include "nss/tst-nss-gai-hv2-canonname.h"
|
||||
@@ -41,6 +42,8 @@ static void do_prepare (int a, char **av)
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
+ mtrace ();
|
||||
+
|
||||
__nss_configure_lookup ("hosts", "test_gai_hv2_canonname");
|
||||
|
||||
struct addrinfo hints = {};
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 10dc63542f337693..d6046a707f1d742a 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -1196,9 +1196,7 @@ free_and_return:
|
||||
if (malloc_name)
|
||||
free ((char *) name);
|
||||
free (addrmem);
|
||||
- if (res.free_at)
|
||||
- free (res.at);
|
||||
- free (res.canon);
|
||||
+ gaih_result_reset (&res);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
commit b195fd86c616b147dad3a63498b79e0dedb4662b
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 22:17:36 2022 +0530
|
||||
|
||||
gaih_inet: Simplify canon name resolution
|
||||
|
||||
Simplify logic for allocation of canon to remove the canonbuf variable;
|
||||
canon now always points to an allocated block. Also pull the canon name
|
||||
set into a separate function.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit d01411f6bc61429fc027c38827bf3103b48eef2e)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 702d8a50e0c218d2..5c0d873e1d766099 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -285,7 +285,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
\
|
||||
if (localcanon != NULL && canon == NULL) \
|
||||
{ \
|
||||
- canonbuf = __strdup (localcanon); \
|
||||
+ char *canonbuf = __strdup (localcanon); \
|
||||
if (canonbuf == NULL) \
|
||||
{ \
|
||||
__resolv_context_put (res_ctx); \
|
||||
@@ -323,6 +323,41 @@ getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
|
||||
return __strdup (name);
|
||||
}
|
||||
|
||||
+/* Process looked up canonical name and if necessary, decode to IDNA. Result
|
||||
+ is a new string written to CANONP and the earlier string is freed. */
|
||||
+
|
||||
+static int
|
||||
+process_canonname (const struct addrinfo *req, const char *orig_name,
|
||||
+ char **canonp)
|
||||
+{
|
||||
+ char *canon = *canonp;
|
||||
+
|
||||
+ if ((req->ai_flags & AI_CANONNAME) != 0)
|
||||
+ {
|
||||
+ bool do_idn = req->ai_flags & AI_CANONIDN;
|
||||
+ if (do_idn)
|
||||
+ {
|
||||
+ char *out;
|
||||
+ int rc = __idna_from_dns_encoding (canon ?: orig_name, &out);
|
||||
+ if (rc == 0)
|
||||
+ {
|
||||
+ free (canon);
|
||||
+ canon = out;
|
||||
+ }
|
||||
+ else if (rc == EAI_IDN_ENCODE)
|
||||
+ /* Use the punycode name as a fallback. */
|
||||
+ do_idn = false;
|
||||
+ else
|
||||
+ return -rc;
|
||||
+ }
|
||||
+ if (!do_idn && canon == NULL && (canon = __strdup (orig_name)) == NULL)
|
||||
+ return -EAI_MEMORY;
|
||||
+ }
|
||||
+
|
||||
+ *canonp = canon;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
gaih_inet (const char *name, const struct gaih_service *service,
|
||||
const struct addrinfo *req, struct addrinfo **pai,
|
||||
@@ -332,7 +367,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
|
||||
struct gaih_addrtuple *at = NULL;
|
||||
bool got_ipv6 = false;
|
||||
- const char *canon = NULL;
|
||||
+ char *canon = NULL;
|
||||
const char *orig_name = name;
|
||||
|
||||
/* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
@@ -453,7 +488,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
bool malloc_name = false;
|
||||
struct gaih_addrtuple *addrmem = NULL;
|
||||
- char *canonbuf = NULL;
|
||||
int result = 0;
|
||||
|
||||
if (name != NULL)
|
||||
@@ -495,7 +529,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
|
||||
if (req->ai_flags & AI_CANONNAME)
|
||||
- canon = name;
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (name);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto free_and_return;
|
||||
+ }
|
||||
+ canon = canonbuf;
|
||||
+ }
|
||||
|
||||
goto process_list;
|
||||
}
|
||||
@@ -545,7 +587,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
|
||||
if (req->ai_flags & AI_CANONNAME)
|
||||
- canon = name;
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (name);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto free_and_return;
|
||||
+ }
|
||||
+ canon = canonbuf;
|
||||
+ }
|
||||
|
||||
goto process_list;
|
||||
}
|
||||
@@ -676,9 +726,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
(*pat)->next = NULL;
|
||||
if (added_canon || air->canon == NULL)
|
||||
(*pat)->name = NULL;
|
||||
- else if (canonbuf == NULL)
|
||||
+ else if (canon == NULL)
|
||||
{
|
||||
- canonbuf = __strdup (air->canon);
|
||||
+ char *canonbuf = __strdup (air->canon);
|
||||
if (canonbuf == NULL)
|
||||
{
|
||||
result = -EAI_MEMORY;
|
||||
@@ -748,9 +798,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
/* Always start afresh; continue should discard previous results
|
||||
and the hosts database does not support merge. */
|
||||
at = NULL;
|
||||
- free (canonbuf);
|
||||
+ free (canon);
|
||||
free (addrmem);
|
||||
- canon = canonbuf = NULL;
|
||||
+ canon = NULL;
|
||||
addrmem = NULL;
|
||||
got_ipv6 = false;
|
||||
|
||||
@@ -805,7 +855,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
no_data = 1;
|
||||
|
||||
if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
|
||||
- canon = at->name;
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (at->name);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto free_and_return;
|
||||
+ }
|
||||
+ canon = canonbuf;
|
||||
+ }
|
||||
|
||||
struct gaih_addrtuple **pat = &at;
|
||||
|
||||
@@ -893,7 +952,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if ((req->ai_flags & AI_CANONNAME) != 0
|
||||
&& canon == NULL)
|
||||
{
|
||||
- canonbuf = getcanonname (nip, at, name);
|
||||
+ char *canonbuf = getcanonname (nip, at, name);
|
||||
if (canonbuf == NULL)
|
||||
{
|
||||
__resolv_context_put (res_ctx);
|
||||
@@ -1004,6 +1063,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
|
||||
{
|
||||
+ /* Set up the canonical name if we need it. */
|
||||
+ if ((result = process_canonname (req, orig_name, &canon)) != 0)
|
||||
+ goto free_and_return;
|
||||
+
|
||||
struct gaih_servtuple *st2;
|
||||
struct gaih_addrtuple *at2 = at;
|
||||
size_t socklen;
|
||||
@@ -1014,48 +1077,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
*/
|
||||
while (at2 != NULL)
|
||||
{
|
||||
- /* Only the first entry gets the canonical name. */
|
||||
- if (at2 == at && (req->ai_flags & AI_CANONNAME) != 0)
|
||||
- {
|
||||
- if (canon == NULL)
|
||||
- /* If the canonical name cannot be determined, use
|
||||
- the passed in string. */
|
||||
- canon = orig_name;
|
||||
-
|
||||
- bool do_idn = req->ai_flags & AI_CANONIDN;
|
||||
- if (do_idn)
|
||||
- {
|
||||
- char *out;
|
||||
- int rc = __idna_from_dns_encoding (canon, &out);
|
||||
- if (rc == 0)
|
||||
- canon = out;
|
||||
- else if (rc == EAI_IDN_ENCODE)
|
||||
- /* Use the punycode name as a fallback. */
|
||||
- do_idn = false;
|
||||
- else
|
||||
- {
|
||||
- result = -rc;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
- if (!do_idn)
|
||||
- {
|
||||
- if (canonbuf != NULL)
|
||||
- /* We already allocated the string using malloc, but
|
||||
- the buffer is now owned by canon. */
|
||||
- canonbuf = NULL;
|
||||
- else
|
||||
- {
|
||||
- canon = __strdup (canon);
|
||||
- if (canon == NULL)
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
family = at2->family;
|
||||
if (family == AF_INET6)
|
||||
{
|
||||
@@ -1078,7 +1099,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
|
||||
if (ai == NULL)
|
||||
{
|
||||
- free ((char *) canon);
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
@@ -1138,7 +1158,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (malloc_name)
|
||||
free ((char *) name);
|
||||
free (addrmem);
|
||||
- free (canonbuf);
|
||||
+ free (canon);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
commit f7efb43738f255db32cfa4e84a491c09f6da66e2
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Mar 3 23:07:42 2022 +0530
|
||||
|
||||
getaddrinfo: Fix leak with AI_ALL [BZ #28852]
|
||||
|
||||
Use realloc in convert_hostent_to_gaih_addrtuple and fix up pointers in
|
||||
the result list so that a single block is maintained for
|
||||
hostbyname3_r/hostbyname2_r and freed in gaih_inet. This result is
|
||||
never merged with any other results, since the hosts database does not
|
||||
permit merging.
|
||||
|
||||
Resolves BZ #28852.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 300460460706ce3ffe29a7df8966e68323ec5bf1)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 5c0d873e1d766099..ed70e6cb3944d219 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -189,19 +189,16 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/* Convert struct hostent to a list of struct gaih_addrtuple objects.
|
||||
- h_name is not copied, and the struct hostent object must not be
|
||||
- deallocated prematurely. *RESULT must be NULL or a pointer to a
|
||||
- linked-list. The new addresses are appended at the end. */
|
||||
+/* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name
|
||||
+ is not copied, and the struct hostent object must not be deallocated
|
||||
+ prematurely. The new addresses are appended to the tuple array in
|
||||
+ RESULT. */
|
||||
static bool
|
||||
convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
int family,
|
||||
struct hostent *h,
|
||||
struct gaih_addrtuple **result)
|
||||
{
|
||||
- while (*result)
|
||||
- result = &(*result)->next;
|
||||
-
|
||||
/* Count the number of addresses in h->h_addr_list. */
|
||||
size_t count = 0;
|
||||
for (char **p = h->h_addr_list; *p != NULL; ++p)
|
||||
@@ -212,10 +209,30 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
|
||||
return true;
|
||||
|
||||
- struct gaih_addrtuple *array = calloc (count, sizeof (*array));
|
||||
+ struct gaih_addrtuple *array = *result;
|
||||
+ size_t old = 0;
|
||||
+
|
||||
+ while (array != NULL)
|
||||
+ {
|
||||
+ old++;
|
||||
+ array = array->next;
|
||||
+ }
|
||||
+
|
||||
+ array = realloc (*result, (old + count) * sizeof (*array));
|
||||
+
|
||||
if (array == NULL)
|
||||
return false;
|
||||
|
||||
+ *result = array;
|
||||
+
|
||||
+ /* Update the next pointers on reallocation. */
|
||||
+ for (size_t i = 0; i < old; i++)
|
||||
+ array[i].next = array + i + 1;
|
||||
+
|
||||
+ array += old;
|
||||
+
|
||||
+ memset (array, 0, count * sizeof (*array));
|
||||
+
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (family == AF_INET && req->ai_family == AF_INET6)
|
||||
@@ -235,7 +252,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
array[0].name = h->h_name;
|
||||
array[count - 1].next = NULL;
|
||||
|
||||
- *result = array;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
commit e05e5889b8a307fe4be55b03bcbd7a1c62fc2f2d
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Feb 10 13:27:11 2022 +0530
|
||||
|
||||
gaih_inet: Simplify service resolution
|
||||
|
||||
Refactor the code to split out the service resolution code into a
|
||||
separate function. Allocate the service tuples array just once to the
|
||||
size of the typeproto array, thus avoiding the unnecessary pointer
|
||||
chasing and stack allocations.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 8d6cf99f2fb81a097f9334c125e5c23604af1a98)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index ed70e6cb3944d219..8c78ef9570fe0f58 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -100,14 +100,12 @@ struct gaih_service
|
||||
|
||||
struct gaih_servtuple
|
||||
{
|
||||
- struct gaih_servtuple *next;
|
||||
int socktype;
|
||||
int protocol;
|
||||
int port;
|
||||
+ bool set;
|
||||
};
|
||||
|
||||
-static const struct gaih_servtuple nullserv;
|
||||
-
|
||||
|
||||
struct gaih_typeproto
|
||||
{
|
||||
@@ -180,11 +178,11 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
}
|
||||
while (r);
|
||||
|
||||
- st->next = NULL;
|
||||
st->socktype = tp->socktype;
|
||||
st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
? req->ai_protocol : tp->protocol);
|
||||
st->port = s->s_port;
|
||||
+ st->set = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -375,20 +373,11 @@ process_canonname (const struct addrinfo *req, const char *orig_name,
|
||||
}
|
||||
|
||||
static int
|
||||
-gaih_inet (const char *name, const struct gaih_service *service,
|
||||
- const struct addrinfo *req, struct addrinfo **pai,
|
||||
- unsigned int *naddrs, struct scratch_buffer *tmpbuf)
|
||||
+get_servtuples (const struct gaih_service *service, const struct addrinfo *req,
|
||||
+ struct gaih_servtuple *st, struct scratch_buffer *tmpbuf)
|
||||
{
|
||||
+ int i;
|
||||
const struct gaih_typeproto *tp = gaih_inet_typeproto;
|
||||
- struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
|
||||
- struct gaih_addrtuple *at = NULL;
|
||||
- bool got_ipv6 = false;
|
||||
- char *canon = NULL;
|
||||
- const char *orig_name = name;
|
||||
-
|
||||
- /* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
- function. */
|
||||
- size_t alloca_used = sizeof (struct scratch_buffer);
|
||||
|
||||
if (req->ai_protocol || req->ai_socktype)
|
||||
{
|
||||
@@ -410,98 +399,88 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
}
|
||||
|
||||
- int port = 0;
|
||||
- if (service != NULL)
|
||||
+ if (service != NULL && (tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
|
||||
+ return -EAI_SERVICE;
|
||||
+
|
||||
+ if (service == NULL || service->num >= 0)
|
||||
{
|
||||
- if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
|
||||
- return -EAI_SERVICE;
|
||||
+ int port = service != NULL ? htons (service->num) : 0;
|
||||
|
||||
- if (service->num < 0)
|
||||
+ if (req->ai_socktype || req->ai_protocol)
|
||||
{
|
||||
- if (tp->name[0])
|
||||
- {
|
||||
- st = (struct gaih_servtuple *)
|
||||
- alloca_account (sizeof (struct gaih_servtuple), alloca_used);
|
||||
-
|
||||
- int rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf);
|
||||
- if (__glibc_unlikely (rc != 0))
|
||||
- return rc;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- struct gaih_servtuple **pst = &st;
|
||||
- for (tp++; tp->name[0]; tp++)
|
||||
- {
|
||||
- struct gaih_servtuple *newp;
|
||||
+ st[0].socktype = tp->socktype;
|
||||
+ st[0].protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
+ ? req->ai_protocol : tp->protocol);
|
||||
+ st[0].port = port;
|
||||
+ st[0].set = true;
|
||||
|
||||
- if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
|
||||
- continue;
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if (req->ai_socktype != 0
|
||||
- && req->ai_socktype != tp->socktype)
|
||||
- continue;
|
||||
- if (req->ai_protocol != 0
|
||||
- && !(tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
- && req->ai_protocol != tp->protocol)
|
||||
- continue;
|
||||
+ /* Neither socket type nor protocol is set. Return all socket types
|
||||
+ we know about. */
|
||||
+ for (i = 0, ++tp; tp->name[0]; ++tp)
|
||||
+ if (tp->defaultflag)
|
||||
+ {
|
||||
+ st[i].socktype = tp->socktype;
|
||||
+ st[i].protocol = tp->protocol;
|
||||
+ st[i].port = port;
|
||||
+ st[i++].set = true;
|
||||
+ }
|
||||
|
||||
- newp = (struct gaih_servtuple *)
|
||||
- alloca_account (sizeof (struct gaih_servtuple),
|
||||
- alloca_used);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if (gaih_inet_serv (service->name,
|
||||
- tp, req, newp, tmpbuf) != 0)
|
||||
- continue;
|
||||
+ if (tp->name[0])
|
||||
+ return gaih_inet_serv (service->name, tp, req, st, tmpbuf);
|
||||
|
||||
- *pst = newp;
|
||||
- pst = &(newp->next);
|
||||
- }
|
||||
- if (st == (struct gaih_servtuple *) &nullserv)
|
||||
- return -EAI_SERVICE;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- port = htons (service->num);
|
||||
- goto got_port;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
+ for (i = 0, tp++; tp->name[0]; tp++)
|
||||
{
|
||||
- got_port:
|
||||
+ if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
|
||||
+ continue;
|
||||
|
||||
- if (req->ai_socktype || req->ai_protocol)
|
||||
- {
|
||||
- st = alloca_account (sizeof (struct gaih_servtuple), alloca_used);
|
||||
- st->next = NULL;
|
||||
- st->socktype = tp->socktype;
|
||||
- st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
- ? req->ai_protocol : tp->protocol);
|
||||
- st->port = port;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Neither socket type nor protocol is set. Return all socket types
|
||||
- we know about. */
|
||||
- struct gaih_servtuple **lastp = &st;
|
||||
- for (++tp; tp->name[0]; ++tp)
|
||||
- if (tp->defaultflag)
|
||||
- {
|
||||
- struct gaih_servtuple *newp;
|
||||
+ if (req->ai_socktype != 0
|
||||
+ && req->ai_socktype != tp->socktype)
|
||||
+ continue;
|
||||
+ if (req->ai_protocol != 0
|
||||
+ && !(tp->protoflag & GAI_PROTO_PROTOANY)
|
||||
+ && req->ai_protocol != tp->protocol)
|
||||
+ continue;
|
||||
|
||||
- newp = alloca_account (sizeof (struct gaih_servtuple),
|
||||
- alloca_used);
|
||||
- newp->next = NULL;
|
||||
- newp->socktype = tp->socktype;
|
||||
- newp->protocol = tp->protocol;
|
||||
- newp->port = port;
|
||||
+ if (gaih_inet_serv (service->name,
|
||||
+ tp, req, &st[i], tmpbuf) != 0)
|
||||
+ continue;
|
||||
|
||||
- *lastp = newp;
|
||||
- lastp = &newp->next;
|
||||
- }
|
||||
- }
|
||||
+ i++;
|
||||
}
|
||||
|
||||
+ if (!st[0].set)
|
||||
+ return -EAI_SERVICE;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+gaih_inet (const char *name, const struct gaih_service *service,
|
||||
+ const struct addrinfo *req, struct addrinfo **pai,
|
||||
+ unsigned int *naddrs, struct scratch_buffer *tmpbuf)
|
||||
+{
|
||||
+ struct gaih_servtuple st[sizeof (gaih_inet_typeproto)
|
||||
+ / sizeof (struct gaih_typeproto)] = {0};
|
||||
+
|
||||
+ struct gaih_addrtuple *at = NULL;
|
||||
+ bool got_ipv6 = false;
|
||||
+ char *canon = NULL;
|
||||
+ const char *orig_name = name;
|
||||
+
|
||||
+ /* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
+ function. */
|
||||
+ size_t alloca_used = sizeof (struct scratch_buffer);
|
||||
+
|
||||
+ int rc;
|
||||
+ if ((rc = get_servtuples (service, req, st, tmpbuf)) != 0)
|
||||
+ return rc;
|
||||
+
|
||||
bool malloc_name = false;
|
||||
struct gaih_addrtuple *addrmem = NULL;
|
||||
int result = 0;
|
||||
@@ -1083,7 +1062,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if ((result = process_canonname (req, orig_name, &canon)) != 0)
|
||||
goto free_and_return;
|
||||
|
||||
- struct gaih_servtuple *st2;
|
||||
struct gaih_addrtuple *at2 = at;
|
||||
size_t socklen;
|
||||
sa_family_t family;
|
||||
@@ -1109,7 +1087,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
else
|
||||
socklen = sizeof (struct sockaddr_in);
|
||||
|
||||
- for (st2 = st; st2 != NULL; st2 = st2->next)
|
||||
+ for (int i = 0; st[i].set; i++)
|
||||
{
|
||||
struct addrinfo *ai;
|
||||
ai = *pai = malloc (sizeof (struct addrinfo) + socklen);
|
||||
@@ -1121,8 +1099,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
ai->ai_flags = req->ai_flags;
|
||||
ai->ai_family = family;
|
||||
- ai->ai_socktype = st2->socktype;
|
||||
- ai->ai_protocol = st2->protocol;
|
||||
+ ai->ai_socktype = st[i].socktype;
|
||||
+ ai->ai_protocol = st[i].protocol;
|
||||
ai->ai_addrlen = socklen;
|
||||
ai->ai_addr = (void *) (ai + 1);
|
||||
|
||||
@@ -1144,7 +1122,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct sockaddr_in6 *sin6p =
|
||||
(struct sockaddr_in6 *) ai->ai_addr;
|
||||
|
||||
- sin6p->sin6_port = st2->port;
|
||||
+ sin6p->sin6_port = st[i].port;
|
||||
sin6p->sin6_flowinfo = 0;
|
||||
memcpy (&sin6p->sin6_addr,
|
||||
at2->addr, sizeof (struct in6_addr));
|
||||
@@ -1154,7 +1132,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
struct sockaddr_in *sinp =
|
||||
(struct sockaddr_in *) ai->ai_addr;
|
||||
- sinp->sin_port = st2->port;
|
||||
+ sinp->sin_port = st[i].port;
|
||||
memcpy (&sinp->sin_addr,
|
||||
at2->addr, sizeof (struct in_addr));
|
||||
memset (sinp->sin_zero, '\0', sizeof (sinp->sin_zero));
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,179 @@
|
|||
commit 3b5a3e5009088a029525277f36228eeb95032358
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Fri Mar 4 14:57:12 2022 +0530
|
||||
|
||||
gaih_inet: Split simple gethostbyname into its own function
|
||||
|
||||
Add a free_at flag in gaih_result to indicate if res.at needs to be
|
||||
freed by the caller.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit b44389cb7fa28a59804571dac09cc32ebfac03d1)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 57b6834c8bb3887c..3870b2dc2edc89cd 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -120,6 +120,7 @@ struct gaih_result
|
||||
{
|
||||
struct gaih_addrtuple *at;
|
||||
char *canon;
|
||||
+ bool free_at;
|
||||
};
|
||||
|
||||
/* Values for `protoflag'. */
|
||||
@@ -565,6 +566,62 @@ out:
|
||||
return result;
|
||||
}
|
||||
|
||||
+/* If possible, call the simple, old functions, which do not support IPv6 scope
|
||||
+ ids, nor retrieving the canonical name. */
|
||||
+
|
||||
+static int
|
||||
+try_simple_gethostbyname (const char *name, const struct addrinfo *req,
|
||||
+ struct scratch_buffer *tmpbuf,
|
||||
+ struct gaih_result *res)
|
||||
+{
|
||||
+ res->at = NULL;
|
||||
+
|
||||
+ if (req->ai_family != AF_INET || (req->ai_flags & AI_CANONNAME) != 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ int rc;
|
||||
+ struct hostent th;
|
||||
+ struct hostent *h;
|
||||
+
|
||||
+ while (1)
|
||||
+ {
|
||||
+ rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf->data,
|
||||
+ tmpbuf->length, &h, &h_errno);
|
||||
+ if (rc != ERANGE || h_errno != NETDB_INTERNAL)
|
||||
+ break;
|
||||
+ if (!scratch_buffer_grow (tmpbuf))
|
||||
+ return -EAI_MEMORY;
|
||||
+ }
|
||||
+
|
||||
+ if (rc == 0)
|
||||
+ {
|
||||
+ if (h != NULL)
|
||||
+ {
|
||||
+ /* We found data, convert it. RES->AT from the conversion will
|
||||
+ either be an allocated block or NULL, both of which are safe to
|
||||
+ pass to free (). */
|
||||
+ if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, &res->at))
|
||||
+ return -EAI_MEMORY;
|
||||
+
|
||||
+ res->free_at = true;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (h_errno == NO_DATA)
|
||||
+ return -EAI_NODATA;
|
||||
+
|
||||
+ return -EAI_NONAME;
|
||||
+ }
|
||||
+
|
||||
+ if (h_errno == NETDB_INTERNAL)
|
||||
+ return -EAI_SYSTEM;
|
||||
+ if (h_errno == TRY_AGAIN)
|
||||
+ return -EAI_AGAIN;
|
||||
+
|
||||
+ /* We made requests but they turned out no data.
|
||||
+ The name is known, though. */
|
||||
+ return -EAI_NODATA;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
gaih_inet (const char *name, const struct gaih_service *service,
|
||||
const struct addrinfo *req, struct addrinfo **pai,
|
||||
@@ -610,6 +667,11 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
else if (res.at != NULL)
|
||||
goto process_list;
|
||||
|
||||
+ if ((result = try_simple_gethostbyname (name, req, tmpbuf, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
+
|
||||
int no_data = 0;
|
||||
int no_inet6_data = 0;
|
||||
nss_action_list nip;
|
||||
@@ -619,69 +681,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct resolv_context *res_ctx = NULL;
|
||||
bool do_merge = false;
|
||||
|
||||
- /* If we do not have to look for IPv6 addresses or the canonical
|
||||
- name, use the simple, old functions, which do not support
|
||||
- IPv6 scope ids, nor retrieving the canonical name. */
|
||||
- if (req->ai_family == AF_INET
|
||||
- && (req->ai_flags & AI_CANONNAME) == 0)
|
||||
- {
|
||||
- int rc;
|
||||
- struct hostent th;
|
||||
- struct hostent *h;
|
||||
-
|
||||
- while (1)
|
||||
- {
|
||||
- rc = __gethostbyname2_r (name, AF_INET, &th,
|
||||
- tmpbuf->data, tmpbuf->length,
|
||||
- &h, &h_errno);
|
||||
- if (rc != ERANGE || h_errno != NETDB_INTERNAL)
|
||||
- break;
|
||||
- if (!scratch_buffer_grow (tmpbuf))
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (rc == 0)
|
||||
- {
|
||||
- if (h != NULL)
|
||||
- {
|
||||
- /* We found data, convert it. */
|
||||
- if (!convert_hostent_to_gaih_addrtuple
|
||||
- (req, AF_INET, h, &addrmem))
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- res.at = addrmem;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- if (h_errno == NO_DATA)
|
||||
- result = -EAI_NODATA;
|
||||
- else
|
||||
- result = -EAI_NONAME;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- if (h_errno == NETDB_INTERNAL)
|
||||
- result = -EAI_SYSTEM;
|
||||
- else if (h_errno == TRY_AGAIN)
|
||||
- result = -EAI_AGAIN;
|
||||
- else
|
||||
- /* We made requests but they turned out no data.
|
||||
- The name is known, though. */
|
||||
- result = -EAI_NODATA;
|
||||
-
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
- goto process_list;
|
||||
- }
|
||||
-
|
||||
#ifdef USE_NSCD
|
||||
if (__nss_not_use_nscd_hosts > 0
|
||||
&& ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
|
||||
@@ -1165,6 +1164,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (malloc_name)
|
||||
free ((char *) name);
|
||||
free (addrmem);
|
||||
+ if (res.free_at)
|
||||
+ free (res.at);
|
||||
free (res.canon);
|
||||
|
||||
return result;
|
|
@ -0,0 +1,328 @@
|
|||
commit 5914a1d55b468ccf0fb6d997a7a4e378339df735
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 15:53:45 2022 +0530
|
||||
|
||||
gaih_inet: Split nscd lookup code into its own function.
|
||||
|
||||
Add a new member got_ipv6 to indicate if the results have an IPv6
|
||||
result and use it instead of the local got_ipv6.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit e7e5315b7fa065a9c8bf525ca9a32f46fa4837e5)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 3870b2dc2edc89cd..7c497a88f8b5b9f8 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -121,6 +121,7 @@ struct gaih_result
|
||||
struct gaih_addrtuple *at;
|
||||
char *canon;
|
||||
bool free_at;
|
||||
+ bool got_ipv6;
|
||||
};
|
||||
|
||||
/* Values for `protoflag'. */
|
||||
@@ -316,7 +317,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
res.canon = canonbuf; \
|
||||
} \
|
||||
if (_family == AF_INET6 && *pat != NULL) \
|
||||
- got_ipv6 = true; \
|
||||
+ res.got_ipv6 = true; \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -467,6 +468,128 @@ get_servtuples (const struct gaih_service *service, const struct addrinfo *req,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef USE_NSCD
|
||||
+/* Query addresses from nscd cache, returning a non-zero value on error.
|
||||
+ RES members have the lookup result; RES->AT is NULL if there were no errors
|
||||
+ but also no results. */
|
||||
+
|
||||
+static int
|
||||
+get_nscd_addresses (const char *name, const struct addrinfo *req,
|
||||
+ struct gaih_result *res)
|
||||
+{
|
||||
+ if (__nss_not_use_nscd_hosts > 0
|
||||
+ && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
|
||||
+ __nss_not_use_nscd_hosts = 0;
|
||||
+
|
||||
+ res->at = NULL;
|
||||
+
|
||||
+ if (__nss_not_use_nscd_hosts || __nss_database_custom[NSS_DBSIDX_hosts])
|
||||
+ return 0;
|
||||
+
|
||||
+ /* Try to use nscd. */
|
||||
+ struct nscd_ai_result *air = NULL;
|
||||
+ int err = __nscd_getai (name, &air, &h_errno);
|
||||
+
|
||||
+ if (__glibc_unlikely (air == NULL))
|
||||
+ {
|
||||
+ /* The database contains a negative entry. */
|
||||
+ if (err == 0)
|
||||
+ return -EAI_NONAME;
|
||||
+ if (__nss_not_use_nscd_hosts == 0)
|
||||
+ {
|
||||
+ if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
|
||||
+ return -EAI_MEMORY;
|
||||
+ if (h_errno == TRY_AGAIN)
|
||||
+ return -EAI_AGAIN;
|
||||
+ return -EAI_SYSTEM;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Transform into gaih_addrtuple list. */
|
||||
+ int result = 0;
|
||||
+ char *addrs = air->addrs;
|
||||
+
|
||||
+ struct gaih_addrtuple *addrfree = calloc (air->naddrs, sizeof (*addrfree));
|
||||
+ struct gaih_addrtuple *at = calloc (air->naddrs, sizeof (*at));
|
||||
+ if (at == NULL)
|
||||
+ {
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ res->free_at = true;
|
||||
+
|
||||
+ int count = 0;
|
||||
+ for (int i = 0; i < air->naddrs; ++i)
|
||||
+ {
|
||||
+ socklen_t size = (air->family[i] == AF_INET
|
||||
+ ? INADDRSZ : IN6ADDRSZ);
|
||||
+
|
||||
+ if (!((air->family[i] == AF_INET
|
||||
+ && req->ai_family == AF_INET6
|
||||
+ && (req->ai_flags & AI_V4MAPPED) != 0)
|
||||
+ || req->ai_family == AF_UNSPEC
|
||||
+ || air->family[i] == req->ai_family))
|
||||
+ {
|
||||
+ /* Skip over non-matching result. */
|
||||
+ addrs += size;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (air->family[i] == AF_INET && req->ai_family == AF_INET6
|
||||
+ && (req->ai_flags & AI_V4MAPPED))
|
||||
+ {
|
||||
+ at[count].family = AF_INET6;
|
||||
+ at[count].addr[3] = *(uint32_t *) addrs;
|
||||
+ at[count].addr[2] = htonl (0xffff);
|
||||
+ }
|
||||
+ else if (req->ai_family == AF_UNSPEC
|
||||
+ || air->family[count] == req->ai_family)
|
||||
+ {
|
||||
+ at[count].family = air->family[count];
|
||||
+ memcpy (at[count].addr, addrs, size);
|
||||
+ if (air->family[count] == AF_INET6)
|
||||
+ res->got_ipv6 = true;
|
||||
+ }
|
||||
+ at[count].next = at + count + 1;
|
||||
+ count++;
|
||||
+ addrs += size;
|
||||
+ }
|
||||
+
|
||||
+ if ((req->ai_flags & AI_CANONNAME) && air->canon != NULL)
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (air->canon);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ res->canon = canonbuf;
|
||||
+ }
|
||||
+
|
||||
+ if (count == 0)
|
||||
+ {
|
||||
+ result = -EAI_NONAME;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ at[count - 1].next = NULL;
|
||||
+
|
||||
+ res->at = at;
|
||||
+
|
||||
+out:
|
||||
+ free (air);
|
||||
+ if (result != 0)
|
||||
+ {
|
||||
+ free (at);
|
||||
+ res->free_at = false;
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/* Convert numeric addresses to binary into RES. On failure, RES->AT is set to
|
||||
NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and
|
||||
the function cannot determine a result, RES->AT is set to NULL and 0
|
||||
@@ -630,7 +753,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct gaih_servtuple st[sizeof (gaih_inet_typeproto)
|
||||
/ sizeof (struct gaih_typeproto)] = {0};
|
||||
|
||||
- bool got_ipv6 = false;
|
||||
const char *orig_name = name;
|
||||
|
||||
/* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
@@ -672,6 +794,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
else if (res.at != NULL)
|
||||
goto process_list;
|
||||
|
||||
+#ifdef USE_NSCD
|
||||
+ if ((result = get_nscd_addresses (name, req, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
+#endif
|
||||
+
|
||||
int no_data = 0;
|
||||
int no_inet6_data = 0;
|
||||
nss_action_list nip;
|
||||
@@ -681,115 +810,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct resolv_context *res_ctx = NULL;
|
||||
bool do_merge = false;
|
||||
|
||||
-#ifdef USE_NSCD
|
||||
- if (__nss_not_use_nscd_hosts > 0
|
||||
- && ++__nss_not_use_nscd_hosts > NSS_NSCD_RETRY)
|
||||
- __nss_not_use_nscd_hosts = 0;
|
||||
-
|
||||
- if (!__nss_not_use_nscd_hosts
|
||||
- && !__nss_database_custom[NSS_DBSIDX_hosts])
|
||||
- {
|
||||
- /* Try to use nscd. */
|
||||
- struct nscd_ai_result *air = NULL;
|
||||
- int err = __nscd_getai (name, &air, &h_errno);
|
||||
- if (air != NULL)
|
||||
- {
|
||||
- /* Transform into gaih_addrtuple list. */
|
||||
- bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
|
||||
- char *addrs = air->addrs;
|
||||
-
|
||||
- addrmem = calloc (air->naddrs, sizeof (*addrmem));
|
||||
- if (addrmem == NULL)
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
- struct gaih_addrtuple *addrfree = addrmem;
|
||||
- struct gaih_addrtuple **pat = &res.at;
|
||||
-
|
||||
- for (int i = 0; i < air->naddrs; ++i)
|
||||
- {
|
||||
- socklen_t size = (air->family[i] == AF_INET
|
||||
- ? INADDRSZ : IN6ADDRSZ);
|
||||
-
|
||||
- if (!((air->family[i] == AF_INET
|
||||
- && req->ai_family == AF_INET6
|
||||
- && (req->ai_flags & AI_V4MAPPED) != 0)
|
||||
- || req->ai_family == AF_UNSPEC
|
||||
- || air->family[i] == req->ai_family))
|
||||
- {
|
||||
- /* Skip over non-matching result. */
|
||||
- addrs += size;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (*pat == NULL)
|
||||
- {
|
||||
- *pat = addrfree++;
|
||||
- (*pat)->scopeid = 0;
|
||||
- }
|
||||
- uint32_t *pataddr = (*pat)->addr;
|
||||
- (*pat)->next = NULL;
|
||||
- if (added_canon || air->canon == NULL)
|
||||
- (*pat)->name = NULL;
|
||||
- else if (res.canon == NULL)
|
||||
- {
|
||||
- char *canonbuf = __strdup (air->canon);
|
||||
- if (canonbuf == NULL)
|
||||
- {
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- res.canon = (*pat)->name = canonbuf;
|
||||
- }
|
||||
-
|
||||
- if (air->family[i] == AF_INET
|
||||
- && req->ai_family == AF_INET6
|
||||
- && (req->ai_flags & AI_V4MAPPED))
|
||||
- {
|
||||
- (*pat)->family = AF_INET6;
|
||||
- pataddr[3] = *(uint32_t *) addrs;
|
||||
- pataddr[2] = htonl (0xffff);
|
||||
- pataddr[1] = 0;
|
||||
- pataddr[0] = 0;
|
||||
- pat = &((*pat)->next);
|
||||
- added_canon = true;
|
||||
- }
|
||||
- else if (req->ai_family == AF_UNSPEC
|
||||
- || air->family[i] == req->ai_family)
|
||||
- {
|
||||
- (*pat)->family = air->family[i];
|
||||
- memcpy (pataddr, addrs, size);
|
||||
- pat = &((*pat)->next);
|
||||
- added_canon = true;
|
||||
- if (air->family[i] == AF_INET6)
|
||||
- got_ipv6 = true;
|
||||
- }
|
||||
- addrs += size;
|
||||
- }
|
||||
-
|
||||
- free (air);
|
||||
-
|
||||
- goto process_list;
|
||||
- }
|
||||
- else if (err == 0)
|
||||
- /* The database contains a negative entry. */
|
||||
- goto free_and_return;
|
||||
- else if (__nss_not_use_nscd_hosts == 0)
|
||||
- {
|
||||
- if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
|
||||
- result = -EAI_MEMORY;
|
||||
- else if (h_errno == TRY_AGAIN)
|
||||
- result = -EAI_AGAIN;
|
||||
- else
|
||||
- result = -EAI_SYSTEM;
|
||||
-
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
no_more = !__nss_database_get (nss_database_hosts, &nip);
|
||||
|
||||
/* If we are looking for both IPv4 and IPv6 address we don't
|
||||
@@ -897,7 +917,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
no_data = 0;
|
||||
if (req->ai_family == AF_INET6)
|
||||
- got_ipv6 = true;
|
||||
+ res.got_ipv6 = true;
|
||||
}
|
||||
else
|
||||
*pat = ((*pat)->next);
|
||||
@@ -940,7 +960,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
&& (req->ai_flags & AI_V4MAPPED)
|
||||
/* Avoid generating the mapped addresses if we
|
||||
know we are not going to need them. */
|
||||
- && ((req->ai_flags & AI_ALL) || !got_ipv6)))
|
||||
+ && ((req->ai_flags & AI_ALL) || !res.got_ipv6)))
|
||||
{
|
||||
gethosts (AF_INET);
|
||||
|
||||
@@ -1091,7 +1111,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
/* If we looked up IPv4 mapped address discard them here if
|
||||
the caller isn't interested in all address and we have
|
||||
found at least one IPv6 address. */
|
||||
- if (got_ipv6
|
||||
+ if (res.got_ipv6
|
||||
&& (req->ai_flags & (AI_V4MAPPED|AI_ALL)) == AI_V4MAPPED
|
||||
&& IN6_IS_ADDR_V4MAPPED (at2->addr))
|
||||
goto ignore;
|
|
@ -0,0 +1,673 @@
|
|||
commit ec71cb961121760f81e55af5489e658dc89e96e6
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 15:56:22 2022 +0530
|
||||
|
||||
gaih_inet: separate nss lookup loop into its own function
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit 906cecbe0889e601c91d9aba738049c73ebe4dd2)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 7c497a88f8b5b9f8..145ea6fa381ad14b 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -159,6 +159,14 @@ static const struct addrinfo default_hints =
|
||||
.ai_next = NULL
|
||||
};
|
||||
|
||||
+static void
|
||||
+gaih_result_reset (struct gaih_result *res)
|
||||
+{
|
||||
+ if (res->free_at)
|
||||
+ free (res->at);
|
||||
+ free (res->canon);
|
||||
+ memset (res, 0, sizeof (*res));
|
||||
+}
|
||||
|
||||
static int
|
||||
gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
@@ -197,13 +205,10 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||||
|
||||
/* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name
|
||||
is not copied, and the struct hostent object must not be deallocated
|
||||
- prematurely. The new addresses are appended to the tuple array in
|
||||
- RESULT. */
|
||||
+ prematurely. The new addresses are appended to the tuple array in RES. */
|
||||
static bool
|
||||
-convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
- int family,
|
||||
- struct hostent *h,
|
||||
- struct gaih_addrtuple **result)
|
||||
+convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
|
||||
+ struct hostent *h, struct gaih_result *res)
|
||||
{
|
||||
/* Count the number of addresses in h->h_addr_list. */
|
||||
size_t count = 0;
|
||||
@@ -215,7 +220,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
|
||||
return true;
|
||||
|
||||
- struct gaih_addrtuple *array = *result;
|
||||
+ struct gaih_addrtuple *array = res->at;
|
||||
size_t old = 0;
|
||||
|
||||
while (array != NULL)
|
||||
@@ -224,12 +229,14 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
array = array->next;
|
||||
}
|
||||
|
||||
- array = realloc (*result, (old + count) * sizeof (*array));
|
||||
+ array = realloc (res->at, (old + count) * sizeof (*array));
|
||||
|
||||
if (array == NULL)
|
||||
return false;
|
||||
|
||||
- *result = array;
|
||||
+ res->got_ipv6 = family == AF_INET6;
|
||||
+ res->at = array;
|
||||
+ res->free_at = true;
|
||||
|
||||
/* Update the next pointers on reallocation. */
|
||||
for (size_t i = 0; i < old; i++)
|
||||
@@ -278,7 +285,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
{ \
|
||||
__resolv_context_put (res_ctx); \
|
||||
result = -EAI_MEMORY; \
|
||||
- goto free_and_return; \
|
||||
+ goto out; \
|
||||
} \
|
||||
} \
|
||||
if (status == NSS_STATUS_NOTFOUND \
|
||||
@@ -288,7 +295,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
{ \
|
||||
__resolv_context_put (res_ctx); \
|
||||
result = -EAI_SYSTEM; \
|
||||
- goto free_and_return; \
|
||||
+ goto out; \
|
||||
} \
|
||||
if (h_errno == TRY_AGAIN) \
|
||||
no_data = EAI_AGAIN; \
|
||||
@@ -297,27 +304,24 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
} \
|
||||
else if (status == NSS_STATUS_SUCCESS) \
|
||||
{ \
|
||||
- if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
|
||||
+ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, res)) \
|
||||
{ \
|
||||
__resolv_context_put (res_ctx); \
|
||||
result = -EAI_SYSTEM; \
|
||||
- goto free_and_return; \
|
||||
+ goto out; \
|
||||
} \
|
||||
- *pat = addrmem; \
|
||||
\
|
||||
- if (localcanon != NULL && res.canon == NULL) \
|
||||
+ if (localcanon != NULL && res->canon == NULL) \
|
||||
{ \
|
||||
char *canonbuf = __strdup (localcanon); \
|
||||
if (canonbuf == NULL) \
|
||||
{ \
|
||||
__resolv_context_put (res_ctx); \
|
||||
result = -EAI_SYSTEM; \
|
||||
- goto free_and_return; \
|
||||
+ goto out; \
|
||||
} \
|
||||
- res.canon = canonbuf; \
|
||||
+ res->canon = canonbuf; \
|
||||
} \
|
||||
- if (_family == AF_INET6 && *pat != NULL) \
|
||||
- res.got_ipv6 = true; \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -590,6 +594,260 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
+static int
|
||||
+get_nss_addresses (const char *name, const struct addrinfo *req,
|
||||
+ struct scratch_buffer *tmpbuf, struct gaih_result *res)
|
||||
+{
|
||||
+ int no_data = 0;
|
||||
+ int no_inet6_data = 0;
|
||||
+ nss_action_list nip;
|
||||
+ enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
|
||||
+ enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
+ int no_more;
|
||||
+ struct resolv_context *res_ctx = NULL;
|
||||
+ bool do_merge = false;
|
||||
+ int result = 0;
|
||||
+
|
||||
+ no_more = !__nss_database_get (nss_database_hosts, &nip);
|
||||
+
|
||||
+ /* If we are looking for both IPv4 and IPv6 address we don't
|
||||
+ want the lookup functions to automatically promote IPv4
|
||||
+ addresses to IPv6 addresses, so we use the no_inet6
|
||||
+ function variant. */
|
||||
+ res_ctx = __resolv_context_get ();
|
||||
+ if (res_ctx == NULL)
|
||||
+ no_more = 1;
|
||||
+
|
||||
+ while (!no_more)
|
||||
+ {
|
||||
+ /* Always start afresh; continue should discard previous results
|
||||
+ and the hosts database does not support merge. */
|
||||
+ gaih_result_reset (res);
|
||||
+
|
||||
+ if (do_merge)
|
||||
+ {
|
||||
+ __set_h_errno (NETDB_INTERNAL);
|
||||
+ __set_errno (EBUSY);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ no_data = 0;
|
||||
+ nss_gethostbyname4_r *fct4 = NULL;
|
||||
+
|
||||
+ /* gethostbyname4_r sends out parallel A and AAAA queries and
|
||||
+ is thus only suitable for PF_UNSPEC. */
|
||||
+ if (req->ai_family == PF_UNSPEC)
|
||||
+ fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
|
||||
+
|
||||
+ if (fct4 != NULL)
|
||||
+ {
|
||||
+ while (1)
|
||||
+ {
|
||||
+ status = DL_CALL_FCT (fct4, (name, &res->at,
|
||||
+ tmpbuf->data, tmpbuf->length,
|
||||
+ &errno, &h_errno,
|
||||
+ NULL));
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ break;
|
||||
+ /* gethostbyname4_r may write into AT, so reset it. */
|
||||
+ res->at = NULL;
|
||||
+ if (status != NSS_STATUS_TRYAGAIN
|
||||
+ || errno != ERANGE || h_errno != NETDB_INTERNAL)
|
||||
+ {
|
||||
+ if (h_errno == TRY_AGAIN)
|
||||
+ no_data = EAI_AGAIN;
|
||||
+ else
|
||||
+ no_data = h_errno == NO_DATA;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!scratch_buffer_grow (tmpbuf))
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ assert (!no_data);
|
||||
+ no_data = 1;
|
||||
+
|
||||
+ if ((req->ai_flags & AI_CANONNAME) != 0 && res->canon == NULL)
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (res->at->name);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ res->canon = canonbuf;
|
||||
+ }
|
||||
+
|
||||
+ struct gaih_addrtuple **pat = &res->at;
|
||||
+
|
||||
+ while (*pat != NULL)
|
||||
+ {
|
||||
+ if ((*pat)->family == AF_INET
|
||||
+ && req->ai_family == AF_INET6
|
||||
+ && (req->ai_flags & AI_V4MAPPED) != 0)
|
||||
+ {
|
||||
+ uint32_t *pataddr = (*pat)->addr;
|
||||
+ (*pat)->family = AF_INET6;
|
||||
+ pataddr[3] = pataddr[0];
|
||||
+ pataddr[2] = htonl (0xffff);
|
||||
+ pataddr[1] = 0;
|
||||
+ pataddr[0] = 0;
|
||||
+ pat = &((*pat)->next);
|
||||
+ no_data = 0;
|
||||
+ }
|
||||
+ else if (req->ai_family == AF_UNSPEC
|
||||
+ || (*pat)->family == req->ai_family)
|
||||
+ {
|
||||
+ pat = &((*pat)->next);
|
||||
+
|
||||
+ no_data = 0;
|
||||
+ if (req->ai_family == AF_INET6)
|
||||
+ res->got_ipv6 = true;
|
||||
+ }
|
||||
+ else
|
||||
+ *pat = ((*pat)->next);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ no_inet6_data = no_data;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ nss_gethostbyname3_r *fct = NULL;
|
||||
+ if (req->ai_flags & AI_CANONNAME)
|
||||
+ /* No need to use this function if we do not look for
|
||||
+ the canonical name. The function does not exist in
|
||||
+ all NSS modules and therefore the lookup would
|
||||
+ often fail. */
|
||||
+ fct = __nss_lookup_function (nip, "gethostbyname3_r");
|
||||
+ if (fct == NULL)
|
||||
+ /* We are cheating here. The gethostbyname2_r
|
||||
+ function does not have the same interface as
|
||||
+ gethostbyname3_r but the extra arguments the
|
||||
+ latter takes are added at the end. So the
|
||||
+ gethostbyname2_r code will just ignore them. */
|
||||
+ fct = __nss_lookup_function (nip, "gethostbyname2_r");
|
||||
+
|
||||
+ if (fct != NULL)
|
||||
+ {
|
||||
+ if (req->ai_family == AF_INET6
|
||||
+ || req->ai_family == AF_UNSPEC)
|
||||
+ {
|
||||
+ gethosts (AF_INET6);
|
||||
+ no_inet6_data = no_data;
|
||||
+ inet6_status = status;
|
||||
+ }
|
||||
+ if (req->ai_family == AF_INET
|
||||
+ || req->ai_family == AF_UNSPEC
|
||||
+ || (req->ai_family == AF_INET6
|
||||
+ && (req->ai_flags & AI_V4MAPPED)
|
||||
+ /* Avoid generating the mapped addresses if we
|
||||
+ know we are not going to need them. */
|
||||
+ && ((req->ai_flags & AI_ALL) || !res->got_ipv6)))
|
||||
+ {
|
||||
+ gethosts (AF_INET);
|
||||
+
|
||||
+ if (req->ai_family == AF_INET)
|
||||
+ {
|
||||
+ no_inet6_data = no_data;
|
||||
+ inet6_status = status;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* If we found one address for AF_INET or AF_INET6,
|
||||
+ don't continue the search. */
|
||||
+ if (inet6_status == NSS_STATUS_SUCCESS
|
||||
+ || status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if ((req->ai_flags & AI_CANONNAME) != 0
|
||||
+ && res->canon == NULL)
|
||||
+ {
|
||||
+ char *canonbuf = getcanonname (nip, res->at, name);
|
||||
+ if (canonbuf == NULL)
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ result = -EAI_MEMORY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ res->canon = canonbuf;
|
||||
+ }
|
||||
+ status = NSS_STATUS_SUCCESS;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* We can have different states for AF_INET and
|
||||
+ AF_INET6. Try to find a useful one for both. */
|
||||
+ if (inet6_status == NSS_STATUS_TRYAGAIN)
|
||||
+ status = NSS_STATUS_TRYAGAIN;
|
||||
+ else if (status == NSS_STATUS_UNAVAIL
|
||||
+ && inet6_status != NSS_STATUS_UNAVAIL)
|
||||
+ status = inet6_status;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Could not locate any of the lookup functions.
|
||||
+ The NSS lookup code does not consistently set
|
||||
+ errno, so we need to supply our own error
|
||||
+ code here. The root cause could either be a
|
||||
+ resource allocation failure, or a missing
|
||||
+ service function in the DSO (so it should not
|
||||
+ be listed in /etc/nsswitch.conf). Assume the
|
||||
+ former, and return EBUSY. */
|
||||
+ status = NSS_STATUS_UNAVAIL;
|
||||
+ __set_h_errno (NETDB_INTERNAL);
|
||||
+ __set_errno (EBUSY);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
|
||||
+ break;
|
||||
+
|
||||
+ /* The hosts database does not support MERGE. */
|
||||
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
|
||||
+ do_merge = true;
|
||||
+
|
||||
+ nip++;
|
||||
+ if (nip->module == NULL)
|
||||
+ no_more = -1;
|
||||
+ }
|
||||
+
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+
|
||||
+ /* If we have a failure which sets errno, report it using
|
||||
+ EAI_SYSTEM. */
|
||||
+ if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
|
||||
+ && h_errno == NETDB_INTERNAL)
|
||||
+ {
|
||||
+ result = -EAI_SYSTEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (no_data != 0 && no_inet6_data != 0)
|
||||
+ {
|
||||
+ /* If both requests timed out report this. */
|
||||
+ if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
|
||||
+ result = -EAI_AGAIN;
|
||||
+ else
|
||||
+ /* We made requests but they turned out no data. The name
|
||||
+ is known, though. */
|
||||
+ result = -EAI_NODATA;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ if (result != 0)
|
||||
+ gaih_result_reset (res);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
/* Convert numeric addresses to binary into RES. On failure, RES->AT is set to
|
||||
NULL and an error code is returned. If AI_NUMERIC_HOST is not requested and
|
||||
the function cannot determine a result, RES->AT is set to NULL and 0
|
||||
@@ -723,7 +981,7 @@ try_simple_gethostbyname (const char *name, const struct addrinfo *req,
|
||||
/* We found data, convert it. RES->AT from the conversion will
|
||||
either be an allocated block or NULL, both of which are safe to
|
||||
pass to free (). */
|
||||
- if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, &res->at))
|
||||
+ if (!convert_hostent_to_gaih_addrtuple (req, AF_INET, h, res))
|
||||
return -EAI_MEMORY;
|
||||
|
||||
res->free_at = true;
|
||||
@@ -801,264 +1059,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
goto process_list;
|
||||
#endif
|
||||
|
||||
- int no_data = 0;
|
||||
- int no_inet6_data = 0;
|
||||
- nss_action_list nip;
|
||||
- enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
|
||||
- enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
- int no_more;
|
||||
- struct resolv_context *res_ctx = NULL;
|
||||
- bool do_merge = false;
|
||||
-
|
||||
- no_more = !__nss_database_get (nss_database_hosts, &nip);
|
||||
-
|
||||
- /* If we are looking for both IPv4 and IPv6 address we don't
|
||||
- want the lookup functions to automatically promote IPv4
|
||||
- addresses to IPv6 addresses, so we use the no_inet6
|
||||
- function variant. */
|
||||
- res_ctx = __resolv_context_get ();
|
||||
- if (res_ctx == NULL)
|
||||
- no_more = 1;
|
||||
-
|
||||
- while (!no_more)
|
||||
- {
|
||||
- /* Always start afresh; continue should discard previous results
|
||||
- and the hosts database does not support merge. */
|
||||
- res.at = NULL;
|
||||
- free (res.canon);
|
||||
- free (addrmem);
|
||||
- res.canon = NULL;
|
||||
- addrmem = NULL;
|
||||
- got_ipv6 = false;
|
||||
-
|
||||
- if (do_merge)
|
||||
- {
|
||||
- __set_h_errno (NETDB_INTERNAL);
|
||||
- __set_errno (EBUSY);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- no_data = 0;
|
||||
- nss_gethostbyname4_r *fct4 = NULL;
|
||||
-
|
||||
- /* gethostbyname4_r sends out parallel A and AAAA queries and
|
||||
- is thus only suitable for PF_UNSPEC. */
|
||||
- if (req->ai_family == PF_UNSPEC)
|
||||
- fct4 = __nss_lookup_function (nip, "gethostbyname4_r");
|
||||
-
|
||||
- if (fct4 != NULL)
|
||||
- {
|
||||
- while (1)
|
||||
- {
|
||||
- status = DL_CALL_FCT (fct4, (name, &res.at,
|
||||
- tmpbuf->data, tmpbuf->length,
|
||||
- &errno, &h_errno,
|
||||
- NULL));
|
||||
- if (status == NSS_STATUS_SUCCESS)
|
||||
- break;
|
||||
- /* gethostbyname4_r may write into AT, so reset it. */
|
||||
- res.at = NULL;
|
||||
- if (status != NSS_STATUS_TRYAGAIN
|
||||
- || errno != ERANGE || h_errno != NETDB_INTERNAL)
|
||||
- {
|
||||
- if (h_errno == TRY_AGAIN)
|
||||
- no_data = EAI_AGAIN;
|
||||
- else
|
||||
- no_data = h_errno == NO_DATA;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (!scratch_buffer_grow (tmpbuf))
|
||||
- {
|
||||
- __resolv_context_put (res_ctx);
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (status == NSS_STATUS_SUCCESS)
|
||||
- {
|
||||
- assert (!no_data);
|
||||
- no_data = 1;
|
||||
-
|
||||
- if ((req->ai_flags & AI_CANONNAME) != 0 && res.canon == NULL)
|
||||
- {
|
||||
- char *canonbuf = __strdup (res.at->name);
|
||||
- if (canonbuf == NULL)
|
||||
- {
|
||||
- __resolv_context_put (res_ctx);
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- res.canon = canonbuf;
|
||||
- }
|
||||
-
|
||||
- struct gaih_addrtuple **pat = &res.at;
|
||||
-
|
||||
- while (*pat != NULL)
|
||||
- {
|
||||
- if ((*pat)->family == AF_INET
|
||||
- && req->ai_family == AF_INET6
|
||||
- && (req->ai_flags & AI_V4MAPPED) != 0)
|
||||
- {
|
||||
- uint32_t *pataddr = (*pat)->addr;
|
||||
- (*pat)->family = AF_INET6;
|
||||
- pataddr[3] = pataddr[0];
|
||||
- pataddr[2] = htonl (0xffff);
|
||||
- pataddr[1] = 0;
|
||||
- pataddr[0] = 0;
|
||||
- pat = &((*pat)->next);
|
||||
- no_data = 0;
|
||||
- }
|
||||
- else if (req->ai_family == AF_UNSPEC
|
||||
- || (*pat)->family == req->ai_family)
|
||||
- {
|
||||
- pat = &((*pat)->next);
|
||||
-
|
||||
- no_data = 0;
|
||||
- if (req->ai_family == AF_INET6)
|
||||
- res.got_ipv6 = true;
|
||||
- }
|
||||
- else
|
||||
- *pat = ((*pat)->next);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- no_inet6_data = no_data;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- nss_gethostbyname3_r *fct = NULL;
|
||||
- if (req->ai_flags & AI_CANONNAME)
|
||||
- /* No need to use this function if we do not look for
|
||||
- the canonical name. The function does not exist in
|
||||
- all NSS modules and therefore the lookup would
|
||||
- often fail. */
|
||||
- fct = __nss_lookup_function (nip, "gethostbyname3_r");
|
||||
- if (fct == NULL)
|
||||
- /* We are cheating here. The gethostbyname2_r
|
||||
- function does not have the same interface as
|
||||
- gethostbyname3_r but the extra arguments the
|
||||
- latter takes are added at the end. So the
|
||||
- gethostbyname2_r code will just ignore them. */
|
||||
- fct = __nss_lookup_function (nip, "gethostbyname2_r");
|
||||
-
|
||||
- if (fct != NULL)
|
||||
- {
|
||||
- struct gaih_addrtuple **pat = &res.at;
|
||||
-
|
||||
- if (req->ai_family == AF_INET6
|
||||
- || req->ai_family == AF_UNSPEC)
|
||||
- {
|
||||
- gethosts (AF_INET6);
|
||||
- no_inet6_data = no_data;
|
||||
- inet6_status = status;
|
||||
- }
|
||||
- if (req->ai_family == AF_INET
|
||||
- || req->ai_family == AF_UNSPEC
|
||||
- || (req->ai_family == AF_INET6
|
||||
- && (req->ai_flags & AI_V4MAPPED)
|
||||
- /* Avoid generating the mapped addresses if we
|
||||
- know we are not going to need them. */
|
||||
- && ((req->ai_flags & AI_ALL) || !res.got_ipv6)))
|
||||
- {
|
||||
- gethosts (AF_INET);
|
||||
-
|
||||
- if (req->ai_family == AF_INET)
|
||||
- {
|
||||
- no_inet6_data = no_data;
|
||||
- inet6_status = status;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* If we found one address for AF_INET or AF_INET6,
|
||||
- don't continue the search. */
|
||||
- if (inet6_status == NSS_STATUS_SUCCESS
|
||||
- || status == NSS_STATUS_SUCCESS)
|
||||
- {
|
||||
- if ((req->ai_flags & AI_CANONNAME) != 0
|
||||
- && res.canon == NULL)
|
||||
- {
|
||||
- char *canonbuf = getcanonname (nip, res.at, name);
|
||||
- if (canonbuf == NULL)
|
||||
- {
|
||||
- __resolv_context_put (res_ctx);
|
||||
- result = -EAI_MEMORY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
- res.canon = canonbuf;
|
||||
- }
|
||||
- status = NSS_STATUS_SUCCESS;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* We can have different states for AF_INET and
|
||||
- AF_INET6. Try to find a useful one for both. */
|
||||
- if (inet6_status == NSS_STATUS_TRYAGAIN)
|
||||
- status = NSS_STATUS_TRYAGAIN;
|
||||
- else if (status == NSS_STATUS_UNAVAIL
|
||||
- && inet6_status != NSS_STATUS_UNAVAIL)
|
||||
- status = inet6_status;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Could not locate any of the lookup functions.
|
||||
- The NSS lookup code does not consistently set
|
||||
- errno, so we need to supply our own error
|
||||
- code here. The root cause could either be a
|
||||
- resource allocation failure, or a missing
|
||||
- service function in the DSO (so it should not
|
||||
- be listed in /etc/nsswitch.conf). Assume the
|
||||
- former, and return EBUSY. */
|
||||
- status = NSS_STATUS_UNAVAIL;
|
||||
- __set_h_errno (NETDB_INTERNAL);
|
||||
- __set_errno (EBUSY);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
|
||||
- break;
|
||||
-
|
||||
- /* The hosts database does not support MERGE. */
|
||||
- if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
|
||||
- do_merge = true;
|
||||
-
|
||||
- nip++;
|
||||
- if (nip->module == NULL)
|
||||
- no_more = -1;
|
||||
- }
|
||||
-
|
||||
- __resolv_context_put (res_ctx);
|
||||
-
|
||||
- /* If we have a failure which sets errno, report it using
|
||||
- EAI_SYSTEM. */
|
||||
- if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
|
||||
- && h_errno == NETDB_INTERNAL)
|
||||
- {
|
||||
- result = -EAI_SYSTEM;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
- if (no_data != 0 && no_inet6_data != 0)
|
||||
- {
|
||||
- /* If both requests timed out report this. */
|
||||
- if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN)
|
||||
- result = -EAI_AGAIN;
|
||||
- else
|
||||
- /* We made requests but they turned out no data. The name
|
||||
- is known, though. */
|
||||
- result = -EAI_NODATA;
|
||||
-
|
||||
- goto free_and_return;
|
||||
- }
|
||||
+ if ((result = get_nss_addresses (name, req, tmpbuf, &res)) != 0)
|
||||
+ goto free_and_return;
|
||||
+ else if (res.at != NULL)
|
||||
+ goto process_list;
|
||||
|
||||
- process_list:
|
||||
- if (res.at == NULL)
|
||||
- {
|
||||
- result = -EAI_NONAME;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
+ /* None of the lookups worked, so name not found. */
|
||||
+ result = -EAI_NONAME;
|
||||
+ goto free_and_return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1089,6 +1097,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
}
|
||||
|
||||
+process_list:
|
||||
{
|
||||
/* Set up the canonical name if we need it. */
|
||||
if ((result = process_canonname (req, orig_name, &res)) != 0)
|
|
@ -0,0 +1,156 @@
|
|||
commit 4d59769087f2143f619b4b38bf93590a86f5c806
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Mon Mar 7 19:48:48 2022 +0530
|
||||
|
||||
gaih_inet: make gethosts into a function
|
||||
|
||||
The macro is quite a pain to debug, so make gethosts into a function to
|
||||
make it easier to maintain.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit cfa3bd48cb19a70e4367a9978dbba09d9df27a72)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 145ea6fa381ad14b..6be109d07f7fcce0 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -268,63 +268,54 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
|
||||
return true;
|
||||
}
|
||||
|
||||
-#define gethosts(_family) \
|
||||
- { \
|
||||
- struct hostent th; \
|
||||
- char *localcanon = NULL; \
|
||||
- no_data = 0; \
|
||||
- while (1) \
|
||||
- { \
|
||||
- status = DL_CALL_FCT (fct, (name, _family, &th, \
|
||||
- tmpbuf->data, tmpbuf->length, \
|
||||
- &errno, &h_errno, NULL, &localcanon)); \
|
||||
- if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \
|
||||
- || errno != ERANGE) \
|
||||
- break; \
|
||||
- if (!scratch_buffer_grow (tmpbuf)) \
|
||||
- { \
|
||||
- __resolv_context_put (res_ctx); \
|
||||
- result = -EAI_MEMORY; \
|
||||
- goto out; \
|
||||
- } \
|
||||
- } \
|
||||
- if (status == NSS_STATUS_NOTFOUND \
|
||||
- || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \
|
||||
- { \
|
||||
- if (h_errno == NETDB_INTERNAL) \
|
||||
- { \
|
||||
- __resolv_context_put (res_ctx); \
|
||||
- result = -EAI_SYSTEM; \
|
||||
- goto out; \
|
||||
- } \
|
||||
- if (h_errno == TRY_AGAIN) \
|
||||
- no_data = EAI_AGAIN; \
|
||||
- else \
|
||||
- no_data = h_errno == NO_DATA; \
|
||||
- } \
|
||||
- else if (status == NSS_STATUS_SUCCESS) \
|
||||
- { \
|
||||
- if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, res)) \
|
||||
- { \
|
||||
- __resolv_context_put (res_ctx); \
|
||||
- result = -EAI_SYSTEM; \
|
||||
- goto out; \
|
||||
- } \
|
||||
- \
|
||||
- if (localcanon != NULL && res->canon == NULL) \
|
||||
- { \
|
||||
- char *canonbuf = __strdup (localcanon); \
|
||||
- if (canonbuf == NULL) \
|
||||
- { \
|
||||
- __resolv_context_put (res_ctx); \
|
||||
- result = -EAI_SYSTEM; \
|
||||
- goto out; \
|
||||
- } \
|
||||
- res->canon = canonbuf; \
|
||||
- } \
|
||||
- } \
|
||||
- }
|
||||
+static int
|
||||
+gethosts (nss_gethostbyname3_r fct, int family, const char *name,
|
||||
+ const struct addrinfo *req, struct scratch_buffer *tmpbuf,
|
||||
+ struct gaih_result *res, enum nss_status *statusp, int *no_datap)
|
||||
+{
|
||||
+ struct hostent th;
|
||||
+ char *localcanon = NULL;
|
||||
+ enum nss_status status;
|
||||
+
|
||||
+ *no_datap = 0;
|
||||
+ while (1)
|
||||
+ {
|
||||
+ *statusp = status = DL_CALL_FCT (fct, (name, family, &th,
|
||||
+ tmpbuf->data, tmpbuf->length,
|
||||
+ &errno, &h_errno, NULL,
|
||||
+ &localcanon));
|
||||
+ if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL
|
||||
+ || errno != ERANGE)
|
||||
+ break;
|
||||
+ if (!scratch_buffer_grow (tmpbuf))
|
||||
+ return -EAI_MEMORY;
|
||||
+ }
|
||||
+ if (status == NSS_STATUS_NOTFOUND
|
||||
+ || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
|
||||
+ {
|
||||
+ if (h_errno == NETDB_INTERNAL)
|
||||
+ return -EAI_SYSTEM;
|
||||
+ if (h_errno == TRY_AGAIN)
|
||||
+ *no_datap = EAI_AGAIN;
|
||||
+ else
|
||||
+ *no_datap = h_errno == NO_DATA;
|
||||
+ }
|
||||
+ else if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (!convert_hostent_to_gaih_addrtuple (req, family, &th, res))
|
||||
+ return -EAI_SYSTEM;
|
||||
+
|
||||
+ if (localcanon != NULL && res->canon == NULL)
|
||||
+ {
|
||||
+ char *canonbuf = __strdup (localcanon);
|
||||
+ if (canonbuf == NULL)
|
||||
+ return -EAI_SYSTEM;
|
||||
+ res->canon = canonbuf;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
+ return 0;
|
||||
+}
|
||||
|
||||
/* This function is called if a canonical name is requested, but if
|
||||
the service function did not provide it. It tries to obtain the
|
||||
@@ -741,7 +732,12 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
|
||||
if (req->ai_family == AF_INET6
|
||||
|| req->ai_family == AF_UNSPEC)
|
||||
{
|
||||
- gethosts (AF_INET6);
|
||||
+ if ((result = gethosts (fct, AF_INET6, name, req, tmpbuf,
|
||||
+ res, &status, &no_data)) != 0)
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ goto out;
|
||||
+ }
|
||||
no_inet6_data = no_data;
|
||||
inet6_status = status;
|
||||
}
|
||||
@@ -753,7 +749,12 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
|
||||
know we are not going to need them. */
|
||||
&& ((req->ai_flags & AI_ALL) || !res->got_ipv6)))
|
||||
{
|
||||
- gethosts (AF_INET);
|
||||
+ if ((result = gethosts (fct, AF_INET, name, req, tmpbuf,
|
||||
+ res, &status, &no_data)) != 0)
|
||||
+ {
|
||||
+ __resolv_context_put (res_ctx);
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
if (req->ai_family == AF_INET)
|
||||
{
|
|
@ -0,0 +1,973 @@
|
|||
commit 1c37b8022e8763fedbb3f79c02e05c6acfe5a215
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Mar 17 11:44:34 2022 +0530
|
||||
|
||||
Simplify allocations and fix merge and continue actions [BZ #28931]
|
||||
|
||||
Allocations for address tuples is currently a bit confusing because of
|
||||
the pointer chasing through PAT, making it hard to observe the sequence
|
||||
in which allocations have been made. Narrow scope of the pointer
|
||||
chasing through PAT so that it is only used where necessary.
|
||||
|
||||
This also tightens actions behaviour with the hosts database in
|
||||
getaddrinfo to comply with the manual text. The "continue" action
|
||||
discards previous results and the "merge" action results in an immedate
|
||||
lookup failure. Consequently, chaining of allocations across modules is
|
||||
no longer necessary, thus opening up cleanup opportunities.
|
||||
|
||||
A test has been added that checks some combinations to ensure that they
|
||||
work correctly.
|
||||
|
||||
Resolves: BZ #28931
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
nss/Makefile
|
||||
(Tests applied in different order from upstream)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index f01674a16e720b88..333edb1588ede881 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -77,6 +77,7 @@ tests-container := \
|
||||
tst-nss-db-endpwent \
|
||||
tst-nss-files-hosts-long \
|
||||
tst-nss-files-hosts-v4mapped \
|
||||
+ tst-nss-gai-actions \
|
||||
tst-nss-test3 \
|
||||
tst-reload1 \
|
||||
tst-reload2 \
|
||||
diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..efca6cd1837a172a
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-actions.c
|
||||
@@ -0,0 +1,149 @@
|
||||
+/* Test continue and merge NSS actions for getaddrinfo.
|
||||
+ Copyright The GNU Toolchain Authors.
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dlfcn.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <nss.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/format_nss.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ ACTION_MERGE = 0,
|
||||
+ ACTION_CONTINUE,
|
||||
+};
|
||||
+
|
||||
+static const char *
|
||||
+family_str (int family)
|
||||
+{
|
||||
+ switch (family)
|
||||
+ {
|
||||
+ case AF_UNSPEC:
|
||||
+ return "AF_UNSPEC";
|
||||
+ case AF_INET:
|
||||
+ return "AF_INET";
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const char *
|
||||
+action_str (int action)
|
||||
+{
|
||||
+ switch (action)
|
||||
+ {
|
||||
+ case ACTION_MERGE:
|
||||
+ return "merge";
|
||||
+ case ACTION_CONTINUE:
|
||||
+ return "continue";
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_one_test (int action, int family, bool canon)
|
||||
+{
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_family = family,
|
||||
+ };
|
||||
+
|
||||
+ struct addrinfo *ai;
|
||||
+
|
||||
+ if (canon)
|
||||
+ hints.ai_flags = AI_CANONNAME;
|
||||
+
|
||||
+ printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n",
|
||||
+ action_str (action), family_str (family),
|
||||
+ canon ? "AI_CANONNAME" : "");
|
||||
+
|
||||
+ int ret = getaddrinfo ("example.org", "80", &hints, &ai);
|
||||
+
|
||||
+ switch (action)
|
||||
+ {
|
||||
+ case ACTION_MERGE:
|
||||
+ if (ret == 0)
|
||||
+ {
|
||||
+ char *formatted = support_format_addrinfo (ai, ret);
|
||||
+
|
||||
+ printf ("merge unexpectedly succeeded:\n %s\n", formatted);
|
||||
+ support_record_failure ();
|
||||
+ free (formatted);
|
||||
+ }
|
||||
+ else
|
||||
+ return;
|
||||
+ case ACTION_CONTINUE:
|
||||
+ {
|
||||
+ char *formatted = support_format_addrinfo (ai, ret);
|
||||
+
|
||||
+ /* Verify that the result appears exactly once. */
|
||||
+ const char *expected = "address: STREAM/TCP 192.0.0.1 80\n"
|
||||
+ "address: DGRAM/UDP 192.0.0.1 80\n"
|
||||
+ "address: RAW/IP 192.0.0.1 80\n";
|
||||
+
|
||||
+ const char *contains = strstr (formatted, expected);
|
||||
+ const char *contains2 = NULL;
|
||||
+
|
||||
+ if (contains != NULL)
|
||||
+ contains2 = strstr (contains + strlen (expected), expected);
|
||||
+
|
||||
+ if (contains == NULL || contains2 != NULL)
|
||||
+ {
|
||||
+ printf ("continue failed:\n%s\n", formatted);
|
||||
+ support_record_failure ();
|
||||
+ }
|
||||
+
|
||||
+ free (formatted);
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+do_one_test_set (int action)
|
||||
+{
|
||||
+ char buf[32];
|
||||
+
|
||||
+ snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files",
|
||||
+ action_str (action));
|
||||
+ __nss_configure_lookup ("hosts", buf);
|
||||
+
|
||||
+ do_one_test (action, AF_UNSPEC, false);
|
||||
+ do_one_test (action, AF_INET, false);
|
||||
+ do_one_test (action, AF_INET, true);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ do_one_test_set (ACTION_CONTINUE);
|
||||
+ do_one_test_set (ACTION_MERGE);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nss/tst-nss-gai-actions.root/etc/host.conf b/nss/tst-nss-gai-actions.root/etc/host.conf
|
||||
new file mode 100644
|
||||
index 0000000000000000..d1a59f73a90f2993
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-actions.root/etc/host.conf
|
||||
@@ -0,0 +1 @@
|
||||
+multi on
|
||||
diff --git a/nss/tst-nss-gai-actions.root/etc/hosts b/nss/tst-nss-gai-actions.root/etc/hosts
|
||||
new file mode 100644
|
||||
index 0000000000000000..50ce9774dc2c21d9
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-gai-actions.root/etc/hosts
|
||||
@@ -0,0 +1,508 @@
|
||||
+192.0.0.1 example.org
|
||||
+192.0.0.2 example.org
|
||||
+192.0.0.3 example.org
|
||||
+192.0.0.4 example.org
|
||||
+192.0.0.5 example.org
|
||||
+192.0.0.6 example.org
|
||||
+192.0.0.7 example.org
|
||||
+192.0.0.8 example.org
|
||||
+192.0.0.9 example.org
|
||||
+192.0.0.10 example.org
|
||||
+192.0.0.11 example.org
|
||||
+192.0.0.12 example.org
|
||||
+192.0.0.13 example.org
|
||||
+192.0.0.14 example.org
|
||||
+192.0.0.15 example.org
|
||||
+192.0.0.16 example.org
|
||||
+192.0.0.17 example.org
|
||||
+192.0.0.18 example.org
|
||||
+192.0.0.19 example.org
|
||||
+192.0.0.20 example.org
|
||||
+192.0.0.21 example.org
|
||||
+192.0.0.22 example.org
|
||||
+192.0.0.23 example.org
|
||||
+192.0.0.24 example.org
|
||||
+192.0.0.25 example.org
|
||||
+192.0.0.26 example.org
|
||||
+192.0.0.27 example.org
|
||||
+192.0.0.28 example.org
|
||||
+192.0.0.29 example.org
|
||||
+192.0.0.30 example.org
|
||||
+192.0.0.31 example.org
|
||||
+192.0.0.32 example.org
|
||||
+192.0.0.33 example.org
|
||||
+192.0.0.34 example.org
|
||||
+192.0.0.35 example.org
|
||||
+192.0.0.36 example.org
|
||||
+192.0.0.37 example.org
|
||||
+192.0.0.38 example.org
|
||||
+192.0.0.39 example.org
|
||||
+192.0.0.40 example.org
|
||||
+192.0.0.41 example.org
|
||||
+192.0.0.42 example.org
|
||||
+192.0.0.43 example.org
|
||||
+192.0.0.44 example.org
|
||||
+192.0.0.45 example.org
|
||||
+192.0.0.46 example.org
|
||||
+192.0.0.47 example.org
|
||||
+192.0.0.48 example.org
|
||||
+192.0.0.49 example.org
|
||||
+192.0.0.50 example.org
|
||||
+192.0.0.51 example.org
|
||||
+192.0.0.52 example.org
|
||||
+192.0.0.53 example.org
|
||||
+192.0.0.54 example.org
|
||||
+192.0.0.55 example.org
|
||||
+192.0.0.56 example.org
|
||||
+192.0.0.57 example.org
|
||||
+192.0.0.58 example.org
|
||||
+192.0.0.59 example.org
|
||||
+192.0.0.60 example.org
|
||||
+192.0.0.61 example.org
|
||||
+192.0.0.62 example.org
|
||||
+192.0.0.63 example.org
|
||||
+192.0.0.64 example.org
|
||||
+192.0.0.65 example.org
|
||||
+192.0.0.66 example.org
|
||||
+192.0.0.67 example.org
|
||||
+192.0.0.68 example.org
|
||||
+192.0.0.69 example.org
|
||||
+192.0.0.70 example.org
|
||||
+192.0.0.71 example.org
|
||||
+192.0.0.72 example.org
|
||||
+192.0.0.73 example.org
|
||||
+192.0.0.74 example.org
|
||||
+192.0.0.75 example.org
|
||||
+192.0.0.76 example.org
|
||||
+192.0.0.77 example.org
|
||||
+192.0.0.78 example.org
|
||||
+192.0.0.79 example.org
|
||||
+192.0.0.80 example.org
|
||||
+192.0.0.81 example.org
|
||||
+192.0.0.82 example.org
|
||||
+192.0.0.83 example.org
|
||||
+192.0.0.84 example.org
|
||||
+192.0.0.85 example.org
|
||||
+192.0.0.86 example.org
|
||||
+192.0.0.87 example.org
|
||||
+192.0.0.88 example.org
|
||||
+192.0.0.89 example.org
|
||||
+192.0.0.90 example.org
|
||||
+192.0.0.91 example.org
|
||||
+192.0.0.92 example.org
|
||||
+192.0.0.93 example.org
|
||||
+192.0.0.94 example.org
|
||||
+192.0.0.95 example.org
|
||||
+192.0.0.96 example.org
|
||||
+192.0.0.97 example.org
|
||||
+192.0.0.98 example.org
|
||||
+192.0.0.99 example.org
|
||||
+192.0.0.100 example.org
|
||||
+192.0.0.101 example.org
|
||||
+192.0.0.102 example.org
|
||||
+192.0.0.103 example.org
|
||||
+192.0.0.104 example.org
|
||||
+192.0.0.105 example.org
|
||||
+192.0.0.106 example.org
|
||||
+192.0.0.107 example.org
|
||||
+192.0.0.108 example.org
|
||||
+192.0.0.109 example.org
|
||||
+192.0.0.110 example.org
|
||||
+192.0.0.111 example.org
|
||||
+192.0.0.112 example.org
|
||||
+192.0.0.113 example.org
|
||||
+192.0.0.114 example.org
|
||||
+192.0.0.115 example.org
|
||||
+192.0.0.116 example.org
|
||||
+192.0.0.117 example.org
|
||||
+192.0.0.118 example.org
|
||||
+192.0.0.119 example.org
|
||||
+192.0.0.120 example.org
|
||||
+192.0.0.121 example.org
|
||||
+192.0.0.122 example.org
|
||||
+192.0.0.123 example.org
|
||||
+192.0.0.124 example.org
|
||||
+192.0.0.125 example.org
|
||||
+192.0.0.126 example.org
|
||||
+192.0.0.127 example.org
|
||||
+192.0.0.128 example.org
|
||||
+192.0.0.129 example.org
|
||||
+192.0.0.130 example.org
|
||||
+192.0.0.131 example.org
|
||||
+192.0.0.132 example.org
|
||||
+192.0.0.133 example.org
|
||||
+192.0.0.134 example.org
|
||||
+192.0.0.135 example.org
|
||||
+192.0.0.136 example.org
|
||||
+192.0.0.137 example.org
|
||||
+192.0.0.138 example.org
|
||||
+192.0.0.139 example.org
|
||||
+192.0.0.140 example.org
|
||||
+192.0.0.141 example.org
|
||||
+192.0.0.142 example.org
|
||||
+192.0.0.143 example.org
|
||||
+192.0.0.144 example.org
|
||||
+192.0.0.145 example.org
|
||||
+192.0.0.146 example.org
|
||||
+192.0.0.147 example.org
|
||||
+192.0.0.148 example.org
|
||||
+192.0.0.149 example.org
|
||||
+192.0.0.150 example.org
|
||||
+192.0.0.151 example.org
|
||||
+192.0.0.152 example.org
|
||||
+192.0.0.153 example.org
|
||||
+192.0.0.154 example.org
|
||||
+192.0.0.155 example.org
|
||||
+192.0.0.156 example.org
|
||||
+192.0.0.157 example.org
|
||||
+192.0.0.158 example.org
|
||||
+192.0.0.159 example.org
|
||||
+192.0.0.160 example.org
|
||||
+192.0.0.161 example.org
|
||||
+192.0.0.162 example.org
|
||||
+192.0.0.163 example.org
|
||||
+192.0.0.164 example.org
|
||||
+192.0.0.165 example.org
|
||||
+192.0.0.166 example.org
|
||||
+192.0.0.167 example.org
|
||||
+192.0.0.168 example.org
|
||||
+192.0.0.169 example.org
|
||||
+192.0.0.170 example.org
|
||||
+192.0.0.171 example.org
|
||||
+192.0.0.172 example.org
|
||||
+192.0.0.173 example.org
|
||||
+192.0.0.174 example.org
|
||||
+192.0.0.175 example.org
|
||||
+192.0.0.176 example.org
|
||||
+192.0.0.177 example.org
|
||||
+192.0.0.178 example.org
|
||||
+192.0.0.179 example.org
|
||||
+192.0.0.180 example.org
|
||||
+192.0.0.181 example.org
|
||||
+192.0.0.182 example.org
|
||||
+192.0.0.183 example.org
|
||||
+192.0.0.184 example.org
|
||||
+192.0.0.185 example.org
|
||||
+192.0.0.186 example.org
|
||||
+192.0.0.187 example.org
|
||||
+192.0.0.188 example.org
|
||||
+192.0.0.189 example.org
|
||||
+192.0.0.190 example.org
|
||||
+192.0.0.191 example.org
|
||||
+192.0.0.192 example.org
|
||||
+192.0.0.193 example.org
|
||||
+192.0.0.194 example.org
|
||||
+192.0.0.195 example.org
|
||||
+192.0.0.196 example.org
|
||||
+192.0.0.197 example.org
|
||||
+192.0.0.198 example.org
|
||||
+192.0.0.199 example.org
|
||||
+192.0.0.200 example.org
|
||||
+192.0.0.201 example.org
|
||||
+192.0.0.202 example.org
|
||||
+192.0.0.203 example.org
|
||||
+192.0.0.204 example.org
|
||||
+192.0.0.205 example.org
|
||||
+192.0.0.206 example.org
|
||||
+192.0.0.207 example.org
|
||||
+192.0.0.208 example.org
|
||||
+192.0.0.209 example.org
|
||||
+192.0.0.210 example.org
|
||||
+192.0.0.211 example.org
|
||||
+192.0.0.212 example.org
|
||||
+192.0.0.213 example.org
|
||||
+192.0.0.214 example.org
|
||||
+192.0.0.215 example.org
|
||||
+192.0.0.216 example.org
|
||||
+192.0.0.217 example.org
|
||||
+192.0.0.218 example.org
|
||||
+192.0.0.219 example.org
|
||||
+192.0.0.220 example.org
|
||||
+192.0.0.221 example.org
|
||||
+192.0.0.222 example.org
|
||||
+192.0.0.223 example.org
|
||||
+192.0.0.224 example.org
|
||||
+192.0.0.225 example.org
|
||||
+192.0.0.226 example.org
|
||||
+192.0.0.227 example.org
|
||||
+192.0.0.228 example.org
|
||||
+192.0.0.229 example.org
|
||||
+192.0.0.230 example.org
|
||||
+192.0.0.231 example.org
|
||||
+192.0.0.232 example.org
|
||||
+192.0.0.233 example.org
|
||||
+192.0.0.234 example.org
|
||||
+192.0.0.235 example.org
|
||||
+192.0.0.236 example.org
|
||||
+192.0.0.237 example.org
|
||||
+192.0.0.238 example.org
|
||||
+192.0.0.239 example.org
|
||||
+192.0.0.240 example.org
|
||||
+192.0.0.241 example.org
|
||||
+192.0.0.242 example.org
|
||||
+192.0.0.243 example.org
|
||||
+192.0.0.244 example.org
|
||||
+192.0.0.245 example.org
|
||||
+192.0.0.246 example.org
|
||||
+192.0.0.247 example.org
|
||||
+192.0.0.248 example.org
|
||||
+192.0.0.249 example.org
|
||||
+192.0.0.250 example.org
|
||||
+192.0.0.251 example.org
|
||||
+192.0.0.252 example.org
|
||||
+192.0.0.253 example.org
|
||||
+192.0.0.254 example.org
|
||||
+192.0.1.1 example.org
|
||||
+192.0.1.2 example.org
|
||||
+192.0.1.3 example.org
|
||||
+192.0.1.4 example.org
|
||||
+192.0.1.5 example.org
|
||||
+192.0.1.6 example.org
|
||||
+192.0.1.7 example.org
|
||||
+192.0.1.8 example.org
|
||||
+192.0.1.9 example.org
|
||||
+192.0.1.10 example.org
|
||||
+192.0.1.11 example.org
|
||||
+192.0.1.12 example.org
|
||||
+192.0.1.13 example.org
|
||||
+192.0.1.14 example.org
|
||||
+192.0.1.15 example.org
|
||||
+192.0.1.16 example.org
|
||||
+192.0.1.17 example.org
|
||||
+192.0.1.18 example.org
|
||||
+192.0.1.19 example.org
|
||||
+192.0.1.20 example.org
|
||||
+192.0.1.21 example.org
|
||||
+192.0.1.22 example.org
|
||||
+192.0.1.23 example.org
|
||||
+192.0.1.24 example.org
|
||||
+192.0.1.25 example.org
|
||||
+192.0.1.26 example.org
|
||||
+192.0.1.27 example.org
|
||||
+192.0.1.28 example.org
|
||||
+192.0.1.29 example.org
|
||||
+192.0.1.30 example.org
|
||||
+192.0.1.31 example.org
|
||||
+192.0.1.32 example.org
|
||||
+192.0.1.33 example.org
|
||||
+192.0.1.34 example.org
|
||||
+192.0.1.35 example.org
|
||||
+192.0.1.36 example.org
|
||||
+192.0.1.37 example.org
|
||||
+192.0.1.38 example.org
|
||||
+192.0.1.39 example.org
|
||||
+192.0.1.40 example.org
|
||||
+192.0.1.41 example.org
|
||||
+192.0.1.42 example.org
|
||||
+192.0.1.43 example.org
|
||||
+192.0.1.44 example.org
|
||||
+192.0.1.45 example.org
|
||||
+192.0.1.46 example.org
|
||||
+192.0.1.47 example.org
|
||||
+192.0.1.48 example.org
|
||||
+192.0.1.49 example.org
|
||||
+192.0.1.50 example.org
|
||||
+192.0.1.51 example.org
|
||||
+192.0.1.52 example.org
|
||||
+192.0.1.53 example.org
|
||||
+192.0.1.54 example.org
|
||||
+192.0.1.55 example.org
|
||||
+192.0.1.56 example.org
|
||||
+192.0.1.57 example.org
|
||||
+192.0.1.58 example.org
|
||||
+192.0.1.59 example.org
|
||||
+192.0.1.60 example.org
|
||||
+192.0.1.61 example.org
|
||||
+192.0.1.62 example.org
|
||||
+192.0.1.63 example.org
|
||||
+192.0.1.64 example.org
|
||||
+192.0.1.65 example.org
|
||||
+192.0.1.66 example.org
|
||||
+192.0.1.67 example.org
|
||||
+192.0.1.68 example.org
|
||||
+192.0.1.69 example.org
|
||||
+192.0.1.70 example.org
|
||||
+192.0.1.71 example.org
|
||||
+192.0.1.72 example.org
|
||||
+192.0.1.73 example.org
|
||||
+192.0.1.74 example.org
|
||||
+192.0.1.75 example.org
|
||||
+192.0.1.76 example.org
|
||||
+192.0.1.77 example.org
|
||||
+192.0.1.78 example.org
|
||||
+192.0.1.79 example.org
|
||||
+192.0.1.80 example.org
|
||||
+192.0.1.81 example.org
|
||||
+192.0.1.82 example.org
|
||||
+192.0.1.83 example.org
|
||||
+192.0.1.84 example.org
|
||||
+192.0.1.85 example.org
|
||||
+192.0.1.86 example.org
|
||||
+192.0.1.87 example.org
|
||||
+192.0.1.88 example.org
|
||||
+192.0.1.89 example.org
|
||||
+192.0.1.90 example.org
|
||||
+192.0.1.91 example.org
|
||||
+192.0.1.92 example.org
|
||||
+192.0.1.93 example.org
|
||||
+192.0.1.94 example.org
|
||||
+192.0.1.95 example.org
|
||||
+192.0.1.96 example.org
|
||||
+192.0.1.97 example.org
|
||||
+192.0.1.98 example.org
|
||||
+192.0.1.99 example.org
|
||||
+192.0.1.100 example.org
|
||||
+192.0.1.101 example.org
|
||||
+192.0.1.102 example.org
|
||||
+192.0.1.103 example.org
|
||||
+192.0.1.104 example.org
|
||||
+192.0.1.105 example.org
|
||||
+192.0.1.106 example.org
|
||||
+192.0.1.107 example.org
|
||||
+192.0.1.108 example.org
|
||||
+192.0.1.109 example.org
|
||||
+192.0.1.110 example.org
|
||||
+192.0.1.111 example.org
|
||||
+192.0.1.112 example.org
|
||||
+192.0.1.113 example.org
|
||||
+192.0.1.114 example.org
|
||||
+192.0.1.115 example.org
|
||||
+192.0.1.116 example.org
|
||||
+192.0.1.117 example.org
|
||||
+192.0.1.118 example.org
|
||||
+192.0.1.119 example.org
|
||||
+192.0.1.120 example.org
|
||||
+192.0.1.121 example.org
|
||||
+192.0.1.122 example.org
|
||||
+192.0.1.123 example.org
|
||||
+192.0.1.124 example.org
|
||||
+192.0.1.125 example.org
|
||||
+192.0.1.126 example.org
|
||||
+192.0.1.127 example.org
|
||||
+192.0.1.128 example.org
|
||||
+192.0.1.129 example.org
|
||||
+192.0.1.130 example.org
|
||||
+192.0.1.131 example.org
|
||||
+192.0.1.132 example.org
|
||||
+192.0.1.133 example.org
|
||||
+192.0.1.134 example.org
|
||||
+192.0.1.135 example.org
|
||||
+192.0.1.136 example.org
|
||||
+192.0.1.137 example.org
|
||||
+192.0.1.138 example.org
|
||||
+192.0.1.139 example.org
|
||||
+192.0.1.140 example.org
|
||||
+192.0.1.141 example.org
|
||||
+192.0.1.142 example.org
|
||||
+192.0.1.143 example.org
|
||||
+192.0.1.144 example.org
|
||||
+192.0.1.145 example.org
|
||||
+192.0.1.146 example.org
|
||||
+192.0.1.147 example.org
|
||||
+192.0.1.148 example.org
|
||||
+192.0.1.149 example.org
|
||||
+192.0.1.150 example.org
|
||||
+192.0.1.151 example.org
|
||||
+192.0.1.152 example.org
|
||||
+192.0.1.153 example.org
|
||||
+192.0.1.154 example.org
|
||||
+192.0.1.155 example.org
|
||||
+192.0.1.156 example.org
|
||||
+192.0.1.157 example.org
|
||||
+192.0.1.158 example.org
|
||||
+192.0.1.159 example.org
|
||||
+192.0.1.160 example.org
|
||||
+192.0.1.161 example.org
|
||||
+192.0.1.162 example.org
|
||||
+192.0.1.163 example.org
|
||||
+192.0.1.164 example.org
|
||||
+192.0.1.165 example.org
|
||||
+192.0.1.166 example.org
|
||||
+192.0.1.167 example.org
|
||||
+192.0.1.168 example.org
|
||||
+192.0.1.169 example.org
|
||||
+192.0.1.170 example.org
|
||||
+192.0.1.171 example.org
|
||||
+192.0.1.172 example.org
|
||||
+192.0.1.173 example.org
|
||||
+192.0.1.174 example.org
|
||||
+192.0.1.175 example.org
|
||||
+192.0.1.176 example.org
|
||||
+192.0.1.177 example.org
|
||||
+192.0.1.178 example.org
|
||||
+192.0.1.179 example.org
|
||||
+192.0.1.180 example.org
|
||||
+192.0.1.181 example.org
|
||||
+192.0.1.182 example.org
|
||||
+192.0.1.183 example.org
|
||||
+192.0.1.184 example.org
|
||||
+192.0.1.185 example.org
|
||||
+192.0.1.186 example.org
|
||||
+192.0.1.187 example.org
|
||||
+192.0.1.188 example.org
|
||||
+192.0.1.189 example.org
|
||||
+192.0.1.190 example.org
|
||||
+192.0.1.191 example.org
|
||||
+192.0.1.192 example.org
|
||||
+192.0.1.193 example.org
|
||||
+192.0.1.194 example.org
|
||||
+192.0.1.195 example.org
|
||||
+192.0.1.196 example.org
|
||||
+192.0.1.197 example.org
|
||||
+192.0.1.198 example.org
|
||||
+192.0.1.199 example.org
|
||||
+192.0.1.200 example.org
|
||||
+192.0.1.201 example.org
|
||||
+192.0.1.202 example.org
|
||||
+192.0.1.203 example.org
|
||||
+192.0.1.204 example.org
|
||||
+192.0.1.205 example.org
|
||||
+192.0.1.206 example.org
|
||||
+192.0.1.207 example.org
|
||||
+192.0.1.208 example.org
|
||||
+192.0.1.209 example.org
|
||||
+192.0.1.210 example.org
|
||||
+192.0.1.211 example.org
|
||||
+192.0.1.212 example.org
|
||||
+192.0.1.213 example.org
|
||||
+192.0.1.214 example.org
|
||||
+192.0.1.215 example.org
|
||||
+192.0.1.216 example.org
|
||||
+192.0.1.217 example.org
|
||||
+192.0.1.218 example.org
|
||||
+192.0.1.219 example.org
|
||||
+192.0.1.220 example.org
|
||||
+192.0.1.221 example.org
|
||||
+192.0.1.222 example.org
|
||||
+192.0.1.223 example.org
|
||||
+192.0.1.224 example.org
|
||||
+192.0.1.225 example.org
|
||||
+192.0.1.226 example.org
|
||||
+192.0.1.227 example.org
|
||||
+192.0.1.228 example.org
|
||||
+192.0.1.229 example.org
|
||||
+192.0.1.230 example.org
|
||||
+192.0.1.231 example.org
|
||||
+192.0.1.232 example.org
|
||||
+192.0.1.233 example.org
|
||||
+192.0.1.234 example.org
|
||||
+192.0.1.235 example.org
|
||||
+192.0.1.236 example.org
|
||||
+192.0.1.237 example.org
|
||||
+192.0.1.238 example.org
|
||||
+192.0.1.239 example.org
|
||||
+192.0.1.240 example.org
|
||||
+192.0.1.241 example.org
|
||||
+192.0.1.242 example.org
|
||||
+192.0.1.243 example.org
|
||||
+192.0.1.244 example.org
|
||||
+192.0.1.245 example.org
|
||||
+192.0.1.246 example.org
|
||||
+192.0.1.247 example.org
|
||||
+192.0.1.248 example.org
|
||||
+192.0.1.249 example.org
|
||||
+192.0.1.250 example.org
|
||||
+192.0.1.251 example.org
|
||||
+192.0.1.252 example.org
|
||||
+192.0.1.253 example.org
|
||||
+192.0.1.254 example.org
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 43dfc6739e350a58..f391dc0a59849aab 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -458,11 +458,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
- at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||||
- at->family = AF_UNSPEC;
|
||||
- at->scopeid = 0;
|
||||
- at->next = NULL;
|
||||
-
|
||||
if (req->ai_flags & AI_IDN)
|
||||
{
|
||||
char *out;
|
||||
@@ -473,13 +468,21 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
malloc_name = true;
|
||||
}
|
||||
|
||||
- if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
|
||||
+ uint32_t addr[4];
|
||||
+ if (__inet_aton_exact (name, (struct in_addr *) addr) != 0)
|
||||
{
|
||||
+ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||||
+ at->scopeid = 0;
|
||||
+ at->next = NULL;
|
||||
+
|
||||
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
|
||||
- at->family = AF_INET;
|
||||
+ {
|
||||
+ memcpy (at->addr, addr, sizeof (at->addr));
|
||||
+ at->family = AF_INET;
|
||||
+ }
|
||||
else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
|
||||
{
|
||||
- at->addr[3] = at->addr[0];
|
||||
+ at->addr[3] = addr[0];
|
||||
at->addr[2] = htonl (0xffff);
|
||||
at->addr[1] = 0;
|
||||
at->addr[0] = 0;
|
||||
@@ -493,49 +496,62 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
if (req->ai_flags & AI_CANONNAME)
|
||||
canon = name;
|
||||
+
|
||||
+ goto process_list;
|
||||
}
|
||||
- else if (at->family == AF_UNSPEC)
|
||||
+
|
||||
+ char *scope_delim = strchr (name, SCOPE_DELIMITER);
|
||||
+ int e;
|
||||
+
|
||||
+ if (scope_delim == NULL)
|
||||
+ e = inet_pton (AF_INET6, name, addr);
|
||||
+ else
|
||||
+ e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr);
|
||||
+
|
||||
+ if (e > 0)
|
||||
{
|
||||
- char *scope_delim = strchr (name, SCOPE_DELIMITER);
|
||||
- int e;
|
||||
- if (scope_delim == NULL)
|
||||
- e = inet_pton (AF_INET6, name, at->addr);
|
||||
+ at = alloca_account (sizeof (struct gaih_addrtuple),
|
||||
+ alloca_used);
|
||||
+ at->scopeid = 0;
|
||||
+ at->next = NULL;
|
||||
+
|
||||
+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||||
+ {
|
||||
+ memcpy (at->addr, addr, sizeof (at->addr));
|
||||
+ at->family = AF_INET6;
|
||||
+ }
|
||||
+ else if (req->ai_family == AF_INET
|
||||
+ && IN6_IS_ADDR_V4MAPPED (addr))
|
||||
+ {
|
||||
+ at->addr[0] = addr[3];
|
||||
+ at->addr[1] = addr[1];
|
||||
+ at->addr[2] = addr[2];
|
||||
+ at->addr[3] = addr[3];
|
||||
+ at->family = AF_INET;
|
||||
+ }
|
||||
else
|
||||
- e = __inet_pton_length (AF_INET6, name, scope_delim - name,
|
||||
- at->addr);
|
||||
- if (e > 0)
|
||||
{
|
||||
- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||||
- at->family = AF_INET6;
|
||||
- else if (req->ai_family == AF_INET
|
||||
- && IN6_IS_ADDR_V4MAPPED (at->addr))
|
||||
- {
|
||||
- at->addr[0] = at->addr[3];
|
||||
- at->family = AF_INET;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = -EAI_ADDRFAMILY;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
- if (scope_delim != NULL
|
||||
- && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
|
||||
- scope_delim + 1,
|
||||
- &at->scopeid) != 0)
|
||||
- {
|
||||
- result = -EAI_NONAME;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
+ result = -EAI_ADDRFAMILY;
|
||||
+ goto free_and_return;
|
||||
+ }
|
||||
|
||||
- if (req->ai_flags & AI_CANONNAME)
|
||||
- canon = name;
|
||||
+ if (scope_delim != NULL
|
||||
+ && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
|
||||
+ scope_delim + 1,
|
||||
+ &at->scopeid) != 0)
|
||||
+ {
|
||||
+ result = -EAI_NONAME;
|
||||
+ goto free_and_return;
|
||||
}
|
||||
+
|
||||
+ if (req->ai_flags & AI_CANONNAME)
|
||||
+ canon = name;
|
||||
+
|
||||
+ goto process_list;
|
||||
}
|
||||
|
||||
- if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
|
||||
+ if ((req->ai_flags & AI_NUMERICHOST) == 0)
|
||||
{
|
||||
- struct gaih_addrtuple **pat = &at;
|
||||
int no_data = 0;
|
||||
int no_inet6_data = 0;
|
||||
nss_action_list nip;
|
||||
@@ -543,6 +559,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
int no_more;
|
||||
struct resolv_context *res_ctx = NULL;
|
||||
+ bool do_merge = false;
|
||||
|
||||
/* If we do not have to look for IPv6 addresses or the canonical
|
||||
name, use the simple, old functions, which do not support
|
||||
@@ -579,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
result = -EAI_MEMORY;
|
||||
goto free_and_return;
|
||||
}
|
||||
- *pat = addrmem;
|
||||
+ at = addrmem;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -632,6 +649,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
|
||||
struct gaih_addrtuple *addrfree = addrmem;
|
||||
+ struct gaih_addrtuple **pat = &at;
|
||||
+
|
||||
for (int i = 0; i < air->naddrs; ++i)
|
||||
{
|
||||
socklen_t size = (air->family[i] == AF_INET
|
||||
@@ -695,12 +714,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
free (air);
|
||||
|
||||
- if (at->family == AF_UNSPEC)
|
||||
- {
|
||||
- result = -EAI_NONAME;
|
||||
- goto free_and_return;
|
||||
- }
|
||||
-
|
||||
goto process_list;
|
||||
}
|
||||
else if (err == 0)
|
||||
@@ -732,6 +745,22 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
while (!no_more)
|
||||
{
|
||||
+ /* Always start afresh; continue should discard previous results
|
||||
+ and the hosts database does not support merge. */
|
||||
+ at = NULL;
|
||||
+ free (canonbuf);
|
||||
+ free (addrmem);
|
||||
+ canon = canonbuf = NULL;
|
||||
+ addrmem = NULL;
|
||||
+ got_ipv6 = false;
|
||||
+
|
||||
+ if (do_merge)
|
||||
+ {
|
||||
+ __set_h_errno (NETDB_INTERNAL);
|
||||
+ __set_errno (EBUSY);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
no_data = 0;
|
||||
nss_gethostbyname4_r *fct4 = NULL;
|
||||
|
||||
@@ -744,12 +773,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
- status = DL_CALL_FCT (fct4, (name, pat,
|
||||
+ status = DL_CALL_FCT (fct4, (name, &at,
|
||||
tmpbuf->data, tmpbuf->length,
|
||||
&errno, &h_errno,
|
||||
NULL));
|
||||
if (status == NSS_STATUS_SUCCESS)
|
||||
break;
|
||||
+ /* gethostbyname4_r may write into AT, so reset it. */
|
||||
+ at = NULL;
|
||||
if (status != NSS_STATUS_TRYAGAIN
|
||||
|| errno != ERANGE || h_errno != NETDB_INTERNAL)
|
||||
{
|
||||
@@ -774,7 +805,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
no_data = 1;
|
||||
|
||||
if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
|
||||
- canon = (*pat)->name;
|
||||
+ canon = at->name;
|
||||
+
|
||||
+ struct gaih_addrtuple **pat = &at;
|
||||
|
||||
while (*pat != NULL)
|
||||
{
|
||||
@@ -826,6 +859,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
|
||||
if (fct != NULL)
|
||||
{
|
||||
+ struct gaih_addrtuple **pat = &at;
|
||||
+
|
||||
if (req->ai_family == AF_INET6
|
||||
|| req->ai_family == AF_UNSPEC)
|
||||
{
|
||||
@@ -899,6 +934,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
|
||||
break;
|
||||
|
||||
+ /* The hosts database does not support MERGE. */
|
||||
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
|
||||
+ do_merge = true;
|
||||
+
|
||||
nip++;
|
||||
if (nip->module == NULL)
|
||||
no_more = -1;
|
||||
@@ -930,7 +969,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
}
|
||||
|
||||
process_list:
|
||||
- if (at->family == AF_UNSPEC)
|
||||
+ if (at == NULL)
|
||||
{
|
||||
result = -EAI_NONAME;
|
||||
goto free_and_return;
|
|
@ -0,0 +1,112 @@
|
|||
commit 849274d48fc59bfa6db3c713c8ced8026b20f3b7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Nov 16 19:55:35 2023 +0100
|
||||
|
||||
elf: Fix force_first handling in dlclose (bug 30981)
|
||||
|
||||
The force_first parameter was ineffective because the dlclose'd
|
||||
object was not necessarily the first in the maps array. Also
|
||||
enable force_first handling unconditionally, regardless of namespace.
|
||||
The initial object in a namespace should be destructed first, too.
|
||||
|
||||
The _dl_sort_maps_dfs function had early returns for relocation
|
||||
dependency processing which broke force_first handling, too, and
|
||||
this is fixed in this change as well.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
||||
index 95a03c9616c6a786..9d158c25498fd8ae 100644
|
||||
--- a/elf/dl-close.c
|
||||
+++ b/elf/dl-close.c
|
||||
@@ -182,6 +182,16 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
}
|
||||
assert (idx == nloaded);
|
||||
|
||||
+ /* Put the dlclose'd map first, so that its destructor runs first.
|
||||
+ The map variable is NULL after a retry. */
|
||||
+ if (map != NULL)
|
||||
+ {
|
||||
+ maps[map->l_idx] = maps[0];
|
||||
+ maps[map->l_idx]->l_idx = map->l_idx;
|
||||
+ maps[0] = map;
|
||||
+ maps[0]->l_idx = 0;
|
||||
+ }
|
||||
+
|
||||
/* Keep track of the lowest index link map we have covered already. */
|
||||
int done_index = -1;
|
||||
while (++done_index < nloaded)
|
||||
@@ -255,9 +265,10 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
}
|
||||
}
|
||||
|
||||
- /* Sort the entries. We can skip looking for the binary itself which is
|
||||
- at the front of the search list for the main namespace. */
|
||||
- _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
|
||||
+ /* Sort the entries. Unless retrying, the maps[0] object (the
|
||||
+ original argument to dlclose) needs to remain first, so that its
|
||||
+ destructor runs first. */
|
||||
+ _dl_sort_maps (maps, nloaded, /* force_first */ map != NULL, true);
|
||||
|
||||
/* Call all termination functions at once. */
|
||||
bool unload_any = false;
|
||||
@@ -768,7 +779,11 @@ _dl_close_worker (struct link_map *map, bool force)
|
||||
/* Recheck if we need to retry, release the lock. */
|
||||
out:
|
||||
if (dl_close_state == rerun)
|
||||
- goto retry;
|
||||
+ {
|
||||
+ /* The map may have been deallocated. */
|
||||
+ map = NULL;
|
||||
+ goto retry;
|
||||
+ }
|
||||
|
||||
dl_close_state = not_pending;
|
||||
}
|
||||
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
|
||||
index e8ef5e8b3588ab53..937feb6e7008bc62 100644
|
||||
--- a/elf/dl-sort-maps.c
|
||||
+++ b/elf/dl-sort-maps.c
|
||||
@@ -260,13 +260,12 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
|
||||
The below memcpy is not needed in the do_reldeps case here,
|
||||
since we wrote back to maps[] during DFS traversal. */
|
||||
if (maps_head == maps)
|
||||
- return;
|
||||
+ break;
|
||||
}
|
||||
assert (maps_head == maps);
|
||||
- return;
|
||||
}
|
||||
-
|
||||
- memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
|
||||
+ else
|
||||
+ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
|
||||
|
||||
/* Skipping the first object at maps[0] is not valid in general,
|
||||
since traversing along object dependency-links may "find" that
|
||||
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
|
||||
index 4bf9052db16fb352..cf6453e9eb85ac65 100644
|
||||
--- a/elf/dso-sort-tests-1.def
|
||||
+++ b/elf/dso-sort-tests-1.def
|
||||
@@ -56,14 +56,16 @@ output: b>a>{}<a<b
|
||||
# relocation(dynamic) dependencies. While this is technically unspecified, the
|
||||
# presumed reasonable practical behavior is for the destructor order to respect
|
||||
# the static DT_NEEDED links (here this means the a->b->c->d order).
|
||||
-# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based
|
||||
-# dynamic_sort=2 algorithm does, although it is still arguable whether going
|
||||
-# beyond spec to do this is the right thing to do.
|
||||
+# The older dynamic_sort=1 algorithm originally did not achieve this,
|
||||
+# but this was a bug in the way _dl_sort_maps was called from _dl_close_worker,
|
||||
+# effectively disabling proper force_first handling.
|
||||
+# The new dynamic_sort=2 algorithm shows the effect of the simpler force_first
|
||||
+# handling: the a object is simply moved to the front.
|
||||
# The below expected outputs are what the two algorithms currently produce
|
||||
# respectively, for regression testing purposes.
|
||||
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
|
||||
-output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
|
||||
-output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
|
||||
+output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<b<c<d<g<f<e];}
|
||||
+output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<g<f<b<c<d<e];}
|
||||
|
||||
# Test that even in the presence of dependency loops involving dlopen'ed
|
||||
# object, that object is initialized last (and not unloaded prematurely).
|
|
@ -0,0 +1,164 @@
|
|||
This patch was developed under embargo and cannot reference an upstream
|
||||
commit. To find the associated commit please review the upstream git
|
||||
log for CVE-2023-4911 to identify the relevant commits.
|
||||
|
||||
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||
Date: Tue Sep 19 11:52:44 2023 -0400
|
||||
|
||||
tunables: Terminate if end of input is reached (CVE-2023-4911)
|
||||
|
||||
The string parsing routine may end up writing beyond bounds of tunestr
|
||||
if the input tunable string is malformed, of the form name=name=val.
|
||||
This gets processed twice, first as name=name=val and next as name=val,
|
||||
resulting in tunestr being name=name=val:name=val, thus overflowing
|
||||
tunestr.
|
||||
|
||||
Terminate the parsing loop at the first instance itself so that tunestr
|
||||
does not overflow.
|
||||
|
||||
This also fixes up tst-env-setuid-tunables to actually handle failures
|
||||
correct and add new tests to validate the fix for this CVE.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
---
|
||||
Tested on x86_64.
|
||||
|
||||
NEWS | 5 +++++
|
||||
elf/dl-tunables.c | 17 ++++++++++-------
|
||||
elf/tst-env-setuid-tunables.c | 36 +++++++++++++++++++++++++++--------
|
||||
3 files changed, 43 insertions(+), 15 deletions(-)
|
||||
|
||||
Conflicts:
|
||||
NEWS
|
||||
(Dropped)
|
||||
elf/tst-env-setuid-tunables.c
|
||||
(Trivial HAVE_TUNABLES conflict)
|
||||
|
||||
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
|
||||
index 8009e54ee5db32be..837474b5044cb5d7 100644
|
||||
--- a/elf/dl-tunables.c
|
||||
+++ b/elf/dl-tunables.c
|
||||
@@ -188,11 +188,7 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
/* If we reach the end of the string before getting a valid name-value
|
||||
pair, bail out. */
|
||||
if (p[len] == '\0')
|
||||
- {
|
||||
- if (__libc_enable_secure)
|
||||
- tunestr[off] = '\0';
|
||||
- return;
|
||||
- }
|
||||
+ break;
|
||||
|
||||
/* We did not find a valid name-value pair before encountering the
|
||||
colon. */
|
||||
@@ -252,9 +248,16 @@ parse_tunables (char *tunestr, char *valstring)
|
||||
}
|
||||
}
|
||||
|
||||
- if (p[len] != '\0')
|
||||
- p += len + 1;
|
||||
+ /* We reached the end while processing the tunable string. */
|
||||
+ if (p[len] == '\0')
|
||||
+ break;
|
||||
+
|
||||
+ p += len + 1;
|
||||
}
|
||||
+
|
||||
+ /* Terminate tunestr before we leave. */
|
||||
+ if (__libc_enable_secure)
|
||||
+ tunestr[off] = '\0';
|
||||
}
|
||||
#endif
|
||||
|
||||
diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
|
||||
index 05619c9adc8b2698..cd4e84364074c613 100644
|
||||
--- a/elf/tst-env-setuid-tunables.c
|
||||
+++ b/elf/tst-env-setuid-tunables.c
|
||||
@@ -52,6 +52,8 @@ const char *teststrings[] =
|
||||
"glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
|
||||
"glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
|
||||
"not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
|
||||
+ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
|
||||
+ "glibc.malloc.check=2",
|
||||
"glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
|
||||
"glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
|
||||
":glibc.malloc.garbage=2:glibc.malloc.check=1",
|
||||
@@ -70,6 +72,8 @@ const char *resultstrings[] =
|
||||
"glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
|
||||
"glibc.malloc.mmap_threshold=4096",
|
||||
"glibc.malloc.mmap_threshold=4096",
|
||||
+ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
|
||||
+ "",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
@@ -84,11 +88,18 @@ test_child (int off)
|
||||
const char *val = getenv ("GLIBC_TUNABLES");
|
||||
|
||||
#if HAVE_TUNABLES
|
||||
+ printf (" [%d] GLIBC_TUNABLES is %s\n", off, val);
|
||||
+ fflush (stdout);
|
||||
if (val != NULL && strcmp (val, resultstrings[off]) == 0)
|
||||
return 0;
|
||||
|
||||
if (val != NULL)
|
||||
- printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
|
||||
+ printf (" [%d] Unexpected GLIBC_TUNABLES VALUE %s, expected %s\n",
|
||||
+ off, val, resultstrings[off]);
|
||||
+ else
|
||||
+ printf (" [%d] GLIBC_TUNABLES environment variable absent\n", off);
|
||||
+
|
||||
+ fflush (stdout);
|
||||
|
||||
return 1;
|
||||
#else
|
||||
@@ -117,21 +128,26 @@ do_test (int argc, char **argv)
|
||||
if (ret != 0)
|
||||
exit (1);
|
||||
|
||||
- exit (EXIT_SUCCESS);
|
||||
+ /* Special return code to make sure that the child executed all the way
|
||||
+ through. */
|
||||
+ exit (42);
|
||||
}
|
||||
else
|
||||
{
|
||||
- int ret = 0;
|
||||
-
|
||||
/* Spawn tests. */
|
||||
for (int i = 0; i < array_length (teststrings); i++)
|
||||
{
|
||||
char buf[INT_BUFSIZE_BOUND (int)];
|
||||
|
||||
- printf ("Spawned test for %s (%d)\n", teststrings[i], i);
|
||||
+ printf ("[%d] Spawned test for %s\n", i, teststrings[i]);
|
||||
snprintf (buf, sizeof (buf), "%d\n", i);
|
||||
+ fflush (stdout);
|
||||
if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
|
||||
- exit (1);
|
||||
+ {
|
||||
+ printf (" [%d] Failed to set GLIBC_TUNABLES: %m", i);
|
||||
+ support_record_failure ();
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
int status = support_capture_subprogram_self_sgid (buf);
|
||||
|
||||
@@ -139,9 +155,14 @@ do_test (int argc, char **argv)
|
||||
if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
|
||||
return EXIT_UNSUPPORTED;
|
||||
|
||||
- ret |= status;
|
||||
+ if (WEXITSTATUS (status) != 42)
|
||||
+ {
|
||||
+ printf (" [%d] child failed with status %d\n", i,
|
||||
+ WEXITSTATUS (status));
|
||||
+ support_record_failure ();
|
||||
+ }
|
||||
}
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,207 @@
|
|||
Author: Charles Fol <folcharles@gmail.com>
|
||||
Date: Thu Mar 28 12:25:38 2024 -0300
|
||||
|
||||
iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
|
||||
|
||||
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
|
||||
(as specified by RFC 1922). While the SOdesignation has the expected
|
||||
bounds checks, neither SS2designation nor SS3designation have its;
|
||||
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
|
||||
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
|
||||
|
||||
Checked on aarch64-linux-gnu.
|
||||
|
||||
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
Tested-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
iconvdata/Makefile
|
||||
(usual tests conflict)
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index d5507a048c6a6508..25bd004e7f92a994 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -75,7 +75,7 @@ ifeq (yes,$(build-shared))
|
||||
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
|
||||
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
|
||||
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
|
||||
- bug-iconv13 bug-iconv14 bug-iconv15
|
||||
+ bug-iconv13 bug-iconv14 bug-iconv15 tst-iconv-iso-2022-cn-ext
|
||||
ifeq ($(have-thread-library),yes)
|
||||
tests += bug-iconv3
|
||||
endif
|
||||
@@ -330,6 +330,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
+ $(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
$(addprefix $(objpfx), $(gconv-modules)) \
|
||||
diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
|
||||
index 2aca91c021f21ba0..c1339fe933d9d1c4 100644
|
||||
--- a/iconvdata/iso-2022-cn-ext.c
|
||||
+++ b/iconvdata/iso-2022-cn-ext.c
|
||||
@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
{ \
|
||||
const char *escseq; \
|
||||
\
|
||||
+ if (outptr + 4 > outend) \
|
||||
+ { \
|
||||
+ result = __GCONV_FULL_OUTPUT; \
|
||||
+ break; \
|
||||
+ } \
|
||||
+ \
|
||||
assert (used == CNS11643_2_set); /* XXX */ \
|
||||
escseq = "*H"; \
|
||||
*outptr++ = ESC; \
|
||||
@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
{ \
|
||||
const char *escseq; \
|
||||
\
|
||||
+ if (outptr + 4 > outend) \
|
||||
+ { \
|
||||
+ result = __GCONV_FULL_OUTPUT; \
|
||||
+ break; \
|
||||
+ } \
|
||||
+ \
|
||||
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
|
||||
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
|
||||
*outptr++ = ESC; \
|
||||
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..96a8765fd5369681
|
||||
--- /dev/null
|
||||
+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <iconv.h>
|
||||
+#include <sys/mman.h>
|
||||
+
|
||||
+#include <support/xunistd.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+/* The test sets up a two memory page buffer with the second page marked
|
||||
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact
|
||||
+ expected amount. Then we carry out various conversions and precisely
|
||||
+ place the start of the output buffer in order to trigger a SIGSEGV if the
|
||||
+ process writes anywhere between 1 and page sized bytes more (only one
|
||||
+ PROT_NONE page is setup as a canary) than expected. These tests exercise
|
||||
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch
|
||||
+ character sets and may run out of buffer space while doing the
|
||||
+ operation. */
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
|
||||
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
|
||||
+
|
||||
+ char *ntf;
|
||||
+ size_t ntfsize;
|
||||
+ char *outbufbase;
|
||||
+ {
|
||||
+ int pgz = getpagesize ();
|
||||
+ TEST_VERIFY_EXIT (pgz > 0);
|
||||
+ ntfsize = 2 * pgz;
|
||||
+
|
||||
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
|
||||
+ | MAP_ANONYMOUS, -1);
|
||||
+ xmprotect (ntf + pgz, pgz, PROT_NONE);
|
||||
+
|
||||
+ outbufbase = ntf + pgz;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
|
||||
+ {
|
||||
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
|
||||
+
|
||||
+ for (int i = 0; i < 9; i++)
|
||||
+ {
|
||||
+ char *inp = inbuf;
|
||||
+ size_t inleft = sizeof (inbuf) - 1;
|
||||
+
|
||||
+ char *outp = outbufbase - i;
|
||||
+ size_t outleft = i;
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
|
||||
+ == (size_t) -1);
|
||||
+ TEST_COMPARE (errno, E2BIG);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Same as before for SS2designation. */
|
||||
+ {
|
||||
+ char inbuf[] = "㴽 \xe3\xb4\xbd";
|
||||
+
|
||||
+ for (int i = 0; i < 14; i++)
|
||||
+ {
|
||||
+ char *inp = inbuf;
|
||||
+ size_t inleft = sizeof (inbuf) - 1;
|
||||
+
|
||||
+ char *outp = outbufbase - i;
|
||||
+ size_t outleft = i;
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
|
||||
+ == (size_t) -1);
|
||||
+ TEST_COMPARE (errno, E2BIG);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Same as before for SS3designation. */
|
||||
+ {
|
||||
+ char inbuf[] = "劄 \xe5\x8a\x84";
|
||||
+
|
||||
+ for (int i = 0; i < 14; i++)
|
||||
+ {
|
||||
+ char *inp = inbuf;
|
||||
+ size_t inleft = sizeof (inbuf) - 1;
|
||||
+
|
||||
+ char *outp = outbufbase - i;
|
||||
+ size_t outleft = i;
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
|
||||
+ == (size_t) -1);
|
||||
+ TEST_COMPARE (errno, E2BIG);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
|
||||
+
|
||||
+ xmunmap (ntf, ntfsize);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,83 @@
|
|||
commit c00b984fcd53f679ca2dafcd1aee2c89836e6e73
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 29 08:28:31 2023 +0200
|
||||
|
||||
nscd: Skip unusable entries in first pass in prune_cache (bug 30800)
|
||||
|
||||
Previously, if an entry was marked unusable for any reason, but had
|
||||
not timed out yet, the assert would trigger.
|
||||
|
||||
One way to get into such state is if a data change is detected during
|
||||
re-validation of an entry. This causes the entry to be marked as not
|
||||
usable. If exits nscd soon after that, then the clock jumps
|
||||
backwards, and nscd restarted, the cache re-validation run after
|
||||
startup triggers the removed assert.
|
||||
|
||||
The change is more complicated than just the removal of the assert
|
||||
because entries marked as not usable should be garbage-collected in
|
||||
the second pass. To make this happen, it is necessary to update some
|
||||
book-keeping data.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/nscd/cache.c b/nscd/cache.c
|
||||
index 78b2269788699e6f..ac5902ae10b791bb 100644
|
||||
--- a/nscd/cache.c
|
||||
+++ b/nscd/cache.c
|
||||
@@ -371,8 +371,11 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
|
||||
serv2str[runp->type], str, dh->timeout);
|
||||
}
|
||||
|
||||
- /* Check whether the entry timed out. */
|
||||
- if (dh->timeout < now)
|
||||
+ /* Check whether the entry timed out. Timed out entries
|
||||
+ will be revalidated. For unusable records, it is still
|
||||
+ necessary to record that the bucket needs to be scanned
|
||||
+ again below. */
|
||||
+ if (dh->timeout < now || !dh->usable)
|
||||
{
|
||||
/* This hash bucket could contain entries which need to
|
||||
be looked at. */
|
||||
@@ -384,7 +387,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
|
||||
/* We only have to look at the data of the first entries
|
||||
since the count information is kept in the data part
|
||||
which is shared. */
|
||||
- if (runp->first)
|
||||
+ if (runp->first && dh->usable)
|
||||
{
|
||||
|
||||
/* At this point there are two choices: we reload the
|
||||
@@ -400,9 +403,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
|
||||
{
|
||||
/* Remove the value. */
|
||||
dh->usable = false;
|
||||
-
|
||||
- /* We definitely have some garbage entries now. */
|
||||
- any = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -414,18 +414,15 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
|
||||
|
||||
time_t timeout = readdfcts[runp->type] (table, runp, dh);
|
||||
next_timeout = MIN (next_timeout, timeout);
|
||||
-
|
||||
- /* If the entry has been replaced, we might need
|
||||
- cleanup. */
|
||||
- any |= !dh->usable;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* If the entry has been replaced, we might need cleanup. */
|
||||
+ any |= !dh->usable;
|
||||
}
|
||||
else
|
||||
- {
|
||||
- assert (dh->usable);
|
||||
- next_timeout = MIN (next_timeout, dh->timeout);
|
||||
- }
|
||||
+ /* Entry has not timed out and is usable. */
|
||||
+ next_timeout = MIN (next_timeout, dh->timeout);
|
||||
|
||||
run = runp->next;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 15:00:45 2024 +0200
|
||||
|
||||
CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
|
||||
|
||||
Using alloca matches what other caches do. The request length is
|
||||
bounded by MAXKEYLEN.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||
index 2f71bf2999dad56b..f13a11b4c4fe3d99 100644
|
||||
--- a/nscd/netgroupcache.c
|
||||
+++ b/nscd/netgroupcache.c
|
||||
@@ -503,12 +503,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
= (struct indataset *) mempool_alloc (db,
|
||||
sizeof (*dataset) + req->key_len,
|
||||
1);
|
||||
- struct indataset dataset_mem;
|
||||
bool cacheable = true;
|
||||
if (__glibc_unlikely (dataset == NULL))
|
||||
{
|
||||
cacheable = false;
|
||||
- dataset = &dataset_mem;
|
||||
+ /* The alloca is safe because nscd_run_worker verfies that
|
||||
+ key_len is not larger than MAXKEYLEN. */
|
||||
+ dataset = alloca (sizeof (*dataset) + req->key_len);
|
||||
}
|
||||
|
||||
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
|
|
@ -0,0 +1,52 @@
|
|||
commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 15:01:07 2024 +0200
|
||||
|
||||
CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678)
|
||||
|
||||
If we failed to add a not-found response to the cache, the dataset
|
||||
point can be null, resulting in a null pointer dereference.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||
index f13a11b4c4fe3d99..08668e96a9fd2c77 100644
|
||||
--- a/nscd/netgroupcache.c
|
||||
+++ b/nscd/netgroupcache.c
|
||||
@@ -148,7 +148,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
/* No such service. */
|
||||
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
|
||||
&key_copy);
|
||||
- goto writeout;
|
||||
+ goto maybe_cache_add;
|
||||
}
|
||||
|
||||
memset (&data, '\0', sizeof (data));
|
||||
@@ -349,7 +349,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
{
|
||||
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
|
||||
&key_copy);
|
||||
- goto writeout;
|
||||
+ goto maybe_cache_add;
|
||||
}
|
||||
|
||||
total = buffilled;
|
||||
@@ -411,14 +411,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
|
||||
if (he == NULL && fd != -1)
|
||||
- {
|
||||
- /* We write the dataset before inserting it to the database
|
||||
- since while inserting this thread might block and so would
|
||||
- unnecessarily let the receiver wait. */
|
||||
- writeout:
|
||||
+ /* We write the dataset before inserting it to the database since
|
||||
+ while inserting this thread might block and so would
|
||||
+ unnecessarily let the receiver wait. */
|
||||
writeall (fd, &dataset->resp, dataset->head.recsize);
|
||||
- }
|
||||
|
||||
+ maybe_cache_add:
|
||||
if (cacheable)
|
||||
{
|
||||
/* If necessary, we also propagate the data to disk. */
|
|
@ -0,0 +1,53 @@
|
|||
commit b048a482f088e53144d26a61c390bed0210f49f2
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 15:01:07 2024 +0200
|
||||
|
||||
CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678)
|
||||
|
||||
The addgetnetgrentX call in addinnetgrX may have failed to produce
|
||||
a result, so the result variable in addinnetgrX can be NULL.
|
||||
Use db->negtimeout as the fallback value if there is no result data;
|
||||
the timeout is also overwritten below.
|
||||
|
||||
Also avoid sending a second not-found response. (The client
|
||||
disconnects after receiving the first response, so the data stream did
|
||||
not go out of sync even without this fix.) It is still beneficial to
|
||||
add the negative response to the mapping, so that the client can get
|
||||
it from there in the future, instead of going through the socket.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||
index 08668e96a9fd2c77..5ed16f871c433531 100644
|
||||
--- a/nscd/netgroupcache.c
|
||||
+++ b/nscd/netgroupcache.c
|
||||
@@ -512,14 +512,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
|
||||
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
|
||||
sizeof (innetgroup_response_header),
|
||||
- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
|
||||
+ he == NULL ? 0 : dh->nreloads + 1,
|
||||
+ result == NULL ? db->negtimeout : result->head.ttl);
|
||||
/* Set the notfound status and timeout based on the result from
|
||||
getnetgrent. */
|
||||
- dataset->head.notfound = result->head.notfound;
|
||||
+ dataset->head.notfound = result == NULL || result->head.notfound;
|
||||
dataset->head.timeout = timeout;
|
||||
|
||||
dataset->resp.version = NSCD_VERSION;
|
||||
- dataset->resp.found = result->resp.found;
|
||||
+ dataset->resp.found = result != NULL && result->resp.found;
|
||||
/* Until we find a matching entry the result is 0. */
|
||||
dataset->resp.result = 0;
|
||||
|
||||
@@ -567,7 +568,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (he == NULL)
|
||||
+ /* addgetnetgrentX may have already sent a notfound response. Do
|
||||
+ not send another one. */
|
||||
+ if (he == NULL && dataset->resp.found)
|
||||
{
|
||||
/* We write the dataset before inserting it to the database
|
||||
since while inserting this thread might block and so would
|
|
@ -0,0 +1,383 @@
|
|||
commit c04a21e050d64a1193a6daab872bca2528bda44b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 25 15:01:07 2024 +0200
|
||||
|
||||
CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
|
||||
|
||||
This avoids potential memory corruption when the underlying NSS
|
||||
callback function does not use the buffer space to store all strings
|
||||
(e.g., for constant strings).
|
||||
|
||||
Instead of custom buffer management, two scratch buffers are used.
|
||||
This increases stack usage somewhat.
|
||||
|
||||
Scratch buffer allocation failure is handled by return -1
|
||||
(an invalid timeout value) instead of terminating the process.
|
||||
This fixes bug 31679.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||
index 5ed16f871c433531..92c9cb36fb00d72e 100644
|
||||
--- a/nscd/netgroupcache.c
|
||||
+++ b/nscd/netgroupcache.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
+#include <scratch_buffer.h>
|
||||
|
||||
#include "../inet/netgroup.h"
|
||||
#include "nscd.h"
|
||||
@@ -66,6 +67,16 @@ struct dataset
|
||||
char strdata[0];
|
||||
};
|
||||
|
||||
+/* Send a notfound response to FD. Always returns -1 to indicate an
|
||||
+ ephemeral error. */
|
||||
+static time_t
|
||||
+send_notfound (int fd)
|
||||
+{
|
||||
+ if (fd != -1)
|
||||
+ TEMP_FAILURE_RETRY (send (fd, ¬found, sizeof (notfound), MSG_NOSIGNAL));
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
/* Sends a notfound message and prepares a notfound dataset to write to the
|
||||
cache. Returns true if there was enough memory to allocate the dataset and
|
||||
returns the dataset in DATASETP, total bytes to write in TOTALP and the
|
||||
@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
||||
total = sizeof (notfound);
|
||||
timeout = time (NULL) + db->negtimeout;
|
||||
|
||||
- if (fd != -1)
|
||||
- TEMP_FAILURE_RETRY (send (fd, ¬found, total, MSG_NOSIGNAL));
|
||||
+ send_notfound (fd);
|
||||
|
||||
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
|
||||
/* If we cannot permanently store the result, so be it. */
|
||||
@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
+struct addgetnetgrentX_scratch
|
||||
+{
|
||||
+ /* This is the result that the caller should use. It can be NULL,
|
||||
+ point into buffer, or it can be in the cache. */
|
||||
+ struct dataset *dataset;
|
||||
+
|
||||
+ struct scratch_buffer buffer;
|
||||
+
|
||||
+ /* Used internally in addgetnetgrentX as a staging area. */
|
||||
+ struct scratch_buffer tmp;
|
||||
+
|
||||
+ /* Number of bytes in buffer that are actually used. */
|
||||
+ size_t buffer_used;
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
|
||||
+{
|
||||
+ scratch->dataset = NULL;
|
||||
+ scratch_buffer_init (&scratch->buffer);
|
||||
+ scratch_buffer_init (&scratch->tmp);
|
||||
+
|
||||
+ /* Reserve space for the header. */
|
||||
+ scratch->buffer_used = sizeof (struct dataset);
|
||||
+ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
|
||||
+ "initial buffer space");
|
||||
+ memset (scratch->tmp.data, 0, sizeof (struct dataset));
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
|
||||
+{
|
||||
+ scratch_buffer_free (&scratch->buffer);
|
||||
+ scratch_buffer_free (&scratch->tmp);
|
||||
+}
|
||||
+
|
||||
+/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
|
||||
+ could not be resized, otherwise a pointer to the copy. */
|
||||
+static char *
|
||||
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
|
||||
+ const char *s, size_t length)
|
||||
+{
|
||||
+ while (true)
|
||||
+ {
|
||||
+ size_t remaining = scratch->buffer.length - scratch->buffer_used;
|
||||
+ if (remaining >= length)
|
||||
+ break;
|
||||
+ if (!scratch_buffer_grow_preserve (&scratch->buffer))
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ char *copy = scratch->buffer.data + scratch->buffer_used;
|
||||
+ memcpy (copy, s, length);
|
||||
+ scratch->buffer_used += length;
|
||||
+ return copy;
|
||||
+}
|
||||
+
|
||||
+/* Copy S into SCRATCH, including its null terminator. Returns false
|
||||
+ if SCRATCH could not be resized. */
|
||||
+static bool
|
||||
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
|
||||
+{
|
||||
+ if (s == NULL)
|
||||
+ s = "";
|
||||
+ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
|
||||
+}
|
||||
+
|
||||
+/* Caller must initialize and free *SCRATCH. If the return value is
|
||||
+ negative, this function has sent a notfound response. */
|
||||
static time_t
|
||||
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
const char *key, uid_t uid, struct hashentry *he,
|
||||
- struct datahead *dh, struct dataset **resultp,
|
||||
- void **tofreep)
|
||||
+ struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
|
||||
{
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
|
||||
char *key_copy = NULL;
|
||||
struct __netgrent data;
|
||||
- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
|
||||
- size_t buffilled = sizeof (*dataset);
|
||||
- char *buffer = NULL;
|
||||
size_t nentries = 0;
|
||||
size_t group_len = strlen (key) + 1;
|
||||
struct name_list *first_needed
|
||||
= alloca (sizeof (struct name_list) + group_len);
|
||||
- *tofreep = NULL;
|
||||
|
||||
if (netgroup_database == NULL
|
||||
&& !__nss_database_get (nss_database_netgroup, &netgroup_database))
|
||||
@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
|
||||
memset (&data, '\0', sizeof (data));
|
||||
- buffer = xmalloc (buflen);
|
||||
- *tofreep = buffer;
|
||||
first_needed->next = first_needed;
|
||||
memcpy (first_needed->name, key, group_len);
|
||||
data.needed_groups = first_needed;
|
||||
@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
while (1)
|
||||
{
|
||||
int e;
|
||||
- status = getfct.f (&data, buffer + buffilled,
|
||||
- buflen - buffilled - req->key_len, &e);
|
||||
+ status = getfct.f (&data, scratch->tmp.data,
|
||||
+ scratch->tmp.length, &e);
|
||||
if (status == NSS_STATUS_SUCCESS)
|
||||
{
|
||||
if (data.type == triple_val)
|
||||
@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
const char *nhost = data.val.triple.host;
|
||||
const char *nuser = data.val.triple.user;
|
||||
const char *ndomain = data.val.triple.domain;
|
||||
-
|
||||
- size_t hostlen = strlen (nhost ?: "") + 1;
|
||||
- size_t userlen = strlen (nuser ?: "") + 1;
|
||||
- size_t domainlen = strlen (ndomain ?: "") + 1;
|
||||
-
|
||||
- if (nhost == NULL || nuser == NULL || ndomain == NULL
|
||||
- || nhost > nuser || nuser > ndomain)
|
||||
- {
|
||||
- const char *last = nhost;
|
||||
- if (last == NULL
|
||||
- || (nuser != NULL && nuser > last))
|
||||
- last = nuser;
|
||||
- if (last == NULL
|
||||
- || (ndomain != NULL && ndomain > last))
|
||||
- last = ndomain;
|
||||
-
|
||||
- size_t bufused
|
||||
- = (last == NULL
|
||||
- ? buffilled
|
||||
- : last + strlen (last) + 1 - buffer);
|
||||
-
|
||||
- /* We have to make temporary copies. */
|
||||
- size_t needed = hostlen + userlen + domainlen;
|
||||
-
|
||||
- if (buflen - req->key_len - bufused < needed)
|
||||
- {
|
||||
- buflen += MAX (buflen, 2 * needed);
|
||||
- /* Save offset in the old buffer. We don't
|
||||
- bother with the NULL check here since
|
||||
- we'll do that later anyway. */
|
||||
- size_t nhostdiff = nhost - buffer;
|
||||
- size_t nuserdiff = nuser - buffer;
|
||||
- size_t ndomaindiff = ndomain - buffer;
|
||||
-
|
||||
- char *newbuf = xrealloc (buffer, buflen);
|
||||
- /* Fix up the triplet pointers into the new
|
||||
- buffer. */
|
||||
- nhost = (nhost ? newbuf + nhostdiff
|
||||
- : NULL);
|
||||
- nuser = (nuser ? newbuf + nuserdiff
|
||||
- : NULL);
|
||||
- ndomain = (ndomain ? newbuf + ndomaindiff
|
||||
- : NULL);
|
||||
- *tofreep = buffer = newbuf;
|
||||
- }
|
||||
-
|
||||
- nhost = memcpy (buffer + bufused,
|
||||
- nhost ?: "", hostlen);
|
||||
- nuser = memcpy ((char *) nhost + hostlen,
|
||||
- nuser ?: "", userlen);
|
||||
- ndomain = memcpy ((char *) nuser + userlen,
|
||||
- ndomain ?: "", domainlen);
|
||||
- }
|
||||
-
|
||||
- char *wp = buffer + buffilled;
|
||||
- wp = memmove (wp, nhost ?: "", hostlen);
|
||||
- wp += hostlen;
|
||||
- wp = memmove (wp, nuser ?: "", userlen);
|
||||
- wp += userlen;
|
||||
- wp = memmove (wp, ndomain ?: "", domainlen);
|
||||
- wp += domainlen;
|
||||
- buffilled = wp - buffer;
|
||||
+ if (!(addgetnetgrentX_append (scratch, nhost)
|
||||
+ && addgetnetgrentX_append (scratch, nuser)
|
||||
+ && addgetnetgrentX_append (scratch, ndomain)))
|
||||
+ return send_notfound (fd);
|
||||
++nentries;
|
||||
}
|
||||
else
|
||||
@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
|
||||
{
|
||||
- buflen *= 2;
|
||||
- *tofreep = buffer = xrealloc (buffer, buflen);
|
||||
+ if (!scratch_buffer_grow (&scratch->tmp))
|
||||
+ return send_notfound (fd);
|
||||
}
|
||||
else if (status == NSS_STATUS_RETURN
|
||||
|| status == NSS_STATUS_NOTFOUND
|
||||
@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
goto maybe_cache_add;
|
||||
}
|
||||
|
||||
- total = buffilled;
|
||||
+ /* Capture the result size without the key appended. */
|
||||
+ total = scratch->buffer_used;
|
||||
+
|
||||
+ /* Make a copy of the key. The scratch buffer must not move after
|
||||
+ this point. */
|
||||
+ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
|
||||
+ if (key_copy == NULL)
|
||||
+ return send_notfound (fd);
|
||||
|
||||
/* Fill in the dataset. */
|
||||
- dataset = (struct dataset *) buffer;
|
||||
+ dataset = scratch->buffer.data;
|
||||
timeout = datahead_init_pos (&dataset->head, total + req->key_len,
|
||||
total - offsetof (struct dataset, resp),
|
||||
he == NULL ? 0 : dh->nreloads + 1,
|
||||
@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
dataset->resp.version = NSCD_VERSION;
|
||||
dataset->resp.found = 1;
|
||||
dataset->resp.nresults = nentries;
|
||||
- dataset->resp.result_len = buffilled - sizeof (*dataset);
|
||||
-
|
||||
- assert (buflen - buffilled >= req->key_len);
|
||||
- key_copy = memcpy (buffer + buffilled, key, req->key_len);
|
||||
- buffilled += req->key_len;
|
||||
+ dataset->resp.result_len = total - sizeof (*dataset);
|
||||
|
||||
/* Now we can determine whether on refill we have to create a new
|
||||
record or not. */
|
||||
@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
if (__glibc_likely (newp != NULL))
|
||||
{
|
||||
/* Adjust pointer into the memory block. */
|
||||
- key_copy = (char *) newp + (key_copy - buffer);
|
||||
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
|
||||
|
||||
dataset = memcpy (newp, dataset, total + req->key_len);
|
||||
cacheable = true;
|
||||
@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
|
||||
out:
|
||||
- *resultp = dataset;
|
||||
+ scratch->dataset = dataset;
|
||||
|
||||
return timeout;
|
||||
}
|
||||
@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
if (user != NULL)
|
||||
key = (char *) rawmemchr (key, '\0') + 1;
|
||||
const char *domain = *key++ ? key : NULL;
|
||||
+ struct addgetnetgrentX_scratch scratch;
|
||||
+
|
||||
+ addgetnetgrentX_scratch_init (&scratch);
|
||||
|
||||
if (__glibc_unlikely (debug_level > 0))
|
||||
{
|
||||
@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
group, group_len,
|
||||
db, uid);
|
||||
time_t timeout;
|
||||
- void *tofree;
|
||||
if (result != NULL)
|
||||
- {
|
||||
- timeout = result->head.timeout;
|
||||
- tofree = NULL;
|
||||
- }
|
||||
+ timeout = result->head.timeout;
|
||||
else
|
||||
{
|
||||
request_header req_get =
|
||||
@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
.key_len = group_len
|
||||
};
|
||||
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
|
||||
- &result, &tofree);
|
||||
+ &scratch);
|
||||
+ result = scratch.dataset;
|
||||
+ if (timeout < 0)
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
struct indataset
|
||||
@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||
}
|
||||
|
||||
out:
|
||||
- free (tofree);
|
||||
+ addgetnetgrentX_scratch_free (&scratch);
|
||||
return timeout;
|
||||
}
|
||||
|
||||
@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
|
||||
const char *key, uid_t uid, struct hashentry *he,
|
||||
struct datahead *dh)
|
||||
{
|
||||
- struct dataset *ignore;
|
||||
- void *tofree;
|
||||
- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
|
||||
- &ignore, &tofree);
|
||||
- free (tofree);
|
||||
+ struct addgetnetgrentX_scratch scratch;
|
||||
+ addgetnetgrentX_scratch_init (&scratch);
|
||||
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
|
||||
+ addgetnetgrentX_scratch_free (&scratch);
|
||||
+ if (timeout < 0)
|
||||
+ timeout = 0;
|
||||
return timeout;
|
||||
}
|
||||
|
||||
@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
|
||||
.key_len = he->len
|
||||
};
|
||||
|
||||
- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
||||
+ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
|
||||
+ he, dh);
|
||||
+ if (timeout < 0)
|
||||
+ timeout = 0;
|
||||
+ return timeout;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
Only backport po/it.po and po/ja.po changes for the ESTALE message
|
||||
translation which we use during CI testing.
|
||||
|
||||
commit 7ff33eca6860648fb909df954da4996ce853d01d
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Fri Jul 7 11:27:08 2023 -0400
|
||||
|
||||
Translations: Add new ro support and update others.
|
||||
|
||||
This brings in the new Romanian language translations, and updates
|
||||
nine other translations. Important translations in this update
|
||||
include the Italian and Japanese translations for ESTALE which
|
||||
remove the mention of "NFS" from the error message translation.
|
||||
|
||||
diff --git a/po/it.po b/po/it.po
|
||||
index abd762b6e383008b..4c62751a92b15e64 100644
|
||||
--- a/po/it.po
|
||||
+++ b/po/it.po
|
||||
@@ -5692,6 +5692,15 @@ msgstr "Troppi utenti"
|
||||
msgid "Disk quota exceeded"
|
||||
msgstr "Quota disco superata"
|
||||
|
||||
+#. TRANS This indicates an internal confusion in the
|
||||
+#. TRANS file system which is due to file system rearrangements on the server host
|
||||
+#. TRANS for NFS file systems or corruption in other file systems.
|
||||
+#. TRANS Repairing this condition usually requires unmounting, possibly repairing
|
||||
+#. TRANS and remounting the file system.
|
||||
+#: sysdeps/gnu/errlist.h:471
|
||||
+msgid "Stale file handle"
|
||||
+msgstr "Riferimento al file obsoleto"
|
||||
+
|
||||
# lf
|
||||
#. TRANS An attempt was made to NFS-mount a remote file system with a file name that
|
||||
#. TRANS already specifies an NFS-mounted file.
|
||||
diff --git a/po/ja.po b/po/ja.po
|
||||
index 87ceb0abb22507b0..07d90ba0205f7065 100644
|
||||
--- a/po/ja.po
|
||||
+++ b/po/ja.po
|
||||
@@ -5279,6 +5279,15 @@ msgstr "ユーザが多すぎます"
|
||||
msgid "Disk quota exceeded"
|
||||
msgstr "ディスク使用量制限を超過しました"
|
||||
|
||||
+#. TRANS This indicates an internal confusion in the
|
||||
+#. TRANS file system which is due to file system rearrangements on the server host
|
||||
+#. TRANS for NFS file systems or corruption in other file systems.
|
||||
+#. TRANS Repairing this condition usually requires unmounting, possibly repairing
|
||||
+#. TRANS and remounting the file system.
|
||||
+#: sysdeps/gnu/errlist.h:471
|
||||
+msgid "Stale file handle"
|
||||
+msgstr "古いファイルハンドルです"
|
||||
+
|
||||
#. TRANS An attempt was made to NFS-mount a remote file system with a file name that
|
||||
#. TRANS already specifies an NFS-mounted file.
|
||||
#. TRANS (This is an error on some operating systems, but we expect it to work
|
|
@ -0,0 +1,23 @@
|
|||
From 61a4425dd412701f6c3545d8c1acd7e1a378ee8b Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 26 Jan 2022 12:18:21 -0800
|
||||
Subject: x86: Don't check PTWRITE in tst-cpu-features-cpuinfo.c
|
||||
|
||||
Don't check PTWRITE against /proc/cpuinfo since kernel doesn't report
|
||||
PTWRITE in /proc/cpuinfo.
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
index 91a656b61d..981b2be5fd 100644
|
||||
--- a/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
+++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
@@ -218,7 +218,10 @@ do_test (int argc, char **argv)
|
||||
fails += CHECK_PROC (popcnt, POPCNT);
|
||||
fails += CHECK_PROC (3dnowprefetch, PREFETCHW);
|
||||
fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
|
||||
+#if 0
|
||||
+ /* NB: /proc/cpuinfo doesn't report this feature. */
|
||||
fails += CHECK_PROC (ptwrite, PTWRITE);
|
||||
+#endif
|
||||
fails += CHECK_PROC (pse, PSE);
|
||||
fails += CHECK_PROC (pse36, PSE_36);
|
||||
fails += CHECK_PROC (psn, PSN);
|
|
@ -0,0 +1,25 @@
|
|||
From db9b47e9f996bbdb831580ff7343542a017c80ee Mon Sep 17 00:00:00 2001
|
||||
From: DJ Delorie <dj@redhat.com>
|
||||
Date: Thu, 9 Mar 2023 22:32:54 -0500
|
||||
Subject: x86: Don't check PREFETCHWT1 in tst-cpu-features-cpuinfo.c
|
||||
|
||||
Don't check PREFETCHWT1 against /proc/cpuinfo since kernel doesn't report
|
||||
PREFETCHWT1 in /proc/cpuinfo.
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
index c25240774e..e963592c4b 100644
|
||||
--- a/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
+++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c
|
||||
@@ -217,7 +217,10 @@ do_test (int argc, char **argv)
|
||||
fails += CHECK_PROC (pku, PKU);
|
||||
fails += CHECK_PROC (popcnt, POPCNT);
|
||||
fails += CHECK_PROC (3dnowprefetch, PREFETCHW);
|
||||
+#if 0
|
||||
+ /* NB: /proc/cpuinfo doesn't report this feature. */
|
||||
fails += CHECK_PROC (prefetchwt1, PREFETCHWT1);
|
||||
+#endif
|
||||
#if 0
|
||||
/* NB: /proc/cpuinfo doesn't report this feature. */
|
||||
fails += CHECK_PROC (ptwrite, PTWRITE);
|
|
@ -0,0 +1,21 @@
|
|||
From 6229aa74fb47af17744d765cc49dbf94d3cefe12 Mon Sep 17 00:00:00 2001
|
||||
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||
Date: Wed, 26 Jan 2022 12:18:30 -0800
|
||||
Subject: x86: Use CHECK_FEATURE_PRESENT on PCONFIG
|
||||
|
||||
PCONFIG is a privileged instruction. Use CHECK_FEATURE_PRESENT, instead
|
||||
of CHECK_FEATURE_ACTIVE, on PCONFIG in tst-cpu-features-supports.c.
|
||||
|
||||
diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
|
||||
index 9f10f02954..11065b642f 100644
|
||||
--- a/sysdeps/x86/tst-cpu-features-supports.c
|
||||
+++ b/sysdeps/x86/tst-cpu-features-supports.c
|
||||
@@ -143,7 +143,7 @@ do_test (int argc, char **argv)
|
||||
fails += CHECK_FEATURE_ACTIVE (movdiri, MOVDIRI);
|
||||
fails += CHECK_FEATURE_ACTIVE (movdir64b, MOVDIR64B);
|
||||
fails += CHECK_FEATURE_ACTIVE (osxsave, OSXSAVE);
|
||||
- fails += CHECK_FEATURE_ACTIVE (pconfig, PCONFIG);
|
||||
+ fails += CHECK_FEATURE_PRESENT (pconfig, PCONFIG);
|
||||
fails += CHECK_FEATURE_ACTIVE (pku, PKU);
|
||||
#endif
|
||||
fails += CHECK_FEATURE_ACTIVE (popcnt, POPCNT);
|
|
@ -0,0 +1,111 @@
|
|||
commit 856bab7717ef6d1033fd7cbf7cfb2ddefbfffb07
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Thu Feb 9 14:56:21 2023 +0100
|
||||
|
||||
x86/dl-cacheinfo: remove unsused parameter from handle_amd
|
||||
|
||||
Also replace an unreachable assert with __builtin_unreachable.
|
||||
|
||||
Conflicts:
|
||||
sysdeps/x86/dl-cacheinfo.h
|
||||
(different backport order downstream)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index 3408700fc0b06e5b..cc2f8862ce88f655 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -311,7 +311,7 @@ handle_intel (int name, const struct cpu_features *cpu_features)
|
||||
|
||||
|
||||
static long int __attribute__ ((noinline))
|
||||
-handle_amd (int name, const struct cpu_features *cpu_features)
|
||||
+handle_amd (int name)
|
||||
{
|
||||
unsigned int eax;
|
||||
unsigned int ebx;
|
||||
@@ -334,24 +334,23 @@ handle_amd (int name, const struct cpu_features *cpu_features)
|
||||
|
||||
switch (name)
|
||||
{
|
||||
- case _SC_LEVEL1_ICACHE_ASSOC:
|
||||
- case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
- case _SC_LEVEL2_CACHE_ASSOC:
|
||||
- case _SC_LEVEL3_CACHE_ASSOC:
|
||||
- return ecx?((ebx >> 22) & 0x3ff) + 1 : 0;
|
||||
- case _SC_LEVEL1_ICACHE_LINESIZE:
|
||||
- case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
- case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
- case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
- return ecx?(ebx & 0xfff) + 1 : 0;
|
||||
- case _SC_LEVEL1_ICACHE_SIZE:
|
||||
- case _SC_LEVEL1_DCACHE_SIZE:
|
||||
- case _SC_LEVEL2_CACHE_SIZE:
|
||||
- case _SC_LEVEL3_CACHE_SIZE:
|
||||
- return ecx?(((ebx >> 22) & 0x3ff) + 1)*((ebx & 0xfff) + 1)\
|
||||
- *(ecx + 1):0;
|
||||
- default:
|
||||
- assert (! "cannot happen");
|
||||
+ case _SC_LEVEL1_ICACHE_ASSOC:
|
||||
+ case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
+ case _SC_LEVEL2_CACHE_ASSOC:
|
||||
+ case _SC_LEVEL3_CACHE_ASSOC:
|
||||
+ return ecx ? ((ebx >> 22) & 0x3ff) + 1 : 0;
|
||||
+ case _SC_LEVEL1_ICACHE_LINESIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
+ case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
+ case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
+ return ecx ? (ebx & 0xfff) + 1 : 0;
|
||||
+ case _SC_LEVEL1_ICACHE_SIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_SIZE:
|
||||
+ case _SC_LEVEL2_CACHE_SIZE:
|
||||
+ case _SC_LEVEL3_CACHE_SIZE:
|
||||
+ return ecx ? (((ebx >> 22) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1): 0;
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -701,31 +700,26 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
}
|
||||
else if (cpu_features->basic.kind == arch_kind_amd)
|
||||
{
|
||||
- data = handle_amd (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
|
||||
- core = handle_amd (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||
- shared = handle_amd (_SC_LEVEL3_CACHE_SIZE, cpu_features);
|
||||
+ data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
|
||||
+ core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
|
||||
+ shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
|
||||
shared_per_thread = shared;
|
||||
|
||||
- level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
|
||||
- level1_icache_linesize
|
||||
- = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);
|
||||
+ level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
|
||||
+ level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
level1_dcache_size = data;
|
||||
- level1_dcache_assoc
|
||||
- = handle_amd (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
|
||||
- level1_dcache_linesize
|
||||
- = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
|
||||
+ level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
|
||||
+ level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
|
||||
level2_cache_size = core;
|
||||
- level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
|
||||
- level2_cache_linesize
|
||||
- = handle_amd (_SC_LEVEL2_CACHE_LINESIZE, cpu_features);
|
||||
+ level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
|
||||
+ level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
|
||||
level3_cache_size = shared;
|
||||
- level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC, cpu_features);
|
||||
- level3_cache_linesize
|
||||
- = handle_amd (_SC_LEVEL3_CACHE_LINESIZE, cpu_features);
|
||||
+ level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC);
|
||||
+ level3_cache_linesize = handle_amd (_SC_LEVEL3_CACHE_LINESIZE);
|
||||
|
||||
if (shared <= 0)
|
||||
/* No shared L3 cache. All we have is the L2 cache. */
|
||||
- shared = core;
|
||||
+ shared = core;
|
||||
|
||||
if (shared_per_thread <= 0)
|
||||
shared_per_thread = shared;
|
|
@ -0,0 +1,281 @@
|
|||
commit dcad5c8578130dec7f35fd5b0885304b59f9f543
|
||||
Author: Sajan Karumanchi <sajan.karumanchi@amd.com>
|
||||
Date: Tue Aug 1 15:20:55 2023 +0000
|
||||
|
||||
x86: Fix for cache computation on AMD legacy cpus.
|
||||
|
||||
Some legacy AMD CPUs and hypervisors have the _cpuid_ '0x8000_001D'
|
||||
set to Zero, thus resulting in zeroed-out computed cache values.
|
||||
This patch reintroduces the old way of cache computation as a
|
||||
fail-safe option to handle these exceptions.
|
||||
Fixed 'level4_cache_size' value through handle_amd().
|
||||
|
||||
Reviewed-by: Premachandra Mallappa <premachandra.mallappa@amd.com>
|
||||
Tested-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index cc2f8862ce88f655..aed1a7be56610e99 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -315,40 +315,206 @@ handle_amd (int name)
|
||||
{
|
||||
unsigned int eax;
|
||||
unsigned int ebx;
|
||||
- unsigned int ecx;
|
||||
+ unsigned int ecx = 0;
|
||||
unsigned int edx;
|
||||
- unsigned int count = 0x1;
|
||||
+ unsigned int max_cpuid = 0;
|
||||
+ unsigned int fn = 0;
|
||||
|
||||
/* No level 4 cache (yet). */
|
||||
if (name > _SC_LEVEL3_CACHE_LINESIZE)
|
||||
return 0;
|
||||
|
||||
- if (name >= _SC_LEVEL3_CACHE_SIZE)
|
||||
- count = 0x3;
|
||||
- else if (name >= _SC_LEVEL2_CACHE_SIZE)
|
||||
- count = 0x2;
|
||||
- else if (name >= _SC_LEVEL1_DCACHE_SIZE)
|
||||
- count = 0x0;
|
||||
+ __cpuid (0x80000000, max_cpuid, ebx, ecx, edx);
|
||||
+
|
||||
+ if (max_cpuid >= 0x8000001D)
|
||||
+ /* Use __cpuid__ '0x8000_001D' to compute cache details. */
|
||||
+ {
|
||||
+ unsigned int count = 0x1;
|
||||
+
|
||||
+ if (name >= _SC_LEVEL3_CACHE_SIZE)
|
||||
+ count = 0x3;
|
||||
+ else if (name >= _SC_LEVEL2_CACHE_SIZE)
|
||||
+ count = 0x2;
|
||||
+ else if (name >= _SC_LEVEL1_DCACHE_SIZE)
|
||||
+ count = 0x0;
|
||||
+
|
||||
+ __cpuid_count (0x8000001D, count, eax, ebx, ecx, edx);
|
||||
+
|
||||
+ if (ecx != 0)
|
||||
+ {
|
||||
+ switch (name)
|
||||
+ {
|
||||
+ case _SC_LEVEL1_ICACHE_ASSOC:
|
||||
+ case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
+ case _SC_LEVEL2_CACHE_ASSOC:
|
||||
+ case _SC_LEVEL3_CACHE_ASSOC:
|
||||
+ return ((ebx >> 22) & 0x3ff) + 1;
|
||||
+ case _SC_LEVEL1_ICACHE_LINESIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
+ case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
+ case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
+ return (ebx & 0xfff) + 1;
|
||||
+ case _SC_LEVEL1_ICACHE_SIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_SIZE:
|
||||
+ case _SC_LEVEL2_CACHE_SIZE:
|
||||
+ case _SC_LEVEL3_CACHE_SIZE:
|
||||
+ return (((ebx >> 22) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1);
|
||||
+ default:
|
||||
+ __builtin_unreachable ();
|
||||
+ }
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Legacy cache computation for CPUs prior to Bulldozer family.
|
||||
+ This is also a fail-safe mechanism for some hypervisors that
|
||||
+ accidentally configure __cpuid__ '0x8000_001D' to Zero. */
|
||||
|
||||
- __cpuid_count (0x8000001D, count, eax, ebx, ecx, edx);
|
||||
+ fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
|
||||
+
|
||||
+ if (max_cpuid < fn)
|
||||
+ return 0;
|
||||
+
|
||||
+ __cpuid (fn, eax, ebx, ecx, edx);
|
||||
+
|
||||
+ if (name < _SC_LEVEL1_DCACHE_SIZE)
|
||||
+ {
|
||||
+ name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
|
||||
+ ecx = edx;
|
||||
+ }
|
||||
|
||||
switch (name)
|
||||
{
|
||||
- case _SC_LEVEL1_ICACHE_ASSOC:
|
||||
- case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
- case _SC_LEVEL2_CACHE_ASSOC:
|
||||
+ case _SC_LEVEL1_DCACHE_SIZE:
|
||||
+ return (ecx >> 14) & 0x3fc00;
|
||||
+
|
||||
+ case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
+ ecx >>= 16;
|
||||
+ if ((ecx & 0xff) == 0xff)
|
||||
+ {
|
||||
+ /* Fully associative. */
|
||||
+ return (ecx << 2) & 0x3fc00;
|
||||
+ }
|
||||
+ return ecx & 0xff;
|
||||
+
|
||||
+ case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
+ return ecx & 0xff;
|
||||
+
|
||||
+ case _SC_LEVEL2_CACHE_SIZE:
|
||||
+ return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
|
||||
+
|
||||
+ case _SC_LEVEL2_CACHE_ASSOC:
|
||||
+ switch ((ecx >> 12) & 0xf)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ case 1:
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ return (ecx >> 12) & 0xf;
|
||||
+ case 6:
|
||||
+ return 8;
|
||||
+ case 8:
|
||||
+ return 16;
|
||||
+ case 10:
|
||||
+ return 32;
|
||||
+ case 11:
|
||||
+ return 48;
|
||||
+ case 12:
|
||||
+ return 64;
|
||||
+ case 13:
|
||||
+ return 96;
|
||||
+ case 14:
|
||||
+ return 128;
|
||||
+ case 15:
|
||||
+ return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff);
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
+ return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
|
||||
+
|
||||
+ case _SC_LEVEL3_CACHE_SIZE:
|
||||
+ {
|
||||
+ long int total_l3_cache = 0, l3_cache_per_thread = 0;
|
||||
+ unsigned int threads = 0;
|
||||
+ const struct cpu_features *cpu_features;
|
||||
+
|
||||
+ if ((edx & 0xf000) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ total_l3_cache = (edx & 0x3ffc0000) << 1;
|
||||
+ cpu_features = __get_cpu_features ();
|
||||
+
|
||||
+ /* Figure out the number of logical threads that share L3. */
|
||||
+ if (max_cpuid >= 0x80000008)
|
||||
+ {
|
||||
+ /* Get width of APIC ID. */
|
||||
+ __cpuid (0x80000008, eax, ebx, ecx, edx);
|
||||
+ threads = (ecx & 0xff) + 1;
|
||||
+ }
|
||||
+
|
||||
+ if (threads == 0)
|
||||
+ {
|
||||
+ /* If APIC ID width is not available, use logical
|
||||
+ processor count. */
|
||||
+ __cpuid (0x00000001, eax, ebx, ecx, edx);
|
||||
+ if ((edx & (1 << 28)) != 0)
|
||||
+ threads = (ebx >> 16) & 0xff;
|
||||
+ }
|
||||
+
|
||||
+ /* Cap usage of highest cache level to the number of
|
||||
+ supported threads. */
|
||||
+ if (threads > 0)
|
||||
+ l3_cache_per_thread = total_l3_cache/threads;
|
||||
+
|
||||
+ /* Get shared cache per ccx for Zen architectures. */
|
||||
+ if (cpu_features->basic.family >= 0x17)
|
||||
+ {
|
||||
+ long int l3_cache_per_ccx = 0;
|
||||
+ /* Get number of threads share the L3 cache in CCX. */
|
||||
+ __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx);
|
||||
+ unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1;
|
||||
+ l3_cache_per_ccx = l3_cache_per_thread * threads_per_ccx;
|
||||
+ return l3_cache_per_ccx;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ return l3_cache_per_thread;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
case _SC_LEVEL3_CACHE_ASSOC:
|
||||
- return ecx ? ((ebx >> 22) & 0x3ff) + 1 : 0;
|
||||
- case _SC_LEVEL1_ICACHE_LINESIZE:
|
||||
- case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
- case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
+ switch ((edx >> 12) & 0xf)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ case 1:
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ return (edx >> 12) & 0xf;
|
||||
+ case 6:
|
||||
+ return 8;
|
||||
+ case 8:
|
||||
+ return 16;
|
||||
+ case 10:
|
||||
+ return 32;
|
||||
+ case 11:
|
||||
+ return 48;
|
||||
+ case 12:
|
||||
+ return 64;
|
||||
+ case 13:
|
||||
+ return 96;
|
||||
+ case 14:
|
||||
+ return 128;
|
||||
+ case 15:
|
||||
+ return ((edx & 0x3ffc0000) << 1) / (edx & 0xff);
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
- return ecx ? (ebx & 0xfff) + 1 : 0;
|
||||
- case _SC_LEVEL1_ICACHE_SIZE:
|
||||
- case _SC_LEVEL1_DCACHE_SIZE:
|
||||
- case _SC_LEVEL2_CACHE_SIZE:
|
||||
- case _SC_LEVEL3_CACHE_SIZE:
|
||||
- return ecx ? (((ebx >> 22) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1): 0;
|
||||
+ return (edx & 0xf000) == 0 ? 0 : edx & 0xff;
|
||||
+
|
||||
default:
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
@@ -703,7 +869,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
|
||||
core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
|
||||
shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
|
||||
- shared_per_thread = shared;
|
||||
|
||||
level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
|
||||
level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
@@ -716,13 +881,20 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
level3_cache_size = shared;
|
||||
level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC);
|
||||
level3_cache_linesize = handle_amd (_SC_LEVEL3_CACHE_LINESIZE);
|
||||
+ level4_cache_size = handle_amd (_SC_LEVEL4_CACHE_SIZE);
|
||||
|
||||
if (shared <= 0)
|
||||
- /* No shared L3 cache. All we have is the L2 cache. */
|
||||
- shared = core;
|
||||
+ {
|
||||
+ /* No shared L3 cache. All we have is the L2 cache. */
|
||||
+ shared = core;
|
||||
+ }
|
||||
+ else if (cpu_features->basic.family < 0x17)
|
||||
+ {
|
||||
+ /* Account for exclusive L2 and L3 caches. */
|
||||
+ shared += core;
|
||||
+ }
|
||||
|
||||
- if (shared_per_thread <= 0)
|
||||
- shared_per_thread = shared;
|
||||
+ shared_per_thread = shared;
|
||||
}
|
||||
|
||||
cpu_features->level1_icache_size = level1_icache_size;
|
|
@ -0,0 +1,261 @@
|
|||
commit 103a469dc7755fd9e8ccf362f3dd4c55dc761908
|
||||
Author: Sajan Karumanchi <sajan.karumanchi@amd.com>
|
||||
Date: Wed Jan 18 18:29:04 2023 +0100
|
||||
|
||||
x86: Cache computation for AMD architecture.
|
||||
|
||||
All AMD architectures cache details will be computed based on
|
||||
__cpuid__ `0x8000_001D` and the reference to __cpuid__ `0x8000_0006` will be
|
||||
zeroed out for future architectures.
|
||||
|
||||
Reviewed-by: Premachandra Mallappa <premachandra.mallappa@amd.com>
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index 8f85f70858413ebe..a7d2cc5fef03884b 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -311,117 +311,47 @@ handle_intel (int name, const struct cpu_features *cpu_features)
|
||||
|
||||
|
||||
static long int __attribute__ ((noinline))
|
||||
-handle_amd (int name)
|
||||
+handle_amd (int name, const struct cpu_features *cpu_features)
|
||||
{
|
||||
unsigned int eax;
|
||||
unsigned int ebx;
|
||||
unsigned int ecx;
|
||||
unsigned int edx;
|
||||
- __cpuid (0x80000000, eax, ebx, ecx, edx);
|
||||
+ unsigned int count = 0x1;
|
||||
|
||||
/* No level 4 cache (yet). */
|
||||
if (name > _SC_LEVEL3_CACHE_LINESIZE)
|
||||
return 0;
|
||||
|
||||
- unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
|
||||
- if (eax < fn)
|
||||
- return 0;
|
||||
-
|
||||
- __cpuid (fn, eax, ebx, ecx, edx);
|
||||
+ if (name >= _SC_LEVEL3_CACHE_SIZE)
|
||||
+ count = 0x3;
|
||||
+ else if (name >= _SC_LEVEL2_CACHE_SIZE)
|
||||
+ count = 0x2;
|
||||
+ else if (name >= _SC_LEVEL1_DCACHE_SIZE)
|
||||
+ count = 0x0;
|
||||
|
||||
- if (name < _SC_LEVEL1_DCACHE_SIZE)
|
||||
- {
|
||||
- name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
|
||||
- ecx = edx;
|
||||
- }
|
||||
+ __cpuid_count (0x8000001D, count, eax, ebx, ecx, edx);
|
||||
|
||||
switch (name)
|
||||
{
|
||||
- case _SC_LEVEL1_DCACHE_SIZE:
|
||||
- return (ecx >> 14) & 0x3fc00;
|
||||
-
|
||||
- case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
- ecx >>= 16;
|
||||
- if ((ecx & 0xff) == 0xff)
|
||||
- /* Fully associative. */
|
||||
- return (ecx << 2) & 0x3fc00;
|
||||
- return ecx & 0xff;
|
||||
-
|
||||
- case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
- return ecx & 0xff;
|
||||
-
|
||||
- case _SC_LEVEL2_CACHE_SIZE:
|
||||
- return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
|
||||
-
|
||||
- case _SC_LEVEL2_CACHE_ASSOC:
|
||||
- switch ((ecx >> 12) & 0xf)
|
||||
- {
|
||||
- case 0:
|
||||
- case 1:
|
||||
- case 2:
|
||||
- case 4:
|
||||
- return (ecx >> 12) & 0xf;
|
||||
- case 6:
|
||||
- return 8;
|
||||
- case 8:
|
||||
- return 16;
|
||||
- case 10:
|
||||
- return 32;
|
||||
- case 11:
|
||||
- return 48;
|
||||
- case 12:
|
||||
- return 64;
|
||||
- case 13:
|
||||
- return 96;
|
||||
- case 14:
|
||||
- return 128;
|
||||
- case 15:
|
||||
- return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff);
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
- /* NOTREACHED */
|
||||
-
|
||||
- case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
- return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
|
||||
-
|
||||
- case _SC_LEVEL3_CACHE_SIZE:
|
||||
- return (edx & 0xf000) == 0 ? 0 : (edx & 0x3ffc0000) << 1;
|
||||
-
|
||||
- case _SC_LEVEL3_CACHE_ASSOC:
|
||||
- switch ((edx >> 12) & 0xf)
|
||||
- {
|
||||
- case 0:
|
||||
- case 1:
|
||||
- case 2:
|
||||
- case 4:
|
||||
- return (edx >> 12) & 0xf;
|
||||
- case 6:
|
||||
- return 8;
|
||||
- case 8:
|
||||
- return 16;
|
||||
- case 10:
|
||||
- return 32;
|
||||
- case 11:
|
||||
- return 48;
|
||||
- case 12:
|
||||
- return 64;
|
||||
- case 13:
|
||||
- return 96;
|
||||
- case 14:
|
||||
- return 128;
|
||||
- case 15:
|
||||
- return ((edx & 0x3ffc0000) << 1) / (edx & 0xff);
|
||||
- default:
|
||||
- return 0;
|
||||
- }
|
||||
- /* NOTREACHED */
|
||||
-
|
||||
- case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
- return (edx & 0xf000) == 0 ? 0 : edx & 0xff;
|
||||
-
|
||||
- default:
|
||||
- assert (! "cannot happen");
|
||||
+ case _SC_LEVEL1_ICACHE_ASSOC:
|
||||
+ case _SC_LEVEL1_DCACHE_ASSOC:
|
||||
+ case _SC_LEVEL2_CACHE_ASSOC:
|
||||
+ case _SC_LEVEL3_CACHE_ASSOC:
|
||||
+ return ecx?((ebx >> 22) & 0x3ff) + 1 : 0;
|
||||
+ case _SC_LEVEL1_ICACHE_LINESIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_LINESIZE:
|
||||
+ case _SC_LEVEL2_CACHE_LINESIZE:
|
||||
+ case _SC_LEVEL3_CACHE_LINESIZE:
|
||||
+ return ecx?(ebx & 0xfff) + 1 : 0;
|
||||
+ case _SC_LEVEL1_ICACHE_SIZE:
|
||||
+ case _SC_LEVEL1_DCACHE_SIZE:
|
||||
+ case _SC_LEVEL2_CACHE_SIZE:
|
||||
+ case _SC_LEVEL3_CACHE_SIZE:
|
||||
+ return ecx?(((ebx >> 22) & 0x3ff) + 1)*((ebx & 0xfff) + 1)\
|
||||
+ *(ecx + 1):0;
|
||||
+ default:
|
||||
+ assert (! "cannot happen");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -698,10 +628,6 @@ static void
|
||||
dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
{
|
||||
/* Find out what brand of processor. */
|
||||
- unsigned int ebx;
|
||||
- unsigned int ecx;
|
||||
- unsigned int edx;
|
||||
- int max_cpuid_ex;
|
||||
long int data = -1;
|
||||
long int shared = -1;
|
||||
long int core = -1;
|
||||
@@ -771,70 +697,30 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
}
|
||||
else if (cpu_features->basic.kind == arch_kind_amd)
|
||||
{
|
||||
- data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
|
||||
- core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
|
||||
- shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
|
||||
+ data = handle_amd (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
|
||||
+ core = handle_amd (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||
+ shared = handle_amd (_SC_LEVEL3_CACHE_SIZE, cpu_features);
|
||||
|
||||
- level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
|
||||
- level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
+ level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
|
||||
+ level1_icache_linesize
|
||||
+ = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);
|
||||
level1_dcache_size = data;
|
||||
- level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
|
||||
- level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
|
||||
+ level1_dcache_assoc
|
||||
+ = handle_amd (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
|
||||
+ level1_dcache_linesize
|
||||
+ = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
|
||||
level2_cache_size = core;
|
||||
- level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
|
||||
- level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
|
||||
+ level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
|
||||
+ level2_cache_linesize
|
||||
+ = handle_amd (_SC_LEVEL2_CACHE_LINESIZE, cpu_features);
|
||||
level3_cache_size = shared;
|
||||
- level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC);
|
||||
- level3_cache_linesize = handle_amd (_SC_LEVEL3_CACHE_LINESIZE);
|
||||
-
|
||||
- /* Get maximum extended function. */
|
||||
- __cpuid (0x80000000, max_cpuid_ex, ebx, ecx, edx);
|
||||
+ level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC, cpu_features);
|
||||
+ level3_cache_linesize
|
||||
+ = handle_amd (_SC_LEVEL3_CACHE_LINESIZE, cpu_features);
|
||||
|
||||
if (shared <= 0)
|
||||
- /* No shared L3 cache. All we have is the L2 cache. */
|
||||
- shared = core;
|
||||
- else
|
||||
- {
|
||||
- /* Figure out the number of logical threads that share L3. */
|
||||
- if (max_cpuid_ex >= 0x80000008)
|
||||
- {
|
||||
- /* Get width of APIC ID. */
|
||||
- __cpuid (0x80000008, max_cpuid_ex, ebx, ecx, edx);
|
||||
- threads = 1 << ((ecx >> 12) & 0x0f);
|
||||
- }
|
||||
-
|
||||
- if (threads == 0 || cpu_features->basic.family >= 0x17)
|
||||
- {
|
||||
- /* If APIC ID width is not available, use logical
|
||||
- processor count. */
|
||||
- __cpuid (0x00000001, max_cpuid_ex, ebx, ecx, edx);
|
||||
-
|
||||
- if ((edx & (1 << 28)) != 0)
|
||||
- threads = (ebx >> 16) & 0xff;
|
||||
- }
|
||||
-
|
||||
- /* Cap usage of highest cache level to the number of
|
||||
- supported threads. */
|
||||
- if (threads > 0)
|
||||
- shared /= threads;
|
||||
-
|
||||
- /* Get shared cache per ccx for Zen architectures. */
|
||||
- if (cpu_features->basic.family >= 0x17)
|
||||
- {
|
||||
- unsigned int eax;
|
||||
-
|
||||
- /* Get number of threads share the L3 cache in CCX. */
|
||||
- __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx);
|
||||
-
|
||||
- unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1;
|
||||
- shared *= threads_per_ccx;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- /* Account for exclusive L2 and L3 caches. */
|
||||
- shared += core;
|
||||
- }
|
||||
- }
|
||||
+ /* No shared L3 cache. All we have is the L2 cache. */
|
||||
+ shared = core;
|
||||
}
|
||||
|
||||
cpu_features->level1_icache_size = level1_icache_size;
|
|
@ -0,0 +1,200 @@
|
|||
glibc-rh2169978-2.patch already changes _rtld_global_ro@GLIBC_PRIVATE
|
||||
layout, so we can include this change alongside it. This will allow us
|
||||
to include new hwcaps and platform names without changing internal ABI.
|
||||
|
||||
commit 5ecc98241229d494aaad23a4a3fe106fe11e1f40
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Aug 25 16:34:20 2022 +0200
|
||||
|
||||
s390: Move hwcaps/platform names out of _rtld_global_ro
|
||||
|
||||
Changes to these arrays are often backported to stable releases,
|
||||
but additions to these arrays shift the offsets of the following
|
||||
_rltd_global_ro members, thus breaking the GLIBC_PRIVATE ABI.
|
||||
|
||||
Obviously, this change is itself an internal ABI break, but at least
|
||||
it will avoid further ABI breaks going forward.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
|
||||
index ade8663218c30ab2..80e88557c9924ff0 100644
|
||||
--- a/sysdeps/s390/Makefile
|
||||
+++ b/sysdeps/s390/Makefile
|
||||
@@ -43,6 +43,8 @@ $(modpfx)gconv-modules-s390.conf: ../sysdeps/s390/gconv-modules-s390.conf \
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),elf)
|
||||
+sysdep-dl-routines += dl-procinfo-s390
|
||||
+
|
||||
ifeq ($(build-shared),yes)
|
||||
tests += tst-dl-runtime-resolve-noaudit tst-dl-runtime-resolve-audit \
|
||||
tst-dl-runtime-profile-noaudit
|
||||
diff --git a/sysdeps/s390/dl-procinfo-s390.c b/sysdeps/s390/dl-procinfo-s390.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..559f3827936cd017
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/dl-procinfo-s390.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Data for s390 version of processor capability information.
|
||||
+ Copyright (C) 2006-2022 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <dl-procinfo.h>
|
||||
+
|
||||
+const char _dl_s390_cap_flags[_DL_HWCAP_COUNT][9] =
|
||||
+ {
|
||||
+ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh",
|
||||
+ "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt",
|
||||
+ "vxp2", "nnpa", "pcimio", "sie"
|
||||
+ };
|
||||
+
|
||||
+const char _dl_s390_platforms[_DL_PLATFORMS_COUNT][7] =
|
||||
+ {
|
||||
+ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15",
|
||||
+ "z16"
|
||||
+ };
|
||||
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
|
||||
index 755b54ff13a0fa2f..e63ac00382501e00 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.c
|
||||
+++ b/sysdeps/s390/dl-procinfo.c
|
||||
@@ -17,66 +17,10 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
-/* This information must be kept in sync with the _DL_HWCAP_COUNT and
|
||||
- _DL_PLATFORM_COUNT definitions in procinfo.h.
|
||||
-
|
||||
- If anything should be added here check whether the size of each string
|
||||
- is still ok with the given array size.
|
||||
-
|
||||
- All the #ifdefs in the definitions are quite irritating but
|
||||
- necessary if we want to avoid duplicating the information. There
|
||||
- are three different modes:
|
||||
-
|
||||
- - PROCINFO_DECL is defined. This means we are only interested in
|
||||
- declarations.
|
||||
-
|
||||
- - PROCINFO_DECL is not defined:
|
||||
-
|
||||
- + if SHARED is defined the file is included in an array
|
||||
- initializer. The .element = { ... } syntax is needed.
|
||||
-
|
||||
- + if SHARED is not defined a normal array initialization is
|
||||
- needed.
|
||||
- */
|
||||
-
|
||||
-#ifndef PROCINFO_CLASS
|
||||
-# define PROCINFO_CLASS
|
||||
-#endif
|
||||
-
|
||||
-#if !defined PROCINFO_DECL && defined SHARED
|
||||
- ._dl_s390_cap_flags
|
||||
-#else
|
||||
-PROCINFO_CLASS const char _dl_s390_cap_flags[23][9]
|
||||
-#endif
|
||||
-#ifndef PROCINFO_DECL
|
||||
-= {
|
||||
- "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh",
|
||||
- "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt",
|
||||
- "vxp2", "nnpa", "pcimio", "sie"
|
||||
- }
|
||||
-#endif
|
||||
-#if !defined SHARED || defined PROCINFO_DECL
|
||||
-;
|
||||
-#else
|
||||
-,
|
||||
-#endif
|
||||
-
|
||||
-#if !defined PROCINFO_DECL && defined SHARED
|
||||
- ._dl_s390_platforms
|
||||
-#else
|
||||
-PROCINFO_CLASS const char _dl_s390_platforms[11][7]
|
||||
-#endif
|
||||
-#ifndef PROCINFO_DECL
|
||||
-= {
|
||||
- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15",
|
||||
- "z16"
|
||||
- }
|
||||
-#endif
|
||||
-#if !defined SHARED || defined PROCINFO_DECL
|
||||
-;
|
||||
-#else
|
||||
-,
|
||||
-#endif
|
||||
+/* The hwcap and platform strings are now in
|
||||
+ sysdeps/s390/dl-procinfo-s390.c. */
|
||||
|
||||
+/* Needed by sysdeps/unix/sysv/linux/dl-vdso-setup.c (as included from
|
||||
+ sysdeps/generic/ldsodefs.h). */
|
||||
#undef PROCINFO_DECL
|
||||
#undef PROCINFO_CLASS
|
||||
diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
|
||||
index d44e1dd97441bd90..eb782fc3014cd012 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.h
|
||||
+++ b/sysdeps/s390/dl-procinfo.h
|
||||
@@ -22,8 +22,10 @@
|
||||
#include <ldsodefs.h>
|
||||
|
||||
#define _DL_HWCAP_COUNT 23
|
||||
+extern const char _dl_s390_cap_flags[_DL_HWCAP_COUNT][9] attribute_hidden;
|
||||
|
||||
#define _DL_PLATFORMS_COUNT 11
|
||||
+extern const char _dl_s390_platforms[_DL_PLATFORMS_COUNT][7] attribute_hidden;
|
||||
|
||||
/* The kernel provides up to 32 capability bits with elf_hwcap. */
|
||||
#define _DL_FIRST_PLATFORM 32
|
||||
@@ -79,7 +81,7 @@ static inline const char *
|
||||
__attribute__ ((unused))
|
||||
_dl_hwcap_string (int idx)
|
||||
{
|
||||
- return GLRO(dl_s390_cap_flags)[idx];
|
||||
+ return _dl_s390_cap_flags[idx];
|
||||
};
|
||||
|
||||
static inline int
|
||||
@@ -90,7 +92,7 @@ _dl_string_hwcap (const char *str)
|
||||
|
||||
for (i = 0; i < _DL_HWCAP_COUNT; i++)
|
||||
{
|
||||
- if (strcmp (str, GLRO(dl_s390_cap_flags)[i]) == 0)
|
||||
+ if (strcmp (str, _dl_s390_cap_flags[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
@@ -105,7 +107,7 @@ _dl_string_platform (const char *str)
|
||||
if (str != NULL)
|
||||
for (i = 0; i < _DL_PLATFORMS_COUNT; ++i)
|
||||
{
|
||||
- if (strcmp (str, GLRO(dl_s390_platforms)[i]) == 0)
|
||||
+ if (strcmp (str, _dl_s390_platforms[i]) == 0)
|
||||
return _DL_FIRST_PLATFORM + i;
|
||||
}
|
||||
return -1;
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
|
||||
index 76ce33e31d3a280d..c99870b2e18b9e9e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
|
||||
@@ -40,7 +40,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
|
||||
|
||||
for (i = 0; i < _DL_HWCAP_COUNT; ++i)
|
||||
if (word & (1UL << i))
|
||||
- _dl_printf (" %s", GLRO(dl_s390_cap_flags)[i]);
|
||||
+ _dl_printf (" %s", _dl_s390_cap_flags[i]);
|
||||
|
||||
_dl_printf ("\n");
|
||||
|
|
@ -0,0 +1,683 @@
|
|||
Backported with an additional line in
|
||||
sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list in order to
|
||||
maintain tunable ordering, which happens to be ABI.
|
||||
|
||||
commit 41f67ccbe92b4fd09e1062b383e55e407ae5bfa1
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Thu Feb 2 14:57:50 2023 +0100
|
||||
|
||||
S390: Influence hwcaps/stfle via GLIBC_TUNABLES.
|
||||
|
||||
This patch enables the option to influence hwcaps and stfle bits used
|
||||
by the s390 specific ifunc-resolvers. The currently x86-specific
|
||||
tunable glibc.cpu.hwcaps is also used on s390x to achieve the task. In
|
||||
addition the user can also set a CPU arch-level like z13 instead of
|
||||
single HWCAP and STFLE features.
|
||||
|
||||
Note that the tunable only handles the features which are really used
|
||||
in the IFUNC-resolvers. All others are ignored as the values are only
|
||||
used inside glibc. Thus we can influence:
|
||||
- HWCAP_S390_VXRS (z13)
|
||||
- HWCAP_S390_VXRS_EXT (z14)
|
||||
- HWCAP_S390_VXRS_EXT2 (z15)
|
||||
- STFLE_MIE3 (z15)
|
||||
|
||||
The influenced hwcap/stfle-bits are stored in the s390-specific
|
||||
cpu_features struct which also contains reserved fields for future
|
||||
usage.
|
||||
|
||||
The ifunc-resolvers and users of stfle bits are adjusted to use the
|
||||
information from cpu_features struct.
|
||||
|
||||
On 31bit, the ELF_MACHINE_IRELATIVE macro is now also defined.
|
||||
Otherwise the new ifunc-resolvers segfaults as they depend on
|
||||
the not yet processed_rtld_global_ro@GLIBC_PRIVATE relocation.
|
||||
|
||||
diff --git a/manual/tunables.texi b/manual/tunables.texi
|
||||
index 5ab3212f34e3dc37..561e0df230646de1 100644
|
||||
--- a/manual/tunables.texi
|
||||
+++ b/manual/tunables.texi
|
||||
@@ -469,7 +469,11 @@ enable CPU/ARCH feature @code{yyy}, disable CPU/ARCH feature @code{xxx}
|
||||
and @code{zzz} where the feature name is case-sensitive and has to match
|
||||
the ones in @code{sysdeps/x86/cpu-features.h}.
|
||||
|
||||
-This tunable is specific to i386 and x86-64.
|
||||
+On s390x, the supported HWCAP and STFLE features can be found in
|
||||
+@code{sysdeps/s390/cpu-features.c}. In addition the user can also set
|
||||
+a CPU arch-level like @code{z13} instead of single HWCAP and STFLE features.
|
||||
+
|
||||
+This tunable is specific to i386, x86-64 and s390x.
|
||||
@end deftp
|
||||
|
||||
@deftp Tunable glibc.cpu.cached_memopt
|
||||
diff --git a/sysdeps/s390/cpu-features.c b/sysdeps/s390/cpu-features.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..afeb9b56382efa96
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/cpu-features.c
|
||||
@@ -0,0 +1,239 @@
|
||||
+/* Initialize cpu feature data. s390x version.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <cpu-features.h>
|
||||
+
|
||||
+#if HAVE_TUNABLES
|
||||
+# include <elf/dl-tunables.h>
|
||||
+# include <ifunc-memcmp.h>
|
||||
+# include <string.h>
|
||||
+extern __typeof (memcmp) MEMCMP_DEFAULT;
|
||||
+#endif
|
||||
+
|
||||
+#if HAVE_TUNABLES
|
||||
+# define S390_COPY_CPU_FEATURES(SRC_PTR, DEST_PTR) \
|
||||
+ (DEST_PTR)->hwcap = (SRC_PTR)->hwcap; \
|
||||
+ (DEST_PTR)->stfle_bits[0] = (SRC_PTR)->stfle_bits[0];
|
||||
+
|
||||
+static void
|
||||
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
|
||||
+{
|
||||
+ /* The current IFUNC selection is always using the most recent
|
||||
+ features which are available via AT_HWCAP or STFLE-bits. But in
|
||||
+ some scenarios it is useful to adjust this selection.
|
||||
+
|
||||
+ The environment variable:
|
||||
+
|
||||
+ GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,zzz,....
|
||||
+
|
||||
+ can be used to enable HWCAP/STFLE feature yyy, disable HWCAP/STFLE feature
|
||||
+ xxx, where the feature name is case-sensitive and has to match the ones
|
||||
+ used below. Furthermore, the ARCH-level zzz can be used to set various
|
||||
+ HWCAP/STFLE features at once. */
|
||||
+
|
||||
+ /* Copy the features from dl_s390_cpu_features, which contains the features
|
||||
+ provided by AT_HWCAP and stfle-instruction. */
|
||||
+ struct cpu_features *cpu_features = &GLRO(dl_s390_cpu_features);
|
||||
+ struct cpu_features cpu_features_orig;
|
||||
+ S390_COPY_CPU_FEATURES (cpu_features, &cpu_features_orig);
|
||||
+ struct cpu_features cpu_features_curr;
|
||||
+ S390_COPY_CPU_FEATURES (cpu_features, &cpu_features_curr);
|
||||
+
|
||||
+ const char *token = valp->strval;
|
||||
+ do
|
||||
+ {
|
||||
+ const char *token_end, *feature;
|
||||
+ bool disable;
|
||||
+ size_t token_len;
|
||||
+ size_t feature_len;
|
||||
+
|
||||
+ /* Find token separator or end of string. */
|
||||
+ for (token_end = token; *token_end != ','; token_end++)
|
||||
+ if (*token_end == '\0')
|
||||
+ break;
|
||||
+
|
||||
+ /* Determine feature. */
|
||||
+ token_len = token_end - token;
|
||||
+ if (*token == '-')
|
||||
+ {
|
||||
+ disable = true;
|
||||
+ feature = token + 1;
|
||||
+ feature_len = token_len - 1;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ disable = false;
|
||||
+ feature = token;
|
||||
+ feature_len = token_len;
|
||||
+ }
|
||||
+
|
||||
+ /* Handle only the features here which are really used in the
|
||||
+ IFUNC-resolvers. All others are ignored as the values are only used
|
||||
+ inside glibc. */
|
||||
+ bool reset_features = false;
|
||||
+ unsigned long int hwcap_mask = 0UL;
|
||||
+ unsigned long long stfle_bits0_mask = 0ULL;
|
||||
+
|
||||
+ if ((*feature == 'z' || *feature == 'a'))
|
||||
+ {
|
||||
+ if ((feature_len == 5 && *feature == 'z'
|
||||
+ && MEMCMP_DEFAULT (feature, "zEC12", 5) == 0)
|
||||
+ || (feature_len == 6 && *feature == 'a'
|
||||
+ && MEMCMP_DEFAULT (feature, "arch10", 6) == 0))
|
||||
+ {
|
||||
+ reset_features = true;
|
||||
+ disable = true;
|
||||
+ hwcap_mask = HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT
|
||||
+ | HWCAP_S390_VXRS_EXT2;
|
||||
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
|
||||
+ }
|
||||
+ else if ((feature_len == 3 && *feature == 'z'
|
||||
+ && MEMCMP_DEFAULT (feature, "z13", 3) == 0)
|
||||
+ || (feature_len == 6 && *feature == 'a'
|
||||
+ && MEMCMP_DEFAULT (feature, "arch11", 6) == 0))
|
||||
+ {
|
||||
+ reset_features = true;
|
||||
+ disable = true;
|
||||
+ hwcap_mask = HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
|
||||
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
|
||||
+ }
|
||||
+ else if ((feature_len == 3 && *feature == 'z'
|
||||
+ && MEMCMP_DEFAULT (feature, "z14", 3) == 0)
|
||||
+ || (feature_len == 6 && *feature == 'a'
|
||||
+ && MEMCMP_DEFAULT (feature, "arch12", 6) == 0))
|
||||
+ {
|
||||
+ reset_features = true;
|
||||
+ disable = true;
|
||||
+ hwcap_mask = HWCAP_S390_VXRS_EXT2;
|
||||
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
|
||||
+ }
|
||||
+ else if ((feature_len == 3 && *feature == 'z'
|
||||
+ && (MEMCMP_DEFAULT (feature, "z15", 3) == 0
|
||||
+ || MEMCMP_DEFAULT (feature, "z16", 3) == 0))
|
||||
+ || (feature_len == 6
|
||||
+ && (MEMCMP_DEFAULT (feature, "arch13", 6) == 0
|
||||
+ || MEMCMP_DEFAULT (feature, "arch14", 6) == 0)))
|
||||
+ {
|
||||
+ /* For z15 or newer we don't have to disable something,
|
||||
+ but we have to reset to the original values. */
|
||||
+ reset_features = true;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (*feature == 'H')
|
||||
+ {
|
||||
+ if (feature_len == 15
|
||||
+ && MEMCMP_DEFAULT (feature, "HWCAP_S390_VXRS", 15) == 0)
|
||||
+ {
|
||||
+ hwcap_mask = HWCAP_S390_VXRS;
|
||||
+ if (disable)
|
||||
+ hwcap_mask |= HWCAP_S390_VXRS_EXT | HWCAP_S390_VXRS_EXT2;
|
||||
+ }
|
||||
+ else if (feature_len == 19
|
||||
+ && MEMCMP_DEFAULT (feature, "HWCAP_S390_VXRS_EXT", 19) == 0)
|
||||
+ {
|
||||
+ hwcap_mask = HWCAP_S390_VXRS_EXT;
|
||||
+ if (disable)
|
||||
+ hwcap_mask |= HWCAP_S390_VXRS_EXT2;
|
||||
+ else
|
||||
+ hwcap_mask |= HWCAP_S390_VXRS;
|
||||
+ }
|
||||
+ else if (feature_len == 20
|
||||
+ && MEMCMP_DEFAULT (feature, "HWCAP_S390_VXRS_EXT2", 20) == 0)
|
||||
+ {
|
||||
+ hwcap_mask = HWCAP_S390_VXRS_EXT2;
|
||||
+ if (!disable)
|
||||
+ hwcap_mask |= HWCAP_S390_VXRS | HWCAP_S390_VXRS_EXT;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (*feature == 'S')
|
||||
+ {
|
||||
+ if (feature_len == 10
|
||||
+ && MEMCMP_DEFAULT (feature, "STFLE_MIE3", 10) == 0)
|
||||
+ {
|
||||
+ stfle_bits0_mask = S390_STFLE_MASK_ARCH13_MIE3;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Perform the actions determined above. */
|
||||
+ if (reset_features)
|
||||
+ {
|
||||
+ S390_COPY_CPU_FEATURES (&cpu_features_orig, &cpu_features_curr);
|
||||
+ }
|
||||
+
|
||||
+ if (hwcap_mask != 0UL)
|
||||
+ {
|
||||
+ if (disable)
|
||||
+ cpu_features_curr.hwcap &= ~hwcap_mask;
|
||||
+ else
|
||||
+ cpu_features_curr.hwcap |= hwcap_mask;
|
||||
+ }
|
||||
+
|
||||
+ if (stfle_bits0_mask != 0ULL)
|
||||
+ {
|
||||
+ if (disable)
|
||||
+ cpu_features_curr.stfle_bits[0] &= ~stfle_bits0_mask;
|
||||
+ else
|
||||
+ cpu_features_curr.stfle_bits[0] |= stfle_bits0_mask;
|
||||
+ }
|
||||
+
|
||||
+ /* Jump over current token ... */
|
||||
+ token += token_len;
|
||||
+
|
||||
+ /* ... and skip token separator for next round. */
|
||||
+ if (*token == ',') token++;
|
||||
+ }
|
||||
+ while (*token != '\0');
|
||||
+
|
||||
+ /* Copy back the features after checking that no unsupported features were
|
||||
+ enabled by user. */
|
||||
+ cpu_features->hwcap = cpu_features_curr.hwcap & cpu_features_orig.hwcap;
|
||||
+ cpu_features->stfle_bits[0] = cpu_features_curr.stfle_bits[0]
|
||||
+ & cpu_features_orig.stfle_bits[0];
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static inline void
|
||||
+init_cpu_features (struct cpu_features *cpu_features)
|
||||
+{
|
||||
+ /* Fill cpu_features as passed by kernel and machine. */
|
||||
+ cpu_features->hwcap = GLRO(dl_hwcap);
|
||||
+
|
||||
+ /* We want just 1 double word to be returned. */
|
||||
+ if (__glibc_likely ((cpu_features->hwcap & HWCAP_S390_STFLE)
|
||||
+ && (cpu_features->hwcap & HWCAP_S390_ZARCH)
|
||||
+ && (cpu_features->hwcap & HWCAP_S390_HIGH_GPRS)))
|
||||
+ {
|
||||
+ register unsigned long reg0 __asm__("0") = 0;
|
||||
+ __asm__ __volatile__(".machine push" "\n\t"
|
||||
+ ".machine \"z9-109\"" "\n\t"
|
||||
+ ".machinemode \"zarch_nohighgprs\"\n\t"
|
||||
+ "stfle %0" "\n\t"
|
||||
+ ".machine pop" "\n"
|
||||
+ : "=QS" (cpu_features->stfle_bits[0]),
|
||||
+ "+d" (reg0)
|
||||
+ : : "cc");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ cpu_features->stfle_bits[0] = 0ULL;
|
||||
+ }
|
||||
+
|
||||
+#if HAVE_TUNABLES
|
||||
+ TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
|
||||
+#endif
|
||||
+}
|
||||
diff --git a/sysdeps/s390/cpu-features.h b/sysdeps/s390/cpu-features.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..5e6b58f7c5bb07e4
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/cpu-features.h
|
||||
@@ -0,0 +1,46 @@
|
||||
+/* Initialize cpu feature data. s390x version.
|
||||
+ Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+
|
||||
+ 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef __CPU_FEATURES_S390X_H
|
||||
+# define __CPU_FEATURES_S390X_H
|
||||
+
|
||||
+#define S390_STFLE_BITS_Z10 34 /* General instructions extension */
|
||||
+#define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
|
||||
+#define S390_STFLE_BITS_ARCH13_MIE3 61 /* Miscellaneous-Instruction-Extensions
|
||||
+ Facility 3, e.g. mvcrl. */
|
||||
+
|
||||
+#define S390_STFLE_MASK_ARCH13_MIE3 (1ULL << (63 - S390_STFLE_BITS_ARCH13_MIE3))
|
||||
+
|
||||
+
|
||||
+#define S390_IS_ARCH13_MIE3(STFLE_BITS_ARRAY) \
|
||||
+ (((STFLE_BITS_ARRAY)[0] & S390_STFLE_MASK_ARCH13_MIE3) != 0)
|
||||
+
|
||||
+#define S390_IS_Z196(STFLE_BITS_ARRAY) \
|
||||
+ (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0)
|
||||
+
|
||||
+#define S390_IS_Z10(STFLE_BITS_ARRAY) \
|
||||
+ (((STFLE_BITS_ARRAY)[0] & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0)
|
||||
+
|
||||
+struct cpu_features
|
||||
+{
|
||||
+ unsigned long int hwcap;
|
||||
+ unsigned long int __reserved_hwcap2;
|
||||
+ unsigned long long stfle_bits[3];
|
||||
+ unsigned long long __reserved[11];
|
||||
+};
|
||||
+
|
||||
+#endif /* __CPU_FEATURES_S390X_H */
|
||||
diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
|
||||
index e63ac00382501e00..7f03aaba3f500034 100644
|
||||
--- a/sysdeps/s390/dl-procinfo.c
|
||||
+++ b/sysdeps/s390/dl-procinfo.c
|
||||
@@ -22,5 +22,42 @@
|
||||
|
||||
/* Needed by sysdeps/unix/sysv/linux/dl-vdso-setup.c (as included from
|
||||
sysdeps/generic/ldsodefs.h). */
|
||||
+
|
||||
+/* All the #ifdefs in the definitions are quite irritating but
|
||||
+ necessary if we want to avoid duplicating the information. There
|
||||
+ are three different modes:
|
||||
+
|
||||
+ - PROCINFO_DECL is defined. This means we are only interested in
|
||||
+ declarations.
|
||||
+
|
||||
+ - PROCINFO_DECL is not defined:
|
||||
+
|
||||
+ + if SHARED is defined the file is included in an array
|
||||
+ initializer. The .element = { ... } syntax is needed.
|
||||
+
|
||||
+ + if SHARED is not defined a normal array initialization is
|
||||
+ needed.
|
||||
+ */
|
||||
+
|
||||
+#ifndef PROCINFO_CLASS
|
||||
+# define PROCINFO_CLASS
|
||||
+#endif
|
||||
+
|
||||
+#if !IS_IN (ldconfig)
|
||||
+# if !defined PROCINFO_DECL && defined SHARED
|
||||
+ ._dl_s390_cpu_features
|
||||
+# else
|
||||
+PROCINFO_CLASS struct cpu_features _dl_s390_cpu_features
|
||||
+# endif
|
||||
+# ifndef PROCINFO_DECL
|
||||
+= { }
|
||||
+# endif
|
||||
+# if !defined SHARED || defined PROCINFO_DECL
|
||||
+;
|
||||
+# else
|
||||
+,
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
#undef PROCINFO_DECL
|
||||
#undef PROCINFO_CLASS
|
||||
diff --git a/sysdeps/s390/dl-tunables.list b/sysdeps/s390/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..7a09828c48a368ef
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/dl-tunables.list
|
||||
@@ -0,0 +1,25 @@
|
||||
+# s390 specific tunables.
|
||||
+# Copyright (C) 2023 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
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+glibc {
|
||||
+ cpu {
|
||||
+ hwcaps {
|
||||
+ type: STRING
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/sysdeps/s390/ldsodefs.h b/sysdeps/s390/ldsodefs.h
|
||||
index 61549d4069289b9f..acf6a98b21c7e077 100644
|
||||
--- a/sysdeps/s390/ldsodefs.h
|
||||
+++ b/sysdeps/s390/ldsodefs.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#define _S390_LDSODEFS_H 1
|
||||
|
||||
#include <elf.h>
|
||||
+#include <cpu-features.h>
|
||||
|
||||
struct La_s390_32_regs;
|
||||
struct La_s390_32_retval;
|
||||
diff --git a/sysdeps/s390/libc-start.c b/sysdeps/s390/libc-start.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..eb35d6679fb7d62c
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/s390/libc-start.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/* Override csu/libc-start.c on s390x.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#ifndef SHARED
|
||||
+
|
||||
+/* Mark symbols hidden in static PIE for early self relocation to work. */
|
||||
+# if BUILD_PIE_DEFAULT
|
||||
+# pragma GCC visibility push(hidden)
|
||||
+# endif
|
||||
+# include <ldsodefs.h>
|
||||
+# include <cpu-features.c>
|
||||
+
|
||||
+extern struct cpu_features _dl_s390_cpu_features;
|
||||
+
|
||||
+# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_s390_cpu_features)
|
||||
+
|
||||
+#endif
|
||||
+#include <csu/libc-start.c>
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
index 2ef38b72ddac7c18..af2c75f5df7c7e1d 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-impl-list.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
+#include <cpu-features.h>
|
||||
#include <ifunc-impl-list.h>
|
||||
#include <ifunc-resolve.h>
|
||||
#include <ifunc-memset.h>
|
||||
@@ -81,14 +82,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
size_t i = 0;
|
||||
|
||||
/* Get hardware information. */
|
||||
- unsigned long int dl_hwcap = GLRO (dl_hwcap);
|
||||
- unsigned long long stfle_bits = 0ULL;
|
||||
- if ((dl_hwcap & HWCAP_S390_STFLE)
|
||||
- && (dl_hwcap & HWCAP_S390_ZARCH)
|
||||
- && (dl_hwcap & HWCAP_S390_HIGH_GPRS))
|
||||
- {
|
||||
- S390_STORE_STFLE (stfle_bits);
|
||||
- }
|
||||
+ const struct cpu_features *features = &GLRO(dl_s390_cpu_features);
|
||||
+ unsigned long int dl_hwcap = features->hwcap;
|
||||
+ const unsigned long long * __attribute__((unused)) stfle_bits
|
||||
+ = features->stfle_bits;
|
||||
|
||||
#if HAVE_MEMSET_IFUNC
|
||||
IFUNC_IMPL (i, name, memset,
|
||||
diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
index 4e50f2b22582fee8..c22d59d2a341fff7 100644
|
||||
--- a/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
+++ b/sysdeps/s390/multiarch/ifunc-resolve.h
|
||||
@@ -19,42 +19,17 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dl-procinfo.h>
|
||||
+#include <cpu-features.h>
|
||||
|
||||
-#define S390_STFLE_BITS_Z10 34 /* General instructions extension */
|
||||
-#define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */
|
||||
-#define S390_STFLE_BITS_ARCH13_MIE3 61 /* Miscellaneous-Instruction-Extensions
|
||||
- Facility 3, e.g. mvcrl. */
|
||||
-
|
||||
-#define S390_IS_ARCH13_MIE3(STFLE_BITS) \
|
||||
- ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_ARCH13_MIE3))) != 0)
|
||||
-
|
||||
-#define S390_IS_Z196(STFLE_BITS) \
|
||||
- ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0)
|
||||
-
|
||||
-#define S390_IS_Z10(STFLE_BITS) \
|
||||
- ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z10))) != 0)
|
||||
-
|
||||
-#define S390_STORE_STFLE(STFLE_BITS) \
|
||||
- /* We want just 1 double word to be returned. */ \
|
||||
- register unsigned long reg0 __asm__("0") = 0; \
|
||||
- \
|
||||
- __asm__ __volatile__(".machine push" "\n\t" \
|
||||
- ".machine \"z9-109\"" "\n\t" \
|
||||
- ".machinemode \"zarch_nohighgprs\"\n\t" \
|
||||
- "stfle %0" "\n\t" \
|
||||
- ".machine pop" "\n" \
|
||||
- : "=QS" (STFLE_BITS), "+d" (reg0) \
|
||||
- : : "cc");
|
||||
#define s390_libc_ifunc_expr_stfle_init() \
|
||||
- unsigned long long stfle_bits = 0ULL; \
|
||||
- if (__glibc_likely ((hwcap & HWCAP_S390_STFLE) \
|
||||
- && (hwcap & HWCAP_S390_ZARCH) \
|
||||
- && (hwcap & HWCAP_S390_HIGH_GPRS))) \
|
||||
- { \
|
||||
- S390_STORE_STFLE (stfle_bits); \
|
||||
- }
|
||||
+ const unsigned long long *stfle_bits = features->stfle_bits;
|
||||
+
|
||||
+#define s390_libc_ifunc_expr_init() \
|
||||
+ const struct cpu_features *features = &GLRO(dl_s390_cpu_features); \
|
||||
+ /* The hwcap from kernel is passed as argument, but we \
|
||||
+ explicitly use the hwcaps from cpu-features struct. */ \
|
||||
+ hwcap = features->hwcap;
|
||||
|
||||
-#define s390_libc_ifunc_expr_init()
|
||||
#define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \
|
||||
__ifunc (TYPE_FUNC, FUNC, EXPR, unsigned long int hwcap, \
|
||||
s390_libc_ifunc_expr_init);
|
||||
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
|
||||
index ba681d1eac7bda53..34e5bcb8d7f18694 100644
|
||||
--- a/sysdeps/s390/s390-32/dl-machine.h
|
||||
+++ b/sysdeps/s390/s390-32/dl-machine.h
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <dl-irel.h>
|
||||
#include <dl-static-tls.h>
|
||||
#include <dl-machine-rel.h>
|
||||
+#include <cpu-features.c>
|
||||
+
|
||||
+#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE
|
||||
|
||||
/* This is an older, now obsolete value. */
|
||||
#define EM_S390_OLD 0xA390
|
||||
@@ -289,6 +292,12 @@ dl_platform_init (void)
|
||||
if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
|
||||
/* Avoid an empty string which would disturb us. */
|
||||
GLRO(dl_platform) = NULL;
|
||||
+
|
||||
+#ifdef SHARED
|
||||
+ /* init_cpu_features has been called early from __libc_start_main in
|
||||
+ static executable. */
|
||||
+ init_cpu_features (&GLRO(dl_s390_cpu_features));
|
||||
+#endif
|
||||
}
|
||||
|
||||
static inline Elf32_Addr
|
||||
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
|
||||
index af2cffd9f904274e..e308937ca9ca54cf 100644
|
||||
--- a/sysdeps/s390/s390-64/dl-machine.h
|
||||
+++ b/sysdeps/s390/s390-64/dl-machine.h
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <dl-irel.h>
|
||||
#include <dl-static-tls.h>
|
||||
#include <dl-machine-rel.h>
|
||||
+#include <cpu-features.c>
|
||||
|
||||
#define ELF_MACHINE_IRELATIVE R_390_IRELATIVE
|
||||
|
||||
@@ -237,6 +238,13 @@ dl_platform_init (void)
|
||||
if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
|
||||
/* Avoid an empty string which would disturb us. */
|
||||
GLRO(dl_platform) = NULL;
|
||||
+
|
||||
+#ifdef SHARED
|
||||
+ /* init_cpu_features has been called early from __libc_start_main in
|
||||
+ static executable. */
|
||||
+ init_cpu_features (&GLRO(dl_s390_cpu_features));
|
||||
+#endif
|
||||
+
|
||||
}
|
||||
|
||||
static inline Elf64_Addr
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
index c3bc83f33910af22..3dd7e891c5e37b1a 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
@@ -25,3 +25,4 @@
|
||||
@order glibc.rtld.optional_static_tls
|
||||
@order glibc.malloc.tcache_max
|
||||
@order glibc.malloc.check
|
||||
+@order glibc.cpu.hwcaps
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/sysconf.c b/sysdeps/unix/sysv/linux/s390/sysconf.c
|
||||
index 2364a8b7abcd138a..14821b5f248cd991 100644
|
||||
--- a/sysdeps/unix/sysv/linux/s390/sysconf.c
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/sysconf.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <unistd.h>
|
||||
#include <dl-procinfo.h>
|
||||
+#include <cpu-features.h>
|
||||
|
||||
static long int linux_sysconf (int name);
|
||||
|
||||
@@ -44,12 +45,14 @@ get_cache_info (int level, int attr, int type)
|
||||
|| type < CACHE_TYPE_DATA || type > CACHE_TYPE_INSTRUCTION)
|
||||
return 0L;
|
||||
|
||||
+ const struct cpu_features *features = &GLRO(dl_s390_cpu_features);
|
||||
+
|
||||
/* Check if ecag-instruction is available.
|
||||
ecag - extract CPU attribute (only in zarch; arch >= z10; in as 2.24) */
|
||||
- if (!(GLRO (dl_hwcap) & HWCAP_S390_STFLE)
|
||||
+ if (!(features->hwcap & HWCAP_S390_STFLE)
|
||||
#if !defined __s390x__
|
||||
- || !(GLRO (dl_hwcap) & HWCAP_S390_ZARCH)
|
||||
- || !(GLRO (dl_hwcap) & HWCAP_S390_HIGH_GPRS)
|
||||
+ || !(features->hwcap & HWCAP_S390_ZARCH)
|
||||
+ || !(features->hwcap & HWCAP_S390_HIGH_GPRS)
|
||||
#endif /* !__s390x__ */
|
||||
)
|
||||
{
|
||||
@@ -62,25 +65,7 @@ get_cache_info (int level, int attr, int type)
|
||||
return 0L;
|
||||
}
|
||||
|
||||
- /* Store facility list and check for z10.
|
||||
- (see ifunc-resolver for details) */
|
||||
- register unsigned long reg0 __asm__("0") = 0;
|
||||
-#ifdef __s390x__
|
||||
- unsigned long stfle_bits;
|
||||
-# define STFLE_Z10_MASK (1UL << (63 - 34))
|
||||
-#else
|
||||
- unsigned long long stfle_bits;
|
||||
-# define STFLE_Z10_MASK (1ULL << (63 - 34))
|
||||
-#endif /* !__s390x__ */
|
||||
- __asm__ __volatile__(".machine push" "\n\t"
|
||||
- ".machinemode \"zarch_nohighgprs\"\n\t"
|
||||
- ".machine \"z9-109\"" "\n\t"
|
||||
- "stfle %0" "\n\t"
|
||||
- ".machine pop" "\n"
|
||||
- : "=QS" (stfle_bits), "+d" (reg0)
|
||||
- : : "cc");
|
||||
-
|
||||
- if (!(stfle_bits & STFLE_Z10_MASK))
|
||||
+ if (!S390_IS_Z10 (features->stfle_bits))
|
||||
{
|
||||
/* We are at least on a z9 machine.
|
||||
Return 256byte for LINESIZE for L1 d/i-cache,
|
|
@ -0,0 +1,141 @@
|
|||
From fd78cfa72ea2bab30fdb4e1e0672b34471426c05 Mon Sep 17 00:00:00 2001
|
||||
From: Vitaly Buka <vitalybuka@google.com>
|
||||
Date: Sat, 18 Feb 2023 12:53:41 -0800
|
||||
Subject: [PATCH] stdlib: Undo post review change to 16adc58e73f3 [BZ #27749]
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
Post review removal of "goto restart" from
|
||||
https://sourceware.org/pipermail/libc-alpha/2021-April/125470.html
|
||||
introduced a bug when some atexit handers skipped.
|
||||
|
||||
Signed-off-by: Vitaly Buka <vitalybuka@google.com>
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
---
|
||||
stdlib/Makefile | 1 +
|
||||
stdlib/exit.c | 7 +++-
|
||||
stdlib/test-atexit-recursive.c | 75 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 81 insertions(+), 2 deletions(-)
|
||||
create mode 100644 stdlib/test-atexit-recursive.c
|
||||
|
||||
diff --git a/stdlib/Makefile b/stdlib/Makefile
|
||||
index ff5096ad1b..cd32f53b56 100644
|
||||
--- a/stdlib/Makefile
|
||||
+++ b/stdlib/Makefile
|
||||
@@ -171,6 +171,7 @@ tests := \
|
||||
test-a64l \
|
||||
test-at_quick_exit-race \
|
||||
test-atexit-race \
|
||||
+ test-atexit-recursive \
|
||||
test-bz22786 \
|
||||
test-canon \
|
||||
test-canon2 \
|
||||
diff --git a/stdlib/exit.c b/stdlib/exit.c
|
||||
index 6b1eed6445..1cd0bdfe94 100644
|
||||
--- a/stdlib/exit.c
|
||||
+++ b/stdlib/exit.c
|
||||
@@ -51,7 +51,10 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
exit (). */
|
||||
while (true)
|
||||
{
|
||||
- struct exit_function_list *cur = *listp;
|
||||
+ struct exit_function_list *cur;
|
||||
+
|
||||
+ restart:
|
||||
+ cur = *listp;
|
||||
|
||||
if (cur == NULL)
|
||||
{
|
||||
@@ -113,7 +116,7 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
|
||||
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
|
||||
/* The last exit function, or another thread, has registered
|
||||
more exit functions. Start the loop over. */
|
||||
- continue;
|
||||
+ goto restart;
|
||||
}
|
||||
|
||||
*listp = cur->next;
|
||||
diff --git a/stdlib/test-atexit-recursive.c b/stdlib/test-atexit-recursive.c
|
||||
new file mode 100644
|
||||
index 0000000000..0596b9763b
|
||||
--- /dev/null
|
||||
+++ b/stdlib/test-atexit-recursive.c
|
||||
@@ -0,0 +1,75 @@
|
||||
+/* Support file for atexit/exit, etc. race tests (BZ #27749).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* Check that atexit handler registed from another handler still called. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+static void
|
||||
+atexit_cb (void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+atexit_last (void)
|
||||
+{
|
||||
+ _exit (1);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+atexit_recursive (void)
|
||||
+{
|
||||
+ atexit (&atexit_cb);
|
||||
+ atexit (&atexit_last);
|
||||
+}
|
||||
+
|
||||
+_Noreturn static void
|
||||
+test_and_exit (int count)
|
||||
+{
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ atexit (&atexit_cb);
|
||||
+ atexit (&atexit_recursive);
|
||||
+ exit (0);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ for (int i = 0; i < 100; ++i)
|
||||
+ if (xfork () == 0)
|
||||
+ test_and_exit (i);
|
||||
+
|
||||
+ for (int i = 0; i < 100; ++i)
|
||||
+ {
|
||||
+ int status;
|
||||
+ xwaitpid (0, &status, 0);
|
||||
+ if (!WIFEXITED (status))
|
||||
+ FAIL_EXIT1 ("Failed iterations %d", i);
|
||||
+ TEST_COMPARE (WEXITSTATUS (status), 1);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#define TEST_FUNCTION do_test
|
||||
+#include <support/test-driver.c>
|
||||
--
|
||||
2.39.2
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
commit d0f07f7df8d9758c838674b70144ac73bcbd1634
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue May 30 13:25:50 2023 +0200
|
||||
|
||||
elf: Make more functions available for binding during dlclose (bug 30425)
|
||||
|
||||
Previously, after destructors for a DSO have been invoked, ld.so refused
|
||||
to bind against that DSO in all cases. Relax this restriction somewhat
|
||||
if the referencing object is itself a DSO that is being unloaded. This
|
||||
assumes that the symbol reference is not going to be stored anywhere.
|
||||
|
||||
The situation in the test case can arise fairly easily with C++ and
|
||||
objects that are built with different optimization levels and therefore
|
||||
define different functions with vague linkage.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(Test conflicts resolved by hand)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 0daa8a85ec1a1bc5..8e1f91bcd917fd4e 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -392,6 +392,7 @@ tests += \
|
||||
tst-debug1 \
|
||||
tst-deep1 \
|
||||
tst-dl-is_dso \
|
||||
+ tst-dlclose-lazy \
|
||||
tst-dlmodcount \
|
||||
tst-dlmopen1 \
|
||||
tst-dlmopen3 \
|
||||
@@ -742,6 +743,8 @@ modules-names = \
|
||||
tst-deep1mod2 \
|
||||
tst-deep1mod3 \
|
||||
tst-dlmopen1mod \
|
||||
+ tst-dlclose-lazy-mod1 \
|
||||
+ tst-dlclose-lazy-mod2 \
|
||||
tst-dlmopen-dlerror-mod \
|
||||
tst-dlmopen-gethostbyname-mod \
|
||||
tst-dlmopen-twice-mod1 \
|
||||
@@ -2676,3 +2679,8 @@ tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
$(objpfx)tst-dlmopen-twice.out: \
|
||||
$(objpfx)tst-dlmopen-twice-mod1.so \
|
||||
$(objpfx)tst-dlmopen-twice-mod2.so
|
||||
+
|
||||
+LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed
|
||||
+$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so
|
||||
+$(objpfx)tst-dlclose-lazy.out: \
|
||||
+ $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
|
||||
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
|
||||
index 3391a990c8d288e5..94ae2d0c46696118 100644
|
||||
--- a/elf/dl-lookup.c
|
||||
+++ b/elf/dl-lookup.c
|
||||
@@ -380,8 +380,25 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
||||
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
|
||||
continue;
|
||||
|
||||
- /* Do not look into objects which are going to be removed. */
|
||||
- if (map->l_removed)
|
||||
+ /* Do not look into objects which are going to be removed,
|
||||
+ except when the referencing object itself is being removed.
|
||||
+
|
||||
+ The second part covers the situation when an object lazily
|
||||
+ binds to another object while running its destructor, but the
|
||||
+ destructor of the other object has already run, so that
|
||||
+ dlclose has set l_removed. It may not always be obvious how
|
||||
+ to avoid such a scenario to programmers creating DSOs,
|
||||
+ particularly if C++ vague linkage is involved and triggers
|
||||
+ symbol interposition.
|
||||
+
|
||||
+ Accepting these to-be-removed objects makes the lazy and
|
||||
+ BIND_NOW cases more similar. (With BIND_NOW, the symbol is
|
||||
+ resolved early, before the destructor call, so the issue does
|
||||
+ not arise.). Behavior matches the constructor scenario: the
|
||||
+ implementation allows binding to symbols of objects whose
|
||||
+ constructors have not run. In fact, not doing this would be
|
||||
+ mostly incompatible with symbol interposition. */
|
||||
+ if (map->l_removed && !(undef_map != NULL && undef_map->l_removed))
|
||||
continue;
|
||||
|
||||
/* Print some debugging info if wanted. */
|
||||
diff --git a/elf/tst-dlclose-lazy-mod1.c b/elf/tst-dlclose-lazy-mod1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..8439dc1925cc8b41
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlclose-lazy-mod1.c
|
||||
@@ -0,0 +1,36 @@
|
||||
+/* Lazy binding during dlclose. Directly loaded module.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This function is called from exported_function below. It is only
|
||||
+ defined in this module. The weak attribute mimics how G++
|
||||
+ implements vague linkage for C++. */
|
||||
+void __attribute__ ((weak))
|
||||
+lazily_bound_exported_function (void)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+/* Called from tst-dlclose-lazy-mod2.so. */
|
||||
+void
|
||||
+exported_function (int call_it)
|
||||
+{
|
||||
+ if (call_it)
|
||||
+ /* Previous to the fix this would crash when called during dlclose
|
||||
+ since symbols from the DSO were no longer available for binding
|
||||
+ (bug 30425) after the DSO started being closed by dlclose. */
|
||||
+ lazily_bound_exported_function ();
|
||||
+}
|
||||
diff --git a/elf/tst-dlclose-lazy-mod2.c b/elf/tst-dlclose-lazy-mod2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..767f69ffdb23a685
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlclose-lazy-mod2.c
|
||||
@@ -0,0 +1,49 @@
|
||||
+/* Lazy binding during dlclose. Indirectly loaded module.
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+void
|
||||
+exported_function (int ignored)
|
||||
+{
|
||||
+ /* This function is interposed from tst-dlclose-lazy-mod1.so and
|
||||
+ thus never called. */
|
||||
+ abort ();
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+init (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlclose-lazy-mod2.so constructor called");
|
||||
+
|
||||
+ /* Trigger lazy binding to the definition in
|
||||
+ tst-dlclose-lazy-mod1.so, but not for
|
||||
+ lazily_bound_exported_function in that module. */
|
||||
+ exported_function (0);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+fini (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlclose-lazy-mod2.so destructor called");
|
||||
+
|
||||
+ /* Trigger the lazily_bound_exported_function call in
|
||||
+ exported_function in tst-dlclose-lazy-mod1.so. */
|
||||
+ exported_function (1);
|
||||
+}
|
||||
diff --git a/elf/tst-dlclose-lazy.c b/elf/tst-dlclose-lazy.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..976a6bb6f64fa981
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlclose-lazy.c
|
||||
@@ -0,0 +1,47 @@
|
||||
+/* Test lazy binding during dlclose (bug 30425).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+/* This test re-creates a situation that can arise naturally for C++
|
||||
+ applications due to the use of vague linkage and differences in the
|
||||
+ set of compiler-emitted functions. A function in
|
||||
+ tst-dlclose-lazy-mod1.so (exported_function) interposes a function
|
||||
+ in tst-dlclose-lazy-mod2.so. This function is called from the
|
||||
+ destructor in tst-dlclose-lazy-mod2.so, after the destructor for
|
||||
+ tst-dlclose-lazy-mod1.so has already completed. Prior to the fix
|
||||
+ for bug 30425, this would lead to a lazy binding failure in
|
||||
+ tst-dlclose-lazy-mod1.so because dlclose had already marked the DSO
|
||||
+ as unavailable for binding (by setting l_removed). */
|
||||
+
|
||||
+#include <dlfcn.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+int
|
||||
+main (void)
|
||||
+{
|
||||
+ /* Load tst-dlclose-lazy-mod1.so, indirectly loading
|
||||
+ tst-dlclose-lazy-mod2.so. */
|
||||
+ void *handle = xdlopen ("tst-dlclose-lazy-mod1.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||
+
|
||||
+ /* Invoke the destructor of tst-dlclose-lazy-mod2.so, which calls
|
||||
+ into tst-dlclose-lazy-mod1.so after its destructor has been
|
||||
+ called. */
|
||||
+ xdlclose (handle);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
|
@ -0,0 +1,45 @@
|
|||
From ed2f9dc9420c4c61436328778a70459d0a35556a Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Mon, 8 May 2023 22:10:20 -0500
|
||||
Subject: [PATCH] x86: Use 64MB as nt-store threshold if no cacheinfo [BZ
|
||||
#30429]
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
If `non_temporal_threshold` is below `minimum_non_temporal_threshold`,
|
||||
it almost certainly means we failed to read the systems cache info.
|
||||
|
||||
In this case, rather than defaulting the minimum correct value, we
|
||||
should default to a value that gets at least reasonable
|
||||
performance. 64MB is chosen conservatively to be at the very high
|
||||
end. This should never cause non-temporal stores when, if we had read
|
||||
cache info, we wouldn't have otherwise.
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
---
|
||||
sysdeps/x86/dl-cacheinfo.h | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index ec88945b39..877e73d700 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -749,8 +749,16 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
reflected in the manual. */
|
||||
unsigned long int maximum_non_temporal_threshold = SIZE_MAX >> 4;
|
||||
unsigned long int minimum_non_temporal_threshold = 0x4040;
|
||||
+
|
||||
+ /* If `non_temporal_threshold` less than `minimum_non_temporal_threshold`
|
||||
+ it most likely means we failed to detect the cache info. We don't want
|
||||
+ to default to `minimum_non_temporal_threshold` as such a small value,
|
||||
+ while correct, has bad performance. We default to 64MB as reasonable
|
||||
+ default bound. 64MB is likely conservative in that most/all systems would
|
||||
+ choose a lower value so it should never forcing non-temporal stores when
|
||||
+ they otherwise wouldn't be used. */
|
||||
if (non_temporal_threshold < minimum_non_temporal_threshold)
|
||||
- non_temporal_threshold = minimum_non_temporal_threshold;
|
||||
+ non_temporal_threshold = 64 * 1024 * 1024;
|
||||
else if (non_temporal_threshold > maximum_non_temporal_threshold)
|
||||
non_temporal_threshold = maximum_non_temporal_threshold;
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
From af992e7abdc9049714da76cae1e5e18bc4838fb8 Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed, 7 Jun 2023 13:18:01 -0500
|
||||
Subject: [PATCH] x86: Increase `non_temporal_threshold` to roughly `sizeof_L3
|
||||
/ 4`
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
Current `non_temporal_threshold` set to roughly '3/4 * sizeof_L3 /
|
||||
ncores_per_socket'. This patch updates that value to roughly
|
||||
'sizeof_L3 / 4`
|
||||
|
||||
The original value (specifically dividing the `ncores_per_socket`) was
|
||||
done to limit the amount of other threads' data a `memcpy`/`memset`
|
||||
could evict.
|
||||
|
||||
Dividing by 'ncores_per_socket', however leads to exceedingly low
|
||||
non-temporal thresholds and leads to using non-temporal stores in
|
||||
cases where REP MOVSB is multiple times faster.
|
||||
|
||||
Furthermore, non-temporal stores are written directly to main memory
|
||||
so using it at a size much smaller than L3 can place soon to be
|
||||
accessed data much further away than it otherwise could be. As well,
|
||||
modern machines are able to detect streaming patterns (especially if
|
||||
REP MOVSB is used) and provide LRU hints to the memory subsystem. This
|
||||
in affect caps the total amount of eviction at 1/cache_associativity,
|
||||
far below meaningfully thrashing the entire cache.
|
||||
|
||||
As best I can tell, the benchmarks that lead this small threshold
|
||||
where done comparing non-temporal stores versus standard cacheable
|
||||
stores. A better comparison (linked below) is to be REP MOVSB which,
|
||||
on the measure systems, is nearly 2x faster than non-temporal stores
|
||||
at the low-end of the previous threshold, and within 10% for over
|
||||
100MB copies (well past even the current threshold). In cases with a
|
||||
low number of threads competing for bandwidth, REP MOVSB is ~2x faster
|
||||
up to `sizeof_L3`.
|
||||
|
||||
The divisor of `4` is a somewhat arbitrary value. From benchmarks it
|
||||
seems Skylake and Icelake both prefer a divisor of `2`, but older CPUs
|
||||
such as Broadwell prefer something closer to `8`. This patch is meant
|
||||
to be followed up by another one to make the divisor cpu-specific, but
|
||||
in the meantime (and for easier backporting), this patch settles on
|
||||
`4` as a middle-ground.
|
||||
|
||||
Benchmarks comparing non-temporal stores, REP MOVSB, and cacheable
|
||||
stores where done using:
|
||||
https://github.com/goldsteinn/memcpy-nt-benchmarks
|
||||
|
||||
Sheets results (also available in pdf on the github):
|
||||
https://docs.google.com/spreadsheets/d/e/2PACX-1vS183r0rW_jRX6tG_E90m9qVuFiMbRIJvi5VAE8yYOvEOIEEc3aSNuEsrFbuXw5c3nGboxMmrupZD7K/pubhtml
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
---
|
||||
sysdeps/x86/dl-cacheinfo.h | 70 +++++++++++++++++++++++---------------
|
||||
1 file changed, 43 insertions(+), 27 deletions(-)
|
||||
|
||||
|
||||
[diff rebased by DJ]
|
||||
diff -rup a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h 2023-07-25 00:38:39.386831871 -0400
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h 2023-07-25 00:38:40.372870369 -0400
|
||||
@@ -408,7 +408,7 @@ handle_zhaoxin (int name)
|
||||
}
|
||||
|
||||
static void
|
||||
-get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
|
||||
+get_common_cache_info (long int *shared_ptr, long int * shared_per_thread_ptr, unsigned int *threads_ptr,
|
||||
long int core)
|
||||
{
|
||||
unsigned int eax;
|
||||
@@ -427,6 +427,7 @@ get_common_cache_info (long int *shared_
|
||||
unsigned int family = cpu_features->basic.family;
|
||||
unsigned int model = cpu_features->basic.model;
|
||||
long int shared = *shared_ptr;
|
||||
+ long int shared_per_thread = *shared_per_thread_ptr;
|
||||
unsigned int threads = *threads_ptr;
|
||||
bool inclusive_cache = true;
|
||||
bool support_count_mask = true;
|
||||
@@ -442,6 +443,7 @@ get_common_cache_info (long int *shared_
|
||||
/* Try L2 otherwise. */
|
||||
level = 2;
|
||||
shared = core;
|
||||
+ shared_per_thread = core;
|
||||
threads_l2 = 0;
|
||||
threads_l3 = -1;
|
||||
}
|
||||
@@ -598,29 +600,28 @@ get_common_cache_info (long int *shared_
|
||||
}
|
||||
else
|
||||
{
|
||||
-intel_bug_no_cache_info:
|
||||
- /* Assume that all logical threads share the highest cache
|
||||
- level. */
|
||||
- threads
|
||||
- = ((cpu_features->features[CPUID_INDEX_1].cpuid.ebx >> 16)
|
||||
- & 0xff);
|
||||
- }
|
||||
-
|
||||
- /* Cap usage of highest cache level to the number of supported
|
||||
- threads. */
|
||||
- if (shared > 0 && threads > 0)
|
||||
- shared /= threads;
|
||||
+ intel_bug_no_cache_info:
|
||||
+ /* Assume that all logical threads share the highest cache
|
||||
+ level. */
|
||||
+ threads = ((cpu_features->features[CPUID_INDEX_1].cpuid.ebx >> 16)
|
||||
+ & 0xff);
|
||||
+
|
||||
+ /* Get per-thread size of highest level cache. */
|
||||
+ if (shared_per_thread > 0 && threads > 0)
|
||||
+ shared_per_thread /= threads;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Account for non-inclusive L2 and L3 caches. */
|
||||
if (!inclusive_cache)
|
||||
{
|
||||
if (threads_l2 > 0)
|
||||
- core /= threads_l2;
|
||||
+ shared_per_thread += core / threads_l2;
|
||||
shared += core;
|
||||
}
|
||||
|
||||
*shared_ptr = shared;
|
||||
+ *shared_per_thread_ptr = shared_per_thread;
|
||||
*threads_ptr = threads;
|
||||
}
|
||||
|
||||
@@ -630,6 +631,7 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
/* Find out what brand of processor. */
|
||||
long int data = -1;
|
||||
long int shared = -1;
|
||||
+ long int shared_per_thread = -1;
|
||||
long int core = -1;
|
||||
unsigned int threads = 0;
|
||||
unsigned long int level1_icache_size = -1;
|
||||
@@ -650,6 +652,7 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
|
||||
core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||
shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
|
||||
+ shared_per_thread = shared;
|
||||
|
||||
level1_icache_size
|
||||
= handle_intel (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
|
||||
@@ -673,13 +676,14 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
level4_cache_size
|
||||
= handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features);
|
||||
|
||||
- get_common_cache_info (&shared, &threads, core);
|
||||
+ get_common_cache_info (&shared, &shared_per_thread, &threads, core);
|
||||
}
|
||||
else if (cpu_features->basic.kind == arch_kind_zhaoxin)
|
||||
{
|
||||
data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
|
||||
core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
|
||||
shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
|
||||
+ shared_per_thread = shared;
|
||||
|
||||
level1_icache_size = handle_zhaoxin (_SC_LEVEL1_ICACHE_SIZE);
|
||||
level1_icache_linesize = handle_zhaoxin (_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
@@ -693,13 +697,14 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC);
|
||||
level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE);
|
||||
|
||||
- get_common_cache_info (&shared, &threads, core);
|
||||
+ get_common_cache_info (&shared, &shared_per_thread, &threads, core);
|
||||
}
|
||||
else if (cpu_features->basic.kind == arch_kind_amd)
|
||||
{
|
||||
data = handle_amd (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
|
||||
core = handle_amd (_SC_LEVEL2_CACHE_SIZE, cpu_features);
|
||||
shared = handle_amd (_SC_LEVEL3_CACHE_SIZE, cpu_features);
|
||||
+ shared_per_thread = shared;
|
||||
|
||||
level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
|
||||
level1_icache_linesize
|
||||
@@ -721,6 +726,9 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
if (shared <= 0)
|
||||
/* No shared L3 cache. All we have is the L2 cache. */
|
||||
shared = core;
|
||||
+
|
||||
+ if (shared_per_thread <= 0)
|
||||
+ shared_per_thread = shared;
|
||||
}
|
||||
|
||||
cpu_features->level1_icache_size = level1_icache_size;
|
||||
@@ -736,17 +744,25 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
cpu_features->level3_cache_linesize = level3_cache_linesize;
|
||||
cpu_features->level4_cache_size = level4_cache_size;
|
||||
|
||||
- /* The default setting for the non_temporal threshold is 3/4 of one
|
||||
- thread's share of the chip's cache. For most Intel and AMD processors
|
||||
- with an initial release date between 2017 and 2020, a thread's typical
|
||||
- share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4
|
||||
- threshold leaves 125 KBytes to 500 KBytes of the thread's data
|
||||
- in cache after a maximum temporal copy, which will maintain
|
||||
- in cache a reasonable portion of the thread's stack and other
|
||||
- active data. If the threshold is set higher than one thread's
|
||||
- share of the cache, it has a substantial risk of negatively
|
||||
- impacting the performance of other threads running on the chip. */
|
||||
- unsigned long int non_temporal_threshold = shared * 3 / 4;
|
||||
+ /* The default setting for the non_temporal threshold is 1/4 of size
|
||||
+ of the chip's cache. For most Intel and AMD processors with an
|
||||
+ initial release date between 2017 and 2023, a thread's typical
|
||||
+ share of the cache is from 18-64MB. Using the 1/4 L3 is meant to
|
||||
+ estimate the point where non-temporal stores begin out-competing
|
||||
+ REP MOVSB. As well the point where the fact that non-temporal
|
||||
+ stores are forced back to main memory would already occurred to the
|
||||
+ majority of the lines in the copy. Note, concerns about the
|
||||
+ entire L3 cache being evicted by the copy are mostly alleviated
|
||||
+ by the fact that modern HW detects streaming patterns and
|
||||
+ provides proper LRU hints so that the maximum thrashing
|
||||
+ capped at 1/associativity. */
|
||||
+ unsigned long int non_temporal_threshold = shared / 4;
|
||||
+ /* If no ERMS, we use the per-thread L3 chunking. Normal cacheable stores run
|
||||
+ a higher risk of actually thrashing the cache as they don't have a HW LRU
|
||||
+ hint. As well, their performance in highly parallel situations is
|
||||
+ noticeably worse. */
|
||||
+ if (!CPU_FEATURE_USABLE_P (cpu_features, ERMS))
|
||||
+ non_temporal_threshold = shared_per_thread * 3 / 4;
|
||||
/* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
||||
|
|
@ -0,0 +1,475 @@
|
|||
From f193ea20eddc6cef84cba54cf1a647204ee6a86b Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed, 7 Jun 2023 13:18:02 -0500
|
||||
Subject: [PATCH] x86: Refactor Intel `init_cpu_features`
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
This patch should have no affect on existing functionality.
|
||||
|
||||
The current code, which has a single switch for model detection and
|
||||
setting prefered features, is difficult to follow/extend. The cases
|
||||
use magic numbers and many microarchitectures are missing. This makes
|
||||
it difficult to reason about what is implemented so far and/or
|
||||
how/where to add support for new features.
|
||||
|
||||
This patch splits the model detection and preference setting stages so
|
||||
that CPU preferences can be set based on a complete list of available
|
||||
microarchitectures, rather than based on model magic numbers.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
---
|
||||
sysdeps/x86/cpu-features.c | 390 +++++++++++++++++++++++++++++--------
|
||||
1 file changed, 309 insertions(+), 81 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
index 0a99efdb28..d52a718e92 100644
|
||||
--- a/sysdeps/x86/cpu-features.c
|
||||
+++ b/sysdeps/x86/cpu-features.c
|
||||
@@ -417,6 +417,216 @@ _Static_assert (((index_arch_Fast_Unaligned_Load
|
||||
== index_arch_Fast_Copy_Backward)),
|
||||
"Incorrect index_arch_Fast_Unaligned_Load");
|
||||
|
||||
+
|
||||
+/* Intel Family-6 microarch list. */
|
||||
+enum
|
||||
+{
|
||||
+ /* Atom processors. */
|
||||
+ INTEL_ATOM_BONNELL,
|
||||
+ INTEL_ATOM_SILVERMONT,
|
||||
+ INTEL_ATOM_AIRMONT,
|
||||
+ INTEL_ATOM_GOLDMONT,
|
||||
+ INTEL_ATOM_GOLDMONT_PLUS,
|
||||
+ INTEL_ATOM_SIERRAFOREST,
|
||||
+ INTEL_ATOM_GRANDRIDGE,
|
||||
+ INTEL_ATOM_TREMONT,
|
||||
+
|
||||
+ /* Bigcore processors. */
|
||||
+ INTEL_BIGCORE_MEROM,
|
||||
+ INTEL_BIGCORE_PENRYN,
|
||||
+ INTEL_BIGCORE_DUNNINGTON,
|
||||
+ INTEL_BIGCORE_NEHALEM,
|
||||
+ INTEL_BIGCORE_WESTMERE,
|
||||
+ INTEL_BIGCORE_SANDYBRIDGE,
|
||||
+ INTEL_BIGCORE_IVYBRIDGE,
|
||||
+ INTEL_BIGCORE_HASWELL,
|
||||
+ INTEL_BIGCORE_BROADWELL,
|
||||
+ INTEL_BIGCORE_SKYLAKE,
|
||||
+ INTEL_BIGCORE_KABYLAKE,
|
||||
+ INTEL_BIGCORE_COMETLAKE,
|
||||
+ INTEL_BIGCORE_SKYLAKE_AVX512,
|
||||
+ INTEL_BIGCORE_CANNONLAKE,
|
||||
+ INTEL_BIGCORE_ICELAKE,
|
||||
+ INTEL_BIGCORE_TIGERLAKE,
|
||||
+ INTEL_BIGCORE_ROCKETLAKE,
|
||||
+ INTEL_BIGCORE_SAPPHIRERAPIDS,
|
||||
+ INTEL_BIGCORE_RAPTORLAKE,
|
||||
+ INTEL_BIGCORE_EMERALDRAPIDS,
|
||||
+ INTEL_BIGCORE_METEORLAKE,
|
||||
+ INTEL_BIGCORE_LUNARLAKE,
|
||||
+ INTEL_BIGCORE_ARROWLAKE,
|
||||
+ INTEL_BIGCORE_GRANITERAPIDS,
|
||||
+
|
||||
+ /* Mixed (bigcore + atom SOC). */
|
||||
+ INTEL_MIXED_LAKEFIELD,
|
||||
+ INTEL_MIXED_ALDERLAKE,
|
||||
+
|
||||
+ /* KNL. */
|
||||
+ INTEL_KNIGHTS_MILL,
|
||||
+ INTEL_KNIGHTS_LANDING,
|
||||
+
|
||||
+ /* Unknown. */
|
||||
+ INTEL_UNKNOWN,
|
||||
+};
|
||||
+
|
||||
+static unsigned int
|
||||
+intel_get_fam6_microarch (unsigned int model,
|
||||
+ __attribute__ ((unused)) unsigned int stepping)
|
||||
+{
|
||||
+ switch (model)
|
||||
+ {
|
||||
+ case 0x1C:
|
||||
+ case 0x26:
|
||||
+ return INTEL_ATOM_BONNELL;
|
||||
+ case 0x27:
|
||||
+ case 0x35:
|
||||
+ case 0x36:
|
||||
+ /* Really Saltwell, but Saltwell is just a die shrink of Bonnell
|
||||
+ (microarchitecturally identical). */
|
||||
+ return INTEL_ATOM_BONNELL;
|
||||
+ case 0x37:
|
||||
+ case 0x4A:
|
||||
+ case 0x4D:
|
||||
+ case 0x5D:
|
||||
+ return INTEL_ATOM_SILVERMONT;
|
||||
+ case 0x4C:
|
||||
+ case 0x5A:
|
||||
+ case 0x75:
|
||||
+ return INTEL_ATOM_AIRMONT;
|
||||
+ case 0x5C:
|
||||
+ case 0x5F:
|
||||
+ return INTEL_ATOM_GOLDMONT;
|
||||
+ case 0x7A:
|
||||
+ return INTEL_ATOM_GOLDMONT_PLUS;
|
||||
+ case 0xAF:
|
||||
+ return INTEL_ATOM_SIERRAFOREST;
|
||||
+ case 0xB6:
|
||||
+ return INTEL_ATOM_GRANDRIDGE;
|
||||
+ case 0x86:
|
||||
+ case 0x96:
|
||||
+ case 0x9C:
|
||||
+ return INTEL_ATOM_TREMONT;
|
||||
+ case 0x0F:
|
||||
+ case 0x16:
|
||||
+ return INTEL_BIGCORE_MEROM;
|
||||
+ case 0x17:
|
||||
+ return INTEL_BIGCORE_PENRYN;
|
||||
+ case 0x1D:
|
||||
+ return INTEL_BIGCORE_DUNNINGTON;
|
||||
+ case 0x1A:
|
||||
+ case 0x1E:
|
||||
+ case 0x1F:
|
||||
+ case 0x2E:
|
||||
+ return INTEL_BIGCORE_NEHALEM;
|
||||
+ case 0x25:
|
||||
+ case 0x2C:
|
||||
+ case 0x2F:
|
||||
+ return INTEL_BIGCORE_WESTMERE;
|
||||
+ case 0x2A:
|
||||
+ case 0x2D:
|
||||
+ return INTEL_BIGCORE_SANDYBRIDGE;
|
||||
+ case 0x3A:
|
||||
+ case 0x3E:
|
||||
+ return INTEL_BIGCORE_IVYBRIDGE;
|
||||
+ case 0x3C:
|
||||
+ case 0x3F:
|
||||
+ case 0x45:
|
||||
+ case 0x46:
|
||||
+ return INTEL_BIGCORE_HASWELL;
|
||||
+ case 0x3D:
|
||||
+ case 0x47:
|
||||
+ case 0x4F:
|
||||
+ case 0x56:
|
||||
+ return INTEL_BIGCORE_BROADWELL;
|
||||
+ case 0x4E:
|
||||
+ case 0x5E:
|
||||
+ return INTEL_BIGCORE_SKYLAKE;
|
||||
+ case 0x8E:
|
||||
+ /*
|
||||
+ Stepping = {9}
|
||||
+ -> Amberlake
|
||||
+ Stepping = {10}
|
||||
+ -> Coffeelake
|
||||
+ Stepping = {11, 12}
|
||||
+ -> Whiskeylake
|
||||
+ else
|
||||
+ -> Kabylake
|
||||
+
|
||||
+ All of these are derivatives of Kabylake (Skylake client).
|
||||
+ */
|
||||
+ return INTEL_BIGCORE_KABYLAKE;
|
||||
+ case 0x9E:
|
||||
+ /*
|
||||
+ Stepping = {10, 11, 12, 13}
|
||||
+ -> Coffeelake
|
||||
+ else
|
||||
+ -> Kabylake
|
||||
+
|
||||
+ Coffeelake is a derivatives of Kabylake (Skylake client).
|
||||
+ */
|
||||
+ return INTEL_BIGCORE_KABYLAKE;
|
||||
+ case 0xA5:
|
||||
+ case 0xA6:
|
||||
+ return INTEL_BIGCORE_COMETLAKE;
|
||||
+ case 0x66:
|
||||
+ return INTEL_BIGCORE_CANNONLAKE;
|
||||
+ case 0x55:
|
||||
+ /*
|
||||
+ Stepping = {6, 7}
|
||||
+ -> Cascadelake
|
||||
+ Stepping = {11}
|
||||
+ -> Cooperlake
|
||||
+ else
|
||||
+ -> Skylake-avx512
|
||||
+
|
||||
+ These are all microarchitecturally indentical, so use
|
||||
+ Skylake-avx512 for all of them.
|
||||
+ */
|
||||
+ return INTEL_BIGCORE_SKYLAKE_AVX512;
|
||||
+ case 0x6A:
|
||||
+ case 0x6C:
|
||||
+ case 0x7D:
|
||||
+ case 0x7E:
|
||||
+ case 0x9D:
|
||||
+ return INTEL_BIGCORE_ICELAKE;
|
||||
+ case 0x8C:
|
||||
+ case 0x8D:
|
||||
+ return INTEL_BIGCORE_TIGERLAKE;
|
||||
+ case 0xA7:
|
||||
+ return INTEL_BIGCORE_ROCKETLAKE;
|
||||
+ case 0x8F:
|
||||
+ return INTEL_BIGCORE_SAPPHIRERAPIDS;
|
||||
+ case 0xB7:
|
||||
+ case 0xBA:
|
||||
+ case 0xBF:
|
||||
+ return INTEL_BIGCORE_RAPTORLAKE;
|
||||
+ case 0xCF:
|
||||
+ return INTEL_BIGCORE_EMERALDRAPIDS;
|
||||
+ case 0xAA:
|
||||
+ case 0xAC:
|
||||
+ return INTEL_BIGCORE_METEORLAKE;
|
||||
+ case 0xbd:
|
||||
+ return INTEL_BIGCORE_LUNARLAKE;
|
||||
+ case 0xc6:
|
||||
+ return INTEL_BIGCORE_ARROWLAKE;
|
||||
+ case 0xAD:
|
||||
+ case 0xAE:
|
||||
+ return INTEL_BIGCORE_GRANITERAPIDS;
|
||||
+ case 0x8A:
|
||||
+ return INTEL_MIXED_LAKEFIELD;
|
||||
+ case 0x97:
|
||||
+ case 0x9A:
|
||||
+ case 0xBE:
|
||||
+ return INTEL_MIXED_ALDERLAKE;
|
||||
+ case 0x85:
|
||||
+ return INTEL_KNIGHTS_MILL;
|
||||
+ case 0x57:
|
||||
+ return INTEL_KNIGHTS_LANDING;
|
||||
+ default:
|
||||
+ return INTEL_UNKNOWN;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static inline void
|
||||
init_cpu_features (struct cpu_features *cpu_features)
|
||||
{
|
||||
@@ -453,129 +663,147 @@ init_cpu_features (struct cpu_features *cpu_features)
|
||||
if (family == 0x06)
|
||||
{
|
||||
model += extended_model;
|
||||
- switch (model)
|
||||
+ unsigned int microarch
|
||||
+ = intel_get_fam6_microarch (model, stepping);
|
||||
+
|
||||
+ switch (microarch)
|
||||
{
|
||||
- case 0x1c:
|
||||
- case 0x26:
|
||||
- /* BSF is slow on Atom. */
|
||||
+ /* Atom / KNL tuning. */
|
||||
+ case INTEL_ATOM_BONNELL:
|
||||
+ /* BSF is slow on Bonnell. */
|
||||
cpu_features->preferred[index_arch_Slow_BSF]
|
||||
- |= bit_arch_Slow_BSF;
|
||||
+ |= bit_arch_Slow_BSF;
|
||||
break;
|
||||
|
||||
- case 0x57:
|
||||
- /* Knights Landing. Enable Silvermont optimizations. */
|
||||
-
|
||||
- case 0x7a:
|
||||
- /* Unaligned load versions are faster than SSSE3
|
||||
- on Goldmont Plus. */
|
||||
-
|
||||
- case 0x5c:
|
||||
- case 0x5f:
|
||||
/* Unaligned load versions are faster than SSSE3
|
||||
- on Goldmont. */
|
||||
+ on Airmont, Silvermont, Goldmont, and Goldmont Plus. */
|
||||
+ case INTEL_ATOM_AIRMONT:
|
||||
+ case INTEL_ATOM_SILVERMONT:
|
||||
+ case INTEL_ATOM_GOLDMONT:
|
||||
+ case INTEL_ATOM_GOLDMONT_PLUS:
|
||||
|
||||
- case 0x4c:
|
||||
- case 0x5a:
|
||||
- case 0x75:
|
||||
- /* Airmont is a die shrink of Silvermont. */
|
||||
+ /* Knights Landing. Enable Silvermont optimizations. */
|
||||
+ case INTEL_KNIGHTS_LANDING:
|
||||
|
||||
- case 0x37:
|
||||
- case 0x4a:
|
||||
- case 0x4d:
|
||||
- case 0x5d:
|
||||
- /* Unaligned load versions are faster than SSSE3
|
||||
- on Silvermont. */
|
||||
cpu_features->preferred[index_arch_Fast_Unaligned_Load]
|
||||
- |= (bit_arch_Fast_Unaligned_Load
|
||||
- | bit_arch_Fast_Unaligned_Copy
|
||||
- | bit_arch_Prefer_PMINUB_for_stringop
|
||||
- | bit_arch_Slow_SSE4_2);
|
||||
+ |= (bit_arch_Fast_Unaligned_Load
|
||||
+ | bit_arch_Fast_Unaligned_Copy
|
||||
+ | bit_arch_Prefer_PMINUB_for_stringop
|
||||
+ | bit_arch_Slow_SSE4_2);
|
||||
break;
|
||||
|
||||
- case 0x86:
|
||||
- case 0x96:
|
||||
- case 0x9c:
|
||||
+ case INTEL_ATOM_TREMONT:
|
||||
/* Enable rep string instructions, unaligned load, unaligned
|
||||
- copy, pminub and avoid SSE 4.2 on Tremont. */
|
||||
+ copy, pminub and avoid SSE 4.2 on Tremont. */
|
||||
cpu_features->preferred[index_arch_Fast_Rep_String]
|
||||
- |= (bit_arch_Fast_Rep_String
|
||||
- | bit_arch_Fast_Unaligned_Load
|
||||
- | bit_arch_Fast_Unaligned_Copy
|
||||
- | bit_arch_Prefer_PMINUB_for_stringop
|
||||
- | bit_arch_Slow_SSE4_2);
|
||||
+ |= (bit_arch_Fast_Rep_String
|
||||
+ | bit_arch_Fast_Unaligned_Load
|
||||
+ | bit_arch_Fast_Unaligned_Copy
|
||||
+ | bit_arch_Prefer_PMINUB_for_stringop
|
||||
+ | bit_arch_Slow_SSE4_2);
|
||||
break;
|
||||
|
||||
+ /*
|
||||
+ Default tuned Knights microarch.
|
||||
+ case INTEL_KNIGHTS_MILL:
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ Default tuned atom microarch.
|
||||
+ case INTEL_ATOM_SIERRAFOREST:
|
||||
+ case INTEL_ATOM_GRANDRIDGE:
|
||||
+ */
|
||||
+
|
||||
+ /* Bigcore/Default Tuning. */
|
||||
default:
|
||||
/* Unknown family 0x06 processors. Assuming this is one
|
||||
of Core i3/i5/i7 processors if AVX is available. */
|
||||
if (!CPU_FEATURES_CPU_P (cpu_features, AVX))
|
||||
break;
|
||||
/* Fall through. */
|
||||
-
|
||||
- case 0x1a:
|
||||
- case 0x1e:
|
||||
- case 0x1f:
|
||||
- case 0x25:
|
||||
- case 0x2c:
|
||||
- case 0x2e:
|
||||
- case 0x2f:
|
||||
+ case INTEL_BIGCORE_NEHALEM:
|
||||
+ case INTEL_BIGCORE_WESTMERE:
|
||||
/* Rep string instructions, unaligned load, unaligned copy,
|
||||
and pminub are fast on Intel Core i3, i5 and i7. */
|
||||
cpu_features->preferred[index_arch_Fast_Rep_String]
|
||||
- |= (bit_arch_Fast_Rep_String
|
||||
- | bit_arch_Fast_Unaligned_Load
|
||||
- | bit_arch_Fast_Unaligned_Copy
|
||||
- | bit_arch_Prefer_PMINUB_for_stringop);
|
||||
+ |= (bit_arch_Fast_Rep_String
|
||||
+ | bit_arch_Fast_Unaligned_Load
|
||||
+ | bit_arch_Fast_Unaligned_Copy
|
||||
+ | bit_arch_Prefer_PMINUB_for_stringop);
|
||||
break;
|
||||
+
|
||||
+ /*
|
||||
+ Default tuned Bigcore microarch.
|
||||
+ case INTEL_BIGCORE_SANDYBRIDGE:
|
||||
+ case INTEL_BIGCORE_IVYBRIDGE:
|
||||
+ case INTEL_BIGCORE_HASWELL:
|
||||
+ case INTEL_BIGCORE_BROADWELL:
|
||||
+ case INTEL_BIGCORE_SKYLAKE:
|
||||
+ case INTEL_BIGCORE_KABYLAKE:
|
||||
+ case INTEL_BIGCORE_COMETLAKE:
|
||||
+ case INTEL_BIGCORE_SKYLAKE_AVX512:
|
||||
+ case INTEL_BIGCORE_CANNONLAKE:
|
||||
+ case INTEL_BIGCORE_ICELAKE:
|
||||
+ case INTEL_BIGCORE_TIGERLAKE:
|
||||
+ case INTEL_BIGCORE_ROCKETLAKE:
|
||||
+ case INTEL_BIGCORE_RAPTORLAKE:
|
||||
+ case INTEL_BIGCORE_METEORLAKE:
|
||||
+ case INTEL_BIGCORE_LUNARLAKE:
|
||||
+ case INTEL_BIGCORE_ARROWLAKE:
|
||||
+ case INTEL_BIGCORE_SAPPHIRERAPIDS:
|
||||
+ case INTEL_BIGCORE_EMERALDRAPIDS:
|
||||
+ case INTEL_BIGCORE_GRANITERAPIDS:
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ Default tuned Mixed (bigcore + atom SOC).
|
||||
+ case INTEL_MIXED_LAKEFIELD:
|
||||
+ case INTEL_MIXED_ALDERLAKE:
|
||||
+ */
|
||||
}
|
||||
|
||||
- /* Disable TSX on some processors to avoid TSX on kernels that
|
||||
- weren't updated with the latest microcode package (which
|
||||
- disables broken feature by default). */
|
||||
- switch (model)
|
||||
+ /* Disable TSX on some processors to avoid TSX on kernels that
|
||||
+ weren't updated with the latest microcode package (which
|
||||
+ disables broken feature by default). */
|
||||
+ switch (microarch)
|
||||
{
|
||||
- case 0x55:
|
||||
+ case INTEL_BIGCORE_SKYLAKE_AVX512:
|
||||
+ /* 0x55 (Skylake-avx512) && stepping <= 5 disable TSX. */
|
||||
if (stepping <= 5)
|
||||
goto disable_tsx;
|
||||
break;
|
||||
- case 0x8e:
|
||||
- /* NB: Although the errata documents that for model == 0x8e,
|
||||
- only 0xb stepping or lower are impacted, the intention of
|
||||
- the errata was to disable TSX on all client processors on
|
||||
- all steppings. Include 0xc stepping which is an Intel
|
||||
- Core i7-8665U, a client mobile processor. */
|
||||
- case 0x9e:
|
||||
+
|
||||
+ case INTEL_BIGCORE_KABYLAKE:
|
||||
+ /* NB: Although the errata documents that for model == 0x8e
|
||||
+ (kabylake skylake client), only 0xb stepping or lower are
|
||||
+ impacted, the intention of the errata was to disable TSX on
|
||||
+ all client processors on all steppings. Include 0xc
|
||||
+ stepping which is an Intel Core i7-8665U, a client mobile
|
||||
+ processor. */
|
||||
if (stepping > 0xc)
|
||||
break;
|
||||
/* Fall through. */
|
||||
- case 0x4e:
|
||||
- case 0x5e:
|
||||
- {
|
||||
+ case INTEL_BIGCORE_SKYLAKE:
|
||||
/* Disable Intel TSX and enable RTM_ALWAYS_ABORT for
|
||||
processors listed in:
|
||||
|
||||
https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html
|
||||
*/
|
||||
-disable_tsx:
|
||||
+ disable_tsx:
|
||||
CPU_FEATURE_UNSET (cpu_features, HLE);
|
||||
CPU_FEATURE_UNSET (cpu_features, RTM);
|
||||
CPU_FEATURE_SET (cpu_features, RTM_ALWAYS_ABORT);
|
||||
- }
|
||||
- break;
|
||||
- case 0x3f:
|
||||
- /* Xeon E7 v3 with stepping >= 4 has working TSX. */
|
||||
- if (stepping >= 4)
|
||||
break;
|
||||
- /* Fall through. */
|
||||
- case 0x3c:
|
||||
- case 0x45:
|
||||
- case 0x46:
|
||||
- /* Disable Intel TSX on Haswell processors (except Xeon E7 v3
|
||||
- with stepping >= 4) to avoid TSX on kernels that weren't
|
||||
- updated with the latest microcode package (which disables
|
||||
- broken feature by default). */
|
||||
- CPU_FEATURE_UNSET (cpu_features, RTM);
|
||||
- break;
|
||||
+
|
||||
+ case INTEL_BIGCORE_HASWELL:
|
||||
+ /* Xeon E7 v3 (model == 0x3f) with stepping >= 4 has working
|
||||
+ TSX. Haswell also include other model numbers that have
|
||||
+ working TSX. */
|
||||
+ if (model == 0x3f && stepping >= 4)
|
||||
+ break;
|
||||
+
|
||||
+ CPU_FEATURE_UNSET (cpu_features, RTM);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
From 180897c161a171d8ef0faee1c6c9fd6b57d8b13b Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed, 7 Jun 2023 13:18:03 -0500
|
||||
Subject: [PATCH] x86: Make the divisor in setting `non_temporal_threshold` cpu
|
||||
specific
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
Different systems prefer a different divisors.
|
||||
|
||||
From benchmarks[1] so far the following divisors have been found:
|
||||
ICX : 2
|
||||
SKX : 2
|
||||
BWD : 8
|
||||
|
||||
For Intel, we are generalizing that BWD and older prefers 8 as a
|
||||
divisor, and SKL and newer prefers 2. This number can be further tuned
|
||||
as benchmarks are run.
|
||||
|
||||
[1]: https://github.com/goldsteinn/memcpy-nt-benchmarks
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
---
|
||||
sysdeps/x86/cpu-features.c | 31 ++++++++++++++++++++---------
|
||||
sysdeps/x86/dl-cacheinfo.h | 32 ++++++++++++++++++------------
|
||||
sysdeps/x86/dl-diagnostics-cpu.c | 11 ++++++----
|
||||
sysdeps/x86/include/cpu-features.h | 3 +++
|
||||
4 files changed, 51 insertions(+), 26 deletions(-)
|
||||
|
||||
[DJ - edited for ABI compatibility]
|
||||
|
||||
diff -rup a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
|
||||
--- a/sysdeps/x86/cpu-features.c 2023-07-26 17:56:19.679300711 -0400
|
||||
+++ b/sysdeps/x86/cpu-features.c 2023-07-28 15:27:00.336324265 -0400
|
||||
@@ -35,6 +35,9 @@ extern void TUNABLE_CALLBACK (set_x86_sh
|
||||
# endif
|
||||
#endif
|
||||
|
||||
+unsigned long int __rtld_global_ro_cachesize_non_temporal_divisor
|
||||
+ attribute_hidden;
|
||||
+
|
||||
#if CET_ENABLED
|
||||
# include <dl-cet.h>
|
||||
#endif
|
||||
@@ -614,6 +617,7 @@ init_cpu_features (struct cpu_features *
|
||||
unsigned int stepping = 0;
|
||||
enum cpu_features_kind kind;
|
||||
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor = 4;
|
||||
#if !HAS_CPUID
|
||||
if (__get_cpuid_max (0, 0) == 0)
|
||||
{
|
||||
@@ -694,13 +698,13 @@ init_cpu_features (struct cpu_features *
|
||||
|
||||
/* Bigcore/Default Tuning. */
|
||||
default:
|
||||
+ default_tuning:
|
||||
/* Unknown family 0x06 processors. Assuming this is one
|
||||
of Core i3/i5/i7 processors if AVX is available. */
|
||||
if (!CPU_FEATURES_CPU_P (cpu_features, AVX))
|
||||
break;
|
||||
- /* Fall through. */
|
||||
- case INTEL_BIGCORE_NEHALEM:
|
||||
- case INTEL_BIGCORE_WESTMERE:
|
||||
+
|
||||
+ enable_modern_features:
|
||||
/* Rep string instructions, unaligned load, unaligned copy,
|
||||
and pminub are fast on Intel Core i3, i5 and i7. */
|
||||
cpu_features->preferred[index_arch_Fast_Rep_String]
|
||||
@@ -710,12 +714,23 @@ init_cpu_features (struct cpu_features *
|
||||
| bit_arch_Prefer_PMINUB_for_stringop);
|
||||
break;
|
||||
|
||||
- /*
|
||||
- Default tuned Bigcore microarch.
|
||||
+ case INTEL_BIGCORE_NEHALEM:
|
||||
+ case INTEL_BIGCORE_WESTMERE:
|
||||
+ /* Older CPUs prefer non-temporal stores at lower threshold. */
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor = 8;
|
||||
+ goto enable_modern_features;
|
||||
+
|
||||
+ /* Older Bigcore microarch (smaller non-temporal store
|
||||
+ threshold). */
|
||||
case INTEL_BIGCORE_SANDYBRIDGE:
|
||||
case INTEL_BIGCORE_IVYBRIDGE:
|
||||
case INTEL_BIGCORE_HASWELL:
|
||||
case INTEL_BIGCORE_BROADWELL:
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor = 8;
|
||||
+ goto default_tuning;
|
||||
+
|
||||
+ /* Newer Bigcore microarch (larger non-temporal store
|
||||
+ threshold). */
|
||||
case INTEL_BIGCORE_SKYLAKE:
|
||||
case INTEL_BIGCORE_KABYLAKE:
|
||||
case INTEL_BIGCORE_COMETLAKE:
|
||||
@@ -731,13 +746,14 @@ init_cpu_features (struct cpu_features *
|
||||
case INTEL_BIGCORE_SAPPHIRERAPIDS:
|
||||
case INTEL_BIGCORE_EMERALDRAPIDS:
|
||||
case INTEL_BIGCORE_GRANITERAPIDS:
|
||||
- */
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor = 2;
|
||||
+ goto default_tuning;
|
||||
|
||||
- /*
|
||||
- Default tuned Mixed (bigcore + atom SOC).
|
||||
+ /* Default tuned Mixed (bigcore + atom SOC). */
|
||||
case INTEL_MIXED_LAKEFIELD:
|
||||
case INTEL_MIXED_ALDERLAKE:
|
||||
- */
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor = 2;
|
||||
+ goto default_tuning;
|
||||
}
|
||||
|
||||
/* Disable TSX on some processors to avoid TSX on kernels that
|
||||
diff -rup a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h 2023-07-26 17:56:18.662261475 -0400
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h 2023-07-26 17:56:20.756342261 -0400
|
||||
@@ -744,19 +744,25 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
cpu_features->level3_cache_linesize = level3_cache_linesize;
|
||||
cpu_features->level4_cache_size = level4_cache_size;
|
||||
|
||||
- /* The default setting for the non_temporal threshold is 1/4 of size
|
||||
- of the chip's cache. For most Intel and AMD processors with an
|
||||
- initial release date between 2017 and 2023, a thread's typical
|
||||
- share of the cache is from 18-64MB. Using the 1/4 L3 is meant to
|
||||
- estimate the point where non-temporal stores begin out-competing
|
||||
- REP MOVSB. As well the point where the fact that non-temporal
|
||||
- stores are forced back to main memory would already occurred to the
|
||||
- majority of the lines in the copy. Note, concerns about the
|
||||
- entire L3 cache being evicted by the copy are mostly alleviated
|
||||
- by the fact that modern HW detects streaming patterns and
|
||||
- provides proper LRU hints so that the maximum thrashing
|
||||
- capped at 1/associativity. */
|
||||
- unsigned long int non_temporal_threshold = shared / 4;
|
||||
+ unsigned long int cachesize_non_temporal_divisor
|
||||
+ = __rtld_global_ro_cachesize_non_temporal_divisor;
|
||||
+ if (cachesize_non_temporal_divisor <= 0)
|
||||
+ cachesize_non_temporal_divisor = 4;
|
||||
+
|
||||
+ /* The default setting for the non_temporal threshold is [1/8, 1/2] of size
|
||||
+ of the chip's cache (depending on `cachesize_non_temporal_divisor` which
|
||||
+ is microarch specific. The defeault is 1/4). For most Intel and AMD
|
||||
+ processors with an initial release date between 2017 and 2023, a thread's
|
||||
+ typical share of the cache is from 18-64MB. Using a reasonable size
|
||||
+ fraction of L3 is meant to estimate the point where non-temporal stores
|
||||
+ begin out-competing REP MOVSB. As well the point where the fact that
|
||||
+ non-temporal stores are forced back to main memory would already occurred
|
||||
+ to the majority of the lines in the copy. Note, concerns about the entire
|
||||
+ L3 cache being evicted by the copy are mostly alleviated by the fact that
|
||||
+ modern HW detects streaming patterns and provides proper LRU hints so that
|
||||
+ the maximum thrashing capped at 1/associativity. */
|
||||
+ unsigned long int non_temporal_threshold
|
||||
+ = shared / cachesize_non_temporal_divisor;
|
||||
/* If no ERMS, we use the per-thread L3 chunking. Normal cacheable stores run
|
||||
a higher risk of actually thrashing the cache as they don't have a HW LRU
|
||||
hint. As well, their performance in highly parallel situations is
|
||||
diff -rup a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
|
||||
--- a/sysdeps/x86/dl-diagnostics-cpu.c 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/x86/dl-diagnostics-cpu.c 2023-07-26 17:56:20.761342454 -0400
|
||||
@@ -117,4 +117,6 @@ _dl_diagnostics_cpu (void)
|
||||
+ sizeof (cpu_features->level4_cache_size)
|
||||
== sizeof (*cpu_features),
|
||||
"last cpu_features field has been printed");
|
||||
+ print_cpu_features_value ("cachesize_non_temporal_divisor",
|
||||
+ __rtld_global_ro_cachesize_non_temporal_divisor);
|
||||
}
|
||||
diff -rup a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
|
||||
--- a/sysdeps/x86/include/cpu-features.h 2021-08-01 21:33:43.000000000 -0400
|
||||
+++ b/sysdeps/x86/include/cpu-features.h 2023-07-27 13:51:52.081494751 -0400
|
||||
@@ -919,6 +919,10 @@ struct cpu_features
|
||||
unsigned long int level4_cache_size;
|
||||
};
|
||||
|
||||
+/* When no user non_temporal_threshold is specified. We default to
|
||||
+ cachesize / cachesize_non_temporal_divisor. */
|
||||
+extern unsigned long int __rtld_global_ro_cachesize_non_temporal_divisor;
|
||||
+
|
||||
/* Get a pointer to the CPU features structure. */
|
||||
extern const struct cpu_features *_dl_x86_get_cpu_features (void)
|
||||
__attribute__ ((pure));
|
|
@ -0,0 +1,49 @@
|
|||
From 47f747217811db35854ea06741be3685e8bbd44d Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Mon, 17 Jul 2023 23:14:33 -0500
|
||||
Subject: [PATCH] x86: Fix slight bug in `shared_per_thread` cache size
|
||||
calculation.
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
After:
|
||||
```
|
||||
commit af992e7abdc9049714da76cae1e5e18bc4838fb8
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Jun 7 13:18:01 2023 -0500
|
||||
|
||||
x86: Increase `non_temporal_threshold` to roughly `sizeof_L3 / 4`
|
||||
```
|
||||
|
||||
Split `shared` (cumulative cache size) from `shared_per_thread` (cache
|
||||
size per socket), the `shared_per_thread` *can* be slightly off from
|
||||
the previous calculation.
|
||||
|
||||
Previously we added `core` even if `threads_l2` was invalid, and only
|
||||
used `threads_l2` to divide `core` if it was present. The changed
|
||||
version only included `core` if `threads_l2` was valid.
|
||||
|
||||
This change restores the old behavior if `threads_l2` is invalid by
|
||||
adding the entire value of `core`.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
---
|
||||
sysdeps/x86/dl-cacheinfo.h | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index c98fa57a7b..43be2c1229 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -614,8 +614,8 @@ get_common_cache_info (long int *shared_ptr, long int * shared_per_thread_ptr, u
|
||||
/* Account for non-inclusive L2 and L3 caches. */
|
||||
if (!inclusive_cache)
|
||||
{
|
||||
- if (threads_l2 > 0)
|
||||
- shared_per_thread += core / threads_l2;
|
||||
+ long int core_per_thread = threads_l2 > 0 ? (core / threads_l2) : core;
|
||||
+ shared_per_thread += core_per_thread;
|
||||
shared += core;
|
||||
}
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
From 8b9a0af8ca012217bf90d1dc0694f85b49ae09da Mon Sep 17 00:00:00 2001
|
||||
From: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Tue, 18 Jul 2023 10:27:59 -0500
|
||||
Subject: [PATCH] [PATCH v1] x86: Use `3/4*sizeof(per-thread-L3)` as low bound
|
||||
for NT threshold.
|
||||
Content-type: text/plain; charset=UTF-8
|
||||
|
||||
On some machines we end up with incomplete cache information. This can
|
||||
make the new calculation of `sizeof(total-L3)/custom-divisor` end up
|
||||
lower than intended (and lower than the prior value). So reintroduce
|
||||
the old bound as a lower bound to avoid potentially regressing code
|
||||
where we don't have complete information to make the decision.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
---
|
||||
sysdeps/x86/dl-cacheinfo.h | 15 ++++++++++++---
|
||||
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
[diff rebased by DJ]
|
||||
diff -rup a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h 2023-07-25 00:38:43.343986368 -0400
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h 2023-07-25 00:38:44.336025100 -0400
|
||||
@@ -751,8 +751,8 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
|
||||
/* The default setting for the non_temporal threshold is [1/8, 1/2] of size
|
||||
of the chip's cache (depending on `cachesize_non_temporal_divisor` which
|
||||
- is microarch specific. The defeault is 1/4). For most Intel and AMD
|
||||
- processors with an initial release date between 2017 and 2023, a thread's
|
||||
+ is microarch specific. The default is 1/4). For most Intel processors
|
||||
+ with an initial release date between 2017 and 2023, a thread's
|
||||
typical share of the cache is from 18-64MB. Using a reasonable size
|
||||
fraction of L3 is meant to estimate the point where non-temporal stores
|
||||
begin out-competing REP MOVSB. As well the point where the fact that
|
||||
@@ -763,12 +763,21 @@ dl_init_cacheinfo (struct cpu_features *
|
||||
the maximum thrashing capped at 1/associativity. */
|
||||
unsigned long int non_temporal_threshold
|
||||
= shared / cachesize_non_temporal_divisor;
|
||||
+
|
||||
+ /* If the computed non_temporal_threshold <= 3/4 * per-thread L3, we most
|
||||
+ likely have incorrect/incomplete cache info in which case, default to
|
||||
+ 3/4 * per-thread L3 to avoid regressions. */
|
||||
+ unsigned long int non_temporal_threshold_lowbound
|
||||
+ = shared_per_thread * 3 / 4;
|
||||
+ if (non_temporal_threshold < non_temporal_threshold_lowbound)
|
||||
+ non_temporal_threshold = non_temporal_threshold_lowbound;
|
||||
+
|
||||
/* If no ERMS, we use the per-thread L3 chunking. Normal cacheable stores run
|
||||
a higher risk of actually thrashing the cache as they don't have a HW LRU
|
||||
hint. As well, their performance in highly parallel situations is
|
||||
noticeably worse. */
|
||||
if (!CPU_FEATURE_USABLE_P (cpu_features, ERMS))
|
||||
- non_temporal_threshold = shared_per_thread * 3 / 4;
|
||||
+ non_temporal_threshold = non_temporal_threshold_lowbound;
|
||||
/* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
|
@ -0,0 +1,37 @@
|
|||
commit 885a7f0feee951f514a121788f46f33b2867110f
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Fri Aug 11 12:29:11 2023 -0500
|
||||
|
||||
x86: Fix incorrect scope of setting `shared_per_thread` [BZ# 30745]
|
||||
|
||||
The:
|
||||
|
||||
```
|
||||
if (shared_per_thread > 0 && threads > 0)
|
||||
shared_per_thread /= threads;
|
||||
```
|
||||
|
||||
Code was accidentally moved to inside the else scope. This doesn't
|
||||
match how it was previously (before af992e7abd).
|
||||
|
||||
This patch fixes that by putting the division after the `else` block.
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index aed1a7be56610e99..f950e488cfbe42dd 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -770,11 +770,10 @@ get_common_cache_info (long int *shared_ptr, long int * shared_per_thread_ptr, u
|
||||
level. */
|
||||
threads = ((cpu_features->features[CPUID_INDEX_1].cpuid.ebx >> 16)
|
||||
& 0xff);
|
||||
-
|
||||
- /* Get per-thread size of highest level cache. */
|
||||
- if (shared_per_thread > 0 && threads > 0)
|
||||
- shared_per_thread /= threads;
|
||||
}
|
||||
+ /* Get per-thread size of highest level cache. */
|
||||
+ if (shared_per_thread > 0 && threads > 0)
|
||||
+ shared_per_thread /= threads;
|
||||
}
|
||||
|
||||
/* Account for non-inclusive L2 and L3 caches. */
|
|
@ -0,0 +1,27 @@
|
|||
commit abcf8db7fa46b73fd5b8193ce11f9312301b84c7
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Wed Jun 7 11:21:48 2023 +0200
|
||||
|
||||
resolv_conf: release lock on allocation failure (bug 30527)
|
||||
|
||||
When the initial allocation of global fails, the local lock is left
|
||||
locked.
|
||||
|
||||
Reported by Steffen Lammel of SAP HANA development.
|
||||
|
||||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||||
index 9010bf0ea4d84557..aab79e9f4e323df9 100644
|
||||
--- a/resolv/resolv_conf.c
|
||||
+++ b/resolv/resolv_conf.c
|
||||
@@ -93,7 +93,10 @@ get_locked_global (void)
|
||||
{
|
||||
global_copy = calloc (1, sizeof (*global));
|
||||
if (global_copy == NULL)
|
||||
- return NULL;
|
||||
+ {
|
||||
+ __libc_lock_unlock (lock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
atomic_store_relaxed (&global, global_copy);
|
||||
resolv_conf_array_init (&global_copy->array);
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
commit 1d44530a5be2442e064baa48139adc9fdfb1fc6b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Jun 15 12:08:22 2023 +0200
|
||||
|
||||
string: strerror must not return NULL (bug 30555)
|
||||
|
||||
For strerror, this fixes commit 28aff047818eb1726394296d27b ("string:
|
||||
Implement strerror in terms of strerror_l"). This commit avoids
|
||||
returning NULL for strerror_l as well, although POSIX allows this
|
||||
behavior for strerror_l.
|
||||
|
||||
Reviewed-by: Arjun Shankar <arjun@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
string/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/string/Makefile b/string/Makefile
|
||||
index f0fce2a0b8dea752..a385c8fdfed330b2 100644
|
||||
--- a/string/Makefile
|
||||
+++ b/string/Makefile
|
||||
@@ -63,7 +63,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \
|
||||
tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt \
|
||||
test-endian-types test-endian-file-scope \
|
||||
test-endian-sign-conversion tst-memmove-overflow \
|
||||
- test-sig_np
|
||||
+ test-sig_np tst-strerror-fail
|
||||
|
||||
# Both tests require the .mo translation files generated by msgfmt.
|
||||
tests-translation := tst-strsignal \
|
||||
diff --git a/string/strerror_l.c b/string/strerror_l.c
|
||||
index a381c79c5a0ba2a1..20aa3efe4714faee 100644
|
||||
--- a/string/strerror_l.c
|
||||
+++ b/string/strerror_l.c
|
||||
@@ -43,10 +43,15 @@ __strerror_l (int errnum, locale_t loc)
|
||||
struct tls_internal_t *tls_internal = __glibc_tls_internal ();
|
||||
free (tls_internal->strerror_l_buf);
|
||||
if (__asprintf (&tls_internal->strerror_l_buf, "%s%d",
|
||||
- translate ("Unknown error ", loc), errnum) == -1)
|
||||
- tls_internal->strerror_l_buf = NULL;
|
||||
-
|
||||
- err = tls_internal->strerror_l_buf;
|
||||
+ translate ("Unknown error ", loc), errnum) > 0)
|
||||
+ err = tls_internal->strerror_l_buf;
|
||||
+ else
|
||||
+ {
|
||||
+ /* The memory was freed above. */
|
||||
+ tls_internal->strerror_l_buf = NULL;
|
||||
+ /* Provide a fallback translation. */
|
||||
+ err = (char *) translate ("Unknown error", loc);
|
||||
+ }
|
||||
}
|
||||
else
|
||||
err = (char *) translate (err, loc);
|
||||
diff --git a/string/tst-strerror-fail.c b/string/tst-strerror-fail.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e0fa45ab2b12f6b3
|
||||
--- /dev/null
|
||||
+++ b/string/tst-strerror-fail.c
|
||||
@@ -0,0 +1,77 @@
|
||||
+/* Check that strerror, strerror_l do not return NULL on failure (bug 30555).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+
|
||||
+#include <locale.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+
|
||||
+/* Interposed malloc that can be used to inject allocation failures. */
|
||||
+
|
||||
+static volatile bool fail_malloc;
|
||||
+
|
||||
+void *
|
||||
+malloc (size_t size)
|
||||
+{
|
||||
+ if (fail_malloc)
|
||||
+ return NULL;
|
||||
+
|
||||
+ static void *(*original_malloc) (size_t);
|
||||
+ if (original_malloc == NULL)
|
||||
+ original_malloc = xdlsym (RTLD_NEXT, "malloc");
|
||||
+ return original_malloc (size);
|
||||
+}
|
||||
+
|
||||
+/* Callbacks for the actual tests. Use fork to run both tests with a
|
||||
+ clean state. */
|
||||
+
|
||||
+static void
|
||||
+test_strerror (void *closure)
|
||||
+{
|
||||
+ fail_malloc = true;
|
||||
+ const char *s = strerror (999);
|
||||
+ fail_malloc = false;
|
||||
+ TEST_COMPARE_STRING (s, "Unknown error");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_strerror_l (void *closure)
|
||||
+{
|
||||
+ locale_t loc = newlocale (LC_ALL, "C", (locale_t) 0);
|
||||
+ TEST_VERIFY (loc != (locale_t) 0);
|
||||
+ fail_malloc = true;
|
||||
+ const char *s = strerror_l (999, loc);
|
||||
+ fail_malloc = false;
|
||||
+ TEST_COMPARE_STRING (s, "Unknown error");
|
||||
+ freelocale (loc);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ support_isolate_in_subprocess (test_strerror, NULL);
|
||||
+ support_isolate_in_subprocess (test_strerror_l, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,147 @@
|
|||
commit d653fd2d9ebe23c2b16b76edf717c5dbd5ce9b77
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Mar 10 08:50:51 2022 +0100
|
||||
|
||||
malloc: Exit early on test failure in tst-realloc
|
||||
|
||||
This addresses more (correct) use-after-free warnings reported by
|
||||
GCC 12 on some targets.
|
||||
|
||||
Fixes commit c094c232eb3246154265bb035182f92fe1b17ab8 ("Avoid
|
||||
-Wuse-after-free in tests [BZ #26779].").
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c
|
||||
index 80711beab1257ed5..e985b9d565086257 100644
|
||||
--- a/malloc/tst-realloc.c
|
||||
+++ b/malloc/tst-realloc.c
|
||||
@@ -20,15 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <libc-diag.h>
|
||||
-
|
||||
-static int errors = 0;
|
||||
-
|
||||
-static void
|
||||
-merror (const char *msg)
|
||||
-{
|
||||
- ++errors;
|
||||
- printf ("Error: %s\n", msg);
|
||||
-}
|
||||
+#include <support/check.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
@@ -51,11 +43,11 @@ do_test (void)
|
||||
save = errno;
|
||||
|
||||
if (p != NULL)
|
||||
- merror ("realloc (NULL, -1) succeeded.");
|
||||
+ FAIL_EXIT1 ("realloc (NULL, -1) succeeded.");
|
||||
|
||||
/* errno should be set to ENOMEM on failure (POSIX). */
|
||||
if (p == NULL && save != ENOMEM)
|
||||
- merror ("errno is not set correctly");
|
||||
+ FAIL_EXIT1 ("errno is not set correctly");
|
||||
|
||||
errno = 0;
|
||||
|
||||
@@ -64,18 +56,18 @@ do_test (void)
|
||||
save = errno;
|
||||
|
||||
if (p == NULL)
|
||||
- merror ("realloc (NULL, 10) failed.");
|
||||
+ FAIL_EXIT1 ("realloc (NULL, 10) failed.");
|
||||
|
||||
free (p);
|
||||
|
||||
p = calloc (20, 1);
|
||||
if (p == NULL)
|
||||
- merror ("calloc (20, 1) failed.");
|
||||
+ FAIL_EXIT1 ("calloc (20, 1) failed.");
|
||||
|
||||
/* Check increasing size preserves contents (C89). */
|
||||
p = realloc (p, 200);
|
||||
if (p == NULL)
|
||||
- merror ("realloc (p, 200) failed.");
|
||||
+ FAIL_EXIT1 ("realloc (p, 200) failed.");
|
||||
|
||||
c = p;
|
||||
ok = 1;
|
||||
@@ -87,20 +79,20 @@ do_test (void)
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
- merror ("first 20 bytes were not cleared");
|
||||
+ FAIL_EXIT1 ("first 20 bytes were not cleared");
|
||||
|
||||
free (p);
|
||||
|
||||
p = realloc (NULL, 100);
|
||||
if (p == NULL)
|
||||
- merror ("realloc (NULL, 100) failed.");
|
||||
+ FAIL_EXIT1 ("realloc (NULL, 100) failed.");
|
||||
|
||||
memset (p, 0xff, 100);
|
||||
|
||||
/* Check decreasing size preserves contents (C89). */
|
||||
p = realloc (p, 16);
|
||||
if (p == NULL)
|
||||
- merror ("realloc (p, 16) failed.");
|
||||
+ FAIL_EXIT1 ("realloc (p, 16) failed.");
|
||||
|
||||
c = p;
|
||||
ok = 1;
|
||||
@@ -112,7 +104,7 @@ do_test (void)
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
- merror ("first 16 bytes were not correct");
|
||||
+ FAIL_EXIT1 ("first 16 bytes were not correct");
|
||||
|
||||
/* Check failed realloc leaves original untouched (C89). */
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
@@ -124,7 +116,7 @@ do_test (void)
|
||||
c = realloc (p, -1);
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
if (c != NULL)
|
||||
- merror ("realloc (p, -1) succeeded.");
|
||||
+ FAIL_EXIT1 ("realloc (p, -1) succeeded.");
|
||||
|
||||
c = p;
|
||||
ok = 1;
|
||||
@@ -136,29 +128,21 @@ do_test (void)
|
||||
}
|
||||
|
||||
if (ok == 0)
|
||||
- merror ("first 16 bytes were not correct after failed realloc");
|
||||
+ FAIL_EXIT1 ("first 16 bytes were not correct after failed realloc");
|
||||
|
||||
-#if __GNUC_PREREQ (12, 0)
|
||||
- /* Ignore a valid warning about using a pointer made indeterminate
|
||||
- by a prior call to realloc(). */
|
||||
- DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
-#endif
|
||||
/* realloc (p, 0) frees p (C89) and returns NULL (glibc). */
|
||||
p = realloc (p, 0);
|
||||
-#if __GNUC_PREREQ (12, 0)
|
||||
- DIAG_POP_NEEDS_COMMENT;
|
||||
-#endif
|
||||
if (p != NULL)
|
||||
- merror ("realloc (p, 0) returned non-NULL.");
|
||||
+ FAIL_EXIT1 ("realloc (p, 0) returned non-NULL.");
|
||||
|
||||
/* realloc (NULL, 0) acts like malloc (0) (glibc). */
|
||||
p = realloc (NULL, 0);
|
||||
if (p == NULL)
|
||||
- merror ("realloc (NULL, 0) returned NULL.");
|
||||
+ FAIL_EXIT1 ("realloc (NULL, 0) returned NULL.");
|
||||
|
||||
free (p);
|
||||
|
||||
- return errors != 0;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
|
@ -0,0 +1,382 @@
|
|||
commit 3e5760fcb48528d48deeb60cb885a97bb731160c
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Wed Sep 28 20:09:34 2022 +0000
|
||||
|
||||
Update _FloatN header support for C++ in GCC 13
|
||||
|
||||
GCC 13 adds support for _FloatN and _FloatNx types in C++, so breaking
|
||||
the installed glibc headers that assume such support is not present.
|
||||
GCC mostly works around this with fixincludes, but that doesn't help
|
||||
for building glibc and its tests (glibc doesn't itself contain C++
|
||||
code, but there's C++ code built for tests). Update glibc's
|
||||
bits/floatn-common.h and bits/floatn.h headers to handle the GCC 13
|
||||
support directly.
|
||||
|
||||
In general the changes match those made by fixincludes, though I think
|
||||
the ones in sysdeps/powerpc/bits/floatn.h, where the header tests
|
||||
__LDBL_MANT_DIG__ == 113 or uses #elif, wouldn't match the existing
|
||||
fixincludes patterns.
|
||||
|
||||
Some places involving special C++ handling in relation to _FloatN
|
||||
support are not changed. There's no need to change the
|
||||
__HAVE_FLOATN_NOT_TYPEDEF definition (also in a form that wouldn't be
|
||||
matched by the fixincludes fixes) because it's only used in relation
|
||||
to macro definitions using features not supported for C++
|
||||
(__builtin_types_compatible_p and _Generic). And there's no need to
|
||||
change the inline function overloads for issignaling, iszero and
|
||||
iscanonical in C++ because cases where types have the same format but
|
||||
are no longer compatible types are handled automatically by the C++
|
||||
overload resolution rules.
|
||||
|
||||
This patch also does not change the overload handling for iseqsig, and
|
||||
there I think changes *are* needed, beyond those in this patch or made
|
||||
by fixincludes. The way that overload is defined, via a template
|
||||
parameter to a structure type, requires overloads whenever the types
|
||||
are incompatible, even if they have the same format. So I think we
|
||||
need to add overloads with GCC 13 for every supported _FloatN and
|
||||
_FloatNx type, rather than just having one for _Float128 when it has a
|
||||
different ABI to long double as at present (but for older GCC, such
|
||||
overloads must not be defined for types that end up defined as
|
||||
typedefs for another type).
|
||||
|
||||
Tested with build-many-glibcs.py: compilers build for
|
||||
aarch64-linux-gnu ia64-linux-gnu mips64-linux-gnu powerpc-linux-gnu
|
||||
powerpc64le-linux-gnu x86_64-linux-gnu; glibcs build for
|
||||
aarch64-linux-gnu ia64-linux-gnu i686-linux-gnu mips-linux-gnu
|
||||
mips64-linux-gnu-n32 powerpc-linux-gnu powerpc64le-linux-gnu
|
||||
x86_64-linux-gnu.
|
||||
|
||||
diff --git a/bits/floatn-common.h b/bits/floatn-common.h
|
||||
index b43c9532d8b01cca..45d4555f48483fff 100644
|
||||
--- a/bits/floatn-common.h
|
||||
+++ b/bits/floatn-common.h
|
||||
@@ -78,7 +78,7 @@
|
||||
or _FloatNx types, if __HAVE_<type> is 1. The corresponding
|
||||
literal suffixes exist since GCC 7, for C only. */
|
||||
# if __HAVE_FLOAT16
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* No corresponding suffix available for this type. */
|
||||
# define __f16(x) ((_Float16) x##f)
|
||||
# else
|
||||
@@ -87,7 +87,7 @@
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT32
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __f32(x) x##f
|
||||
# else
|
||||
# define __f32(x) x##f32
|
||||
@@ -95,7 +95,7 @@
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT64
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# ifdef __NO_LONG_DOUBLE_MATH
|
||||
# define __f64(x) x##l
|
||||
# else
|
||||
@@ -107,7 +107,7 @@
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT32X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __f32x(x) x
|
||||
# else
|
||||
# define __f32x(x) x##f32x
|
||||
@@ -115,7 +115,7 @@
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT64X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# if __HAVE_FLOAT64X_LONG_DOUBLE
|
||||
# define __f64x(x) x##l
|
||||
# else
|
||||
@@ -127,7 +127,7 @@
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT128X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# error "_Float128X supported but no constant suffix"
|
||||
# else
|
||||
# define __f128x(x) x##f128x
|
||||
@@ -136,7 +136,7 @@
|
||||
|
||||
/* Defined to a complex type if __HAVE_<type> is 1. */
|
||||
# if __HAVE_FLOAT16
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# define __CFLOAT16 __cfloat16
|
||||
# else
|
||||
@@ -145,7 +145,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT32
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __CFLOAT32 _Complex float
|
||||
# else
|
||||
# define __CFLOAT32 _Complex _Float32
|
||||
@@ -153,7 +153,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT64
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# ifdef __NO_LONG_DOUBLE_MATH
|
||||
# define __CFLOAT64 _Complex long double
|
||||
# else
|
||||
@@ -165,7 +165,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT32X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __CFLOAT32X _Complex double
|
||||
# else
|
||||
# define __CFLOAT32X _Complex _Float32x
|
||||
@@ -173,7 +173,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT64X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# if __HAVE_FLOAT64X_LONG_DOUBLE
|
||||
# define __CFLOAT64X _Complex long double
|
||||
# else
|
||||
@@ -185,7 +185,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
# endif
|
||||
|
||||
# if __HAVE_FLOAT128X
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# error "_Float128X supported but no complex type"
|
||||
# else
|
||||
# define __CFLOAT128X _Complex _Float128x
|
||||
@@ -195,7 +195,7 @@ typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
|
||||
/* The remaining of this file provides support for older compilers. */
|
||||
# if __HAVE_FLOAT16
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
|
||||
# endif
|
||||
|
||||
@@ -210,7 +210,7 @@ typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
|
||||
|
||||
# if __HAVE_FLOAT32
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef float _Float32;
|
||||
# endif
|
||||
|
||||
@@ -234,7 +234,7 @@ typedef float _Float32;
|
||||
|
||||
# ifdef __NO_LONG_DOUBLE_MATH
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef long double _Float64;
|
||||
# endif
|
||||
|
||||
@@ -247,7 +247,7 @@ typedef long double _Float64;
|
||||
|
||||
# else
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef double _Float64;
|
||||
# endif
|
||||
|
||||
@@ -264,7 +264,7 @@ typedef double _Float64;
|
||||
|
||||
# if __HAVE_FLOAT32X
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef double _Float32x;
|
||||
# endif
|
||||
|
||||
@@ -281,7 +281,7 @@ typedef double _Float32x;
|
||||
|
||||
# if __HAVE_FLOAT64X_LONG_DOUBLE
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef long double _Float64x;
|
||||
# endif
|
||||
|
||||
@@ -294,7 +294,7 @@ typedef long double _Float64x;
|
||||
|
||||
# else
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef _Float128 _Float64x;
|
||||
# endif
|
||||
|
||||
@@ -311,7 +311,7 @@ typedef _Float128 _Float64x;
|
||||
|
||||
# if __HAVE_FLOAT128X
|
||||
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# error "_Float128x supported but no type"
|
||||
# endif
|
||||
|
||||
diff --git a/sysdeps/ia64/bits/floatn.h b/sysdeps/ia64/bits/floatn.h
|
||||
index 60c5a130e12d88a1..3d493909aeebf81e 100644
|
||||
--- a/sysdeps/ia64/bits/floatn.h
|
||||
+++ b/sysdeps/ia64/bits/floatn.h
|
||||
@@ -56,7 +56,7 @@
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The literal suffix f128 exists only since GCC 7.0. */
|
||||
# define __f128(x) x##q
|
||||
# else
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* Add a typedef for older GCC compilers which don't natively support
|
||||
_Complex _Float128. */
|
||||
typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
@@ -80,7 +80,7 @@ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
# if __HAVE_FLOAT128
|
||||
|
||||
/* The type _Float128 exists only since GCC 7.0. */
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef __float128 _Float128;
|
||||
# endif
|
||||
|
||||
diff --git a/sysdeps/ieee754/ldbl-128/bits/floatn.h b/sysdeps/ieee754/ldbl-128/bits/floatn.h
|
||||
index da50ae796f681c60..d75a3d12e890c0be 100644
|
||||
--- a/sysdeps/ieee754/ldbl-128/bits/floatn.h
|
||||
+++ b/sysdeps/ieee754/ldbl-128/bits/floatn.h
|
||||
@@ -55,7 +55,7 @@
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The literal suffix f128 exists only since GCC 7.0. */
|
||||
# define __f128(x) x##l
|
||||
# else
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __CFLOAT128 _Complex long double
|
||||
# else
|
||||
# define __CFLOAT128 _Complex _Float128
|
||||
@@ -76,7 +76,7 @@
|
||||
# if __HAVE_FLOAT128
|
||||
|
||||
/* The type _Float128 exists only since GCC 7.0. */
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef long double _Float128;
|
||||
# endif
|
||||
|
||||
diff --git a/sysdeps/mips/ieee754/bits/floatn.h b/sysdeps/mips/ieee754/bits/floatn.h
|
||||
index b7720a2889e59e8f..fe7be983592e1e0e 100644
|
||||
--- a/sysdeps/mips/ieee754/bits/floatn.h
|
||||
+++ b/sysdeps/mips/ieee754/bits/floatn.h
|
||||
@@ -55,7 +55,7 @@
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The literal suffix f128 exists only since GCC 7.0. */
|
||||
# define __f128(x) x##l
|
||||
# else
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
# define __CFLOAT128 _Complex long double
|
||||
# else
|
||||
# define __CFLOAT128 _Complex _Float128
|
||||
@@ -76,7 +76,7 @@
|
||||
# if __HAVE_FLOAT128
|
||||
|
||||
/* The type _Float128 exists only since GCC 7.0. */
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef long double _Float128;
|
||||
# endif
|
||||
|
||||
diff --git a/sysdeps/powerpc/bits/floatn.h b/sysdeps/powerpc/bits/floatn.h
|
||||
index fab164e0a2907668..a5a572f646dac2bf 100644
|
||||
--- a/sysdeps/powerpc/bits/floatn.h
|
||||
+++ b/sysdeps/powerpc/bits/floatn.h
|
||||
@@ -57,7 +57,7 @@
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The literal suffix (f128) exist for powerpc only since GCC 7.0. */
|
||||
# if __LDBL_MANT_DIG__ == 113
|
||||
# define __f128(x) x##l
|
||||
@@ -71,10 +71,10 @@
|
||||
|
||||
/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if __LDBL_MANT_DIG__ == 113 && defined __cplusplus
|
||||
+# if __LDBL_MANT_DIG__ == 113 && defined __cplusplus && !__GNUC_PREREQ (13, 0)
|
||||
typedef long double _Float128;
|
||||
# define __CFLOAT128 _Complex long double
|
||||
-# elif !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# elif !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The type _Float128 exist for powerpc only since GCC 7.0. */
|
||||
typedef __float128 _Float128;
|
||||
/* Add a typedef for older GCC and C++ compilers which don't natively support
|
||||
diff --git a/sysdeps/x86/bits/floatn.h b/sysdeps/x86/bits/floatn.h
|
||||
index f0c51716a99c1886..8674273f46b87069 100644
|
||||
--- a/sysdeps/x86/bits/floatn.h
|
||||
+++ b/sysdeps/x86/bits/floatn.h
|
||||
@@ -58,7 +58,7 @@
|
||||
/* Defined to concatenate the literal suffix to be used with _Float128
|
||||
types, if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* The literal suffix f128 exists only since GCC 7.0. */
|
||||
# define __f128(x) x##q
|
||||
# else
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
/* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */
|
||||
# if __HAVE_FLOAT128
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
/* Add a typedef for older GCC compilers which don't natively support
|
||||
_Complex _Float128. */
|
||||
typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
@@ -82,7 +82,7 @@ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
|
||||
# if __HAVE_FLOAT128
|
||||
|
||||
/* The type _Float128 exists only since GCC 7.0. */
|
||||
-# if !__GNUC_PREREQ (7, 0) || defined __cplusplus
|
||||
+# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
|
||||
typedef __float128 _Float128;
|
||||
# endif
|
||||
|
|
@ -0,0 +1,897 @@
|
|||
commit f66780ba46805760a328f01967836416b06c93ca
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Oct 31 23:20:08 2022 +0000
|
||||
|
||||
Fix build with GCC 13 _FloatN, _FloatNx built-in functions
|
||||
|
||||
GCC 13 has added more _FloatN and _FloatNx versions of existing
|
||||
<math.h> and <complex.h> built-in functions, for use in libstdc++-v3.
|
||||
|
||||
This breaks the glibc build because of how those functions are defined
|
||||
as aliases to functions with the same ABI but different types. Add
|
||||
appropriate -fno-builtin-* options for compiling relevant files, as
|
||||
already done for the case of long double functions aliasing double
|
||||
ones and based on the list of files used there.
|
||||
|
||||
I fixed some mistakes in that list of double files that I noticed
|
||||
while implementing this fix, but there may well be more such
|
||||
(harmless) cases, in this list or the new one (files that don't
|
||||
actually exist or don't define the named functions as aliases so don't
|
||||
need the options). I did try to exclude cases where glibc doesn't
|
||||
define certain functions for _FloatN or _FloatNx types at all from the
|
||||
new uses of -fno-builtin-* options. As with the options for double
|
||||
files (see the commit message for commit
|
||||
49348beafe9ba150c9bd48595b3f372299bddbb0, "Fix build with GCC 10 when
|
||||
long double = double."), it's deliberate that the options are used
|
||||
even if GCC currently doesn't have a built-in version of a given
|
||||
functions, so providing some level of future-proofing against more
|
||||
such built-in functions being added in future.
|
||||
|
||||
Tested with build-many-glibcs.py for aarch64-linux-gnu
|
||||
powerpc-linux-gnu powerpc64le-linux-gnu x86_64-linux-gnu (compilers
|
||||
and glibcs builds) with GCC mainline.
|
||||
|
||||
Conflicts:
|
||||
math/Makefile
|
||||
(missing narrowing fma, sqrt downstream)
|
||||
|
||||
diff --git a/math/Makefile b/math/Makefile
|
||||
index ceb1eb2085c8bfd4..2edb044d9d590de1 100644
|
||||
--- a/math/Makefile
|
||||
+++ b/math/Makefile
|
||||
@@ -661,16 +661,18 @@ CFLAGS-s_csinh.c += -fno-builtin-csinhl
|
||||
CFLAGS-s_csqrt.c += -fno-builtin-csqrtl
|
||||
CFLAGS-s_ctan.c += -fno-builtin-ctanl
|
||||
CFLAGS-s_ctanh.c += -fno-builtin-ctanhl
|
||||
-CFLAGS-s_dadd.c += -fno-builtin-daddl
|
||||
-CFLAGS-s_ddiv.c += -fno-builtin-ddivl
|
||||
-CFLAGS-s_dmul.c += -fno-builtin-dmull
|
||||
-CFLAGS-s_dsub.c += -fno-builtin-dsubl
|
||||
CFLAGS-s_erf.c += -fno-builtin-erfl
|
||||
CFLAGS-s_erfc.c += -fno-builtin-erfcl
|
||||
CFLAGS-e_exp.c += -fno-builtin-expl
|
||||
CFLAGS-w_exp10.c += -fno-builtin-exp10l
|
||||
CFLAGS-e_exp2.c += -fno-builtin-exp2l
|
||||
CFLAGS-s_expm1.c += -fno-builtin-expm1l
|
||||
+CFLAGS-s_f32xaddf64.c += -fno-builtin-daddl
|
||||
+CFLAGS-s_f32xdivf64.c += -fno-builtin-ddivl
|
||||
+CFLAGS-s_f32xfmaf64.c += -fno-builtin-dfmal
|
||||
+CFLAGS-s_f32xmulf64.c += -fno-builtin-dmull
|
||||
+CFLAGS-s_f32xsqrtf64.c += -fno-builtin-dsqrtl
|
||||
+CFLAGS-s_f32xsubf64.c += -fno-builtin-dsubl
|
||||
CFLAGS-s_fabs.c += -fno-builtin-fabsl
|
||||
CFLAGS-s_fadd.c += -fno-builtin-faddl
|
||||
CFLAGS-s_fdim.c += -fno-builtin-fdiml
|
||||
@@ -688,7 +690,6 @@ CFLAGS-s_frexp.c += -fno-builtin-frexpl
|
||||
CFLAGS-s_fromfp.c += -fno-builtin-fromfpl
|
||||
CFLAGS-s_fromfpx.c += -fno-builtin-fromfpxl
|
||||
CFLAGS-s_fsub.c += -fno-builtin-fsubl
|
||||
-CFLAGS-s_gamma.c += -fno-builtin-gammal
|
||||
CFLAGS-s_getpayload.c += -fno-builtin-getpayloadl
|
||||
CFLAGS-w_hypot.c += -fno-builtin-hypotl
|
||||
CFLAGS-w_ilogb.c += -fno-builtin-ilogbl
|
||||
@@ -747,6 +748,240 @@ CFLAGS-s_y1.c += -fno-builtin-y1l
|
||||
CFLAGS-s_yn.c += -fno-builtin-ynl
|
||||
endif
|
||||
|
||||
+# Likewise, for _Float32x and _Float64 aliases.
|
||||
+CFLAGS-w_acos.c += -fno-builtin-acosf32x -fno-builtin-acosf64
|
||||
+CFLAGS-w_acosh.c += -fno-builtin-acoshf32x -fno-builtin-acoshf64
|
||||
+CFLAGS-w_asin.c += -fno-builtin-asinf32x -fno-builtin-asinf64
|
||||
+CFLAGS-s_asinh.c += -fno-builtin-asinhf32x -fno-builtin-asinhf64
|
||||
+CFLAGS-s_atan.c += -fno-builtin-atanf32x -fno-builtin-atanf64
|
||||
+CFLAGS-w_atan2.c += -fno-builtin-atan2f32x -fno-builtin-atan2f64
|
||||
+CFLAGS-w_atanh.c += -fno-builtin-atanhf32x -fno-builtin-atanhf64
|
||||
+CFLAGS-s_cabs.c += -fno-builtin-cabsf32x -fno-builtin-cabsf64
|
||||
+CFLAGS-s_cacos.c += -fno-builtin-cacosf32x -fno-builtin-cacosf64
|
||||
+CFLAGS-s_cacosh.c += -fno-builtin-cacoshf32x -fno-builtin-cacoshf64
|
||||
+CFLAGS-s_canonicalize.c += -fno-builtin-canonicalizef32x -fno-builtin-canonicalizef64
|
||||
+CFLAGS-s_carg.c += -fno-builtin-cargf32x -fno-builtin-cargf64
|
||||
+CFLAGS-s_casin.c += -fno-builtin-casinf32x -fno-builtin-casinf64
|
||||
+CFLAGS-s_casinh.c += -fno-builtin-casinhf32x -fno-builtin-casinhf64
|
||||
+CFLAGS-s_catan.c += -fno-builtin-catanf32x -fno-builtin-catanf64
|
||||
+CFLAGS-s_catanh.c += -fno-builtin-catanhf32x -fno-builtin-catanhf64
|
||||
+CFLAGS-s_cbrt.c += -fno-builtin-cbrtf32x -fno-builtin-cbrtf64
|
||||
+CFLAGS-s_ccos.c += -fno-builtin-ccosf32x -fno-builtin-ccosf64
|
||||
+CFLAGS-s_ccosh.c += -fno-builtin-ccoshf32x -fno-builtin-ccoshf64
|
||||
+CFLAGS-s_ceil.c += -fno-builtin-ceilf32x -fno-builtin-ceilf64
|
||||
+CFLAGS-s_cexp.c += -fno-builtin-cexpf32x -fno-builtin-cexpf64
|
||||
+CFLAGS-s_cimag.c += -fno-builtin-cimagf32x -fno-builtin-cimagf64
|
||||
+CFLAGS-s_clog.c += -fno-builtin-clogf32x -fno-builtin-clogf64
|
||||
+CFLAGS-s_clog10.c += -fno-builtin-clog10f32x -fno-builtin-clog10f64
|
||||
+CFLAGS-s_conj.c += -fno-builtin-conjf32x -fno-builtin-conjf64
|
||||
+CFLAGS-s_copysign.c += -fno-builtin-copysignf32x -fno-builtin-copysignf64
|
||||
+CFLAGS-s_cos.c += -fno-builtin-cosf32x -fno-builtin-cosf64
|
||||
+CFLAGS-w_cosh.c += -fno-builtin-coshf32x -fno-builtin-coshf64
|
||||
+CFLAGS-s_cpow.c += -fno-builtin-cpowf32x -fno-builtin-cpowf64
|
||||
+CFLAGS-s_cproj.c += -fno-builtin-cprojf32x -fno-builtin-cprojf64
|
||||
+CFLAGS-s_creal.c += -fno-builtin-crealf32x -fno-builtin-crealf64
|
||||
+CFLAGS-s_csin.c += -fno-builtin-csinf32x -fno-builtin-csinf64
|
||||
+CFLAGS-s_csinh.c += -fno-builtin-csinhf32x -fno-builtin-csinhf64
|
||||
+CFLAGS-s_csqrt.c += -fno-builtin-csqrtf32x -fno-builtin-csqrtf64
|
||||
+CFLAGS-s_ctan.c += -fno-builtin-ctanf32x -fno-builtin-ctanf64
|
||||
+CFLAGS-s_ctanh.c += -fno-builtin-ctanhf32x -fno-builtin-ctanhf64
|
||||
+CFLAGS-s_erf.c += -fno-builtin-erff32x -fno-builtin-erff64
|
||||
+CFLAGS-s_erfc.c += -fno-builtin-erfcf32x -fno-builtin-erfcf64
|
||||
+CFLAGS-e_exp.c += -fno-builtin-expf32x -fno-builtin-expf64
|
||||
+CFLAGS-w_exp10.c += -fno-builtin-exp10f32x -fno-builtin-exp10f64
|
||||
+CFLAGS-e_exp2.c += -fno-builtin-exp2f32x -fno-builtin-exp2f64
|
||||
+CFLAGS-s_expm1.c += -fno-builtin-expm1f32x -fno-builtin-expm1f64
|
||||
+CFLAGS-s_fabs.c += -fno-builtin-fabsf32x -fno-builtin-fabsf64
|
||||
+CFLAGS-s_fadd.c += -fno-builtin-f32addf32x -fno-builtin-f32addf64
|
||||
+CFLAGS-s_fdim.c += -fno-builtin-fdimf32x -fno-builtin-fdimf64
|
||||
+CFLAGS-s_fdiv.c += -fno-builtin-f32divf32x -fno-builtin-f32divf64
|
||||
+CFLAGS-s_ffma.c += -fno-builtin-f32fmaf32x -fno-builtin-f32fmaf64
|
||||
+CFLAGS-s_floor.c += -fno-builtin-floorf32x -fno-builtin-floorf64
|
||||
+CFLAGS-s_fma.c += -fno-builtin-fmaf32x -fno-builtin-fmaf64
|
||||
+CFLAGS-s_fmax.c += -fno-builtin-fmaxf32x -fno-builtin-fmaxf64
|
||||
+CFLAGS-s_fmaximum.c += -fno-builtin-fmaximumf32x -fno-builtin-fmaximumf64
|
||||
+CFLAGS-s_fmaximum_mag.c += -fno-builtin-fmaximum_magf32x -fno-builtin-fmaximum_magf64
|
||||
+CFLAGS-s_fmaximum_mag_num.c += -fno-builtin-fmaximum_mag_numf32x -fno-builtin-fmaximum_mag_numf64
|
||||
+CFLAGS-s_fmaximum_num.c += -fno-builtin-fmaximum_numf32x -fno-builtin-fmaximum_numf64
|
||||
+CFLAGS-s_fmaxmag.c += -fno-builtin-fmaxmagf32x -fno-builtin-fmaxmagf64
|
||||
+CFLAGS-s_fmin.c += -fno-builtin-fminf32x -fno-builtin-fminf64
|
||||
+CFLAGS-s_fminimum.c += -fno-builtin-fminimumf32x -fno-builtin-fminimumf64
|
||||
+CFLAGS-s_fminimum_mag.c += -fno-builtin-fminimum_magf32x -fno-builtin-fminimum_magf64
|
||||
+CFLAGS-s_fminimum_mag_num.c += -fno-builtin-fminimum_mag_numf32x -fno-builtin-fminimum_mag_numf64
|
||||
+CFLAGS-s_fminimum_num.c += -fno-builtin-fminimum_numf32x -fno-builtin-fminimum_numf64
|
||||
+CFLAGS-s_fminmag.c += -fno-builtin-fminmagf32x -fno-builtin-fminmagf64
|
||||
+CFLAGS-w_fmod.c += -fno-builtin-fmodf32x -fno-builtin-fmodf64
|
||||
+CFLAGS-s_fmul.c += -fno-builtin-f32mulf32x -fno-builtin-f32mulf64
|
||||
+CFLAGS-s_frexp.c += -fno-builtin-frexpf32x -fno-builtin-frexpf64
|
||||
+CFLAGS-s_fromfp.c += -fno-builtin-fromfpf32x -fno-builtin-fromfpf64
|
||||
+CFLAGS-s_fromfpx.c += -fno-builtin-fromfpxf32x -fno-builtin-fromfpxf64
|
||||
+CFLAGS-s_fsqrt.c += -fno-builtin-f32sqrtf32x -fno-builtin-f32sqrtf64
|
||||
+CFLAGS-s_fsub.c += -fno-builtin-f32subf32x -fno-builtin-f32subf64
|
||||
+CFLAGS-s_getpayload.c += -fno-builtin-getpayloadf32x -fno-builtin-getpayloadf64
|
||||
+CFLAGS-w_hypot.c += -fno-builtin-hypotf32x -fno-builtin-hypotf64
|
||||
+CFLAGS-w_ilogb.c += -fno-builtin-ilogbf32x -fno-builtin-ilogbf64
|
||||
+CFLAGS-w_j0.c += -fno-builtin-j0f32x -fno-builtin-j0f64
|
||||
+CFLAGS-w_j1.c += -fno-builtin-j1f32x -fno-builtin-j1f64
|
||||
+CFLAGS-w_jn.c += -fno-builtin-jnf32x -fno-builtin-jnf64
|
||||
+CFLAGS-s_ldexp.c += -fno-builtin-ldexpf32x -fno-builtin-ldexpf64
|
||||
+CFLAGS-w_lgamma.c += -fno-builtin-lgammaf32x -fno-builtin-lgammaf64
|
||||
+CFLAGS-w_lgamma_r.c += -fno-builtin-lgammaf32x_r -fno-builtin-lgammaf64_r
|
||||
+CFLAGS-w_llogb.c += -fno-builtin-llogbf32x -fno-builtin-llogbf64
|
||||
+CFLAGS-s_llrint.c += -fno-builtin-llrintf32x -fno-builtin-llrintf64
|
||||
+CFLAGS-s_llround.c += -fno-builtin-llroundf32x -fno-builtin-llroundf64
|
||||
+CFLAGS-e_log.c += -fno-builtin-logf32x -fno-builtin-logf64
|
||||
+CFLAGS-w_log10.c += -fno-builtin-log10f32x -fno-builtin-log10f64
|
||||
+CFLAGS-w_log1p.c += -fno-builtin-log1pf32x -fno-builtin-log1pf64
|
||||
+CFLAGS-e_log2.c += -fno-builtin-log2f32x -fno-builtin-log2f64
|
||||
+CFLAGS-s_logb.c += -fno-builtin-logbf32x -fno-builtin-logbf64
|
||||
+CFLAGS-s_lrint.c += -fno-builtin-lrintf32x -fno-builtin-lrintf64
|
||||
+CFLAGS-s_lround.c += -fno-builtin-lroundf32x -fno-builtin-lroundf64
|
||||
+CFLAGS-s_modf.c += -fno-builtin-modff32x -fno-builtin-modff64
|
||||
+CFLAGS-s_nan.c += -fno-builtin-nanf32x -fno-builtin-nanf64
|
||||
+CFLAGS-s_nearbyint.c += -fno-builtin-nearbyintf32x -fno-builtin-nearbyintf64
|
||||
+CFLAGS-s_nextafter.c += -fno-builtin-nextafterf32x -fno-builtin-nextafterf64
|
||||
+CFLAGS-s_nextdown.c += -fno-builtin-nextdownf32x -fno-builtin-nextdownf64
|
||||
+CFLAGS-s_nextup.c += -fno-builtin-nextupf32x -fno-builtin-nextupf64
|
||||
+CFLAGS-e_pow.c += -fno-builtin-powf32x -fno-builtin-powf64
|
||||
+CFLAGS-w_remainder.c += -fno-builtin-remainderf32x -fno-builtin-remainderf64
|
||||
+CFLAGS-s_remquo.c += -fno-builtin-remquof32x -fno-builtin-remquof64
|
||||
+CFLAGS-s_rint.c += -fno-builtin-rintf32x -fno-builtin-rintf64
|
||||
+CFLAGS-s_round.c += -fno-builtin-roundf32x -fno-builtin-roundf64
|
||||
+CFLAGS-s_roundeven.c += -fno-builtin-roundevenf32x -fno-builtin-roundevenf64
|
||||
+CFLAGS-w_scalbln.c += -fno-builtin-scalblnf32x -fno-builtin-scalblnf64
|
||||
+CFLAGS-s_scalbn.c += -fno-builtin-scalbnf32x -fno-builtin-scalbnf64
|
||||
+CFLAGS-s_setpayload.c += -fno-builtin-setpayloadf32x -fno-builtin-setpayloadf64
|
||||
+CFLAGS-s_setpayloadsig.c += -fno-builtin-setpayloadsigf32x -fno-builtin-setpayloadsigf64
|
||||
+CFLAGS-s_sin.c += -fno-builtin-sinf32x -fno-builtin-sinf64
|
||||
+CFLAGS-s_sincos.c += -fno-builtin-sincosf32x -fno-builtin-sincosf64
|
||||
+CFLAGS-w_sinh.c += -fno-builtin-sinhf32x -fno-builtin-sinhf64
|
||||
+CFLAGS-w_sqrt.c += -fno-builtin-sqrtf32x -fno-builtin-sqrtf64
|
||||
+CFLAGS-s_tan.c += -fno-builtin-tanf32x -fno-builtin-tanf64
|
||||
+CFLAGS-s_tanh.c += -fno-builtin-tanhf32x -fno-builtin-tanhf64
|
||||
+CFLAGS-w_tgamma.c += -fno-builtin-tgammaf32x -fno-builtin-tgammaf64
|
||||
+CFLAGS-s_totalorder.c += -fno-builtin-totalorderf32x -fno-builtin-totalorderf64
|
||||
+CFLAGS-s_totalordermag.c += -fno-builtin-totalordermagf32x -fno-builtin-totalordermagf64
|
||||
+CFLAGS-s_trunc.c += -fno-builtin-truncf32x -fno-builtin-truncf64
|
||||
+CFLAGS-s_ufromfp.c += -fno-builtin-ufromfpf32x -fno-builtin-ufromfpf64
|
||||
+CFLAGS-s_ufromfpx.c += -fno-builtin-ufromfpxf32x -fno-builtin-ufromfpxf64
|
||||
+CFLAGS-s_y0.c += -fno-builtin-y0f32x -fno-builtin-y0f64
|
||||
+CFLAGS-s_y1.c += -fno-builtin-y1f32x -fno-builtin-y1f64
|
||||
+CFLAGS-s_yn.c += -fno-builtin-ynf32x -fno-builtin-ynf64
|
||||
+
|
||||
+# Likewise, for _Float32 aliases.
|
||||
+CFLAGS-w_acosf.c += -fno-builtin-acosf32
|
||||
+CFLAGS-w_acoshf.c += -fno-builtin-acoshf32
|
||||
+CFLAGS-w_asinf.c += -fno-builtin-asinf32
|
||||
+CFLAGS-s_asinhf.c += -fno-builtin-asinhf32
|
||||
+CFLAGS-s_atanf.c += -fno-builtin-atanf32
|
||||
+CFLAGS-w_atan2f.c += -fno-builtin-atan2f32
|
||||
+CFLAGS-w_atanhf.c += -fno-builtin-atanhf32
|
||||
+CFLAGS-s_cabsf.c += -fno-builtin-cabsf32
|
||||
+CFLAGS-s_cacosf.c += -fno-builtin-cacosf32
|
||||
+CFLAGS-s_cacoshf.c += -fno-builtin-cacoshf32
|
||||
+CFLAGS-s_canonicalizef.c += -fno-builtin-canonicalizef32
|
||||
+CFLAGS-s_cargf.c += -fno-builtin-cargf32
|
||||
+CFLAGS-s_casinf.c += -fno-builtin-casinf32
|
||||
+CFLAGS-s_casinhf.c += -fno-builtin-casinhf32
|
||||
+CFLAGS-s_catanf.c += -fno-builtin-catanf32
|
||||
+CFLAGS-s_catanhf.c += -fno-builtin-catanhf32
|
||||
+CFLAGS-s_cbrtf.c += -fno-builtin-cbrtf32
|
||||
+CFLAGS-s_ccosf.c += -fno-builtin-ccosf32
|
||||
+CFLAGS-s_ccoshf.c += -fno-builtin-ccoshf32
|
||||
+CFLAGS-s_ceilf.c += -fno-builtin-ceilf32
|
||||
+CFLAGS-s_cexpf.c += -fno-builtin-cexpf32
|
||||
+CFLAGS-s_cimagf.c += -fno-builtin-cimagf32
|
||||
+CFLAGS-s_clogf.c += -fno-builtin-clogf32
|
||||
+CFLAGS-s_clog10f.c += -fno-builtin-clog10f32
|
||||
+CFLAGS-s_conjf.c += -fno-builtin-conjf32
|
||||
+CFLAGS-s_copysignf.c += -fno-builtin-copysignf32
|
||||
+CFLAGS-s_cosf.c += -fno-builtin-cosf32
|
||||
+CFLAGS-w_coshf.c += -fno-builtin-coshf32
|
||||
+CFLAGS-s_cpowf.c += -fno-builtin-cpowf32
|
||||
+CFLAGS-s_cprojf.c += -fno-builtin-cprojf32
|
||||
+CFLAGS-s_crealf.c += -fno-builtin-crealf32
|
||||
+CFLAGS-s_csinf.c += -fno-builtin-csinf32
|
||||
+CFLAGS-s_csinhf.c += -fno-builtin-csinhf32
|
||||
+CFLAGS-s_csqrtf.c += -fno-builtin-csqrtf32
|
||||
+CFLAGS-s_ctanf.c += -fno-builtin-ctanf32
|
||||
+CFLAGS-s_ctanhf.c += -fno-builtin-ctanhf32
|
||||
+CFLAGS-s_erff.c += -fno-builtin-erff32
|
||||
+CFLAGS-s_erfcf.c += -fno-builtin-erfcf32
|
||||
+CFLAGS-e_expf.c += -fno-builtin-expf32
|
||||
+CFLAGS-w_exp10f.c += -fno-builtin-exp10f32
|
||||
+CFLAGS-e_exp2f.c += -fno-builtin-exp2f32
|
||||
+CFLAGS-s_expm1f.c += -fno-builtin-expm1f32
|
||||
+CFLAGS-s_fabsf.c += -fno-builtin-fabsf32
|
||||
+CFLAGS-s_fdimf.c += -fno-builtin-fdimf32
|
||||
+CFLAGS-s_floorf.c += -fno-builtin-floorf32
|
||||
+CFLAGS-s_fmaf.c += -fno-builtin-fmaf32
|
||||
+CFLAGS-s_fmaxf.c += -fno-builtin-fmaxf32
|
||||
+CFLAGS-s_fmaximumf.c += -fno-builtin-fmaximumf32
|
||||
+CFLAGS-s_fmaximum_magf.c += -fno-builtin-fmaximum_magf32
|
||||
+CFLAGS-s_fmaximum_mag_numf.c += -fno-builtin-fmaximum_mag_numf32
|
||||
+CFLAGS-s_fmaximum_numf.c += -fno-builtin-fmaximum_numf32
|
||||
+CFLAGS-s_fmaxmagf.c += -fno-builtin-fmaxmagf32
|
||||
+CFLAGS-s_fminf.c += -fno-builtin-fminf32
|
||||
+CFLAGS-s_fminimumf.c += -fno-builtin-fminimumf32
|
||||
+CFLAGS-s_fminimum_magf.c += -fno-builtin-fminimum_magf32
|
||||
+CFLAGS-s_fminimum_mag_numf.c += -fno-builtin-fminimum_mag_numf32
|
||||
+CFLAGS-s_fminimum_numf.c += -fno-builtin-fminimum_numf32
|
||||
+CFLAGS-s_fminmagf.c += -fno-builtin-fminmagf32
|
||||
+CFLAGS-w_fmodf.c += -fno-builtin-fmodf32
|
||||
+CFLAGS-s_frexpf.c += -fno-builtin-frexpf32
|
||||
+CFLAGS-s_fromfpf.c += -fno-builtin-fromfpf32
|
||||
+CFLAGS-s_fromfpxf.c += -fno-builtin-fromfpxf32
|
||||
+CFLAGS-s_getpayloadf.c += -fno-builtin-getpayloadf32
|
||||
+CFLAGS-w_hypotf.c += -fno-builtin-hypotf32
|
||||
+CFLAGS-w_ilogbf.c += -fno-builtin-ilogbf32
|
||||
+CFLAGS-w_j0f.c += -fno-builtin-j0f32
|
||||
+CFLAGS-w_j1f.c += -fno-builtin-j1f32
|
||||
+CFLAGS-w_jnf.c += -fno-builtin-jnf32
|
||||
+CFLAGS-s_ldexpf.c += -fno-builtin-ldexpf32
|
||||
+CFLAGS-w_lgammaf.c += -fno-builtin-lgammaf32
|
||||
+CFLAGS-w_lgammaf_r.c += -fno-builtin-lgammaf32_r
|
||||
+CFLAGS-w_llogbf.c += -fno-builtin-llogbf32
|
||||
+CFLAGS-s_llrintf.c += -fno-builtin-llrintf32
|
||||
+CFLAGS-s_llroundf.c += -fno-builtin-llroundf32
|
||||
+CFLAGS-e_logf.c += -fno-builtin-logf32
|
||||
+CFLAGS-w_log10f.c += -fno-builtin-log10f32
|
||||
+CFLAGS-w_log1pf.c += -fno-builtin-log1pf32
|
||||
+CFLAGS-e_log2f.c += -fno-builtin-log2f32
|
||||
+CFLAGS-s_logbf.c += -fno-builtin-logbf32
|
||||
+CFLAGS-s_lrintf.c += -fno-builtin-lrintf32
|
||||
+CFLAGS-s_lroundf.c += -fno-builtin-lroundf32
|
||||
+CFLAGS-s_modff.c += -fno-builtin-modff32
|
||||
+CFLAGS-s_nanf.c += -fno-builtin-nanf32
|
||||
+CFLAGS-s_nearbyintf.c += -fno-builtin-nearbyintf32
|
||||
+CFLAGS-s_nextafterf.c += -fno-builtin-nextafterf32
|
||||
+CFLAGS-s_nextdownf.c += -fno-builtin-nextdownf32
|
||||
+CFLAGS-s_nextupf.c += -fno-builtin-nextupf32
|
||||
+CFLAGS-e_powf.c += -fno-builtin-powf32
|
||||
+CFLAGS-w_remainderf.c += -fno-builtin-remainderf32
|
||||
+CFLAGS-s_remquof.c += -fno-builtin-remquof32
|
||||
+CFLAGS-s_rintf.c += -fno-builtin-rintf32
|
||||
+CFLAGS-s_roundf.c += -fno-builtin-roundf32
|
||||
+CFLAGS-s_roundevenf.c += -fno-builtin-roundevenf32
|
||||
+CFLAGS-w_scalblnf.c += -fno-builtin-scalblnf32
|
||||
+CFLAGS-s_scalbnf.c += -fno-builtin-scalbnf32
|
||||
+CFLAGS-s_setpayloadf.c += -fno-builtin-setpayloadf32
|
||||
+CFLAGS-s_setpayloadsigf.c += -fno-builtin-setpayloadsigf32
|
||||
+CFLAGS-s_sinf.c += -fno-builtin-sinf32
|
||||
+CFLAGS-s_sincosf.c += -fno-builtin-sincosf32
|
||||
+CFLAGS-w_sinhf.c += -fno-builtin-sinhf32
|
||||
+CFLAGS-w_sqrtf.c += -fno-builtin-sqrtf32
|
||||
+CFLAGS-s_tanf.c += -fno-builtin-tanf32
|
||||
+CFLAGS-s_tanhf.c += -fno-builtin-tanhf32
|
||||
+CFLAGS-w_tgammaf.c += -fno-builtin-tgammaf32
|
||||
+CFLAGS-s_totalorderf.c += -fno-builtin-totalorderf32
|
||||
+CFLAGS-s_totalordermagf.c += -fno-builtin-totalordermagf32
|
||||
+CFLAGS-s_truncf.c += -fno-builtin-truncf32
|
||||
+CFLAGS-s_ufromfpf.c += -fno-builtin-ufromfpf32
|
||||
+CFLAGS-s_ufromfpxf.c += -fno-builtin-ufromfpxf32
|
||||
+CFLAGS-s_y0f.c += -fno-builtin-y0f32
|
||||
+CFLAGS-s_y1f.c += -fno-builtin-y1f32
|
||||
+CFLAGS-s_ynf.c += -fno-builtin-ynf32
|
||||
+
|
||||
# These files quiet sNaNs in a way that is optimized away without
|
||||
# -fsignaling-nans.
|
||||
CFLAGS-s_modf.c += -fsignaling-nans
|
||||
diff --git a/sysdeps/ieee754/float128/Makefile b/sysdeps/ieee754/float128/Makefile
|
||||
index 571a841809234edd..f869e80f268ba446 100644
|
||||
--- a/sysdeps/ieee754/float128/Makefile
|
||||
+++ b/sysdeps/ieee754/float128/Makefile
|
||||
@@ -10,3 +10,130 @@ endif
|
||||
ifeq ($(subdir),wcsmbs)
|
||||
routines += wcstof128_l wcstof128 wcstof128_nan
|
||||
endif
|
||||
+
|
||||
+ifeq ($(subdir),math)
|
||||
+CFLAGS-w_acosf128.c += -fno-builtin-acosf64x
|
||||
+CFLAGS-w_acoshf128.c += -fno-builtin-acoshf64x
|
||||
+CFLAGS-w_asinf128.c += -fno-builtin-asinf64x
|
||||
+CFLAGS-s_asinhf128.c += -fno-builtin-asinhf64x
|
||||
+CFLAGS-s_atanf128.c += -fno-builtin-atanf64x
|
||||
+CFLAGS-w_atan2f128.c += -fno-builtin-atan2f64x
|
||||
+CFLAGS-w_atanhf128.c += -fno-builtin-atanhf64x
|
||||
+CFLAGS-s_cabsf128.c += -fno-builtin-cabsf64x
|
||||
+CFLAGS-s_cacosf128.c += -fno-builtin-cacosf64x
|
||||
+CFLAGS-s_cacoshf128.c += -fno-builtin-cacoshf64x
|
||||
+CFLAGS-s_canonicalizef128.c += -fno-builtin-canonicalizef64x
|
||||
+CFLAGS-s_cargf128.c += -fno-builtin-cargf64x
|
||||
+CFLAGS-s_casinf128.c += -fno-builtin-casinf64x
|
||||
+CFLAGS-s_casinhf128.c += -fno-builtin-casinhf64x
|
||||
+CFLAGS-s_catanf128.c += -fno-builtin-catanf64x
|
||||
+CFLAGS-s_catanhf128.c += -fno-builtin-catanhf64x
|
||||
+CFLAGS-s_cbrtf128.c += -fno-builtin-cbrtf64x
|
||||
+CFLAGS-s_ccosf128.c += -fno-builtin-ccosf64x
|
||||
+CFLAGS-s_ccoshf128.c += -fno-builtin-ccoshf64x
|
||||
+CFLAGS-s_ceilf128.c += -fno-builtin-ceilf64x
|
||||
+CFLAGS-s_cexpf128.c += -fno-builtin-cexpf64x
|
||||
+CFLAGS-s_cimagf128.c += -fno-builtin-cimagf64x
|
||||
+CFLAGS-s_clogf128.c += -fno-builtin-clogf64x
|
||||
+CFLAGS-s_clog10f128.c += -fno-builtin-clog10f64x
|
||||
+CFLAGS-s_conjf128.c += -fno-builtin-conjf64x
|
||||
+CFLAGS-s_copysignf128.c += -fno-builtin-copysignf64x
|
||||
+CFLAGS-s_cosf128.c += -fno-builtin-cosf64x
|
||||
+CFLAGS-w_coshf128.c += -fno-builtin-coshf64x
|
||||
+CFLAGS-s_cpowf128.c += -fno-builtin-cpowf64x
|
||||
+CFLAGS-s_cprojf128.c += -fno-builtin-cprojf64x
|
||||
+CFLAGS-s_crealf128.c += -fno-builtin-crealf64x
|
||||
+CFLAGS-s_csinf128.c += -fno-builtin-csinf64x
|
||||
+CFLAGS-s_csinhf128.c += -fno-builtin-csinhf64x
|
||||
+CFLAGS-s_csqrtf128.c += -fno-builtin-csqrtf64x
|
||||
+CFLAGS-s_ctanf128.c += -fno-builtin-ctanf64x
|
||||
+CFLAGS-s_ctanhf128.c += -fno-builtin-ctanhf64x
|
||||
+CFLAGS-s_daddf128.c += -fno-builtin-f64addf64x
|
||||
+CFLAGS-s_ddivf128.c += -fno-builtin-f64divf64x
|
||||
+CFLAGS-s_dfmaf128.c += -fno-builtin-f64fmaf64x
|
||||
+CFLAGS-s_dmulf128.c += -fno-builtin-f64mulf64x
|
||||
+CFLAGS-s_dsqrtf128.c += -fno-builtin-f64sqrtf64x
|
||||
+CFLAGS-s_dsubf128.c += -fno-builtin-f64subf64x
|
||||
+CFLAGS-s_erff128.c += -fno-builtin-erff64x
|
||||
+CFLAGS-s_erfcf128.c += -fno-builtin-erfcf64x
|
||||
+CFLAGS-e_expf128.c += -fno-builtin-expf64x
|
||||
+CFLAGS-w_exp10f128.c += -fno-builtin-exp10f64x
|
||||
+CFLAGS-e_exp2f128.c += -fno-builtin-exp2f64x
|
||||
+CFLAGS-s_expm1f128.c += -fno-builtin-expm1f64x
|
||||
+CFLAGS-s_fabsf128.c += -fno-builtin-fabsf64x
|
||||
+CFLAGS-s_faddf128.c += -fno-builtin-f32addf64x
|
||||
+CFLAGS-s_fdimf128.c += -fno-builtin-fdimf64x
|
||||
+CFLAGS-s_fdivf128.c += -fno-builtin-f32divf64x
|
||||
+CFLAGS-s_ffmaf128.c += -fno-builtin-f32fmaf64x
|
||||
+CFLAGS-s_floorf128.c += -fno-builtin-floorf64x
|
||||
+CFLAGS-s_fmaf128.c += -fno-builtin-fmaf64x
|
||||
+CFLAGS-s_fmaxf128.c += -fno-builtin-fmaxf64x
|
||||
+CFLAGS-s_fmaximumf128.c += -fno-builtin-fmaximumf64x
|
||||
+CFLAGS-s_fmaximum_magf128.c += -fno-builtin-fmaximum_magf64x
|
||||
+CFLAGS-s_fmaximum_mag_numf128.c += -fno-builtin-fmaximum_mag_numf64x
|
||||
+CFLAGS-s_fmaximum_numf128.c += -fno-builtin-fmaximum_numf64x
|
||||
+CFLAGS-s_fmaxmagf128.c += -fno-builtin-fmaxmagf64x
|
||||
+CFLAGS-s_fminf128.c += -fno-builtin-fminf64x
|
||||
+CFLAGS-s_fminimumf128.c += -fno-builtin-fminimumf64x
|
||||
+CFLAGS-s_fminimum_magf128.c += -fno-builtin-fminimum_magf64x
|
||||
+CFLAGS-s_fminimum_mag_numf128.c += -fno-builtin-fminimum_mag_numf64x
|
||||
+CFLAGS-s_fminimum_numf128.c += -fno-builtin-fminimum_numf64x
|
||||
+CFLAGS-s_fminmagf128.c += -fno-builtin-fminmagf64x
|
||||
+CFLAGS-w_fmodf128.c += -fno-builtin-fmodf64x
|
||||
+CFLAGS-s_fmulf128.c += -fno-builtin-f32mulf64x
|
||||
+CFLAGS-s_frexpf128.c += -fno-builtin-frexpf64x
|
||||
+CFLAGS-s_fromfpf128.c += -fno-builtin-fromfpf64x
|
||||
+CFLAGS-s_fromfpxf128.c += -fno-builtin-fromfpxf64x
|
||||
+CFLAGS-s_fsqrtf128.c += -fno-builtin-f32sqrtf64x
|
||||
+CFLAGS-s_fsubf128.c += -fno-builtin-f32subf64x
|
||||
+CFLAGS-s_getpayloadf128.c += -fno-builtin-getpayloadf64x
|
||||
+CFLAGS-w_hypotf128.c += -fno-builtin-hypotf64x
|
||||
+CFLAGS-w_ilogbf128.c += -fno-builtin-ilogbf64x
|
||||
+CFLAGS-w_j0f128.c += -fno-builtin-j0f64x
|
||||
+CFLAGS-w_j1f128.c += -fno-builtin-j1f64x
|
||||
+CFLAGS-w_jnf128.c += -fno-builtin-jnf64x
|
||||
+CFLAGS-s_ldexpf128.c += -fno-builtin-ldexpf64x
|
||||
+CFLAGS-w_lgammaf128.c += -fno-builtin-lgammaf64x
|
||||
+CFLAGS-w_lgammaf128_r.c += -fno-builtin-lgammaf64x_r
|
||||
+CFLAGS-w_llogbf128.c += -fno-builtin-llogbf64x
|
||||
+CFLAGS-s_llrintf128.c += -fno-builtin-llrintf64x
|
||||
+CFLAGS-s_llroundf128.c += -fno-builtin-llroundf64x
|
||||
+CFLAGS-e_logf128.c += -fno-builtin-logf64x
|
||||
+CFLAGS-w_log10f128.c += -fno-builtin-log10f64x
|
||||
+CFLAGS-w_log1pf128.c += -fno-builtin-log1pf64x
|
||||
+CFLAGS-e_log2f128.c += -fno-builtin-log2f64x
|
||||
+CFLAGS-s_logbf128.c += -fno-builtin-logbf64x
|
||||
+CFLAGS-s_lrintf128.c += -fno-builtin-lrintf64x
|
||||
+CFLAGS-s_lroundf128.c += -fno-builtin-lroundf64x
|
||||
+CFLAGS-s_modff128.c += -fno-builtin-modff64x
|
||||
+CFLAGS-s_nanf128.c += -fno-builtin-nanf64x
|
||||
+CFLAGS-s_nearbyintf128.c += -fno-builtin-nearbyintf64x
|
||||
+CFLAGS-s_nextafterf128.c += -fno-builtin-nextafterf64x
|
||||
+CFLAGS-s_nextdownf128.c += -fno-builtin-nextdownf64x
|
||||
+CFLAGS-s_nextupf128.c += -fno-builtin-nextupf64x
|
||||
+CFLAGS-e_powf128.c += -fno-builtin-powf64x
|
||||
+CFLAGS-w_remainderf128.c += -fno-builtin-remainderf64x
|
||||
+CFLAGS-s_remquof128.c += -fno-builtin-remquof64x
|
||||
+CFLAGS-s_rintf128.c += -fno-builtin-rintf64x
|
||||
+CFLAGS-s_roundf128.c += -fno-builtin-roundf64x
|
||||
+CFLAGS-s_roundevenf128.c += -fno-builtin-roundevenf64x
|
||||
+CFLAGS-w_scalblnf128.c += -fno-builtin-scalblnf64x
|
||||
+CFLAGS-s_scalbnf128.c += -fno-builtin-scalbnf64x
|
||||
+CFLAGS-s_setpayloadf128.c += -fno-builtin-setpayloadf64x
|
||||
+CFLAGS-s_setpayloadsigf128.c += -fno-builtin-setpayloadsigf64x
|
||||
+CFLAGS-s_sinf128.c += -fno-builtin-sinf64x
|
||||
+CFLAGS-s_sincosf128.c += -fno-builtin-sincosf64x
|
||||
+CFLAGS-w_sinhf128.c += -fno-builtin-sinhf64x
|
||||
+CFLAGS-w_sqrtf128.c += -fno-builtin-sqrtf64x
|
||||
+CFLAGS-s_tanf128.c += -fno-builtin-tanf64x
|
||||
+CFLAGS-s_tanhf128.c += -fno-builtin-tanhf64x
|
||||
+CFLAGS-w_tgammaf128.c += -fno-builtin-tgammaf64x
|
||||
+CFLAGS-s_totalorderf128.c += -fno-builtin-totalorderf64x
|
||||
+CFLAGS-s_totalordermagf128.c += -fno-builtin-totalordermagf64x
|
||||
+CFLAGS-s_truncf128.c += -fno-builtin-truncf64x
|
||||
+CFLAGS-s_ufromfpf128.c += -fno-builtin-ufromfpf64x
|
||||
+CFLAGS-s_ufromfpxf128.c += -fno-builtin-ufromfpxf64x
|
||||
+CFLAGS-s_y0f128.c += -fno-builtin-y0f64x
|
||||
+CFLAGS-s_y1f128.c += -fno-builtin-y1f64x
|
||||
+CFLAGS-s_ynf128.c += -fno-builtin-ynf64x
|
||||
+endif
|
||||
diff --git a/sysdeps/ieee754/ldbl-128/Makefile b/sysdeps/ieee754/ldbl-128/Makefile
|
||||
index 8fd6dad343bde2c9..9cbfc7ff6e8cd6f7 100644
|
||||
--- a/sysdeps/ieee754/ldbl-128/Makefile
|
||||
+++ b/sysdeps/ieee754/ldbl-128/Makefile
|
||||
@@ -1 +1,128 @@
|
||||
long-double-fcts = yes
|
||||
+
|
||||
+ifeq ($(subdir),math)
|
||||
+CFLAGS-w_acosl.c += -fno-builtin-acosf64x -fno-builtin-acosf128
|
||||
+CFLAGS-w_acoshl.c += -fno-builtin-acoshf64x -fno-builtin-acoshf128
|
||||
+CFLAGS-w_asinl.c += -fno-builtin-asinf64x -fno-builtin-asinf128
|
||||
+CFLAGS-s_asinhl.c += -fno-builtin-asinhf64x -fno-builtin-asinhf128
|
||||
+CFLAGS-s_atanl.c += -fno-builtin-atanf64x -fno-builtin-atanf128
|
||||
+CFLAGS-w_atan2l.c += -fno-builtin-atan2f64x -fno-builtin-atan2f128
|
||||
+CFLAGS-w_atanhl.c += -fno-builtin-atanhf64x -fno-builtin-atanhf128
|
||||
+CFLAGS-s_cabsl.c += -fno-builtin-cabsf64x -fno-builtin-cabsf128
|
||||
+CFLAGS-s_cacosl.c += -fno-builtin-cacosf64x -fno-builtin-cacosf128
|
||||
+CFLAGS-s_cacoshl.c += -fno-builtin-cacoshf64x -fno-builtin-cacoshf128
|
||||
+CFLAGS-s_canonicalizel.c += -fno-builtin-canonicalizef64x -fno-builtin-canonicalizef128
|
||||
+CFLAGS-s_cargl.c += -fno-builtin-cargf64x -fno-builtin-cargf128
|
||||
+CFLAGS-s_casinl.c += -fno-builtin-casinf64x -fno-builtin-casinf128
|
||||
+CFLAGS-s_casinhl.c += -fno-builtin-casinhf64x -fno-builtin-casinhf128
|
||||
+CFLAGS-s_catanl.c += -fno-builtin-catanf64x -fno-builtin-catanf128
|
||||
+CFLAGS-s_catanhl.c += -fno-builtin-catanhf64x -fno-builtin-catanhf128
|
||||
+CFLAGS-s_cbrtl.c += -fno-builtin-cbrtf64x -fno-builtin-cbrtf128
|
||||
+CFLAGS-s_ccosl.c += -fno-builtin-ccosf64x -fno-builtin-ccosf128
|
||||
+CFLAGS-s_ccoshl.c += -fno-builtin-ccoshf64x -fno-builtin-ccoshf128
|
||||
+CFLAGS-s_ceill.c += -fno-builtin-ceilf64x -fno-builtin-ceilf128
|
||||
+CFLAGS-s_cexpl.c += -fno-builtin-cexpf64x -fno-builtin-cexpf128
|
||||
+CFLAGS-s_cimagl.c += -fno-builtin-cimagf64x -fno-builtin-cimagf128
|
||||
+CFLAGS-s_clogl.c += -fno-builtin-clogf64x -fno-builtin-clogf128
|
||||
+CFLAGS-s_clog10l.c += -fno-builtin-clog10f64x -fno-builtin-clog10f128
|
||||
+CFLAGS-s_conjl.c += -fno-builtin-conjf64x -fno-builtin-conjf128
|
||||
+CFLAGS-s_copysignl.c += -fno-builtin-copysignf64x -fno-builtin-copysignf128
|
||||
+CFLAGS-s_cosl.c += -fno-builtin-cosf64x -fno-builtin-cosf128
|
||||
+CFLAGS-w_coshl.c += -fno-builtin-coshf64x -fno-builtin-coshf128
|
||||
+CFLAGS-s_cpowl.c += -fno-builtin-cpowf64x -fno-builtin-cpowf128
|
||||
+CFLAGS-s_cprojl.c += -fno-builtin-cprojf64x -fno-builtin-cprojf128
|
||||
+CFLAGS-s_creall.c += -fno-builtin-crealf64x -fno-builtin-crealf128
|
||||
+CFLAGS-s_csinl.c += -fno-builtin-csinf64x -fno-builtin-csinf128
|
||||
+CFLAGS-s_csinhl.c += -fno-builtin-csinhf64x -fno-builtin-csinhf128
|
||||
+CFLAGS-s_csqrtl.c += -fno-builtin-csqrtf64x -fno-builtin-csqrtf128
|
||||
+CFLAGS-s_ctanl.c += -fno-builtin-ctanf64x -fno-builtin-ctanf128
|
||||
+CFLAGS-s_ctanhl.c += -fno-builtin-ctanhf64x -fno-builtin-ctanhf128
|
||||
+CFLAGS-s_daddl.c += -fno-builtin-f64addf64x -fno-builtin-f64addf128
|
||||
+CFLAGS-s_ddivl.c += -fno-builtin-f64divf64x -fno-builtin-f64divf128
|
||||
+CFLAGS-s_dfmal.c += -fno-builtin-f64fmaf64x -fno-builtin-f64fmaf128
|
||||
+CFLAGS-s_dmull.c += -fno-builtin-f64mulf64x -fno-builtin-f64mulf128
|
||||
+CFLAGS-s_dsqrtl.c += -fno-builtin-f64sqrtf64x -fno-builtin-f64sqrtf128
|
||||
+CFLAGS-s_dsubl.c += -fno-builtin-f64subf64x -fno-builtin-f64subf128
|
||||
+CFLAGS-s_erfl.c += -fno-builtin-erff64x -fno-builtin-erff128
|
||||
+CFLAGS-s_erfcl.c += -fno-builtin-erfcf64x -fno-builtin-erfcf128
|
||||
+CFLAGS-e_expl.c += -fno-builtin-expf64x -fno-builtin-expf128
|
||||
+CFLAGS-w_exp10l.c += -fno-builtin-exp10f64x -fno-builtin-exp10f128
|
||||
+CFLAGS-e_exp2l.c += -fno-builtin-exp2f64x -fno-builtin-exp2f128
|
||||
+CFLAGS-s_expm1l.c += -fno-builtin-expm1f64x -fno-builtin-expm1f128
|
||||
+CFLAGS-s_fabsl.c += -fno-builtin-fabsf64x -fno-builtin-fabsf128
|
||||
+CFLAGS-s_faddl.c += -fno-builtin-f32addf64x -fno-builtin-f32addf128
|
||||
+CFLAGS-s_fdiml.c += -fno-builtin-fdimf64x -fno-builtin-fdimf128
|
||||
+CFLAGS-s_fdivl.c += -fno-builtin-f32divf64x -fno-builtin-f32divf128
|
||||
+CFLAGS-s_ffmal.c += -fno-builtin-f32fmaf64x -fno-builtin-f32fmaf128
|
||||
+CFLAGS-s_floorl.c += -fno-builtin-floorf64x -fno-builtin-floorf128
|
||||
+CFLAGS-s_fmal.c += -fno-builtin-fmaf64x -fno-builtin-fmaf128
|
||||
+CFLAGS-s_fmaxl.c += -fno-builtin-fmaxf64x -fno-builtin-fmaxf128
|
||||
+CFLAGS-s_fmaximuml.c += -fno-builtin-fmaximumf64x -fno-builtin-fmaximumf128
|
||||
+CFLAGS-s_fmaximum_magl.c += -fno-builtin-fmaximum_magf64x -fno-builtin-fmaximum_magf128
|
||||
+CFLAGS-s_fmaximum_mag_numl.c += -fno-builtin-fmaximum_mag_numf64x -fno-builtin-fmaximum_mag_numf128
|
||||
+CFLAGS-s_fmaximum_numl.c += -fno-builtin-fmaximum_numf64x -fno-builtin-fmaximum_numf128
|
||||
+CFLAGS-s_fmaxmagl.c += -fno-builtin-fmaxmagf64x -fno-builtin-fmaxmagf128
|
||||
+CFLAGS-s_fminl.c += -fno-builtin-fminf64x -fno-builtin-fminf128
|
||||
+CFLAGS-s_fminimuml.c += -fno-builtin-fminimumf64x -fno-builtin-fminimumf128
|
||||
+CFLAGS-s_fminimum_magl.c += -fno-builtin-fminimum_magf64x -fno-builtin-fminimum_magf128
|
||||
+CFLAGS-s_fminimum_mag_numl.c += -fno-builtin-fminimum_mag_numf64x -fno-builtin-fminimum_mag_numf128
|
||||
+CFLAGS-s_fminimum_numl.c += -fno-builtin-fminimum_numf64x -fno-builtin-fminimum_numf128
|
||||
+CFLAGS-s_fminmagl.c += -fno-builtin-fminmagf64x -fno-builtin-fminmagf128
|
||||
+CFLAGS-w_fmodl.c += -fno-builtin-fmodf64x -fno-builtin-fmodf128
|
||||
+CFLAGS-s_fmull.c += -fno-builtin-f32mulf64x -fno-builtin-f32mulf128
|
||||
+CFLAGS-s_frexpl.c += -fno-builtin-frexpf64x -fno-builtin-frexpf128
|
||||
+CFLAGS-s_fromfpl.c += -fno-builtin-fromfpf64x -fno-builtin-fromfpf128
|
||||
+CFLAGS-s_fromfpxl.c += -fno-builtin-fromfpxf64x -fno-builtin-fromfpxf128
|
||||
+CFLAGS-s_fsqrtl.c += -fno-builtin-f32sqrtf64x -fno-builtin-f32sqrtf128
|
||||
+CFLAGS-s_fsubl.c += -fno-builtin-f32subf64x -fno-builtin-f32subf128
|
||||
+CFLAGS-s_getpayloadl.c += -fno-builtin-getpayloadf64x -fno-builtin-getpayloadf128
|
||||
+CFLAGS-w_hypotl.c += -fno-builtin-hypotf64x -fno-builtin-hypotf128
|
||||
+CFLAGS-w_ilogbl.c += -fno-builtin-ilogbf64x -fno-builtin-ilogbf128
|
||||
+CFLAGS-w_j0l.c += -fno-builtin-j0f64x -fno-builtin-j0f128
|
||||
+CFLAGS-w_j1l.c += -fno-builtin-j1f64x -fno-builtin-j1f128
|
||||
+CFLAGS-w_jnl.c += -fno-builtin-jnf64x -fno-builtin-jnf128
|
||||
+CFLAGS-s_ldexpl.c += -fno-builtin-ldexpf64x -fno-builtin-ldexpf128
|
||||
+CFLAGS-w_lgammal.c += -fno-builtin-lgammaf64x -fno-builtin-lgammaf128
|
||||
+CFLAGS-w_lgammal_r.c += -fno-builtin-lgammaf64x_r
|
||||
+CFLAGS-w_llogbl.c += -fno-builtin-llogbf64x -fno-builtin-llogbf128
|
||||
+CFLAGS-s_llrintl.c += -fno-builtin-llrintf64x -fno-builtin-llrintf128
|
||||
+CFLAGS-s_llroundl.c += -fno-builtin-llroundf64x -fno-builtin-llroundf128
|
||||
+CFLAGS-e_logl.c += -fno-builtin-logf64x -fno-builtin-logf128
|
||||
+CFLAGS-w_log10l.c += -fno-builtin-log10f64x -fno-builtin-log10f128
|
||||
+CFLAGS-w_log1pl.c += -fno-builtin-log1pf64x -fno-builtin-log1pf128
|
||||
+CFLAGS-e_log2l.c += -fno-builtin-log2f64x -fno-builtin-log2f128
|
||||
+CFLAGS-s_logbl.c += -fno-builtin-logbf64x -fno-builtin-logbf128
|
||||
+CFLAGS-s_lrintl.c += -fno-builtin-lrintf64x -fno-builtin-lrintf128
|
||||
+CFLAGS-s_lroundl.c += -fno-builtin-lroundf64x -fno-builtin-lroundf128
|
||||
+CFLAGS-s_modfl.c += -fno-builtin-modff64x -fno-builtin-modff128
|
||||
+CFLAGS-s_nanl.c += -fno-builtin-nanf64x -fno-builtin-nanf128
|
||||
+CFLAGS-s_nearbyintl.c += -fno-builtin-nearbyintf64x -fno-builtin-nearbyintf128
|
||||
+CFLAGS-s_nextafterl.c += -fno-builtin-nextafterf64x -fno-builtin-nextafterf128
|
||||
+CFLAGS-s_nextdownl.c += -fno-builtin-nextdownf64x -fno-builtin-nextdownf128
|
||||
+CFLAGS-s_nextupl.c += -fno-builtin-nextupf64x -fno-builtin-nextupf128
|
||||
+CFLAGS-e_powl.c += -fno-builtin-powf64x -fno-builtin-powf128
|
||||
+CFLAGS-w_remainderl.c += -fno-builtin-remainderf64x -fno-builtin-remainderf128
|
||||
+CFLAGS-s_remquol.c += -fno-builtin-remquof64x -fno-builtin-remquof128
|
||||
+CFLAGS-s_rintl.c += -fno-builtin-rintf64x -fno-builtin-rintf128
|
||||
+CFLAGS-s_roundl.c += -fno-builtin-roundf64x -fno-builtin-roundf128
|
||||
+CFLAGS-s_roundevenl.c += -fno-builtin-roundevenf64x -fno-builtin-roundevenf128
|
||||
+CFLAGS-w_scalblnl.c += -fno-builtin-scalblnf64x -fno-builtin-scalblnf128
|
||||
+CFLAGS-s_scalbnl.c += -fno-builtin-scalbnf64x -fno-builtin-scalbnf128
|
||||
+CFLAGS-s_setpayloadl.c += -fno-builtin-setpayloadf64x -fno-builtin-setpayloadf128
|
||||
+CFLAGS-s_setpayloadsigl.c += -fno-builtin-setpayloadsigf64x -fno-builtin-setpayloadsigf128
|
||||
+CFLAGS-s_sinl.c += -fno-builtin-sinf64x -fno-builtin-sinf128
|
||||
+CFLAGS-s_sincosl.c += -fno-builtin-sincosf64x -fno-builtin-sincosf128
|
||||
+CFLAGS-w_sinhl.c += -fno-builtin-sinhf64x -fno-builtin-sinhf128
|
||||
+CFLAGS-w_sqrtl.c += -fno-builtin-sqrtf64x -fno-builtin-sqrtf128
|
||||
+CFLAGS-s_tanl.c += -fno-builtin-tanf64x -fno-builtin-tanf128
|
||||
+CFLAGS-s_tanhl.c += -fno-builtin-tanhf64x -fno-builtin-tanhf128
|
||||
+CFLAGS-w_tgammal.c += -fno-builtin-tgammaf64x -fno-builtin-tgammaf128
|
||||
+CFLAGS-s_totalorderl.c += -fno-builtin-totalorderf64x -fno-builtin-totalorderf128
|
||||
+CFLAGS-s_totalordermagl.c += -fno-builtin-totalordermagf64x -fno-builtin-totalordermagf128
|
||||
+CFLAGS-s_truncl.c += -fno-builtin-truncf64x -fno-builtin-truncf128
|
||||
+CFLAGS-s_ufromfpl.c += -fno-builtin-ufromfpf64x -fno-builtin-ufromfpf128
|
||||
+CFLAGS-s_ufromfpxl.c += -fno-builtin-ufromfpxf64x -fno-builtin-ufromfpxf128
|
||||
+CFLAGS-s_y0l.c += -fno-builtin-y0f64x -fno-builtin-y0f128
|
||||
+CFLAGS-s_y1l.c += -fno-builtin-y1f64x -fno-builtin-y1f128
|
||||
+CFLAGS-s_ynl.c += -fno-builtin-ynf64x -fno-builtin-ynf128
|
||||
+endif
|
||||
diff --git a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile
|
||||
index 75aed7ae6ca217ed..f28f91fa6a1e61a7 100644
|
||||
--- a/sysdeps/ieee754/ldbl-96/Makefile
|
||||
+++ b/sysdeps/ieee754/ldbl-96/Makefile
|
||||
@@ -21,4 +21,130 @@ tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo
|
||||
ifeq ($(have-ssp),yes)
|
||||
CFLAGS-test-sinl-pseudo.c += -fstack-protector-all
|
||||
endif
|
||||
+
|
||||
+CFLAGS-w_acosl.c += -fno-builtin-acosf64x
|
||||
+CFLAGS-w_acoshl.c += -fno-builtin-acoshf64x
|
||||
+CFLAGS-w_asinl.c += -fno-builtin-asinf64x
|
||||
+CFLAGS-s_asinhl.c += -fno-builtin-asinhf64x
|
||||
+CFLAGS-s_atanl.c += -fno-builtin-atanf64x
|
||||
+CFLAGS-w_atan2l.c += -fno-builtin-atan2f64x
|
||||
+CFLAGS-w_atanhl.c += -fno-builtin-atanhf64x
|
||||
+CFLAGS-s_cabsl.c += -fno-builtin-cabsf64x
|
||||
+CFLAGS-s_cacosl.c += -fno-builtin-cacosf64x
|
||||
+CFLAGS-s_cacoshl.c += -fno-builtin-cacoshf64x
|
||||
+CFLAGS-s_canonicalizel.c += -fno-builtin-canonicalizef64x
|
||||
+CFLAGS-s_cargl.c += -fno-builtin-cargf64x
|
||||
+CFLAGS-s_casinl.c += -fno-builtin-casinf64x
|
||||
+CFLAGS-s_casinhl.c += -fno-builtin-casinhf64x
|
||||
+CFLAGS-s_catanl.c += -fno-builtin-catanf64x
|
||||
+CFLAGS-s_catanhl.c += -fno-builtin-catanhf64x
|
||||
+CFLAGS-s_cbrtl.c += -fno-builtin-cbrtf64x
|
||||
+CFLAGS-s_ccosl.c += -fno-builtin-ccosf64x
|
||||
+CFLAGS-s_ccoshl.c += -fno-builtin-ccoshf64x
|
||||
+CFLAGS-s_ceill.c += -fno-builtin-ceilf64x
|
||||
+CFLAGS-s_cexpl.c += -fno-builtin-cexpf64x
|
||||
+CFLAGS-s_cimagl.c += -fno-builtin-cimagf64x
|
||||
+CFLAGS-s_clogl.c += -fno-builtin-clogf64x
|
||||
+CFLAGS-s_clog10l.c += -fno-builtin-clog10f64x
|
||||
+CFLAGS-s_conjl.c += -fno-builtin-conjf64x
|
||||
+CFLAGS-s_copysignl.c += -fno-builtin-copysignf64x
|
||||
+CFLAGS-s_cosl.c += -fno-builtin-cosf64x
|
||||
+CFLAGS-w_coshl.c += -fno-builtin-coshf64x
|
||||
+CFLAGS-s_cpowl.c += -fno-builtin-cpowf64x
|
||||
+CFLAGS-s_cprojl.c += -fno-builtin-cprojf64x
|
||||
+CFLAGS-s_creall.c += -fno-builtin-crealf64x
|
||||
+CFLAGS-s_csinl.c += -fno-builtin-csinf64x
|
||||
+CFLAGS-s_csinhl.c += -fno-builtin-csinhf64x
|
||||
+CFLAGS-s_csqrtl.c += -fno-builtin-csqrtf64x
|
||||
+CFLAGS-s_ctanl.c += -fno-builtin-ctanf64x
|
||||
+CFLAGS-s_ctanhl.c += -fno-builtin-ctanhf64x
|
||||
+CFLAGS-s_daddl.c += -fno-builtin-f64addf64x
|
||||
+CFLAGS-s_ddivl.c += -fno-builtin-f64divf64x
|
||||
+CFLAGS-s_dfmal.c += -fno-builtin-f64fmaf64x
|
||||
+CFLAGS-s_dmull.c += -fno-builtin-f64mulf64x
|
||||
+CFLAGS-s_dsqrtl.c += -fno-builtin-f64sqrtf64x
|
||||
+CFLAGS-s_dsubl.c += -fno-builtin-f64subf64x
|
||||
+CFLAGS-s_erfl.c += -fno-builtin-erff64x
|
||||
+CFLAGS-s_erfcl.c += -fno-builtin-erfcf64x
|
||||
+CFLAGS-e_expl.c += -fno-builtin-expf64x
|
||||
+CFLAGS-w_exp10l.c += -fno-builtin-exp10f64x
|
||||
+CFLAGS-e_exp2l.c += -fno-builtin-exp2f64x
|
||||
+CFLAGS-s_expm1l.c += -fno-builtin-expm1f64x
|
||||
+CFLAGS-s_fabsl.c += -fno-builtin-fabsf64x
|
||||
+CFLAGS-s_faddl.c += -fno-builtin-f32addf64x
|
||||
+CFLAGS-s_fdiml.c += -fno-builtin-fdimf64x
|
||||
+CFLAGS-s_fdivl.c += -fno-builtin-f32divf64x
|
||||
+CFLAGS-s_ffmal.c += -fno-builtin-f32fmaf64x
|
||||
+CFLAGS-s_floorl.c += -fno-builtin-floorf64x
|
||||
+CFLAGS-s_fmal.c += -fno-builtin-fmaf64x
|
||||
+CFLAGS-s_fmaxl.c += -fno-builtin-fmaxf64x
|
||||
+CFLAGS-s_fmaximuml.c += -fno-builtin-fmaximumf64x
|
||||
+CFLAGS-s_fmaximum_magl.c += -fno-builtin-fmaximum_magf64x
|
||||
+CFLAGS-s_fmaximum_mag_numl.c += -fno-builtin-fmaximum_mag_numf64x
|
||||
+CFLAGS-s_fmaximum_numl.c += -fno-builtin-fmaximum_numf64x
|
||||
+CFLAGS-s_fmaxmagl.c += -fno-builtin-fmaxmagf64x
|
||||
+CFLAGS-s_fminl.c += -fno-builtin-fminf64x
|
||||
+CFLAGS-s_fminimuml.c += -fno-builtin-fminimumf64x
|
||||
+CFLAGS-s_fminimum_magl.c += -fno-builtin-fminimum_magf64x
|
||||
+CFLAGS-s_fminimum_mag_numl.c += -fno-builtin-fminimum_mag_numf64x
|
||||
+CFLAGS-s_fminimum_numl.c += -fno-builtin-fminimum_numf64x
|
||||
+CFLAGS-s_fminmagl.c += -fno-builtin-fminmagf64x
|
||||
+CFLAGS-w_fmodl.c += -fno-builtin-fmodf64x
|
||||
+CFLAGS-s_fmull.c += -fno-builtin-f32mulf64x
|
||||
+CFLAGS-s_frexpl.c += -fno-builtin-frexpf64x
|
||||
+CFLAGS-s_fromfpl.c += -fno-builtin-fromfpf64x
|
||||
+CFLAGS-s_fromfpxl.c += -fno-builtin-fromfpxf64x
|
||||
+CFLAGS-s_fsqrtl.c += -fno-builtin-f32sqrtf64x
|
||||
+CFLAGS-s_fsubl.c += -fno-builtin-f32subf64x
|
||||
+CFLAGS-s_getpayloadl.c += -fno-builtin-getpayloadf64x
|
||||
+CFLAGS-w_hypotl.c += -fno-builtin-hypotf64x
|
||||
+CFLAGS-w_ilogbl.c += -fno-builtin-ilogbf64x
|
||||
+CFLAGS-w_j0l.c += -fno-builtin-j0f64x
|
||||
+CFLAGS-w_j1l.c += -fno-builtin-j1f64x
|
||||
+CFLAGS-w_jnl.c += -fno-builtin-jnf64x
|
||||
+CFLAGS-s_ldexpl.c += -fno-builtin-ldexpf64x
|
||||
+CFLAGS-w_lgammal.c += -fno-builtin-lgammaf64x
|
||||
+CFLAGS-w_lgammal_r.c += -fno-builtin-lgammaf64x_r
|
||||
+CFLAGS-w_llogbl.c += -fno-builtin-llogbf64x
|
||||
+CFLAGS-s_llrintl.c += -fno-builtin-llrintf64x
|
||||
+CFLAGS-s_llroundl.c += -fno-builtin-llroundf64x
|
||||
+CFLAGS-e_logl.c += -fno-builtin-logf64x
|
||||
+CFLAGS-w_log10l.c += -fno-builtin-log10f64x
|
||||
+CFLAGS-w_log1pl.c += -fno-builtin-log1pf64x
|
||||
+CFLAGS-e_log2l.c += -fno-builtin-log2f64x
|
||||
+CFLAGS-s_logbl.c += -fno-builtin-logbf64x
|
||||
+CFLAGS-s_lrintl.c += -fno-builtin-lrintf64x
|
||||
+CFLAGS-s_lroundl.c += -fno-builtin-lroundf64x
|
||||
+CFLAGS-s_modfl.c += -fno-builtin-modff64x
|
||||
+CFLAGS-s_nanl.c += -fno-builtin-nanf64x
|
||||
+CFLAGS-s_nearbyintl.c += -fno-builtin-nearbyintf64x
|
||||
+CFLAGS-s_nextafterl.c += -fno-builtin-nextafterf64x
|
||||
+CFLAGS-s_nextdownl.c += -fno-builtin-nextdownf64x
|
||||
+CFLAGS-s_nextupl.c += -fno-builtin-nextupf64x
|
||||
+CFLAGS-e_powl.c += -fno-builtin-powf64x
|
||||
+CFLAGS-w_remainderl.c += -fno-builtin-remainderf64x
|
||||
+CFLAGS-s_remquol.c += -fno-builtin-remquof64x
|
||||
+CFLAGS-s_rintl.c += -fno-builtin-rintf64x
|
||||
+CFLAGS-s_roundl.c += -fno-builtin-roundf64x
|
||||
+CFLAGS-s_roundevenl.c += -fno-builtin-roundevenf64x
|
||||
+CFLAGS-w_scalblnl.c += -fno-builtin-scalblnf64x
|
||||
+CFLAGS-s_scalbnl.c += -fno-builtin-scalbnf64x
|
||||
+CFLAGS-s_setpayloadl.c += -fno-builtin-setpayloadf64x
|
||||
+CFLAGS-s_setpayloadsigl.c += -fno-builtin-setpayloadsigf64x
|
||||
+CFLAGS-s_sinl.c += -fno-builtin-sinf64x
|
||||
+CFLAGS-s_sincosl.c += -fno-builtin-sincosf64x
|
||||
+CFLAGS-w_sinhl.c += -fno-builtin-sinhf64x
|
||||
+CFLAGS-w_sqrtl.c += -fno-builtin-sqrtf64x
|
||||
+CFLAGS-s_tanl.c += -fno-builtin-tanf64x
|
||||
+CFLAGS-s_tanhl.c += -fno-builtin-tanhf64x
|
||||
+CFLAGS-w_tgammal.c += -fno-builtin-tgammaf64x
|
||||
+CFLAGS-s_totalorderl.c += -fno-builtin-totalorderf64x
|
||||
+CFLAGS-s_totalordermagl.c += -fno-builtin-totalordermagf64x
|
||||
+CFLAGS-s_truncl.c += -fno-builtin-truncf64x
|
||||
+CFLAGS-s_ufromfpl.c += -fno-builtin-ufromfpf64x
|
||||
+CFLAGS-s_ufromfpxl.c += -fno-builtin-ufromfpxf64x
|
||||
+CFLAGS-s_y0l.c += -fno-builtin-y0f64x
|
||||
+CFLAGS-s_y1l.c += -fno-builtin-y1f64x
|
||||
+CFLAGS-s_ynl.c += -fno-builtin-ynf64x
|
||||
+
|
||||
endif # $(subdir) == math
|
||||
diff --git a/sysdeps/powerpc/powerpc32/fpu/Makefile b/sysdeps/powerpc/powerpc32/fpu/Makefile
|
||||
index b8b6bb0fa2efcf8c..4c0c65c18a5daea8 100644
|
||||
--- a/sysdeps/powerpc/powerpc32/fpu/Makefile
|
||||
+++ b/sysdeps/powerpc/powerpc32/fpu/Makefile
|
||||
@@ -1,8 +1,8 @@
|
||||
ifeq ($(subdir),math)
|
||||
# lrint is aliased to lrintf, so suppress compiler builtins to
|
||||
# avoid mismatched signatures.
|
||||
-CFLAGS-s_lrint.c += -fno-builtin-lrintf
|
||||
-CFLAGS-s_lround.c += -fno-builtin-lroundf
|
||||
+CFLAGS-s_lrint.c += -fno-builtin-lrintf -fno-builtin-lrintf32
|
||||
+CFLAGS-s_lround.c += -fno-builtin-lroundf -fno-builtin-lroundf32
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),misc)
|
||||
diff --git a/sysdeps/powerpc/powerpc64/fpu/Makefile b/sysdeps/powerpc/powerpc64/fpu/Makefile
|
||||
index 05075c2a75c294c3..9359049b555d4457 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/fpu/Makefile
|
||||
+++ b/sysdeps/powerpc/powerpc64/fpu/Makefile
|
||||
@@ -1,7 +1,9 @@
|
||||
ifeq ($(subdir),math)
|
||||
# lrintf and llrintf are aliased to llrint, so suppress compiler builtins to
|
||||
# avoid mismatched signatures.
|
||||
-CFLAGS-s_llrint.c += -fno-builtin-lrintf -fno-builtin-llrintf
|
||||
+CFLAGS-s_llrint.c += -fno-builtin-lrintf -fno-builtin-llrintf \
|
||||
+ -fno-builtin-lrintf32 -fno-builtin-llrintf32
|
||||
# Same as before but for lroundf and llroundf
|
||||
-CFLAGS-s_llround.c += -fno-builtin-lroundf -fno-builtin-llroundf
|
||||
+CFLAGS-s_llround.c += -fno-builtin-lroundf -fno-builtin-llroundf \
|
||||
+ -fno-builtin-lroundf32 -fno-builtin-llroundf32
|
||||
endif
|
||||
diff --git a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
|
||||
index cc073b53d3292ff8..858061484e1ab419 100644
|
||||
--- a/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
|
||||
+++ b/sysdeps/powerpc/powerpc64/le/fpu/multiarch/Makefile
|
||||
@@ -207,6 +207,131 @@ endef
|
||||
object-suffixes-left := $(all-object-suffixes)
|
||||
include $(o-iterator)
|
||||
|
||||
+CFLAGS-w_acosf128-ifunc.c += -fno-builtin-acosf64x
|
||||
+CFLAGS-w_acoshf128-ifunc.c += -fno-builtin-acoshf64x
|
||||
+CFLAGS-w_asinf128-ifunc.c += -fno-builtin-asinf64x
|
||||
+CFLAGS-s_asinhf128-ifunc.c += -fno-builtin-asinhf64x
|
||||
+CFLAGS-s_atanf128-ifunc.c += -fno-builtin-atanf64x
|
||||
+CFLAGS-w_atan2f128-ifunc.c += -fno-builtin-atan2f64x
|
||||
+CFLAGS-w_atanhf128-ifunc.c += -fno-builtin-atanhf64x
|
||||
+CFLAGS-s_cabsf128-ifunc.c += -fno-builtin-cabsf64x
|
||||
+CFLAGS-s_cacosf128-ifunc.c += -fno-builtin-cacosf64x
|
||||
+CFLAGS-s_cacoshf128-ifunc.c += -fno-builtin-cacoshf64x
|
||||
+CFLAGS-s_canonicalizef128-ifunc.c += -fno-builtin-canonicalizef64x
|
||||
+CFLAGS-s_cargf128-ifunc.c += -fno-builtin-cargf64x
|
||||
+CFLAGS-s_casinf128-ifunc.c += -fno-builtin-casinf64x
|
||||
+CFLAGS-s_casinhf128-ifunc.c += -fno-builtin-casinhf64x
|
||||
+CFLAGS-s_catanf128-ifunc.c += -fno-builtin-catanf64x
|
||||
+CFLAGS-s_catanhf128-ifunc.c += -fno-builtin-catanhf64x
|
||||
+CFLAGS-s_cbrtf128-ifunc.c += -fno-builtin-cbrtf64x
|
||||
+CFLAGS-s_ccosf128-ifunc.c += -fno-builtin-ccosf64x
|
||||
+CFLAGS-s_ccoshf128-ifunc.c += -fno-builtin-ccoshf64x
|
||||
+CFLAGS-s_ceilf128-ifunc.c += -fno-builtin-ceilf64x
|
||||
+CFLAGS-s_cexpf128-ifunc.c += -fno-builtin-cexpf64x
|
||||
+CFLAGS-s_cimagf128-ifunc.c += -fno-builtin-cimagf64x
|
||||
+CFLAGS-s_clogf128-ifunc.c += -fno-builtin-clogf64x
|
||||
+CFLAGS-s_clog10f128-ifunc.c += -fno-builtin-clog10f64x
|
||||
+CFLAGS-s_conjf128-ifunc.c += -fno-builtin-conjf64x
|
||||
+CFLAGS-s_copysignf128-ifunc.c += -fno-builtin-copysignf64x
|
||||
+CFLAGS-s_cosf128-ifunc.c += -fno-builtin-cosf64x
|
||||
+CFLAGS-w_coshf128-ifunc.c += -fno-builtin-coshf64x
|
||||
+CFLAGS-s_cpowf128-ifunc.c += -fno-builtin-cpowf64x
|
||||
+CFLAGS-s_cprojf128-ifunc.c += -fno-builtin-cprojf64x
|
||||
+CFLAGS-s_crealf128-ifunc.c += -fno-builtin-crealf64x
|
||||
+CFLAGS-s_csinf128-ifunc.c += -fno-builtin-csinf64x
|
||||
+CFLAGS-s_csinhf128-ifunc.c += -fno-builtin-csinhf64x
|
||||
+CFLAGS-s_csqrtf128-ifunc.c += -fno-builtin-csqrtf64x
|
||||
+CFLAGS-s_ctanf128-ifunc.c += -fno-builtin-ctanf64x
|
||||
+CFLAGS-s_ctanhf128-ifunc.c += -fno-builtin-ctanhf64x
|
||||
+CFLAGS-s_daddf128-ifunc.c += -fno-builtin-f64addf64x
|
||||
+CFLAGS-s_ddivf128-ifunc.c += -fno-builtin-f64divf64x
|
||||
+CFLAGS-s_dfmaf128-ifunc.c += -fno-builtin-f64fmaf64x
|
||||
+CFLAGS-s_dmulf128-ifunc.c += -fno-builtin-f64mulf64x
|
||||
+CFLAGS-s_dsqrtf128-ifunc.c += -fno-builtin-f64sqrtf64x
|
||||
+CFLAGS-s_dsubf128-ifunc.c += -fno-builtin-f64subf64x
|
||||
+CFLAGS-s_erff128-ifunc.c += -fno-builtin-erff64x
|
||||
+CFLAGS-s_erfcf128-ifunc.c += -fno-builtin-erfcf64x
|
||||
+CFLAGS-e_expf128-ifunc.c += -fno-builtin-expf64x
|
||||
+CFLAGS-w_exp10f128-ifunc.c += -fno-builtin-exp10f64x
|
||||
+CFLAGS-e_exp2f128-ifunc.c += -fno-builtin-exp2f64x
|
||||
+CFLAGS-s_expm1f128-ifunc.c += -fno-builtin-expm1f64x
|
||||
+CFLAGS-s_fabsf128-ifunc.c += -fno-builtin-fabsf64x
|
||||
+CFLAGS-s_faddf128-ifunc.c += -fno-builtin-f32addf64x
|
||||
+CFLAGS-s_fdimf128-ifunc.c += -fno-builtin-fdimf64x
|
||||
+CFLAGS-s_fdivf128-ifunc.c += -fno-builtin-f32divf64x
|
||||
+CFLAGS-s_ffmaf128-ifunc.c += -fno-builtin-f32fmaf64x
|
||||
+CFLAGS-s_floorf128-ifunc.c += -fno-builtin-floorf64x
|
||||
+CFLAGS-s_fmaf128-ifunc.c += -fno-builtin-fmaf64x
|
||||
+CFLAGS-s_fmaxf128-ifunc.c += -fno-builtin-fmaxf64x
|
||||
+CFLAGS-s_fmaximumf128-ifunc.c += -fno-builtin-fmaximumf64x
|
||||
+CFLAGS-s_fmaximum_magf128-ifunc.c += -fno-builtin-fmaximum_magf64x
|
||||
+CFLAGS-s_fmaximum_mag_numf128-ifunc.c += -fno-builtin-fmaximum_mag_numf64x
|
||||
+CFLAGS-s_fmaximum_numf128-ifunc.c += -fno-builtin-fmaximum_numf64x
|
||||
+CFLAGS-s_fmaxmagf128-ifunc.c += -fno-builtin-fmaxmagf64x
|
||||
+CFLAGS-s_fminf128-ifunc.c += -fno-builtin-fminf64x
|
||||
+CFLAGS-s_fminimumf128-ifunc.c += -fno-builtin-fminimumf64x
|
||||
+CFLAGS-s_fminimum_magf128-ifunc.c += -fno-builtin-fminimum_magf64x
|
||||
+CFLAGS-s_fminimum_mag_numf128-ifunc.c += -fno-builtin-fminimum_mag_numf64x
|
||||
+CFLAGS-s_fminimum_numf128-ifunc.c += -fno-builtin-fminimum_numf64x
|
||||
+CFLAGS-s_fminmagf128-ifunc.c += -fno-builtin-fminmagf64x
|
||||
+CFLAGS-w_fmodf128-ifunc.c += -fno-builtin-fmodf64x
|
||||
+CFLAGS-s_fmulf128-ifunc.c += -fno-builtin-f32mulf64x
|
||||
+CFLAGS-s_frexpf128-ifunc.c += -fno-builtin-frexpf64x
|
||||
+CFLAGS-s_fromfpf128-ifunc.c += -fno-builtin-fromfpf64x
|
||||
+CFLAGS-s_fromfpxf128-ifunc.c += -fno-builtin-fromfpxf64x
|
||||
+CFLAGS-s_fsqrtf128-ifunc.c += -fno-builtin-f32sqrtf64x
|
||||
+CFLAGS-s_fsubf128-ifunc.c += -fno-builtin-f32subf64x
|
||||
+CFLAGS-s_getpayloadf128-ifunc.c += -fno-builtin-getpayloadf64x
|
||||
+CFLAGS-w_hypotf128-ifunc.c += -fno-builtin-hypotf64x
|
||||
+CFLAGS-w_ilogbf128-ifunc.c += -fno-builtin-ilogbf64x
|
||||
+CFLAGS-w_j0f128-ifunc.c += -fno-builtin-j0f64x
|
||||
+CFLAGS-w_j1f128-ifunc.c += -fno-builtin-j1f64x
|
||||
+CFLAGS-w_jnf128-ifunc.c += -fno-builtin-jnf64x
|
||||
+CFLAGS-s_ldexpf128-ifunc.c += -fno-builtin-ldexpf64x
|
||||
+CFLAGS-w_lgammaf128-ifunc.c += -fno-builtin-lgammaf64x
|
||||
+CFLAGS-w_lgammaf128_r-ifunc.c += -fno-builtin-lgammaf64x_r
|
||||
+CFLAGS-w_llogbf128-ifunc.c += -fno-builtin-llogbf64x
|
||||
+CFLAGS-s_llrintf128-ifunc.c += -fno-builtin-llrintf64x
|
||||
+CFLAGS-s_llroundf128-ifunc.c += -fno-builtin-llroundf64x
|
||||
+CFLAGS-e_logf128-ifunc.c += -fno-builtin-logf64x
|
||||
+CFLAGS-w_log10f128-ifunc.c += -fno-builtin-log10f64x
|
||||
+CFLAGS-w_log1pf128-ifunc.c += -fno-builtin-log1pf64x
|
||||
+CFLAGS-e_log2f128-ifunc.c += -fno-builtin-log2f64x
|
||||
+CFLAGS-s_logbf128-ifunc.c += -fno-builtin-logbf64x
|
||||
+CFLAGS-s_lrintf128-ifunc.c += -fno-builtin-lrintf64x
|
||||
+CFLAGS-s_lroundf128-ifunc.c += -fno-builtin-lroundf64x
|
||||
+CFLAGS-s_modff128-ifunc.c += -fno-builtin-modff64x
|
||||
+CFLAGS-s_nanf128-ifunc.c += -fno-builtin-nanf64x
|
||||
+CFLAGS-s_nearbyintf128-ifunc.c += -fno-builtin-nearbyintf64x
|
||||
+CFLAGS-s_nextafterf128-ifunc.c += -fno-builtin-nextafterf64x
|
||||
+CFLAGS-s_nextdownf128-ifunc.c += -fno-builtin-nextdownf64x
|
||||
+CFLAGS-s_nextupf128-ifunc.c += -fno-builtin-nextupf64x
|
||||
+CFLAGS-e_powf128-ifunc.c += -fno-builtin-powf64x
|
||||
+CFLAGS-w_remainderf128-ifunc.c += -fno-builtin-remainderf64x
|
||||
+CFLAGS-s_remquof128-ifunc.c += -fno-builtin-remquof64x
|
||||
+CFLAGS-s_rintf128-ifunc.c += -fno-builtin-rintf64x
|
||||
+CFLAGS-s_roundf128-ifunc.c += -fno-builtin-roundf64x
|
||||
+CFLAGS-s_roundevenf128-ifunc.c += -fno-builtin-roundevenf64x
|
||||
+CFLAGS-w_scalblnf128-ifunc.c += -fno-builtin-scalblnf64x
|
||||
+CFLAGS-s_scalbnf128-ifunc.c += -fno-builtin-scalbnf64x
|
||||
+CFLAGS-s_setpayloadf128-ifunc.c += -fno-builtin-setpayloadf64x
|
||||
+CFLAGS-s_setpayloadsigf128-ifunc.c += -fno-builtin-setpayloadsigf64x
|
||||
+CFLAGS-s_sinf128-ifunc.c += -fno-builtin-sinf64x
|
||||
+CFLAGS-s_sincosf128-ifunc.c += -fno-builtin-sincosf64x
|
||||
+CFLAGS-w_sinhf128-ifunc.c += -fno-builtin-sinhf64x
|
||||
+CFLAGS-w_sqrtf128-ifunc.c += -fno-builtin-sqrtf64x
|
||||
+CFLAGS-s_tanf128-ifunc.c += -fno-builtin-tanf64x
|
||||
+CFLAGS-s_tanhf128-ifunc.c += -fno-builtin-tanhf64x
|
||||
+CFLAGS-w_tgammaf128-ifunc.c += -fno-builtin-tgammaf64x
|
||||
+CFLAGS-s_totalorderf128-ifunc.c += -fno-builtin-totalorderf64x
|
||||
+CFLAGS-s_totalordermagf128-ifunc.c += -fno-builtin-totalordermagf64x
|
||||
+CFLAGS-s_truncf128-ifunc.c += -fno-builtin-truncf64x
|
||||
+CFLAGS-s_ufromfpf128-ifunc.c += -fno-builtin-ufromfpf64x
|
||||
+CFLAGS-s_ufromfpxf128-ifunc.c += -fno-builtin-ufromfpxf64x
|
||||
+CFLAGS-s_y0f128-ifunc.c += -fno-builtin-y0f64x
|
||||
+CFLAGS-s_y1f128-ifunc.c += -fno-builtin-y1f64x
|
||||
+CFLAGS-s_ynf128-ifunc.c += -fno-builtin-ynf64x
|
||||
+
|
||||
endif # do_f128_multiarch
|
||||
|
||||
libm-sysdep_routines += e_log-ppc64
|
||||
diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile
|
||||
index 8748956563babf8f..31732aa248fe62cf 100644
|
||||
--- a/sysdeps/x86_64/x32/Makefile
|
||||
+++ b/sysdeps/x86_64/x32/Makefile
|
||||
@@ -2,7 +2,8 @@ ifeq ($(subdir),math)
|
||||
# Since x32 returns 32-bit long int and 64-bit long long int in the
|
||||
# same 64-bit register, we make the 32b-bit lround an alias of the
|
||||
# 64-bit llround. Add -fno-builtin-lround to silence the compiler.
|
||||
-CFLAGS-s_llround.c += -fno-builtin-lround
|
||||
+CFLAGS-s_llround.c += -fno-builtin-lround -fno-builtin-lroundf32x \
|
||||
+ -fno-builtin-lroundf64
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),string)
|
|
@ -0,0 +1,89 @@
|
|||
commit 9cc9d61ee12f2f8620d8e0ea3c42af02bf07fe1e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Nov 4 18:37:16 2022 +0100
|
||||
|
||||
elf: Disable some subtests of ifuncmain1, ifuncmain5 for !PIE
|
||||
|
||||
diff --git a/elf/ifuncmain1.c b/elf/ifuncmain1.c
|
||||
index 747fc02648a5493e..6effce3d77b1f706 100644
|
||||
--- a/elf/ifuncmain1.c
|
||||
+++ b/elf/ifuncmain1.c
|
||||
@@ -19,7 +19,14 @@ typedef int (*foo_p) (void);
|
||||
#endif
|
||||
|
||||
foo_p foo_ptr = foo;
|
||||
+
|
||||
+/* Address-significant access to protected symbols is not supported in
|
||||
+ position-dependent mode on several architectures because GCC
|
||||
+ generates relocations that assume that the address is local to the
|
||||
+ main program. */
|
||||
+#ifdef __PIE__
|
||||
foo_p foo_procted_ptr = foo_protected;
|
||||
+#endif
|
||||
|
||||
extern foo_p get_foo_p (void);
|
||||
extern foo_p get_foo_hidden_p (void);
|
||||
@@ -37,12 +44,16 @@ main (void)
|
||||
if ((*foo_ptr) () != -1)
|
||||
abort ();
|
||||
|
||||
+#ifdef __PIE__
|
||||
if (foo_procted_ptr != foo_protected)
|
||||
abort ();
|
||||
+#endif
|
||||
if (foo_protected () != 0)
|
||||
abort ();
|
||||
+#ifdef __PIE__
|
||||
if ((*foo_procted_ptr) () != 0)
|
||||
abort ();
|
||||
+#endif
|
||||
|
||||
p = get_foo_p ();
|
||||
if (p != foo)
|
||||
@@ -55,8 +66,10 @@ main (void)
|
||||
abort ();
|
||||
|
||||
p = get_foo_protected_p ();
|
||||
+#ifdef __PIE__
|
||||
if (p != foo_protected)
|
||||
abort ();
|
||||
+#endif
|
||||
if (ret_foo_protected != 0 || (*p) () != ret_foo_protected)
|
||||
abort ();
|
||||
|
||||
diff --git a/elf/ifuncmain5.c b/elf/ifuncmain5.c
|
||||
index f398085cb46719d1..6fda768fb6908aed 100644
|
||||
--- a/elf/ifuncmain5.c
|
||||
+++ b/elf/ifuncmain5.c
|
||||
@@ -14,12 +14,19 @@ get_foo (void)
|
||||
return foo;
|
||||
}
|
||||
|
||||
+
|
||||
+/* Address-significant access to protected symbols is not supported in
|
||||
+ position-dependent mode on several architectures because GCC
|
||||
+ generates relocations that assume that the address is local to the
|
||||
+ main program. */
|
||||
+#ifdef __PIE__
|
||||
foo_p
|
||||
__attribute__ ((noinline))
|
||||
get_foo_protected (void)
|
||||
{
|
||||
return foo_protected;
|
||||
}
|
||||
+#endif
|
||||
|
||||
int
|
||||
main (void)
|
||||
@@ -30,9 +37,11 @@ main (void)
|
||||
if ((*p) () != -1)
|
||||
abort ();
|
||||
|
||||
+#ifdef __PIE__
|
||||
p = get_foo_protected ();
|
||||
if ((*p) () != 0)
|
||||
abort ();
|
||||
+#endif
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,938 @@
|
|||
commit 8a78f833d670f86302f2d0c32eb1e4357d9166ff
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Fri Jan 6 19:33:29 2023 +0000
|
||||
|
||||
C2x semantics for <tgmath.h>
|
||||
|
||||
<tgmath.h> implements semantics for integer generic arguments that
|
||||
handle cases involving _FloatN / _FloatNx types as specified in TS
|
||||
18661-3 plus some defect fixes.
|
||||
|
||||
C2x has further changes to the semantics for <tgmath.h> macros with
|
||||
such types, which should also be considered defect fixes (although
|
||||
handled through the integration of TS 18661-3 in C2x rather than
|
||||
through an issue tracking process). Specifically, the rules were
|
||||
changed because of problems raised with using the macros with the
|
||||
evaluation format types such as float_t and _Float32_t: the older
|
||||
version of the rules didn't allow passing _FloatN / _FloatNx types to
|
||||
the narrowing macros returning float or double, or passing float /
|
||||
double / long double to the narrowing macros returning _FloatN /
|
||||
_FloatNx, which was a problem with the evaluation format types which
|
||||
could be either kind of type depending on the value of
|
||||
FLT_EVAL_METHOD.
|
||||
|
||||
Thus the new rules allow cases of mixing types which were not allowed
|
||||
before, and, as part of the changes, the handling of integer arguments
|
||||
was also changed: if there is any _FloatNx generic argument, integer
|
||||
generic arguments are treated as _Float32x (not double), while the
|
||||
rule about treating integer arguments to narrowing macros returning
|
||||
_FloatN or _FloatNx as _Float64 not double was removed (no longer
|
||||
needed now double is a valid argument to such macros).
|
||||
|
||||
I've implemented the changes in GCC's __builtin_tgmath, which thus
|
||||
requires updates to glibc's test expectations so that the tests
|
||||
continue to build with GCC 13 (the test is also updated to test the
|
||||
argument types that weren't allowed before but are now valid under C2x
|
||||
rules).
|
||||
|
||||
Given those test changes, it's then also necessary to fix the
|
||||
implementations in <tgmath.h> to have appropriate semantics with older
|
||||
GCC so that the tests pass with GCC versions before GCC 13 as well.
|
||||
For some cases (non-narrowing macros with two or three generic
|
||||
arguments; narrowing macros returning _Float32x), the older version of
|
||||
__builtin_tgmath doesn't correspond sufficiently well to C2x
|
||||
semantics, so in those cases <tgmath.h> is adjusted to use the older
|
||||
macro implementation instead of __builtin_tgmath. The older macro
|
||||
implementation is itself adjusted to give the desired semantics, with
|
||||
GCC 7 and later. (It's not possible to get the right semantics in all
|
||||
cases for the narrowing macros with GCC 6 and before when the _FloatN
|
||||
/ _FloatNx names are typedefs rather than distinct types.)
|
||||
|
||||
Tested as follows: with the full glibc testsuite for x86_64, GCC 6, 7,
|
||||
11, 13; with execution of the math/tests for aarch64, arm, powerpc and
|
||||
powerpc64le, GCC 6, 7, 12 and 13 (powerpc64le only with GCC 12 and
|
||||
13); with build-many-glibcs.py with GCC 6, 7, 12 and 13.
|
||||
|
||||
Conflicts:
|
||||
math/tgmath.h
|
||||
(missing support for narrowing fma/sqrt downstream
|
||||
means that the definitions for __TGMATH_1_NARROW_*
|
||||
and __TGMATH_3_NARROW_* are not needed)
|
||||
|
||||
diff --git a/math/gen-tgmath-tests.py b/math/gen-tgmath-tests.py
|
||||
index 364963da6525e08d..be5e8cd9a07ef071 100755
|
||||
--- a/math/gen-tgmath-tests.py
|
||||
+++ b/math/gen-tgmath-tests.py
|
||||
@@ -19,14 +19,13 @@
|
||||
|
||||
# As glibc does not support decimal floating point, the types to
|
||||
# consider for generic parameters are standard and binary
|
||||
-# floating-point types, and integer types which are treated as double.
|
||||
-# The corresponding complex types may also be used (including complex
|
||||
-# integer types, which are a GNU extension, but are currently disabled
|
||||
-# here because they do not work properly with tgmath.h).
|
||||
-
|
||||
-# The proposed resolution to TS 18661-1 DR#9
|
||||
-# <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2149.htm#dr_9>
|
||||
-# makes the <tgmath.h> rules for selecting a function to call
|
||||
+# floating-point types, and integer types which are treated as
|
||||
+# _Float32x if any argument has a _FloatNx type and otherwise as
|
||||
+# double. The corresponding complex types may also be used (including
|
||||
+# complex integer types, which are a GNU extension, but are currently
|
||||
+# disabled here because they do not work properly with tgmath.h).
|
||||
+
|
||||
+# C2x makes the <tgmath.h> rules for selecting a function to call
|
||||
# correspond to the usual arithmetic conversions (applied successively
|
||||
# to the arguments for generic parameters in order), which choose the
|
||||
# type whose set of values contains that of the other type (undefined
|
||||
@@ -69,10 +68,6 @@ class Type(object):
|
||||
# Real argument types that correspond to a standard floating type
|
||||
# (float, double or long double; not _FloatN or _FloatNx).
|
||||
standard_real_argument_types_list = []
|
||||
- # Real argument types other than float, double and long double
|
||||
- # (i.e., those that are valid as arguments to narrowing macros
|
||||
- # returning _FloatN or _FloatNx).
|
||||
- non_standard_real_argument_types_list = []
|
||||
# The real floating types by their order properties (which are
|
||||
# tuples giving the positions in both the possible orders above).
|
||||
real_types_order = {}
|
||||
@@ -86,13 +81,16 @@ class Type(object):
|
||||
float64_type = None
|
||||
# The type _Complex _Float64.
|
||||
complex_float64_type = None
|
||||
+ # The type _Float32x.
|
||||
+ float32x_type = None
|
||||
+ # The type _Complex _Float32x.
|
||||
+ complex_float32x_type = None
|
||||
# The type _Float64x.
|
||||
float64x_type = None
|
||||
- # The type _Float64x if available, otherwise _Float64.
|
||||
- float32x_ext_type = None
|
||||
|
||||
def __init__(self, name, suffix=None, mant_dig=None, condition='1',
|
||||
- order=None, integer=False, complex=False, real_type=None):
|
||||
+ order=None, integer=False, complex=False, real_type=None,
|
||||
+ floatnx=False):
|
||||
"""Initialize a Type object, creating any corresponding complex type
|
||||
in the process."""
|
||||
self.name = name
|
||||
@@ -102,6 +100,7 @@ class Type(object):
|
||||
self.order = order
|
||||
self.integer = integer
|
||||
self.complex = complex
|
||||
+ self.floatnx = floatnx
|
||||
if complex:
|
||||
self.complex_type = self
|
||||
self.real_type = real_type
|
||||
@@ -119,8 +118,6 @@ class Type(object):
|
||||
Type.real_argument_types_list.append(self)
|
||||
if not self.name.startswith('_Float'):
|
||||
Type.standard_real_argument_types_list.append(self)
|
||||
- if self.name not in ('float', 'double', 'long double'):
|
||||
- Type.non_standard_real_argument_types_list.append(self)
|
||||
if self.order is not None:
|
||||
Type.real_types_order[self.order] = self
|
||||
if self.name == 'double':
|
||||
@@ -133,26 +130,28 @@ class Type(object):
|
||||
Type.float64_type = self
|
||||
if self.name == '_Complex _Float64':
|
||||
Type.complex_float64_type = self
|
||||
+ if self.name == '_Float32x':
|
||||
+ Type.float32x_type = self
|
||||
+ if self.name == '_Complex _Float32x':
|
||||
+ Type.complex_float32x_type = self
|
||||
if self.name == '_Float64x':
|
||||
Type.float64x_type = self
|
||||
- if self.name == 'Float32x_ext':
|
||||
- Type.float32x_ext_type = self
|
||||
|
||||
@staticmethod
|
||||
def create_type(name, suffix=None, mant_dig=None, condition='1', order=None,
|
||||
integer=False, complex_name=None, complex_ok=True,
|
||||
- internal=False):
|
||||
+ floatnx=False, internal=False):
|
||||
"""Create and register a Type object for a real type, creating any
|
||||
corresponding complex type in the process."""
|
||||
real_type = Type(name, suffix=suffix, mant_dig=mant_dig,
|
||||
condition=condition, order=order, integer=integer,
|
||||
- complex=False)
|
||||
+ complex=False, floatnx=floatnx)
|
||||
if complex_ok:
|
||||
if complex_name is None:
|
||||
complex_name = '_Complex %s' % name
|
||||
complex_type = Type(complex_name, condition=condition,
|
||||
integer=integer, complex=True,
|
||||
- real_type=real_type)
|
||||
+ real_type=real_type, floatnx=floatnx)
|
||||
else:
|
||||
complex_type = None
|
||||
real_type.complex_type = complex_type
|
||||
@@ -160,13 +159,13 @@ class Type(object):
|
||||
if complex_type is not None:
|
||||
complex_type.register_type(internal)
|
||||
|
||||
- def floating_type(self, floatn):
|
||||
+ def floating_type(self, integer_float32x):
|
||||
"""Return the corresponding floating type."""
|
||||
if self.integer:
|
||||
- if floatn:
|
||||
- return (Type.complex_float64_type
|
||||
+ if integer_float32x:
|
||||
+ return (Type.complex_float32x_type
|
||||
if self.complex
|
||||
- else Type.float64_type)
|
||||
+ else Type.float32x_type)
|
||||
else:
|
||||
return (Type.complex_double_type
|
||||
if self.complex
|
||||
@@ -174,9 +173,9 @@ class Type(object):
|
||||
else:
|
||||
return self
|
||||
|
||||
- def real_floating_type(self, floatn):
|
||||
+ def real_floating_type(self, integer_float32x):
|
||||
"""Return the corresponding real floating type."""
|
||||
- return self.real_type.floating_type(floatn)
|
||||
+ return self.real_type.floating_type(integer_float32x)
|
||||
|
||||
def __str__(self):
|
||||
"""Return string representation of a type."""
|
||||
@@ -194,7 +193,8 @@ class Type(object):
|
||||
condition='defined HUGE_VAL_F32', order=(2, 2))
|
||||
Type.create_type('_Float32x', 'f32x', 'FLT32X_MANT_DIG',
|
||||
complex_name='__CFLOAT32X',
|
||||
- condition='defined HUGE_VAL_F32X', order=(3, 3))
|
||||
+ condition='defined HUGE_VAL_F32X', order=(3, 3),
|
||||
+ floatnx=True)
|
||||
Type.create_type('double', '', 'DBL_MANT_DIG', order=(4, 4))
|
||||
Type.create_type('long double', 'l', 'LDBL_MANT_DIG', order=(5, 7))
|
||||
Type.create_type('_Float64', 'f64', 'FLT64_MANT_DIG',
|
||||
@@ -202,7 +202,8 @@ class Type(object):
|
||||
condition='defined HUGE_VAL_F64', order=(6, 5))
|
||||
Type.create_type('_Float64x', 'f64x', 'FLT64X_MANT_DIG',
|
||||
complex_name='__CFLOAT64X',
|
||||
- condition='defined HUGE_VAL_F64X', order=(7, 6))
|
||||
+ condition='defined HUGE_VAL_F64X', order=(7, 6),
|
||||
+ floatnx=True)
|
||||
Type.create_type('_Float128', 'f128', 'FLT128_MANT_DIG',
|
||||
complex_name='__CFLOAT128',
|
||||
condition='defined HUGE_VAL_F128', order=(8, 8))
|
||||
@@ -235,21 +236,16 @@ class Type(object):
|
||||
complex_name='complex_long_double_Float64x',
|
||||
condition='defined HUGE_VAL_F64X', order=(7, 7),
|
||||
internal=True)
|
||||
- # An internal type for the argument type used by f32x*
|
||||
- # narrowing macros (_Float64x if available, otherwise
|
||||
- # _Float64).
|
||||
- Type.create_type('Float32x_ext', None, 'FLT32X_EXT_MANT_DIG',
|
||||
- complex_name='complex_Float32x_ext',
|
||||
- condition='1', internal=True)
|
||||
|
||||
@staticmethod
|
||||
- def can_combine_types(types, floatn):
|
||||
+ def can_combine_types(types):
|
||||
"""Return a C preprocessor conditional for whether the given list of
|
||||
types can be used together as type-generic macro arguments."""
|
||||
have_long_double = False
|
||||
have_float128 = False
|
||||
+ integer_float32x = any(t.floatnx for t in types)
|
||||
for t in types:
|
||||
- t = t.real_floating_type(floatn)
|
||||
+ t = t.real_floating_type(integer_float32x)
|
||||
if t.name == 'long double':
|
||||
have_long_double = True
|
||||
if t.name == '_Float128' or t.name == '_Float64x':
|
||||
@@ -262,14 +258,15 @@ class Type(object):
|
||||
return '1'
|
||||
|
||||
@staticmethod
|
||||
- def combine_types(types, floatn):
|
||||
+ def combine_types(types):
|
||||
"""Return the result of combining a set of types."""
|
||||
have_complex = False
|
||||
combined = None
|
||||
+ integer_float32x = any(t.floatnx for t in types)
|
||||
for t in types:
|
||||
if t.complex:
|
||||
have_complex = True
|
||||
- t = t.real_floating_type(floatn)
|
||||
+ t = t.real_floating_type(integer_float32x)
|
||||
if combined is None:
|
||||
combined = t
|
||||
else:
|
||||
@@ -375,18 +372,8 @@ class Tests(object):
|
||||
'# endif\n')
|
||||
float64x_text = if_cond_text([Type.float64x_type.condition],
|
||||
float64x_text)
|
||||
- float32x_ext_text = ('#ifdef HUGE_VAL_F64X\n'
|
||||
- 'typedef _Float64x Float32x_ext;\n'
|
||||
- 'typedef __CFLOAT64X complex_Float32x_ext;\n'
|
||||
- '# define FLT32X_EXT_MANT_DIG FLT64X_MANT_DIG\n'
|
||||
- '#else\n'
|
||||
- 'typedef _Float64 Float32x_ext;\n'
|
||||
- 'typedef __CFLOAT64 complex_Float32x_ext;\n'
|
||||
- '# define FLT32X_EXT_MANT_DIG FLT64_MANT_DIG\n'
|
||||
- '#endif\n')
|
||||
self.header_list.append(float64_text)
|
||||
self.header_list.append(float64x_text)
|
||||
- self.header_list.append(float32x_ext_text)
|
||||
self.types_seen = set()
|
||||
for t in Type.all_types_list:
|
||||
self.add_type_var(t.name, t.condition)
|
||||
@@ -439,39 +426,33 @@ class Tests(object):
|
||||
narrowing_std = True
|
||||
narrow_cond = '1'
|
||||
narrow_args = [Type.double_type, Type.long_double_type]
|
||||
- narrow_fallback = Type.double_type
|
||||
elif ret == 'double':
|
||||
narrowing = True
|
||||
narrowing_std = True
|
||||
narrow_cond = '1'
|
||||
narrow_args = [Type.long_double_type]
|
||||
- narrow_fallback = Type.long_double_type
|
||||
elif ret.startswith('_Float'):
|
||||
narrowing = True
|
||||
- narrow_args = []
|
||||
+ narrow_args_1 = []
|
||||
+ narrow_args_2 = []
|
||||
nret_type = None
|
||||
- narrow_fallback = None
|
||||
for order, real_type in sorted(Type.real_types_order.items()):
|
||||
if real_type.name == ret:
|
||||
nret_type = real_type
|
||||
elif nret_type and real_type.name.startswith('_Float'):
|
||||
- narrow_args.append(real_type)
|
||||
- if (narrow_fallback is None
|
||||
- and ret.endswith('x') == real_type.name.endswith('x')):
|
||||
- narrow_fallback = real_type
|
||||
+ if ret.endswith('x') == real_type.name.endswith('x'):
|
||||
+ narrow_args_1.append(real_type)
|
||||
+ else:
|
||||
+ narrow_args_2.append(real_type)
|
||||
+ narrow_args = narrow_args_1 + narrow_args_2
|
||||
if narrow_args:
|
||||
narrow_cond = ('(%s && (%s))'
|
||||
% (nret_type.condition,
|
||||
' || '.join(t.condition
|
||||
for t in narrow_args)))
|
||||
- if narrow_fallback is None:
|
||||
- narrow_fallback = narrow_args[0]
|
||||
- if ret == '_Float32x':
|
||||
- narrow_fallback = Type.float32x_ext_type
|
||||
else:
|
||||
# No possible argument types, even conditionally.
|
||||
narrow_cond = '0'
|
||||
- narrowing_nonstd = narrowing and not narrowing_std
|
||||
types = [ret] + args
|
||||
for t in types:
|
||||
if t != 'c' and t != 'g' and t != 'r' and t != 's':
|
||||
@@ -530,19 +511,13 @@ class Tests(object):
|
||||
if t == 'g' or t == 'c':
|
||||
arg_types.append(Type.argument_types_list)
|
||||
elif t == 'r':
|
||||
- if narrowing_std:
|
||||
- arg_types.append(Type.standard_real_argument_types_list)
|
||||
- elif narrowing:
|
||||
- arg_types.append(
|
||||
- Type.non_standard_real_argument_types_list)
|
||||
- else:
|
||||
- arg_types.append(Type.real_argument_types_list)
|
||||
+ arg_types.append(Type.real_argument_types_list)
|
||||
elif t == 's':
|
||||
arg_types.append(Type.standard_real_argument_types_list)
|
||||
arg_types_product = list_product(arg_types)
|
||||
test_num = 0
|
||||
for this_args in arg_types_product:
|
||||
- comb_type = Type.combine_types(this_args, narrowing_nonstd)
|
||||
+ comb_type = Type.combine_types(this_args)
|
||||
if narrowing:
|
||||
# As long as there are no integer arguments, and as
|
||||
# long as the chosen argument type is as wide as all
|
||||
@@ -550,22 +525,22 @@ class Tests(object):
|
||||
# of the macro call do not depend on the exact
|
||||
# function chosen. In particular, for f32x functions
|
||||
# when _Float64x exists, the chosen type should differ
|
||||
- # for _Float32x and _Float64 arguments, but it is not
|
||||
- # always possible to distinguish those types before
|
||||
- # GCC 7 and the implementation does not attempt to do
|
||||
- # so before GCC 8.
|
||||
+ # for double / _Float32x and _Float64 arguments, but
|
||||
+ # it is not always possible to distinguish those types
|
||||
+ # before GCC 7 (resulting in some cases - only real
|
||||
+ # arguments - where a wider argument type is used,
|
||||
+ # which is semantically OK, and others - integer
|
||||
+ # arguments present - where it may not be OK, but is
|
||||
+ # unavoidable).
|
||||
narrow_mant_dig = comb_type.real_type.mant_dig
|
||||
for arg_type in this_args:
|
||||
if arg_type.integer:
|
||||
narrow_mant_dig = 0
|
||||
else:
|
||||
narrow_mant_dig = 0
|
||||
- if (narrowing
|
||||
- and comb_type not in narrow_args
|
||||
- and narrow_fallback is not None):
|
||||
- comb_type = narrow_fallback
|
||||
- can_comb = Type.can_combine_types(this_args, narrowing_nonstd)
|
||||
+ can_comb = Type.can_combine_types(this_args)
|
||||
all_conds = [t.condition for t in this_args]
|
||||
+ narrow_args_cond = '(%s)' % ' && '.join(sorted(set(all_conds)))
|
||||
all_conds.append(can_comb)
|
||||
if narrowing:
|
||||
all_conds.append(narrow_cond)
|
||||
@@ -579,10 +554,69 @@ class Tests(object):
|
||||
test_func_name = 'test_%s_%d' % (macro, test_num)
|
||||
test_num += 1
|
||||
mant_dig = comb_type.real_type.mant_dig
|
||||
+ test_mant_dig_comp = ''
|
||||
+ if (narrowing
|
||||
+ and comb_type not in narrow_args):
|
||||
+ # The expected argument type is the first in
|
||||
+ # narrow_args that can represent all the values of
|
||||
+ # comb_type (which, for the supported cases, means the
|
||||
+ # first with mant_dig at least as large as that for
|
||||
+ # comb_type, provided this isn't the case of an IBM
|
||||
+ # long double argument with binary128 type from
|
||||
+ # narrow_args).
|
||||
+ narrow_extra_conds = []
|
||||
+ test_mant_dig_list = ['#undef NARROW_MANT_DIG\n#if 0\n']
|
||||
+ for t in narrow_args:
|
||||
+ t_cond = '(%s && %s && %s <= %s && %s)' % (
|
||||
+ narrow_args_cond, t.condition, mant_dig, t.mant_dig,
|
||||
+ Type.can_combine_types(this_args + [t]))
|
||||
+ narrow_extra_conds.append(t_cond)
|
||||
+ test_mant_dig_list.append('#elif %s\n'
|
||||
+ '#define NARROW_MANT_DIG %s\n'
|
||||
+ % (t_cond, t.mant_dig))
|
||||
+ test_mant_dig_list.append('#endif\n')
|
||||
+ test_mant_dig_comp = ''.join(test_mant_dig_list)
|
||||
+ all_conds.append('(%s)' % ' || '.join(narrow_extra_conds))
|
||||
+ # A special case where this logic isn't correct is
|
||||
+ # where comb_type is the internal long_double_Float64
|
||||
+ # or long_double_Float64x, which will be detected as
|
||||
+ # not in narrow_args even if the actual type chosen in
|
||||
+ # a particular configuration would have been in
|
||||
+ # narrow_args, so check for that case and handle it
|
||||
+ # appropriately. In particular, if long double has
|
||||
+ # the same format as double and there are long double
|
||||
+ # and _Float64 arguments, and the macro returns
|
||||
+ # _Float32x, the function called should be one for
|
||||
+ # _Float64 arguments, not one for _Float64x arguments
|
||||
+ # that would arise from this logic.
|
||||
+ if comb_type.real_type.name == 'long_double_Float64':
|
||||
+ comb_type_1 = Type.long_double_type
|
||||
+ comb_type_2 = Type.float64_type
|
||||
+ comb_type_is_2_cond = 'LDBL_MANT_DIG <= FLT64_MANT_DIG'
|
||||
+ elif comb_type.real_type.name == 'long_double_Float64x':
|
||||
+ comb_type_1 = Type.long_double_type
|
||||
+ comb_type_2 = Type.float64x_type
|
||||
+ comb_type_is_2_cond = 'LDBL_MANT_DIG < FLT64X_MANT_DIG'
|
||||
+ else:
|
||||
+ comb_type_1 = None
|
||||
+ comb_type_2 = None
|
||||
+ if comb_type_1 is None:
|
||||
+ mant_dig = 'NARROW_MANT_DIG'
|
||||
+ else:
|
||||
+ mant_dig = ''
|
||||
+ if comb_type_1 in narrow_args:
|
||||
+ mant_dig += '!(%s) ? %s : ' % (comb_type_is_2_cond,
|
||||
+ comb_type_1.mant_dig)
|
||||
+ if comb_type_2 in narrow_args:
|
||||
+ mant_dig += '%s ? %s : ' % (comb_type_is_2_cond,
|
||||
+ comb_type_2.mant_dig)
|
||||
+ mant_dig += 'NARROW_MANT_DIG'
|
||||
+ if narrow_mant_dig != 0:
|
||||
+ narrow_mant_dig = mant_dig
|
||||
test_text = '%s, "%s", "%s", %s, %s' % (test_func_name, func_name,
|
||||
test_name, mant_dig,
|
||||
narrow_mant_dig)
|
||||
- test_text = ' { %s },\n' % test_text
|
||||
+ test_text = '%s { %s },\n' % (test_mant_dig_comp, test_text)
|
||||
test_text = if_cond_text(all_conds, test_text)
|
||||
self.test_array_list.append(test_text)
|
||||
call_args = []
|
||||
@@ -730,7 +764,7 @@ class Tests(object):
|
||||
' && strcmp (called_func_name,\n'
|
||||
' tests[i].func_name) == 0)\n'
|
||||
' num_pass++;\n'
|
||||
- '#if !__GNUC_PREREQ (8, 0)\n'
|
||||
+ '#if !__GNUC_PREREQ (7, 0)\n'
|
||||
' else if (tests[i].narrow_mant_dig > 0\n'
|
||||
' && (called_mant_dig\n'
|
||||
' >= tests[i].narrow_mant_dig)\n'
|
||||
@@ -747,6 +781,21 @@ class Tests(object):
|
||||
' tests[i].mant_dig,\n'
|
||||
' called_func_name, called_mant_dig);\n'
|
||||
' }\n'
|
||||
+ ' else if (tests[i].narrow_mant_dig == 0\n'
|
||||
+ ' && strcmp (called_func_name,\n'
|
||||
+ ' tests[i].func_name) == 0)\n'
|
||||
+ ' {\n'
|
||||
+ ' num_pass++;\n'
|
||||
+ ' printf ("Test %zu (%s):\\n"\n'
|
||||
+ ' " Expected: %s precision %d\\n"\n'
|
||||
+ ' " Actual: %s precision %d\\n"\n'
|
||||
+ ' " (unavoidable with old GCC)'
|
||||
+ '\\n\\n",\n'
|
||||
+ ' i, tests[i].test_name,\n'
|
||||
+ ' tests[i].func_name,\n'
|
||||
+ ' tests[i].mant_dig,\n'
|
||||
+ ' called_func_name, called_mant_dig);\n'
|
||||
+ ' }\n'
|
||||
'#endif\n'
|
||||
' else\n'
|
||||
' {\n'
|
||||
diff --git a/math/tgmath.h b/math/tgmath.h
|
||||
index b55cb39c93575ddc..dbd165dd1882dcc4 100644
|
||||
--- a/math/tgmath.h
|
||||
+++ b/math/tgmath.h
|
||||
@@ -37,9 +37,17 @@
|
||||
for older GCC, using other compiler extensions but with macros
|
||||
expanding their arguments many times (so resulting in exponential
|
||||
blowup of the size of expansions when calls to such macros are
|
||||
- nested inside arguments to such macros). */
|
||||
+ nested inside arguments to such macros). Because of a long series
|
||||
+ of defect fixes made after the initial release of TS 18661-1, GCC
|
||||
+ versions before GCC 13 have __builtin_tgmath semantics that, when
|
||||
+ integer arguments are passed to narrowing macros returning
|
||||
+ _Float32x, or non-narrowing macros with at least two generic
|
||||
+ arguments, do not always correspond to the C2X semantics, so more
|
||||
+ complicated macro definitions are also used in some cases for
|
||||
+ versions from GCC 8 to GCC 12. */
|
||||
|
||||
#define __HAVE_BUILTIN_TGMATH __GNUC_PREREQ (8, 0)
|
||||
+#define __HAVE_BUILTIN_TGMATH_C2X __GNUC_PREREQ (13, 0)
|
||||
|
||||
#if __GNUC_PREREQ (2, 7)
|
||||
|
||||
@@ -135,13 +143,14 @@
|
||||
__builtin_tgmath (__TGMATH_NARROW_FUNCS_F32 (F) (X), (Y))
|
||||
# define __TGMATH_2_NARROW_F64(F, X, Y) \
|
||||
__builtin_tgmath (__TGMATH_NARROW_FUNCS_F64 (F) (X), (Y))
|
||||
-# if __HAVE_FLOAT128
|
||||
+# if __HAVE_FLOAT128 && __HAVE_BUILTIN_TGMATH_C2X
|
||||
# define __TGMATH_2_NARROW_F32X(F, X, Y) \
|
||||
__builtin_tgmath (__TGMATH_NARROW_FUNCS_F32X (F) (X), (Y))
|
||||
# endif
|
||||
|
||||
-# else /* !__HAVE_BUILTIN_TGMATH. */
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
# ifdef __NO_LONG_DOUBLE_MATH
|
||||
# define __tgml(fct) fct
|
||||
# else
|
||||
@@ -181,13 +190,17 @@
|
||||
/* Whether an expression (of arithmetic type) has a real type. */
|
||||
# define __expr_is_real(E) (__builtin_classify_type (E) != 9)
|
||||
|
||||
+/* Type T1 if E is 1, type T2 is E is 0. */
|
||||
+# define __tgmath_type_if(T1, T2, E) \
|
||||
+ __typeof__ (*(0 ? (__typeof__ (0 ? (T2 *) 0 : (void *) (E))) 0 \
|
||||
+ : (__typeof__ (0 ? (T1 *) 0 : (void *) (!(E)))) 0))
|
||||
+
|
||||
/* The tgmath real type for T, where E is 0 if T is an integer type
|
||||
and 1 for a floating type. If T has a complex type, it is
|
||||
unspecified whether the return type is real or complex (but it has
|
||||
the correct corresponding real type). */
|
||||
# define __tgmath_real_type_sub(T, E) \
|
||||
- __typeof__ (*(0 ? (__typeof__ (0 ? (double *) 0 : (void *) (E))) 0 \
|
||||
- : (__typeof__ (0 ? (T *) 0 : (void *) (!(E)))) 0))
|
||||
+ __tgmath_type_if (T, double, E)
|
||||
|
||||
/* The tgmath real type of EXPR. */
|
||||
# define __tgmath_real_type(expr) \
|
||||
@@ -215,6 +228,56 @@
|
||||
__real_integer_type (__typeof__ (+(expr))), \
|
||||
__complex_integer_type (__typeof__ (+(expr))))
|
||||
|
||||
+/* The tgmath real type of EXPR1 combined with EXPR2, without handling
|
||||
+ the C2X rule of interpreting integer arguments as _Float32x if any
|
||||
+ argument is _FloatNx. */
|
||||
+# define __tgmath_real_type2_base(expr1, expr2) \
|
||||
+ __typeof ((__tgmath_real_type (expr1)) 0 + (__tgmath_real_type (expr2)) 0)
|
||||
+
|
||||
+/* The tgmath complex type of EXPR1 combined with EXPR2, without
|
||||
+ handling the C2X rule of interpreting integer arguments as
|
||||
+ _Float32x if any argument is _FloatNx. */
|
||||
+# define __tgmath_complex_type2_base(expr1, expr2) \
|
||||
+ __typeof ((__tgmath_complex_type (expr1)) 0 \
|
||||
+ + (__tgmath_complex_type (expr2)) 0)
|
||||
+
|
||||
+/* The tgmath real type of EXPR1 combined with EXPR2 and EXPR3,
|
||||
+ without handling the C2X rule of interpreting integer arguments as
|
||||
+ _Float32x if any argument is _FloatNx. */
|
||||
+# define __tgmath_real_type3_base(expr1, expr2, expr3) \
|
||||
+ __typeof ((__tgmath_real_type (expr1)) 0 \
|
||||
+ + (__tgmath_real_type (expr2)) 0 \
|
||||
+ + (__tgmath_real_type (expr3)) 0)
|
||||
+
|
||||
+/* The tgmath real or complex type of EXPR1 combined with EXPR2 (and
|
||||
+ EXPR3 if applicable). */
|
||||
+# if __HAVE_FLOATN_NOT_TYPEDEF
|
||||
+# define __tgmath_real_type2(expr1, expr2) \
|
||||
+ __tgmath_type_if (_Float32x, __tgmath_real_type2_base (expr1, expr2), \
|
||||
+ _Generic ((expr1) + (expr2), _Float32x: 1, default: 0))
|
||||
+# define __tgmath_complex_type2(expr1, expr2) \
|
||||
+ __tgmath_type_if (_Float32x, \
|
||||
+ __tgmath_type_if (_Complex _Float32x, \
|
||||
+ __tgmath_complex_type2_base (expr1, \
|
||||
+ expr2), \
|
||||
+ _Generic ((expr1) + (expr2), \
|
||||
+ _Complex _Float32x: 1, \
|
||||
+ default: 0)), \
|
||||
+ _Generic ((expr1) + (expr2), _Float32x: 1, default: 0))
|
||||
+# define __tgmath_real_type3(expr1, expr2, expr3) \
|
||||
+ __tgmath_type_if (_Float32x, \
|
||||
+ __tgmath_real_type3_base (expr1, expr2, expr3), \
|
||||
+ _Generic ((expr1) + (expr2) + (expr3), \
|
||||
+ _Float32x: 1, default: 0))
|
||||
+# else
|
||||
+# define __tgmath_real_type2(expr1, expr2) \
|
||||
+ __tgmath_real_type2_base (expr1, expr2)
|
||||
+# define __tgmath_complex_type2(expr1, expr2) \
|
||||
+ __tgmath_complex_type2_base (expr1, expr2)
|
||||
+# define __tgmath_real_type3(expr1, expr2, expr3) \
|
||||
+ __tgmath_real_type3_base (expr1, expr2, expr3)
|
||||
+# endif
|
||||
+
|
||||
# if (__HAVE_DISTINCT_FLOAT16 \
|
||||
|| __HAVE_DISTINCT_FLOAT32 \
|
||||
|| __HAVE_DISTINCT_FLOAT64 \
|
||||
@@ -226,7 +289,10 @@
|
||||
|
||||
/* Expand to text that checks if ARG_COMB has type _Float128, and if
|
||||
so calls the appropriately suffixed FCT (which may include a cast),
|
||||
- or FCT and CFCT for complex functions, with arguments ARG_CALL. */
|
||||
+ or FCT and CFCT for complex functions, with arguments ARG_CALL.
|
||||
+ __TGMATH_F128LD (only used in the __HAVE_FLOAT64X_LONG_DOUBLE case,
|
||||
+ for narrowing macros) handles long double the same as
|
||||
+ _Float128. */
|
||||
# if __HAVE_DISTINCT_FLOAT128 && __GLIBC_USE (IEC_60559_TYPES_EXT)
|
||||
# if (!__HAVE_FLOAT64X \
|
||||
|| __HAVE_FLOAT64X_LONG_DOUBLE \
|
||||
@@ -234,6 +300,10 @@
|
||||
# define __TGMATH_F128(arg_comb, fct, arg_call) \
|
||||
__builtin_types_compatible_p (__typeof (+(arg_comb)), _Float128) \
|
||||
? fct ## f128 arg_call :
|
||||
+# define __TGMATH_F128LD(arg_comb, fct, arg_call) \
|
||||
+ (__builtin_types_compatible_p (__typeof (+(arg_comb)), _Float128) \
|
||||
+ || __builtin_types_compatible_p (__typeof (+(arg_comb)), long double)) \
|
||||
+ ? fct ## f128 arg_call :
|
||||
# define __TGMATH_CF128(arg_comb, fct, cfct, arg_call) \
|
||||
__builtin_types_compatible_p (__typeof (+__real__ (arg_comb)), _Float128) \
|
||||
? (__expr_is_real (arg_comb) \
|
||||
@@ -259,7 +329,7 @@
|
||||
# define __TGMATH_CF128(arg_comb, fct, cfct, arg_call) /* Nothing. */
|
||||
# endif
|
||||
|
||||
-# endif /* !__HAVE_BUILTIN_TGMATH. */
|
||||
+# endif /* !__HAVE_BUILTIN_TGMATH_C2X. */
|
||||
|
||||
/* We have two kinds of generic macros: to support functions which are
|
||||
only defined on real valued parameters and those which are defined
|
||||
@@ -272,14 +342,18 @@
|
||||
__TGMATH_2 (Fct, (Val1), (Val2))
|
||||
# define __TGMATH_BINARY_FIRST_REAL_STD_ONLY(Val1, Val2, Fct) \
|
||||
__TGMATH_2STD (Fct, (Val1), (Val2))
|
||||
-# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
|
||||
+# if __HAVE_BUILTIN_TGMATH_C2X
|
||||
+# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
|
||||
__TGMATH_2 (Fct, (Val1), (Val2))
|
||||
+# endif
|
||||
# define __TGMATH_BINARY_REAL_STD_ONLY(Val1, Val2, Fct) \
|
||||
__TGMATH_2STD (Fct, (Val1), (Val2))
|
||||
-# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
+# if __HAVE_BUILTIN_TGMATH_C2X
|
||||
+# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
__TGMATH_3 (Fct, (Val1), (Val2), (Val3))
|
||||
-# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
+# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
__TGMATH_3 (Fct, (Val1), (Val2), (Val3))
|
||||
+# endif
|
||||
# define __TGMATH_TERNARY_FIRST_REAL_RET_ONLY(Val1, Val2, Val3, Fct) \
|
||||
__TGMATH_3 (Fct, (Val1), (Val2), (Val3))
|
||||
# define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \
|
||||
@@ -289,11 +363,14 @@
|
||||
__TGMATH_1C (Fct, Cfct, (Val))
|
||||
# define __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME(Val, Cfct) \
|
||||
__TGMATH_1 (Cfct, (Val))
|
||||
-# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
|
||||
+# if __HAVE_BUILTIN_TGMATH_C2X
|
||||
+# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
|
||||
__TGMATH_2C (Fct, Cfct, (Val1), (Val2))
|
||||
+# endif
|
||||
|
||||
-# else /* !__HAVE_BUILTIN_TGMATH. */
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_UNARY_REAL_ONLY(Val, Fct) \
|
||||
(__extension__ ((sizeof (+(Val)) == sizeof (double) \
|
||||
|| __builtin_classify_type (Val) != 8) \
|
||||
@@ -330,29 +407,28 @@
|
||||
: (sizeof (+(Val1)) == sizeof (float)) \
|
||||
? (__tgmath_real_type (Val1)) Fct##f (Val1, Val2) \
|
||||
: (__tgmath_real_type (Val1)) __tgml(Fct) (Val1, Val2)))
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \
|
||||
(__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double) \
|
||||
&& __builtin_classify_type ((Val1) + (Val2)) == 8) \
|
||||
? __TGMATH_F128 ((Val1) + (Val2), \
|
||||
- (__typeof \
|
||||
- ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) Fct, \
|
||||
+ (__tgmath_real_type2 (Val1, Val2)) Fct, \
|
||||
(Val1, Val2)) \
|
||||
- (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ (__tgmath_real_type2 (Val1, Val2)) \
|
||||
__tgml(Fct) (Val1, Val2) \
|
||||
: (sizeof (+(Val1)) == sizeof (double) \
|
||||
|| sizeof (+(Val2)) == sizeof (double) \
|
||||
|| __builtin_classify_type (Val1) != 8 \
|
||||
|| __builtin_classify_type (Val2) != 8) \
|
||||
- ? (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ ? (__tgmath_real_type2 (Val1, Val2)) \
|
||||
Fct (Val1, Val2) \
|
||||
- : (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ : (__tgmath_real_type2 (Val1, Val2)) \
|
||||
Fct##f (Val1, Val2)))
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_BINARY_REAL_STD_ONLY(Val1, Val2, Fct) \
|
||||
(__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double) \
|
||||
&& __builtin_classify_type ((Val1) + (Val2)) == 8) \
|
||||
@@ -369,27 +445,24 @@
|
||||
: (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
+ (__tgmath_real_type (Val2)) 0)) \
|
||||
Fct##f (Val1, Val2)))
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
(__extension__ ((sizeof ((Val1) + (Val2)) > sizeof (double) \
|
||||
&& __builtin_classify_type ((Val1) + (Val2)) == 8) \
|
||||
? __TGMATH_F128 ((Val1) + (Val2), \
|
||||
- (__typeof \
|
||||
- ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) Fct, \
|
||||
+ (__tgmath_real_type2 (Val1, Val2)) Fct, \
|
||||
(Val1, Val2, Val3)) \
|
||||
- (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ (__tgmath_real_type2 (Val1, Val2)) \
|
||||
__tgml(Fct) (Val1, Val2, Val3) \
|
||||
: (sizeof (+(Val1)) == sizeof (double) \
|
||||
|| sizeof (+(Val2)) == sizeof (double) \
|
||||
|| __builtin_classify_type (Val1) != 8 \
|
||||
|| __builtin_classify_type (Val2) != 8) \
|
||||
- ? (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ ? (__tgmath_real_type2 (Val1, Val2)) \
|
||||
Fct (Val1, Val2, Val3) \
|
||||
- : (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0)) \
|
||||
+ : (__tgmath_real_type2 (Val1, Val2)) \
|
||||
Fct##f (Val1, Val2, Val3)))
|
||||
|
||||
# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \
|
||||
@@ -397,14 +470,10 @@
|
||||
&& __builtin_classify_type ((Val1) + (Val2) + (Val3)) \
|
||||
== 8) \
|
||||
? __TGMATH_F128 ((Val1) + (Val2) + (Val3), \
|
||||
- (__typeof \
|
||||
- ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0 \
|
||||
- + (__tgmath_real_type (Val3)) 0)) Fct, \
|
||||
+ (__tgmath_real_type3 (Val1, Val2, \
|
||||
+ Val3)) Fct, \
|
||||
(Val1, Val2, Val3)) \
|
||||
- (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0 \
|
||||
- + (__tgmath_real_type (Val3)) 0)) \
|
||||
+ (__tgmath_real_type3 (Val1, Val2, Val3)) \
|
||||
__tgml(Fct) (Val1, Val2, Val3) \
|
||||
: (sizeof (+(Val1)) == sizeof (double) \
|
||||
|| sizeof (+(Val2)) == sizeof (double) \
|
||||
@@ -412,15 +481,13 @@
|
||||
|| __builtin_classify_type (Val1) != 8 \
|
||||
|| __builtin_classify_type (Val2) != 8 \
|
||||
|| __builtin_classify_type (Val3) != 8) \
|
||||
- ? (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0 \
|
||||
- + (__tgmath_real_type (Val3)) 0)) \
|
||||
+ ? (__tgmath_real_type3 (Val1, Val2, Val3)) \
|
||||
Fct (Val1, Val2, Val3) \
|
||||
- : (__typeof ((__tgmath_real_type (Val1)) 0 \
|
||||
- + (__tgmath_real_type (Val2)) 0 \
|
||||
- + (__tgmath_real_type (Val3)) 0)) \
|
||||
+ : (__tgmath_real_type3 (Val1, Val2, Val3)) \
|
||||
Fct##f (Val1, Val2, Val3)))
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_TERNARY_FIRST_REAL_RET_ONLY(Val1, Val2, Val3, Fct) \
|
||||
(__extension__ ((sizeof (+(Val1)) == sizeof (double) \
|
||||
|| __builtin_classify_type (Val1) != 8) \
|
||||
@@ -496,7 +563,9 @@
|
||||
__tgml(Cfct) (Val))))
|
||||
# define __TGMATH_UNARY_REAL_IMAG_RET_REAL_SAME(Val, Cfct) \
|
||||
__TGMATH_UNARY_REAL_IMAG_RET_REAL ((Val), Cfct, Cfct)
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
/* XXX This definition has to be changed as soon as the compiler understands
|
||||
the imaginary keyword. */
|
||||
# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \
|
||||
@@ -505,46 +574,39 @@
|
||||
&& __builtin_classify_type (__real__ (Val1) \
|
||||
+ __real__ (Val2)) == 8) \
|
||||
? __TGMATH_CF128 ((Val1) + (Val2), \
|
||||
- (__typeof \
|
||||
- ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Fct, \
|
||||
- (__typeof \
|
||||
- ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Cfct, \
|
||||
(Val1, Val2)) \
|
||||
(__expr_is_real ((Val1) + (Val2)) \
|
||||
- ? (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ ? (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
__tgml(Fct) (Val1, Val2) \
|
||||
- : (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ : (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
__tgml(Cfct) (Val1, Val2)) \
|
||||
: (sizeof (+__real__ (Val1)) == sizeof (double) \
|
||||
|| sizeof (+__real__ (Val2)) == sizeof (double) \
|
||||
|| __builtin_classify_type (__real__ (Val1)) != 8 \
|
||||
|| __builtin_classify_type (__real__ (Val2)) != 8) \
|
||||
? (__expr_is_real ((Val1) + (Val2)) \
|
||||
- ? (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ ? (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Fct (Val1, Val2) \
|
||||
- : (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ : (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Cfct (Val1, Val2)) \
|
||||
: (__expr_is_real ((Val1) + (Val2)) \
|
||||
- ? (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ ? (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Fct##f (Val1, Val2) \
|
||||
- : (__typeof ((__tgmath_complex_type (Val1)) 0 \
|
||||
- + (__tgmath_complex_type (Val2)) 0)) \
|
||||
+ : (__tgmath_complex_type2 (Val1, Val2)) \
|
||||
Cfct##f (Val1, Val2))))
|
||||
+# endif
|
||||
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_2_NARROW_F(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (double) \
|
||||
? F ## l (X, Y) \
|
||||
: F (X, Y)))
|
||||
+# endif
|
||||
/* In most cases, these narrowing macro definitions based on sizeof
|
||||
ensure that the function called has the right argument format, as
|
||||
for other <tgmath.h> macros for compilers before GCC 8, but may not
|
||||
@@ -553,35 +615,50 @@
|
||||
|
||||
In the case of macros for _Float32x return type, when _Float64x
|
||||
exists, _Float64 arguments should result in the *f64 function being
|
||||
- called while _Float32x arguments should result in the *f64x
|
||||
- function being called. These cases cannot be distinguished using
|
||||
- sizeof (or at all if the types are typedefs rather than different
|
||||
- types). However, for these functions it is OK (does not affect the
|
||||
- final result) to call a function with any argument format at least
|
||||
- as wide as all the floating-point arguments, unless that affects
|
||||
- rounding of integer arguments. Integer arguments are considered to
|
||||
- have type _Float64, so the *f64 functions are preferred for f32x*
|
||||
- macros when no argument has a wider floating-point type. */
|
||||
-# if __HAVE_FLOAT64X_LONG_DOUBLE && __HAVE_DISTINCT_FLOAT128
|
||||
+ called while _Float32x, float and double arguments should result in
|
||||
+ the *f64x function being called (and integer arguments are
|
||||
+ considered to have type _Float32x if any argument has type
|
||||
+ _FloatNx, or double otherwise). These cases cannot be
|
||||
+ distinguished using sizeof (or at all if the types are typedefs
|
||||
+ rather than different types, in which case we err on the side of
|
||||
+ using the wider type if unsure). */
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
+# if __HAVE_FLOATN_NOT_TYPEDEF
|
||||
+# define __TGMATH_NARROW_F32X_USE_F64X(X) \
|
||||
+ !__builtin_types_compatible_p (__typeof (+(X)), _Float64)
|
||||
+# else
|
||||
+# define __TGMATH_NARROW_F32X_USE_F64X(X) \
|
||||
+ (__builtin_types_compatible_p (__typeof (+(X)), double) \
|
||||
+ || __builtin_types_compatible_p (__typeof (+(X)), float) \
|
||||
+ || !__floating_type (__typeof (+(X))))
|
||||
+# endif
|
||||
+# endif
|
||||
+# if __HAVE_FLOAT64X_LONG_DOUBLE && __HAVE_DISTINCT_FLOAT128
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_2_NARROW_F32(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (_Float64) \
|
||||
- ? __TGMATH_F128 ((X) + (Y), F, (X, Y)) \
|
||||
+ ? __TGMATH_F128LD ((X) + (Y), F, (X, Y)) \
|
||||
F ## f64x (X, Y) \
|
||||
: F ## f64 (X, Y)))
|
||||
# define __TGMATH_2_NARROW_F64(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (_Float64) \
|
||||
- ? __TGMATH_F128 ((X) + (Y), F, (X, Y)) \
|
||||
+ ? __TGMATH_F128LD ((X) + (Y), F, (X, Y)) \
|
||||
F ## f64x (X, Y) \
|
||||
: F ## f128 (X, Y)))
|
||||
+# endif
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
# define __TGMATH_2_NARROW_F32X(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (_Float64) \
|
||||
+ || __TGMATH_NARROW_F32X_USE_F64X ((X) + (Y)) \
|
||||
? __TGMATH_F128 ((X) + (Y), F, (X, Y)) \
|
||||
F ## f64x (X, Y) \
|
||||
: F ## f64 (X, Y)))
|
||||
-# elif __HAVE_FLOAT128
|
||||
+# endif
|
||||
+# elif __HAVE_FLOAT128
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_2_NARROW_F32(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (_Float64) \
|
||||
@@ -589,16 +666,21 @@
|
||||
: F ## f64 (X, Y)))
|
||||
# define __TGMATH_2_NARROW_F64(F, X, Y) \
|
||||
(F ## f128 (X, Y))
|
||||
+# endif
|
||||
+# if !__HAVE_BUILTIN_TGMATH_C2X
|
||||
# define __TGMATH_2_NARROW_F32X(F, X, Y) \
|
||||
(__extension__ (sizeof ((__tgmath_real_type (X)) 0 \
|
||||
+ (__tgmath_real_type (Y)) 0) > sizeof (_Float32x) \
|
||||
+ || __TGMATH_NARROW_F32X_USE_F64X ((X) + (Y)) \
|
||||
? F ## f64x (X, Y) \
|
||||
: F ## f64 (X, Y)))
|
||||
-# else
|
||||
+# endif
|
||||
+# else
|
||||
+# if !__HAVE_BUILTIN_TGMATH
|
||||
# define __TGMATH_2_NARROW_F32(F, X, Y) \
|
||||
(F ## f64 (X, Y))
|
||||
# endif
|
||||
-# endif /* !__HAVE_BUILTIN_TGMATH. */
|
||||
+# endif
|
||||
#else
|
||||
# error "Unsupported compiler; you cannot use <tgmath.h>"
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
commit c8126360dfa98024cc40bce915e126309993cdf9
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Aug 23 16:18:42 2021 +0000
|
||||
|
||||
Fix iconv build with GCC mainline
|
||||
|
||||
Current GCC mainline produces -Wstringop-overflow errors building some
|
||||
iconv converters, as discussed at
|
||||
<https://gcc.gnu.org/pipermail/gcc/2021-July/236943.html>. Add an
|
||||
__builtin_unreachable call as suggested so that GCC can see the case
|
||||
that would involve a buffer overflow is unreachable; because the
|
||||
unreachability depends on valid conversion state being passed into the
|
||||
function from previous conversion steps, it's not something the
|
||||
compiler can reasonably deduce on its own.
|
||||
|
||||
Tested with build-many-glibcs.py that, together with
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-August/130244.html>,
|
||||
it restores the glibc build for powerpc-linux-gnu.
|
||||
|
||||
diff --git a/iconv/loop.c b/iconv/loop.c
|
||||
index 062cc1b868c1efa5..560a5f6394e8faf6 100644
|
||||
--- a/iconv/loop.c
|
||||
+++ b/iconv/loop.c
|
||||
@@ -436,6 +436,12 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
return __GCONV_FULL_OUTPUT;
|
||||
|
||||
/* Now add characters from the normal input buffer. */
|
||||
+ if (inlen >= MAX_NEEDED_INPUT)
|
||||
+ /* Avoid a -Wstringop-overflow= warning when this loop is
|
||||
+ unrolled. The compiler cannot otherwise see that this is
|
||||
+ unreachable because it depends on (state->__count & 7) not
|
||||
+ being too large after a previous conversion step. */
|
||||
+ __builtin_unreachable ();
|
||||
do
|
||||
bytebuf[inlen++] = *inptr++;
|
||||
while (inlen < MAX_NEEDED_INPUT && inptr < inend);
|
|
@ -0,0 +1,32 @@
|
|||
commit 3edc4ff2ceff4a59587ebecb94148d3bcfa1df62
|
||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
||||
Date: Wed Jul 19 14:09:26 2023 -0700
|
||||
|
||||
make ‘struct pthread’ a complete type
|
||||
|
||||
* nptl/descr.h (struct pthread): Remove end_padding member, which
|
||||
made this type incomplete.
|
||||
(PTHREAD_STRUCT_END_PADDING): Stop using end_padding.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nptl/descr.h b/nptl/descr.h
|
||||
index dfef9c4bda075d13..c487846c171f9434 100644
|
||||
--- a/nptl/descr.h
|
||||
+++ b/nptl/descr.h
|
||||
@@ -412,11 +412,11 @@ struct pthread
|
||||
/* rseq area registered with the kernel. */
|
||||
struct rseq rseq_area;
|
||||
|
||||
- /* This member must be last. */
|
||||
- char end_padding[];
|
||||
-
|
||||
+ /* Amount of end padding, if any, in this structure.
|
||||
+ This definition relies on rseq_area being last. */
|
||||
#define PTHREAD_STRUCT_END_PADDING \
|
||||
- (sizeof (struct pthread) - offsetof (struct pthread, end_padding))
|
||||
+ (sizeof (struct pthread) - offsetof (struct pthread, rseq_area) \
|
||||
+ + sizeof (struct rseq))
|
||||
} __attribute ((aligned (TCB_ALIGNMENT)));
|
||||
|
||||
static inline bool
|
|
@ -0,0 +1,56 @@
|
|||
commit 2c6b4b272e6b4d07303af25709051c3e96288f2d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Jul 21 16:18:18 2023 +0200
|
||||
|
||||
nptl: Unconditionally use a 32-byte rseq area
|
||||
|
||||
If the kernel headers provide a larger struct rseq, we used that
|
||||
size as the argument to the rseq system call. As a result,
|
||||
rseq registration would fail on older kernels which only accept
|
||||
size 32.
|
||||
|
||||
Conflicts:
|
||||
nptl/descr.h
|
||||
(upstream has an additional #include <internal-sigset.h>)
|
||||
|
||||
diff --git a/nptl/descr.h b/nptl/descr.h
|
||||
index c487846c171f9434..eded9eca38e7275e 100644
|
||||
--- a/nptl/descr.h
|
||||
+++ b/nptl/descr.h
|
||||
@@ -35,7 +35,6 @@
|
||||
#include <bits/types/res_state.h>
|
||||
#include <kernel-features.h>
|
||||
#include <tls-internal-struct.h>
|
||||
-#include <sys/rseq.h>
|
||||
|
||||
#ifndef TCB_ALIGNMENT
|
||||
# define TCB_ALIGNMENT 32
|
||||
@@ -409,14 +408,25 @@ struct pthread
|
||||
/* Used on strsignal. */
|
||||
struct tls_internal_t tls_state;
|
||||
|
||||
- /* rseq area registered with the kernel. */
|
||||
- struct rseq rseq_area;
|
||||
+ /* rseq area registered with the kernel. Use a custom definition
|
||||
+ here to isolate from kernel struct rseq changes. The
|
||||
+ implementation of sched_getcpu needs acccess to the cpu_id field;
|
||||
+ the other fields are unused and not included here. */
|
||||
+ union
|
||||
+ {
|
||||
+ struct
|
||||
+ {
|
||||
+ uint32_t cpu_id_start;
|
||||
+ uint32_t cpu_id;
|
||||
+ };
|
||||
+ char pad[32]; /* Original rseq area size. */
|
||||
+ } rseq_area __attribute__ ((aligned (32)));
|
||||
|
||||
/* Amount of end padding, if any, in this structure.
|
||||
This definition relies on rseq_area being last. */
|
||||
#define PTHREAD_STRUCT_END_PADDING \
|
||||
(sizeof (struct pthread) - offsetof (struct pthread, rseq_area) \
|
||||
- + sizeof (struct rseq))
|
||||
+ + sizeof ((struct pthread) {}.rseq_area))
|
||||
} __attribute ((aligned (TCB_ALIGNMENT)));
|
||||
|
||||
static inline bool
|
|
@ -0,0 +1,27 @@
|
|||
commit 637aac2ae3980de31a6baab236a9255fe853cc76
|
||||
Author: Stefan Liebler <stli@linux.ibm.com>
|
||||
Date: Tue Jul 25 11:34:30 2023 +0200
|
||||
|
||||
Include sys/rseq.h in tst-rseq-disable.c
|
||||
|
||||
Starting with commit 2c6b4b272e6b4d07303af25709051c3e96288f2d
|
||||
"nptl: Unconditionally use a 32-byte rseq area", the testcase
|
||||
misc/tst-rseq-disable is UNSUPPORTED as RSEQ_SIG is not defined.
|
||||
|
||||
The mentioned commit removes inclusion of sys/rseq.h in nptl/descr.h.
|
||||
Thus just include sys/rseq.h in the tst-rseq-disable.c as also done
|
||||
in tst-rseq.c and tst-rseq-nptl.c.
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
|
||||
index 6d73f77e9621da42..964dc728ac5e7b95 100644
|
||||
--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c
|
||||
+++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <support/xthread.h>
|
||||
#include <sysdep.h>
|
||||
#include <thread_pointer.h>
|
||||
+#include <sys/rseq.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef RSEQ_SIG
|
|
@ -0,0 +1,26 @@
|
|||
commit 23ee92deea4c99d0e6a5f48fa7b942909b123ec5
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Jul 20 18:31:48 2023 +0200
|
||||
|
||||
debug: Mark libSegFault.so as NODELETE
|
||||
|
||||
The signal handler installed in the ELF constructor cannot easily
|
||||
be removed again (because the program may have changed handlers
|
||||
in the meantime). Mark the object as NODELETE so that the registered
|
||||
handler function is never unloaded.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/debug/Makefile b/debug/Makefile
|
||||
index 71248e0d457a5b12..9fbc40dc69b477ca 100644
|
||||
--- a/debug/Makefile
|
||||
+++ b/debug/Makefile
|
||||
@@ -213,6 +213,8 @@ extra-libs-others = $(extra-libs)
|
||||
|
||||
libSegFault-routines = segfault
|
||||
libSegFault-inhibit-o = $(filter-out .os,$(object-suffixes))
|
||||
+# libSegFault.so installs a signal handler in its ELF constructor.
|
||||
+LDFLAGS-SegFault.so = -Wl,--enable-new-dtags,-z,nodelete
|
||||
|
||||
libpcprofile-routines = pcprofile
|
||||
libpcprofile-inhibit-o = $(filter-out .os,$(object-suffixes))
|
|
@ -0,0 +1,58 @@
|
|||
commit e2f68b54e8052da14680074fc5df03153216f218
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Mar 17 11:16:57 2022 +0530
|
||||
|
||||
nss: Sort tests and tests-container and put one test per line
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 716bc8f6ef5276b0..aa6d350f2f859d12 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -56,21 +56,30 @@ extra-objs += $(makedb-modules:=.o)
|
||||
|
||||
tests-static = tst-field
|
||||
tests-internal = tst-field
|
||||
-tests = test-netdb test-digits-dots tst-nss-getpwent bug17079 \
|
||||
- tst-nss-test1 \
|
||||
- tst-nss-test2 \
|
||||
- tst-nss-test4 \
|
||||
- tst-nss-test5 \
|
||||
- tst-nss-test_errno
|
||||
-xtests = bug-erange
|
||||
-
|
||||
-tests-container = \
|
||||
- tst-nss-compat1 \
|
||||
- tst-nss-test3 \
|
||||
- tst-nss-files-hosts-long \
|
||||
- tst-nss-db-endpwent \
|
||||
- tst-nss-db-endgrent \
|
||||
- tst-reload1 tst-reload2
|
||||
+
|
||||
+tests := \
|
||||
+ bug17079 \
|
||||
+ test-digits-dots \
|
||||
+ test-netdb \
|
||||
+ tst-nss-getpwent \
|
||||
+ tst-nss-test1 \
|
||||
+ tst-nss-test2 \
|
||||
+ tst-nss-test4 \
|
||||
+ tst-nss-test5 \
|
||||
+ tst-nss-test_errno \
|
||||
+# tests
|
||||
+
|
||||
+xtests = bug-erange
|
||||
+
|
||||
+tests-container := \
|
||||
+ tst-nss-compat1 \
|
||||
+ tst-nss-db-endgrent \
|
||||
+ tst-nss-db-endpwent \
|
||||
+ tst-nss-files-hosts-long \
|
||||
+ tst-nss-test3 \
|
||||
+ tst-reload1 \
|
||||
+ tst-reload2 \
|
||||
+# tests-container
|
||||
|
||||
# Tests which need libdl
|
||||
ifeq (yes,$(build-shared))
|
|
@ -0,0 +1,243 @@
|
|||
commit c437631485a85c3bd034e12f53dd1c8207f05940
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Wed Jul 19 09:55:31 2023 +0200
|
||||
|
||||
Restore lookup of IPv4 mapped addresses in files database (bug 25457)
|
||||
|
||||
This was broken by commit 9c02d0784d ("nss_files: Remove RES_USE_INET6
|
||||
from hosts processing"), which removed too much.
|
||||
|
||||
Conflicts:
|
||||
nss/Makefile
|
||||
(missing tst-nss-gai-actions downstream)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index aa6d350f2f859d12..f01674a16e720b88 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -76,6 +76,7 @@ tests-container := \
|
||||
tst-nss-db-endgrent \
|
||||
tst-nss-db-endpwent \
|
||||
tst-nss-files-hosts-long \
|
||||
+ tst-nss-files-hosts-v4mapped \
|
||||
tst-nss-test3 \
|
||||
tst-reload1 \
|
||||
tst-reload2 \
|
||||
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
|
||||
index d54d91d038a03c18..f6f11fb18b43fa9f 100644
|
||||
--- a/nss/nss_files/files-hosts.c
|
||||
+++ b/nss/nss_files/files-hosts.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <nss.h>
|
||||
|
||||
/* Get implementation for some internal functions. */
|
||||
+#include "../resolv/mapv4v6addr.h"
|
||||
#include "../resolv/res_hconf.h"
|
||||
|
||||
|
||||
@@ -34,8 +35,8 @@
|
||||
#define DATABASE "hosts"
|
||||
#define NEED_H_ERRNO
|
||||
|
||||
-#define EXTRA_ARGS , af
|
||||
-#define EXTRA_ARGS_DECL , int af
|
||||
+#define EXTRA_ARGS , af, flags
|
||||
+#define EXTRA_ARGS_DECL , int af, int flags
|
||||
|
||||
#define ENTDATA hostent_data
|
||||
struct hostent_data
|
||||
@@ -60,8 +61,12 @@ LINE_PARSER
|
||||
af = af == AF_UNSPEC ? AF_INET : af;
|
||||
else
|
||||
{
|
||||
- if (af == AF_INET
|
||||
- && __inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
|
||||
+ if (af == AF_INET6 && (flags & AI_V4MAPPED) != 0
|
||||
+ && __inet_pton (AF_INET, addr, entdata->host_addr) > 0)
|
||||
+ map_v4v6_address ((char *) entdata->host_addr,
|
||||
+ (char *) entdata->host_addr);
|
||||
+ else if (af == AF_INET
|
||||
+ && __inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
|
||||
{
|
||||
if (IN6_IS_ADDR_V4MAPPED (entdata->host_addr))
|
||||
memcpy (entdata->host_addr, entdata->host_addr + 12, INADDRSZ);
|
||||
@@ -94,13 +99,14 @@ LINE_PARSER
|
||||
STRING_FIELD (result->h_name, isspace, 1);
|
||||
})
|
||||
|
||||
-#define EXTRA_ARGS_VALUE , AF_INET
|
||||
+#define EXTRA_ARGS_VALUE , AF_INET, 0
|
||||
#include "files-XXX.c"
|
||||
#undef EXTRA_ARGS_VALUE
|
||||
|
||||
/* We only need to consider IPv4 mapped addresses if the input to the
|
||||
gethostbyaddr() function is an IPv6 address. */
|
||||
-#define EXTRA_ARGS_VALUE , af
|
||||
+#define EXTRA_ARGS_VALUE \
|
||||
+ , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0)
|
||||
DB_LOOKUP (hostbyaddr, ,,,
|
||||
{
|
||||
if (result->h_length == (int) len
|
||||
@@ -152,7 +158,7 @@ gethostbyname3_multi (FILE * stream, const char *name, int af,
|
||||
while (true)
|
||||
{
|
||||
status = internal_getent (stream, &tmp_result_buf, tmp_buffer.data,
|
||||
- tmp_buffer.length, errnop, herrnop, af);
|
||||
+ tmp_buffer.length, errnop, herrnop, af, 0);
|
||||
/* Enlarge the buffer if necessary. */
|
||||
if (status == NSS_STATUS_TRYAGAIN && *herrnop == NETDB_INTERNAL
|
||||
&& *errnop == ERANGE)
|
||||
@@ -337,7 +343,7 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
||||
if (status == NSS_STATUS_SUCCESS)
|
||||
{
|
||||
while ((status = internal_getent (stream, result, buffer, buflen, errnop,
|
||||
- herrnop, af))
|
||||
+ herrnop, af, 0))
|
||||
== NSS_STATUS_SUCCESS)
|
||||
{
|
||||
LOOKUP_NAME_CASE (h_name, h_aliases)
|
||||
@@ -402,7 +408,7 @@ _nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
|
||||
struct hostent result;
|
||||
status = internal_getent (stream, &result, buffer, buflen, errnop,
|
||||
- herrnop, AF_UNSPEC);
|
||||
+ herrnop, AF_UNSPEC, 0);
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
break;
|
||||
|
||||
diff --git a/nss/tst-nss-files-hosts-v4mapped.c b/nss/tst-nss-files-hosts-v4mapped.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..45582904e68adf29
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-files-hosts-v4mapped.c
|
||||
@@ -0,0 +1,41 @@
|
||||
+/* Test lookup of IPv4 mapped addresses in files database (bug 25457)
|
||||
+
|
||||
+ Copyright (C) 2023 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 <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <stdio.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <netdb.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct sockaddr_in6 s6 = { .sin6_family = AF_INET6 };
|
||||
+ inet_pton (AF_INET6, "::ffff:192.168.0.1", &s6.sin6_addr);
|
||||
+
|
||||
+ char node[NI_MAXHOST];
|
||||
+ int res = getnameinfo ((struct sockaddr *) &s6, sizeof (s6), node,
|
||||
+ sizeof (node), NULL, 0, NI_NAMEREQD);
|
||||
+ if (res)
|
||||
+ printf ("%d %s\n", res, gai_strerror (res));
|
||||
+ else
|
||||
+ printf ("node=%s\n", node);
|
||||
+
|
||||
+ return res != 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/nss/tst-nss-files-hosts-v4mapped.root/etc/hosts b/nss/tst-nss-files-hosts-v4mapped.root/etc/hosts
|
||||
new file mode 100644
|
||||
index 0000000000000000..609b25ad39a879b4
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-files-hosts-v4mapped.root/etc/hosts
|
||||
@@ -0,0 +1 @@
|
||||
+192.168.0.1 v4mapped
|
||||
diff --git a/nss/tst-nss-files-hosts-v4mapped.root/etc/nsswitch.conf b/nss/tst-nss-files-hosts-v4mapped.root/etc/nsswitch.conf
|
||||
new file mode 100644
|
||||
index 0000000000000000..5b0c6a419937a013
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-nss-files-hosts-v4mapped.root/etc/nsswitch.conf
|
||||
@@ -0,0 +1 @@
|
||||
+hosts: files
|
||||
diff --git a/resolv/mapv4v6addr.h b/resolv/mapv4v6addr.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..7f85f7d5e393ec5f
|
||||
--- /dev/null
|
||||
+++ b/resolv/mapv4v6addr.h
|
||||
@@ -0,0 +1,69 @@
|
||||
+/*
|
||||
+ * ++Copyright++ 1985, 1988, 1993
|
||||
+ * -
|
||||
+ * Copyright (c) 1985, 1988, 1993
|
||||
+ * The Regents of the University of California. All rights reserved.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ * 4. Neither the name of the University nor the names of its contributors
|
||||
+ * may be used to endorse or promote products derived from this software
|
||||
+ * without specific prior written permission.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
+ * SUCH DAMAGE.
|
||||
+ * -
|
||||
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
+ *
|
||||
+ * Permission to use, copy, modify, and distribute this software for any
|
||||
+ * purpose with or without fee is hereby granted, provided that the above
|
||||
+ * copyright notice and this permission notice appear in all copies, and that
|
||||
+ * the name of Digital Equipment Corporation not be used in advertising or
|
||||
+ * publicity pertaining to distribution of the document or software without
|
||||
+ * specific, written prior permission.
|
||||
+ *
|
||||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
+ * SOFTWARE.
|
||||
+ * -
|
||||
+ * --Copyright--
|
||||
+ */
|
||||
+
|
||||
+#include <string.h>
|
||||
+#include <arpa/nameser.h>
|
||||
+
|
||||
+static void
|
||||
+map_v4v6_address (const char *src, char *dst)
|
||||
+{
|
||||
+ u_char *p = (u_char *) dst;
|
||||
+ int i;
|
||||
+
|
||||
+ /* Move the IPv4 part to the right position. */
|
||||
+ memcpy (dst + 12, src, INADDRSZ);
|
||||
+
|
||||
+ /* Mark this ipv6 addr as a mapped ipv4. */
|
||||
+ for (i = 0; i < 10; i++)
|
||||
+ *p++ = 0x00;
|
||||
+ *p++ = 0xff;
|
||||
+ *p = 0xff;
|
||||
+}
|
|
@ -0,0 +1,187 @@
|
|||
commit bd77dd7e73e3530203be1c52c8a29d08270cb25d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Sep 13 14:10:56 2023 +0200
|
||||
|
||||
CVE-2023-4527: Stack read overflow with large TCP responses in no-aaaa mode
|
||||
|
||||
Without passing alt_dns_packet_buffer, __res_context_search can only
|
||||
store 2048 bytes (what fits into dns_packet_buffer). However,
|
||||
the function returns the total packet size, and the subsequent
|
||||
DNS parsing code in _nss_dns_gethostbyname4_r reads beyond the end
|
||||
of the stack-allocated buffer.
|
||||
|
||||
Fixes commit f282cdbe7f436c75864e5640a4 ("resolv: Implement no-aaaa
|
||||
stub resolver option") and bug 30842.
|
||||
|
||||
Conflits:
|
||||
resolv/Makefile
|
||||
(missing tests)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index ea1518ec2da860c1..2c43d52122ef4343 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -102,6 +102,7 @@ tests += \
|
||||
tst-resolv-invalid-cname \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
+ tst-resolv-noaaaa-vc \
|
||||
tst-resolv-nondecimal \
|
||||
tst-resolv-res_init-multi \
|
||||
tst-resolv-search \
|
||||
@@ -280,6 +281,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 36789965c06757d0..3d261b6810bba5c9 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -428,7 +428,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
{
|
||||
n = __res_context_search (ctx, name, C_IN, T_A,
|
||||
dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
- NULL, NULL, NULL, NULL, NULL);
|
||||
+ &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
|
||||
if (n >= 0)
|
||||
status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
|
||||
&abuf, pat, errnop, herrnop, ttlp);
|
||||
diff --git a/resolv/tst-resolv-noaaaa-vc.c b/resolv/tst-resolv-noaaaa-vc.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..9f5aebd99f2d74a2
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-noaaaa-vc.c
|
||||
@@ -0,0 +1,129 @@
|
||||
+/* Test the RES_NOAAAA resolver option with a large response.
|
||||
+ Copyright (C) 2022-2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
+#include <resolv.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xmemstream.h>
|
||||
+
|
||||
+/* Used to keep track of the number of queries. */
|
||||
+static volatile unsigned int queries;
|
||||
+
|
||||
+/* If true, add a large TXT record at the start of the answer section. */
|
||||
+static volatile bool stuff_txt;
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ /* If not using TCP, just force its use. */
|
||||
+ if (!ctx->tcp)
|
||||
+ {
|
||||
+ struct resolv_response_flags flags = {.tc = true};
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* The test needs to send four queries, the first three are used to
|
||||
+ grow the NSS buffer via the ERANGE handshake. */
|
||||
+ ++queries;
|
||||
+ TEST_VERIFY (queries <= 4);
|
||||
+
|
||||
+ /* AAAA queries are supposed to be disabled. */
|
||||
+ TEST_COMPARE (qtype, T_A);
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+ TEST_COMPARE_STRING (qname, "example.com");
|
||||
+
|
||||
+ struct resolv_response_flags flags = {};
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+
|
||||
+ if (stuff_txt)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, qname, qclass, T_TXT, 60);
|
||||
+ int zero = 0;
|
||||
+ for (int i = 0; i <= 15000; ++i)
|
||||
+ resolv_response_add_data (b, &zero, sizeof (zero));
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < 200; ++i)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
|
||||
+ char ipv4[4] = {192, 0, 2, i + 1};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ _res.options |= RES_NOAAAA;
|
||||
+
|
||||
+ for (int do_stuff_txt = 0; do_stuff_txt < 2; ++do_stuff_txt)
|
||||
+ {
|
||||
+ queries = 0;
|
||||
+ stuff_txt = do_stuff_txt;
|
||||
+
|
||||
+ struct addrinfo *ai = NULL;
|
||||
+ int ret;
|
||||
+ ret = getaddrinfo ("example.com", "80",
|
||||
+ &(struct addrinfo)
|
||||
+ {
|
||||
+ .ai_family = AF_UNSPEC,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ }, &ai);
|
||||
+
|
||||
+ char *expected_result;
|
||||
+ {
|
||||
+ struct xmemstream mem;
|
||||
+ xopen_memstream (&mem);
|
||||
+ for (int i = 0; i < 200; ++i)
|
||||
+ fprintf (mem.out, "address: STREAM/TCP 192.0.2.%d 80\n", i + 1);
|
||||
+ xfclose_memstream (&mem);
|
||||
+ expected_result = mem.buffer;
|
||||
+ }
|
||||
+
|
||||
+ check_addrinfo ("example.com", ai, ret, expected_result);
|
||||
+
|
||||
+ free (expected_result);
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
|
@ -0,0 +1,95 @@
|
|||
commit 472894d2cfee5751b44c0aaa71ed87df81c8e62e
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Oct 11 13:43:56 2023 -0300
|
||||
|
||||
malloc: Use __get_nprocs on arena_get2 (BZ 30945)
|
||||
|
||||
This restore the 2.33 semantic for arena_get2. It was changed by
|
||||
11a02b035b46 to avoid arena_get2 call malloc (back when __get_nproc
|
||||
was refactored to use an scratch_buffer - 903bc7dcc2acafc). The
|
||||
__get_nproc was refactored over then and now it also avoid to call
|
||||
malloc.
|
||||
|
||||
The 11a02b035b46 did not take in consideration any performance
|
||||
implication, which should have been discussed properly. The
|
||||
__get_nprocs_sched is still used as a fallback mechanism if procfs
|
||||
and sysfs is not acessible.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h
|
||||
index c490561581..65742b1036 100644
|
||||
--- a/include/sys/sysinfo.h
|
||||
+++ b/include/sys/sysinfo.h
|
||||
@@ -14,10 +14,6 @@ libc_hidden_proto (__get_nprocs_conf)
|
||||
extern int __get_nprocs (void);
|
||||
libc_hidden_proto (__get_nprocs)
|
||||
|
||||
-/* Return the number of available processors which the process can
|
||||
- be scheduled. */
|
||||
-extern int __get_nprocs_sched (void) attribute_hidden;
|
||||
-
|
||||
/* Return number of physical pages of memory in the system. */
|
||||
extern long int __get_phys_pages (void);
|
||||
libc_hidden_proto (__get_phys_pages)
|
||||
diff --git a/malloc/arena.c b/malloc/arena.c
|
||||
index d1e214ac2e..a1a75e5a2b 100644
|
||||
--- a/malloc/arena.c
|
||||
+++ b/malloc/arena.c
|
||||
@@ -824,7 +824,7 @@ arena_get2 (size_t size, mstate avoid_arena)
|
||||
narenas_limit = mp_.arena_max;
|
||||
else if (narenas > mp_.arena_test)
|
||||
{
|
||||
- int n = __get_nprocs_sched ();
|
||||
+ int n = __get_nprocs ();
|
||||
|
||||
if (n >= 1)
|
||||
narenas_limit = NARENAS_FROM_NCORES (n);
|
||||
diff --git a/misc/getsysstats.c b/misc/getsysstats.c
|
||||
index 5f36adc0e8..23cc112074 100644
|
||||
--- a/misc/getsysstats.c
|
||||
+++ b/misc/getsysstats.c
|
||||
@@ -44,12 +44,6 @@ weak_alias (__get_nprocs, get_nprocs)
|
||||
link_warning (get_nprocs, "warning: get_nprocs will always return 1")
|
||||
|
||||
|
||||
-int
|
||||
-__get_nprocs_sched (void)
|
||||
-{
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
long int
|
||||
__get_phys_pages (void)
|
||||
{
|
||||
diff --git a/sysdeps/mach/getsysstats.c b/sysdeps/mach/getsysstats.c
|
||||
index 5184e5eee1..d3834f3b69 100644
|
||||
--- a/sysdeps/mach/getsysstats.c
|
||||
+++ b/sysdeps/mach/getsysstats.c
|
||||
@@ -62,12 +62,6 @@ __get_nprocs (void)
|
||||
libc_hidden_def (__get_nprocs)
|
||||
weak_alias (__get_nprocs, get_nprocs)
|
||||
|
||||
-int
|
||||
-__get_nprocs_sched (void)
|
||||
-{
|
||||
- return __get_nprocs ();
|
||||
-}
|
||||
-
|
||||
/* Return the number of physical pages on the system. */
|
||||
long int
|
||||
__get_phys_pages (void)
|
||||
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
index b0b6c154ac..1ea7f1f01f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
-int
|
||||
+static int
|
||||
__get_nprocs_sched (void)
|
||||
{
|
||||
enum
|
|
@ -0,0 +1,66 @@
|
|||
commit 89c017de2f52d17862bda9a6f8382e913457bfbe
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Jan 3 13:06:48 2023 -0800
|
||||
|
||||
x86: Check minimum/maximum of non_temporal_threshold [BZ #29953]
|
||||
|
||||
The minimum non_temporal_threshold is 0x4040. non_temporal_threshold may
|
||||
be set to less than the minimum value when the shared cache size isn't
|
||||
available (e.g., in an emulator) or by the tunable. Add checks for
|
||||
minimum and maximum of non_temporal_threshold.
|
||||
|
||||
This fixes BZ #29953.
|
||||
|
||||
(cherry picked from commit 48b74865c63840b288bd85b4d8743533b73b339b)
|
||||
|
||||
diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
|
||||
index a7d2cc5fef03884b..f2d2de458db7358c 100644
|
||||
--- a/sysdeps/x86/dl-cacheinfo.h
|
||||
+++ b/sysdeps/x86/dl-cacheinfo.h
|
||||
@@ -747,6 +747,18 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
share of the cache, it has a substantial risk of negatively
|
||||
impacting the performance of other threads running on the chip. */
|
||||
unsigned long int non_temporal_threshold = shared * 3 / 4;
|
||||
+ /* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
+ 'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
+ if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
||||
+ L(large_memset_4x) loops need 64-byte to cache align and enough space for
|
||||
+ at least 1 iteration of 4x PAGE_SIZE unrolled loop. Both values are
|
||||
+ reflected in the manual. */
|
||||
+ unsigned long int maximum_non_temporal_threshold = SIZE_MAX >> 4;
|
||||
+ unsigned long int minimum_non_temporal_threshold = 0x4040;
|
||||
+ if (non_temporal_threshold < minimum_non_temporal_threshold)
|
||||
+ non_temporal_threshold = minimum_non_temporal_threshold;
|
||||
+ else if (non_temporal_threshold > maximum_non_temporal_threshold)
|
||||
+ non_temporal_threshold = maximum_non_temporal_threshold;
|
||||
|
||||
#if HAVE_TUNABLES
|
||||
/* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */
|
||||
@@ -801,8 +813,8 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
shared = tunable_size;
|
||||
|
||||
tunable_size = TUNABLE_GET (x86_non_temporal_threshold, long int, NULL);
|
||||
- /* NB: Ignore the default value 0. */
|
||||
- if (tunable_size != 0)
|
||||
+ if (tunable_size > minimum_non_temporal_threshold
|
||||
+ && tunable_size <= maximum_non_temporal_threshold)
|
||||
non_temporal_threshold = tunable_size;
|
||||
|
||||
tunable_size = TUNABLE_GET (x86_rep_movsb_threshold, long int, NULL);
|
||||
@@ -817,14 +829,9 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
|
||||
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_data_cache_size, data, 0, SIZE_MAX);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_shared_cache_size, shared, 0, SIZE_MAX);
|
||||
- /* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
|
||||
- 'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
|
||||
- if that operation cannot overflow. Minimum of 0x4040 (16448) because the
|
||||
- L(large_memset_4x) loops need 64-byte to cache align and enough space for
|
||||
- at least 1 iteration of 4x PAGE_SIZE unrolled loop. Both values are
|
||||
- reflected in the manual. */
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_non_temporal_threshold, non_temporal_threshold,
|
||||
- 0x4040, SIZE_MAX >> 4);
|
||||
+ minimum_non_temporal_threshold,
|
||||
+ maximum_non_temporal_threshold);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_rep_movsb_threshold, rep_movsb_threshold,
|
||||
minimum_rep_movsb_threshold, SIZE_MAX);
|
||||
TUNABLE_SET_WITH_BOUNDS (x86_rep_stosb_threshold, rep_stosb_threshold, 1,
|
|
@ -0,0 +1,122 @@
|
|||
commit 6a0d56b009e34caea9cbc0bbec3272345ea8f55a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Feb 21 09:20:28 2023 +0100
|
||||
|
||||
gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling (bug 30151)
|
||||
|
||||
Before this change, sgetsgent_r did not set errno to ERANGE, but
|
||||
sgetsgent only check errno, not the return value from sgetsgent_r.
|
||||
Consequently, sgetsgent did not detect any error, and reported
|
||||
success to the caller, without initializing the struct sgrp object
|
||||
whose address was returned.
|
||||
|
||||
This commit changes sgetsgent_r to set errno as well. This avoids
|
||||
similar issues in applications which only change errno.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 969e9733c7d17edf1e239a73fa172f357561f440)
|
||||
|
||||
diff --git a/gshadow/Makefile b/gshadow/Makefile
|
||||
index 2fdd0c7641d3655f..094a6c7b5aaad16b 100644
|
||||
--- a/gshadow/Makefile
|
||||
+++ b/gshadow/Makefile
|
||||
@@ -26,7 +26,7 @@ headers = gshadow.h
|
||||
routines = getsgent getsgnam sgetsgent fgetsgent putsgent \
|
||||
getsgent_r getsgnam_r sgetsgent_r fgetsgent_r
|
||||
|
||||
-tests = tst-gshadow tst-putsgent tst-fgetsgent_r
|
||||
+tests = tst-gshadow tst-putsgent tst-fgetsgent_r tst-sgetsgent
|
||||
|
||||
CFLAGS-getsgent_r.c += -fexceptions
|
||||
CFLAGS-getsgent.c += -fexceptions
|
||||
diff --git a/gshadow/sgetsgent_r.c b/gshadow/sgetsgent_r.c
|
||||
index 565463b07e8facbe..ae500d64c386d964 100644
|
||||
--- a/gshadow/sgetsgent_r.c
|
||||
+++ b/gshadow/sgetsgent_r.c
|
||||
@@ -61,7 +61,10 @@ __sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer,
|
||||
buffer[buflen - 1] = '\0';
|
||||
sp = strncpy (buffer, string, buflen);
|
||||
if (buffer[buflen - 1] != '\0')
|
||||
- return ERANGE;
|
||||
+ {
|
||||
+ __set_errno (ERANGE);
|
||||
+ return ERANGE;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
sp = (char *) string;
|
||||
diff --git a/gshadow/tst-sgetsgent.c b/gshadow/tst-sgetsgent.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0370c10fd0630b42
|
||||
--- /dev/null
|
||||
+++ b/gshadow/tst-sgetsgent.c
|
||||
@@ -0,0 +1,69 @@
|
||||
+/* Test large input for sgetsgent (bug 30151).
|
||||
+ Copyright (C) 2023 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
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <gshadow.h>
|
||||
+#include <stddef.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xmemstream.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Create a shadow group with 1000 members. */
|
||||
+ struct xmemstream mem;
|
||||
+ xopen_memstream (&mem);
|
||||
+ const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ";
|
||||
+ fprintf (mem.out, "group-name:%s::m0", passwd);
|
||||
+ for (int i = 1; i < 1000; ++i)
|
||||
+ fprintf (mem.out, ",m%d", i);
|
||||
+ xfclose_memstream (&mem);
|
||||
+
|
||||
+ /* Call sgetsgent. */
|
||||
+ char *input = mem.buffer;
|
||||
+ struct sgrp *e = sgetsgent (input);
|
||||
+ TEST_VERIFY_EXIT (e != NULL);
|
||||
+ TEST_COMPARE_STRING (e->sg_namp, "group-name");
|
||||
+ TEST_COMPARE_STRING (e->sg_passwd, passwd);
|
||||
+ /* No administrators. */
|
||||
+ TEST_COMPARE_STRING (e->sg_adm[0], NULL);
|
||||
+ /* Check the members list. */
|
||||
+ for (int i = 0; i < 1000; ++i)
|
||||
+ {
|
||||
+ char *member = xasprintf ("m%d", i);
|
||||
+ TEST_COMPARE_STRING (e->sg_mem[i], member);
|
||||
+ free (member);
|
||||
+ }
|
||||
+ TEST_COMPARE_STRING (e->sg_mem[1000], NULL);
|
||||
+
|
||||
+ /* Check that putsgent brings back the input string. */
|
||||
+ xopen_memstream (&mem);
|
||||
+ TEST_COMPARE (putsgent (e, mem.out), 0);
|
||||
+ xfclose_memstream (&mem);
|
||||
+ /* Compare without the trailing '\n' that putsgent added. */
|
||||
+ TEST_COMPARE (mem.buffer[mem.length - 1], '\n');
|
||||
+ mem.buffer[mem.length - 1] = '\0';
|
||||
+ TEST_COMPARE_STRING (mem.buffer, input);
|
||||
+
|
||||
+ free (mem.buffer);
|
||||
+ free (input);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue