commit 9c8af17c56134cb1cde6a3adc3aa7737c49cbeff
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date:   Mon Nov 13 13:46:50 2017 +0100

    Use libc_hidden_proto / _def for hidden wchar ifunc symbols.
    
    On s390 (31bit) various debug/tst-*chk* testcases are failing as the tests
    are ending with a segmentation fault.
    
    One test is e.g. calling wcsnrtombs in debug/tst-chk1.c:1549.
    The function wcsnrtombs itself calls __wcsnlen. This function is called via
    PLT! The PLT-stub itself loads the address from GOT (r12 is assumed to be
    the GOT-pointer). In this case the loaded address is zero and the following
    branch leads to the segmentation fault.
    
    Due to the attribute-hidden in commit 44af8a32c341672b5160fdc2839767e9a837ad26
    "Mark internal wchar functions with attribute_hidden [BZ #18822]"
    for e.g. the __wcsnlen function, r12 is not loaded with the GOT-pointer
    in wcsnrtombs.
    
    On s390x (64bit), this __wcsnlen call is also using the PLT-stub. But it is
    not failing as the GOT-pointer is setup with larl-instruction by the PLT-stub
    itself.
    Note: On s390x/s390, __wcsnlen is an IFUNC symbol.
    
    On x86_64, __wcsnlen is also an IFUNC symbol and is called via PLT, too.
    
    Further IFUNC symbols on s390 which were marked as hidden by the mentioned
    commit are: __wcscat, __wcsncpy, __wcpncpy, __wcschrnul.
    
    This patch adds the libc_hidden_proto / libc_hidden_def construct and
    removes the attribute_hidden as it conflicts with libc_hidden* construct on
    some architectures. Then the __GI_* symbols are the default-ifunc-variants
    which can be called without PLT.
    
    ChangeLog:
    
            * include/wchar.h (__wcsnlen, __wcscat, __wcsncpy, __wcpncpy,
            __wcschrnul): Add libc_hidden_proto, Remove attribute_hidden.
            * wcsmbs/wcsnlen.c (__wcsnlen): Add libc_hidden_def.
            * wcsmbs/wcscat.c (__wcscat): Likewise.
            * wcsmbs/wcschrnul.c (__wcschrnul): Likewise.
            * wcsmbs/wcsncpy.c (__wcsncpy): Likewise.
            * wcsmbs/wcpncpy.c (__wcpncpy): Likewise.
            * sysdeps/x86_64/multiarch/wcsnlen-c.c (__wcsnlen): Add libc_hidden_def
            which aliases to default ifunc-variant.
            * sysdeps/s390/multiarch/wcsnlen-c.c (__wcsnlen):  Likewise.
            * sysdeps/s390/multiarch/wcscat-c.c (__wcscat): Likewise.
            * sysdeps/s390/multiarch/wcschrnul-c.c  (__wcschrnul): Likewise.
            * sysdeps/s390/multiarch/wcsncpy-c.c (__wcsncpy): Likewise.
            * sysdeps/s390/multiarch/wcpncpy-c.c (__wcpncpy): Likewise.
            * sysdeps/s390/multiarch/wcsnlen.c (__wcsnlen): Redirect symbol in
            header and use s390_vx_libc_ifunc_redirected instead of
            s390_vx_libc_ifunc.
            * sysdeps/s390/multiarch/wcscat.c (__wcscat): Likewise.
            * sysdeps/s390/multiarch/wcschrnul.c (__wcschrnul): Likewise.
            * sysdeps/s390/multiarch/wcsncpy.c (__wcsncpy): Likewise.
            * sysdeps/s390/multiarch/wcpncpy.c (__wcpncpy): Likewise.

