Toshaan Bharvani
5 months ago
106 changed files with 19526 additions and 0 deletions
Binary file not shown.
@ -0,0 +1,432 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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