diff --git a/include/wchar.h b/include/wchar.h
index 24b2eaa..1efc33b 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -152,9 +152,10 @@ extern int __wcsncasecmp (const wchar_t *__s1, const wchar_t *__s2,
      __attribute_pure__;
 extern size_t __wcslen (const wchar_t *__s) __attribute_pure__;
 extern size_t __wcsnlen (const wchar_t *__s, size_t __maxlen)
-     attribute_hidden __attribute_pure__;
-extern wchar_t *__wcscat (wchar_t *dest, const wchar_t *src)
-     attribute_hidden;
+     __attribute_pure__;
+libc_hidden_proto (__wcsnlen)
+extern wchar_t *__wcscat (wchar_t *dest, const wchar_t *src);
+libc_hidden_proto (__wcscat)
 extern wint_t __btowc (int __c) attribute_hidden;
 extern int __mbsinit (const __mbstate_t *__ps);
 extern size_t __mbrtowc (wchar_t *__restrict __pwc,
@@ -182,11 +183,12 @@ extern size_t __wcsnrtombs (char *__restrict __dst,
 			    __mbstate_t *__restrict __ps)
      attribute_hidden;
 extern wchar_t *__wcsncpy (wchar_t *__restrict __dest,
-			   const wchar_t *__restrict __src, size_t __n)
-     attribute_hidden;
+			   const wchar_t *__restrict __src, size_t __n);
+libc_hidden_proto (__wcsncpy)
 extern wchar_t *__wcpcpy (wchar_t *__dest, const wchar_t *__src);
 extern wchar_t *__wcpncpy (wchar_t *__dest, const wchar_t *__src,
-			   size_t __n) attribute_hidden;
+			   size_t __n);
+libc_hidden_proto (__wcpncpy)
 extern wchar_t *__wmemcpy (wchar_t *__s1, const wchar_t *s2,
 			   size_t __n) attribute_hidden;
 extern wchar_t *__wmempcpy (wchar_t *__restrict __s1,
@@ -195,7 +197,8 @@ extern wchar_t *__wmempcpy (wchar_t *__restrict __s1,
 extern wchar_t *__wmemmove (wchar_t *__s1, const wchar_t *__s2,
 			    size_t __n) attribute_hidden;
 extern wchar_t *__wcschrnul (const wchar_t *__s, wchar_t __wc)
-     attribute_hidden __attribute_pure__;
+     __attribute_pure__;
+libc_hidden_proto (__wcschrnul)
 
 extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
 			       size_t __ns) __THROW;
diff --git a/sysdeps/s390/multiarch/wcpncpy-c.c b/sysdeps/s390/multiarch/wcpncpy-c.c
index 7cb834b..b02e40a 100644
--- a/sysdeps/s390/multiarch/wcpncpy-c.c
+++ b/sysdeps/s390/multiarch/wcpncpy-c.c
@@ -21,5 +21,11 @@
 
 # include <wchar.h>
 extern __typeof (__wcpncpy) __wcpncpy_c;
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcpncpy_c, __GI___wcpncpy, __wcpncpy_c);
+# endif /* SHARED */
 # include <wcsmbs/wcpncpy.c>
+libc_hidden_def (__wcpncpy)
 #endif
diff --git a/sysdeps/s390/multiarch/wcpncpy.c b/sysdeps/s390/multiarch/wcpncpy.c
index 1a19a99..a902787 100644
--- a/sysdeps/s390/multiarch/wcpncpy.c
+++ b/sysdeps/s390/multiarch/wcpncpy.c
@@ -17,10 +17,12 @@
    <http://www.gnu.org/licenses/>.  */
 
 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
+# define __wcpncpy __redirect___wcpncpy
 # include <wchar.h>
+# undef __wcpncpy
 # include <ifunc-resolve.h>
 
-s390_vx_libc_ifunc (__wcpncpy)
+s390_vx_libc_ifunc_redirected (__redirect___wcpncpy, __wcpncpy)
 weak_alias (__wcpncpy, wcpncpy)
 
 #else
diff --git a/sysdeps/s390/multiarch/wcscat-c.c b/sysdeps/s390/multiarch/wcscat-c.c
index ef7c000..3ac6110 100644
--- a/sysdeps/s390/multiarch/wcscat-c.c
+++ b/sysdeps/s390/multiarch/wcscat-c.c
@@ -21,5 +21,11 @@
 
 # include <wchar.h>
 extern __typeof (__wcscat) __wcscat_c;
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcscat_c, __GI___wcscat, __wcscat_c);
+# endif /* SHARED */
 # include <wcsmbs/wcscat.c>
+libc_hidden_def (__wcscat)
 #endif
diff --git a/sysdeps/s390/multiarch/wcscat.c b/sysdeps/s390/multiarch/wcscat.c
index 2e7fded..3f1219e 100644
--- a/sysdeps/s390/multiarch/wcscat.c
+++ b/sysdeps/s390/multiarch/wcscat.c
@@ -17,10 +17,12 @@
    <http://www.gnu.org/licenses/>.  */
 
 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
+# define __wcscat __redirect___wcscat
 # include <wchar.h>
+# undef __wcscat
 # include <ifunc-resolve.h>
 
-s390_vx_libc_ifunc (__wcscat)
+s390_vx_libc_ifunc_redirected (__redirect___wcscat, __wcscat)
 weak_alias (__wcscat, wcscat)
 
 #else
diff --git a/sysdeps/s390/multiarch/wcschrnul-c.c b/sysdeps/s390/multiarch/wcschrnul-c.c
index 095ea12..209a305 100644
--- a/sysdeps/s390/multiarch/wcschrnul-c.c
+++ b/sysdeps/s390/multiarch/wcschrnul-c.c
@@ -21,5 +21,11 @@
 
 # include <wchar.h>
 extern __typeof (__wcschrnul) __wcschrnul_c;
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcschrnul_c, __GI___wcschrnul, __wcschrnul_c);
+# endif /* SHARED */
 # include <wcsmbs/wcschrnul.c>
+libc_hidden_def (__wcschrnul)
 #endif
diff --git a/sysdeps/s390/multiarch/wcschrnul.c b/sysdeps/s390/multiarch/wcschrnul.c
index f01ea9f..c112cfb 100644
--- a/sysdeps/s390/multiarch/wcschrnul.c
+++ b/sysdeps/s390/multiarch/wcschrnul.c
@@ -17,10 +17,12 @@
    <http://www.gnu.org/licenses/>.  */
 
 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
+# define __wcschrnul __redirect___wcschrnul
 # include <wchar.h>
+# undef __wcschrnul
 # include <ifunc-resolve.h>
 
-s390_vx_libc_ifunc (__wcschrnul)
+s390_vx_libc_ifunc_redirected (__redirect___wcschrnul, __wcschrnul)
 weak_alias (__wcschrnul, wcschrnul)
 
 #else
diff --git a/sysdeps/s390/multiarch/wcsncpy-c.c b/sysdeps/s390/multiarch/wcsncpy-c.c
index 32ec8ff..d896220 100644
--- a/sysdeps/s390/multiarch/wcsncpy-c.c
+++ b/sysdeps/s390/multiarch/wcsncpy-c.c
@@ -21,5 +21,11 @@
 
 # include <wchar.h>
 extern __typeof (__wcsncpy) __wcsncpy_c;
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcsncpy_c, __GI___wcsncpy, __wcsncpy_c);
+# endif /* SHARED */
 # include <wcsmbs/wcsncpy.c>
+libc_hidden_def (__wcsncpy)
 #endif
diff --git a/sysdeps/s390/multiarch/wcsncpy.c b/sysdeps/s390/multiarch/wcsncpy.c
index 6e1e8f0..e08a82f 100644
--- a/sysdeps/s390/multiarch/wcsncpy.c
+++ b/sysdeps/s390/multiarch/wcsncpy.c
@@ -17,10 +17,12 @@
    <http://www.gnu.org/licenses/>.  */
 
 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
+# define __wcsncpy __redirect___wcsncpy
 # include <wchar.h>
+# undef __wcsncpy
 # include <ifunc-resolve.h>
 
-s390_vx_libc_ifunc (__wcsncpy)
+s390_vx_libc_ifunc_redirected (__redirect___wcsncpy, __wcsncpy)
 weak_alias (__wcsncpy, wcsncpy)
 
 #else
diff --git a/sysdeps/s390/multiarch/wcsnlen-c.c b/sysdeps/s390/multiarch/wcsnlen-c.c
index e86ca65..c6bc0cc 100644
--- a/sysdeps/s390/multiarch/wcsnlen-c.c
+++ b/sysdeps/s390/multiarch/wcsnlen-c.c
@@ -21,5 +21,11 @@
 
 # include <wchar.h>
 extern __typeof (__wcsnlen) __wcsnlen_c;
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcsnlen_c, __GI___wcsnlen, __wcsnlen_c);
+# endif /* SHARED */
 # include <wcsmbs/wcsnlen.c>
+libc_hidden_def (__wcsnlen)
 #endif
diff --git a/sysdeps/s390/multiarch/wcsnlen.c b/sysdeps/s390/multiarch/wcsnlen.c
index 54486b9..df29343 100644
--- a/sysdeps/s390/multiarch/wcsnlen.c
+++ b/sysdeps/s390/multiarch/wcsnlen.c
@@ -17,10 +17,12 @@
    <http://www.gnu.org/licenses/>.  */
 
 #if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)
+# define __wcsnlen __redirect___wcsnlen
 # include <wchar.h>
+# undef __wcsnlen
 # include <ifunc-resolve.h>
 
-s390_vx_libc_ifunc (__wcsnlen)
+s390_vx_libc_ifunc_redirected (__redirect___wcsnlen, __wcsnlen)
 weak_alias (__wcsnlen, wcsnlen)
 
 #else
diff --git a/sysdeps/x86_64/multiarch/wcsnlen-c.c b/sysdeps/x86_64/multiarch/wcsnlen-c.c
index e1ec7cf..a2d1187 100644
--- a/sysdeps/x86_64/multiarch/wcsnlen-c.c
+++ b/sysdeps/x86_64/multiarch/wcsnlen-c.c
@@ -4,6 +4,13 @@
 # define WCSNLEN __wcsnlen_sse2
 
 extern __typeof (wcsnlen) __wcsnlen_sse2;
+
+# ifdef SHARED
+#  undef libc_hidden_def
+#  define libc_hidden_def(name)					\
+  __hidden_ver1 (__wcsnlen_sse2, __GI___wcsnlen, __wcsnlen_sse2);
+libc_hidden_def (__wcsnlen)
+# endif /* SHARED */
 #endif
 
 #include "wcsmbs/wcsnlen.c"
diff --git a/wcsmbs/wcpncpy.c b/wcsmbs/wcpncpy.c
index 42c17ea..8b49d8b 100644
--- a/wcsmbs/wcpncpy.c
+++ b/wcsmbs/wcpncpy.c
@@ -83,5 +83,6 @@ __wcpncpy (wchar_t *dest, const wchar_t *src, size_t n)
 }
 
 #ifndef WCPNCPY
+libc_hidden_def (__wcpncpy)
 weak_alias (__wcpncpy, wcpncpy)
 #endif
diff --git a/wcsmbs/wcscat.c b/wcsmbs/wcscat.c
index d567b73..1f9187b 100644
--- a/wcsmbs/wcscat.c
+++ b/wcsmbs/wcscat.c
@@ -49,5 +49,6 @@ __wcscat (wchar_t *dest, const wchar_t *src)
   return dest;
 }
 #ifndef WCSCAT
+libc_hidden_def (__wcscat)
 weak_alias (__wcscat, wcscat)
 #endif
diff --git a/wcsmbs/wcschrnul.c b/wcsmbs/wcschrnul.c
index 67ddb1a..fed10b3 100644
--- a/wcsmbs/wcschrnul.c
+++ b/wcsmbs/wcschrnul.c
@@ -34,5 +34,6 @@ __wcschrnul (const wchar_t *wcs, const wchar_t wc)
   return (wchar_t *) wcs;
 }
 #ifndef WCSCHRNUL
+libc_hidden_def (__wcschrnul)
 weak_alias (__wcschrnul, wcschrnul)
 #endif
diff --git a/wcsmbs/wcsncpy.c b/wcsmbs/wcsncpy.c
index 27bfb0d..45175ee 100644
--- a/wcsmbs/wcsncpy.c
+++ b/wcsmbs/wcsncpy.c
@@ -84,5 +84,6 @@ __wcsncpy (wchar_t *dest, const wchar_t *src, size_t n)
   return s;
 }
 #ifndef WCSNCPY
+libc_hidden_def (__wcsncpy)
 weak_alias (__wcsncpy, wcsncpy)
 #endif
diff --git a/wcsmbs/wcsnlen.c b/wcsmbs/wcsnlen.c
index 21bb6db..cb9aff8 100644
--- a/wcsmbs/wcsnlen.c
+++ b/wcsmbs/wcsnlen.c
@@ -46,5 +46,6 @@ __wcsnlen (const wchar_t *s, size_t maxlen)
   return len;
 }
 #ifndef WCSNLEN
+libc_hidden_def (__wcsnlen)
 weak_alias (__wcsnlen, wcsnlen)
 #endif
