about summary refs log tree commit diff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-08-20 12:05:50 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-08-20 16:25:22 -0700
commit507abbad59c5777be75a6bac5f887d919af44e6d (patch)
treebe8ce8ae1d1a58edcc848b8f4ef042c448096f52
parent80cc6cd67a2826754d5e4c72f6335f88e150d9ff (diff)
downloadglibc-507abbad59c5777be75a6bac5f887d919af44e6d.tar.gz
glibc-507abbad59c5777be75a6bac5f887d919af44e6d.tar.xz
glibc-507abbad59c5777be75a6bac5f887d919af44e6d.zip
Add i386 strcpy family multiarch functions
-rw-r--r--sysdeps/i386/i686/multiarch/strncpy-c.c8
-rw-r--r--sysdeps/i386/multiarch/Makefile6
-rw-r--r--sysdeps/i386/multiarch/ifunc-impl-list.c22
-rw-r--r--sysdeps/i386/multiarch/rtld-stpcpy.S24
-rw-r--r--sysdeps/i386/multiarch/stpcpy-i386.S17
-rw-r--r--sysdeps/i386/multiarch/stpcpy-i586.S15
-rw-r--r--sysdeps/i386/multiarch/stpcpy-sse2.S (renamed from sysdeps/i386/i686/multiarch/stpcpy-sse2.S)0
-rw-r--r--sysdeps/i386/multiarch/stpcpy-ssse3.S (renamed from sysdeps/i386/i686/multiarch/stpcpy-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/stpcpy.c59
-rw-r--r--sysdeps/i386/multiarch/stpncpy-i386.S13
-rw-r--r--sysdeps/i386/multiarch/stpncpy-sse2.S (renamed from sysdeps/i386/i686/multiarch/stpncpy-sse2.S)0
-rw-r--r--sysdeps/i386/multiarch/stpncpy-ssse3.S (renamed from sysdeps/i386/i686/multiarch/stpncpy-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/stpncpy.c54
-rw-r--r--sysdeps/i386/multiarch/strcpy-i386.c13
-rw-r--r--sysdeps/i386/multiarch/strcpy-i586.S11
-rw-r--r--sysdeps/i386/multiarch/strcpy-sse2.S (renamed from sysdeps/i386/i686/multiarch/strcpy-sse2.S)0
-rw-r--r--sysdeps/i386/multiarch/strcpy-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strcpy-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strcpy.c55
-rw-r--r--sysdeps/i386/multiarch/strncpy-i386.c12
-rw-r--r--sysdeps/i386/multiarch/strncpy-sse2.S (renamed from sysdeps/i386/i686/multiarch/strncpy-sse2.S)0
-rw-r--r--sysdeps/i386/multiarch/strncpy-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strncpy-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strncpy.c52
22 files changed, 347 insertions, 14 deletions
diff --git a/sysdeps/i386/i686/multiarch/strncpy-c.c b/sysdeps/i386/i686/multiarch/strncpy-c.c
deleted file mode 100644
index 201e3f98b3..0000000000
--- a/sysdeps/i386/i686/multiarch/strncpy-c.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#define STRNCPY __strncpy_ia32
-#ifdef SHARED
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(name)  \
-    __hidden_ver1 (__strncpy_ia32, __GI_strncpy, __strncpy_ia32);
-#endif
-
-#include "string/strncpy.c"
diff --git a/sysdeps/i386/multiarch/Makefile b/sysdeps/i386/multiarch/Makefile
index ad8c864fd1..147258cbe9 100644
--- a/sysdeps/i386/multiarch/Makefile
+++ b/sysdeps/i386/multiarch/Makefile
@@ -21,7 +21,11 @@ sysdep_routines += bcopy-i386 bcopy-i686 bcopy-sse2-unaligned \
 		   memchr-sse2-bsf memchr-sse2 \
 		   memcmp-i386 memcmp-i686 memcmp-ssse3 memcmp-sse4 \
 		   memrchr-i386 memrchr-sse2-bsf memrchr-sse2 \
-		   rawmemchr-sse2-bsf rawmemchr-sse2
+		   rawmemchr-sse2-bsf rawmemchr-sse2 \
+		   stpcpy-i386 stpcpy-i586 stpcpy-sse2 stpcpy-ssse3 \
+		   stpncpy-i386 stpncpy-sse2 stpncpy-ssse3 \
+		   strcpy-i386 strcpy-i586 strcpy-sse2 strcpy-ssse3 \
+		   strncpy-i386 strncpy-sse2 strncpy-ssse3
 endif
 
 ifeq (mathyes,$(subdir)$(config-cflags-avx))
diff --git a/sysdeps/i386/multiarch/ifunc-impl-list.c b/sysdeps/i386/multiarch/ifunc-impl-list.c
index b026cb8ee2..73cd46d15c 100644
--- a/sysdeps/i386/multiarch/ifunc-impl-list.c
+++ b/sysdeps/i386/multiarch/ifunc-impl-list.c
@@ -171,14 +171,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __rawmemchr_sse2)
 	      IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_i386))
 
-#if 0
   /* Support sysdeps/i386/i686/multiarch/stpncpy.S.  */
   IFUNC_IMPL (i, name, stpncpy,
 	      IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSSE3),
 			      __stpncpy_ssse3)
 	      IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSE2),
 			      __stpncpy_sse2)
-	      IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_ia32))
+	      IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_i386))
 
   /* Support sysdeps/i386/i686/multiarch/stpcpy.S.  */
   IFUNC_IMPL (i, name, stpcpy,
@@ -186,8 +185,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __stpcpy_ssse3)
 	      IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CPU_FEATURE (SSE2),
 			      __stpcpy_sse2)
-	      IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_ia32))
+	      IFUNC_IMPL_ADD (array, i, stpcpy, HAS_I586, __stpcpy_i586)
+#if !SUPPORT_I586
+	      IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_i386)
+#endif
+	     )
 
+#if 0
   /* Support sysdeps/i386/i686/multiarch/strcasecmp.S.  */
   IFUNC_IMPL (i, name, strcasecmp,
 	      IFUNC_IMPL_ADD (array, i, strcasecmp,
@@ -232,6 +236,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSSE3),
 			      __strcmp_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_ia32))
+#endif
 
   /* Support sysdeps/i386/i686/multiarch/strcpy.S.  */
   IFUNC_IMPL (i, name, strcpy,
@@ -239,8 +244,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __strcpy_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strcpy, HAS_CPU_FEATURE (SSE2),
 			      __strcpy_sse2)
-	      IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_ia32))
+	      IFUNC_IMPL_ADD (array, i, strcpy, HAS_I586, __strcpy_i586)
+#if !SUPPORT_I586
+	      IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_i386)
+#endif
+	     )
 
+#if 0
   /* Support sysdeps/i386/i686/multiarch/strcspn.S.  */
   IFUNC_IMPL (i, name, strcspn,
 	      IFUNC_IMPL_ADD (array, i, strcspn, HAS_CPU_FEATURE (SSE4_2),
@@ -276,6 +286,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSE2),
 			      __strncat_sse2)
 	      IFUNC_IMPL_ADD (array, i, strncat, 1, __strncat_ia32))
+#endif
 
   /* Support sysdeps/i386/i686/multiarch/strncpy.S.  */
   IFUNC_IMPL (i, name, strncpy,
@@ -283,8 +294,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __strncpy_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strncpy, HAS_CPU_FEATURE (SSE2),
 			      __strncpy_sse2)
-	      IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_ia32))
+	      IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_i386))
 
+#if 0
   /* Support sysdeps/i386/i686/multiarch/strnlen.S.  */
   IFUNC_IMPL (i, name, strnlen,
 	      IFUNC_IMPL_ADD (array, i, strnlen, HAS_CPU_FEATURE (SSE2),
diff --git a/sysdeps/i386/multiarch/rtld-stpcpy.S b/sysdeps/i386/multiarch/rtld-stpcpy.S
new file mode 100644
index 0000000000..d64e2bf884
--- /dev/null
+++ b/sysdeps/i386/multiarch/rtld-stpcpy.S
@@ -0,0 +1,24 @@
+/* stpcpy for ld.so
+   Copyright (C) 2015 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 <init-arch.h>
+#if SUPPORT_I586
+# include <sysdeps/i386/i586/stpcpy.S>
+#else
+# include <sysdeps/i386/stpcpy.S>
+#endif
diff --git a/sysdeps/i386/multiarch/stpcpy-i386.S b/sysdeps/i386/multiarch/stpcpy-i386.S
new file mode 100644
index 0000000000..8124c73b4d
--- /dev/null
+++ b/sysdeps/i386/multiarch/stpcpy-i386.S
@@ -0,0 +1,17 @@
+#include <init-arch.h>
+#if !SUPPORT_I586
+# define __stpcpy __stpcpy_i386
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+# undef libc_hidden_def
+# define libc_hidden_def(name)
+# undef weak_alias
+# define weak_alias(name, aliasname)
+# include <sysdeps/i386/stpcpy.S>
+
+# ifdef SHARED
+	.globl __GI_stpcpy
+	.hidden __GI_stpcpy
+	__GI_stpcpy = __stpcpy_i386
+# endif
+#endif
diff --git a/sysdeps/i386/multiarch/stpcpy-i586.S b/sysdeps/i386/multiarch/stpcpy-i586.S
new file mode 100644
index 0000000000..b6934d5590
--- /dev/null
+++ b/sysdeps/i386/multiarch/stpcpy-i586.S
@@ -0,0 +1,15 @@
+#include <init-arch.h>
+#define __stpcpy __stpcpy_i586
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(name)
+#undef libc_hidden_def
+#define libc_hidden_def(name)
+#undef weak_alias
+#define weak_alias(name, aliasname)
+#include <sysdeps/i386/i586/stpcpy.S>
+
+#if defined SHARED && SUPPORT_I586
+	.globl __GI_stpcpy
+	.hidden __GI_stpcpy
+	__GI_stpcpy = __stpcpy_i586
+#endif
diff --git a/sysdeps/i386/i686/multiarch/stpcpy-sse2.S b/sysdeps/i386/multiarch/stpcpy-sse2.S
index 46ca1b3074..46ca1b3074 100644
--- a/sysdeps/i386/i686/multiarch/stpcpy-sse2.S
+++ b/sysdeps/i386/multiarch/stpcpy-sse2.S
diff --git a/sysdeps/i386/i686/multiarch/stpcpy-ssse3.S b/sysdeps/i386/multiarch/stpcpy-ssse3.S
index d971c2da38..d971c2da38 100644
--- a/sysdeps/i386/i686/multiarch/stpcpy-ssse3.S
+++ b/sysdeps/i386/multiarch/stpcpy-ssse3.S
diff --git a/sysdeps/i386/multiarch/stpcpy.c b/sysdeps/i386/multiarch/stpcpy.c
new file mode 100644
index 0000000000..e4f75c4855
--- /dev/null
+++ b/sysdeps/i386/multiarch/stpcpy.c
@@ -0,0 +1,59 @@
+/* Multiple versions of stpcpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define _HAVE_STRING_ARCH_stpcpy
+# define NO_MEMPCPY_STPCPY_REDIRECT
+/* Redefine stpcpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef stpcpy
+# define stpcpy __redirect_stpcpy
+# include <string.h>
+# undef stpcpy
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_stpcpy) __stpcpy_i386 attribute_hidden;
+extern __typeof (__redirect_stpcpy) __stpcpy_i586 attribute_hidden;
+extern __typeof (__redirect_stpcpy) __stpcpy_sse2 attribute_hidden;
+extern __typeof (__redirect_stpcpy) __stpcpy_ssse3 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_stpcpy) __stpcpy;
+extern void *stpcpy_ifunc (void) __asm__ ("__stpcpy");
+
+void *
+stpcpy_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSSE3))
+    return __stpcpy_ssse3;
+  else if (HAS_CPU_FEATURE (SSE2))
+    return __stpcpy_sse2;
+
+  if (HAS_I586)
+    return __stpcpy_i586;
+  else
+    return __stpcpy_i386;
+}
+__asm__ (".type __stpcpy, %gnu_indirect_function");
+
+weak_alias (__stpcpy, stpcpy)
+#endif
diff --git a/sysdeps/i386/multiarch/stpncpy-i386.S b/sysdeps/i386/multiarch/stpncpy-i386.S
new file mode 100644
index 0000000000..4ee1ef6ce6
--- /dev/null
+++ b/sysdeps/i386/multiarch/stpncpy-i386.S
@@ -0,0 +1,13 @@
+#include <init-arch.h>
+#define __stpncpy __stpncpy_i386
+#undef libc_hidden_def
+#define libc_hidden_def(name)
+#undef weak_alias
+#define weak_alias(name, aliasname)
+#include <sysdeps/i386/stpncpy.S>
+
+#ifdef SHARED
+	.globl __GI___stpncpy
+	.hidden __GI___stpncpy
+	__GI___stpncpy = __stpncpy_i386
+#endif
diff --git a/sysdeps/i386/i686/multiarch/stpncpy-sse2.S b/sysdeps/i386/multiarch/stpncpy-sse2.S
index 37a703cb76..37a703cb76 100644
--- a/sysdeps/i386/i686/multiarch/stpncpy-sse2.S
+++ b/sysdeps/i386/multiarch/stpncpy-sse2.S
diff --git a/sysdeps/i386/i686/multiarch/stpncpy-ssse3.S b/sysdeps/i386/multiarch/stpncpy-ssse3.S
index 14ed16f6b5..14ed16f6b5 100644
--- a/sysdeps/i386/i686/multiarch/stpncpy-ssse3.S
+++ b/sysdeps/i386/multiarch/stpncpy-ssse3.S
diff --git a/sysdeps/i386/multiarch/stpncpy.c b/sysdeps/i386/multiarch/stpncpy.c
new file mode 100644
index 0000000000..609d8d4109
--- /dev/null
+++ b/sysdeps/i386/multiarch/stpncpy.c
@@ -0,0 +1,54 @@
+/* Multiple versions of stpncpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define _HAVE_STRING_ARCH_stpncpy
+/* Redefine stpncpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef stpncpy
+# define stpncpy __redirect_stpncpy
+# include <string.h>
+# undef stpncpy
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_stpncpy) __stpncpy_i386 attribute_hidden;
+extern __typeof (__redirect_stpncpy) __stpncpy_sse2 attribute_hidden;
+extern __typeof (__redirect_stpncpy) __stpncpy_ssse3 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_stpncpy) __stpncpy;
+extern void *stpncpy_ifunc (void) __asm__ ("__stpncpy");
+
+void *
+stpncpy_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSSE3))
+    return __stpncpy_ssse3;
+  else if (HAS_CPU_FEATURE (SSE2))
+    return __stpncpy_sse2;
+
+  return __stpncpy_i386;
+}
+__asm__ (".type __stpncpy, %gnu_indirect_function");
+
+weak_alias (__stpncpy, stpncpy)
+#endif
diff --git a/sysdeps/i386/multiarch/strcpy-i386.c b/sysdeps/i386/multiarch/strcpy-i386.c
new file mode 100644
index 0000000000..a98f4d25fb
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcpy-i386.c
@@ -0,0 +1,13 @@
+#include <init-arch.h>
+#if !SUPPORT_I586
+# undef libc_hidden_builtin_def
+# ifdef SHARED
+#  define libc_hidden_builtin_def(name)  \
+    __hidden_ver1 (__strcpy_i386, __GI_strcpy, __strcpy_i386);
+# else
+#  define libc_hidden_builtin_def(name)
+# endif
+#endif
+
+#define STRCPY __strcpy_i386
+#include "string/strcpy.c"
diff --git a/sysdeps/i386/multiarch/strcpy-i586.S b/sysdeps/i386/multiarch/strcpy-i586.S
new file mode 100644
index 0000000000..38c3779503
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcpy-i586.S
@@ -0,0 +1,11 @@
+#include <init-arch.h>
+#define strcpy __strcpy_i586
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(name)
+#include <sysdeps/i386/i586/strcpy.S>
+
+#if defined SHARED && SUPPORT_I586
+	.globl __GI_strcpy
+	.hidden __GI_strcpy
+	__GI_strcpy = __strcpy_i586
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strcpy-sse2.S b/sysdeps/i386/multiarch/strcpy-sse2.S
index a37c44530d..a37c44530d 100644
--- a/sysdeps/i386/i686/multiarch/strcpy-sse2.S
+++ b/sysdeps/i386/multiarch/strcpy-sse2.S
diff --git a/sysdeps/i386/i686/multiarch/strcpy-ssse3.S b/sysdeps/i386/multiarch/strcpy-ssse3.S
index 9f88e7735d..9f88e7735d 100644
--- a/sysdeps/i386/i686/multiarch/strcpy-ssse3.S
+++ b/sysdeps/i386/multiarch/strcpy-ssse3.S
diff --git a/sysdeps/i386/multiarch/strcpy.c b/sysdeps/i386/multiarch/strcpy.c
new file mode 100644
index 0000000000..72daf1e1e2
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcpy.c
@@ -0,0 +1,55 @@
+/* Multiple versions of strcpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+/* Redefine strcpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcpy
+# define strcpy __redirect_strcpy
+# include <string.h>
+# undef strcpy
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strcpy) __strcpy_i386 attribute_hidden;
+extern __typeof (__redirect_strcpy) __strcpy_i586 attribute_hidden;
+extern __typeof (__redirect_strcpy) __strcpy_sse2 attribute_hidden;
+extern __typeof (__redirect_strcpy) __strcpy_ssse3 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strcpy) strcpy;
+extern void *strcpy_ifunc (void) __asm__ ("strcpy");
+
+void *
+strcpy_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSSE3))
+    return __strcpy_ssse3;
+  else if (HAS_CPU_FEATURE (SSE2))
+    return __strcpy_sse2;
+
+  if (HAS_I586)
+    return __strcpy_i586;
+  else
+    return __strcpy_i386;
+}
+__asm__ (".type strcpy, %gnu_indirect_function");
+#endif
diff --git a/sysdeps/i386/multiarch/strncpy-i386.c b/sysdeps/i386/multiarch/strncpy-i386.c
new file mode 100644
index 0000000000..b584d83470
--- /dev/null
+++ b/sysdeps/i386/multiarch/strncpy-i386.c
@@ -0,0 +1,12 @@
+#include <init-arch.h>
+#undef libc_hidden_builtin_def
+#ifdef SHARED
+# define libc_hidden_builtin_def(name)  \
+    __hidden_ver1 (__strncpy_i386, __GI_strncpy, __strncpy_i386);
+#else
+# define libc_hidden_builtin_def(name)
+#endif
+
+#define _HAVE_STRING_ARCH_strncpy
+#define STRNCPY __strncpy_i386
+#include "string/strncpy.c"
diff --git a/sysdeps/i386/i686/multiarch/strncpy-sse2.S b/sysdeps/i386/multiarch/strncpy-sse2.S
index bdd99239a4..bdd99239a4 100644
--- a/sysdeps/i386/i686/multiarch/strncpy-sse2.S
+++ b/sysdeps/i386/multiarch/strncpy-sse2.S
diff --git a/sysdeps/i386/i686/multiarch/strncpy-ssse3.S b/sysdeps/i386/multiarch/strncpy-ssse3.S
index bf82ee447d..bf82ee447d 100644
--- a/sysdeps/i386/i686/multiarch/strncpy-ssse3.S
+++ b/sysdeps/i386/multiarch/strncpy-ssse3.S
diff --git a/sysdeps/i386/multiarch/strncpy.c b/sysdeps/i386/multiarch/strncpy.c
new file mode 100644
index 0000000000..aa98708c3c
--- /dev/null
+++ b/sysdeps/i386/multiarch/strncpy.c
@@ -0,0 +1,52 @@
+/* Multiple versions of strncpy.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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/>.  */
+
+/* Define multiple versions only for the definition in libc.  */
+#if IS_IN (libc)
+# define _HAVE_STRING_ARCH_strncpy
+/* Redefine strncpy so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strncpy
+# define strncpy __redirect_strncpy
+# include <string.h>
+# undef strncpy
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strncpy) __strncpy_i386 attribute_hidden;
+extern __typeof (__redirect_strncpy) __strncpy_sse2 attribute_hidden;
+extern __typeof (__redirect_strncpy) __strncpy_ssse3 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strncpy) strncpy;
+extern void *strncpy_ifunc (void) __asm__ ("strncpy");
+
+void *
+strncpy_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSSE3))
+    return __strncpy_ssse3;
+  else if (HAS_CPU_FEATURE (SSE2))
+    return __strncpy_sse2;
+
+  return __strncpy_i386;
+}
+__asm__ (".type strncpy, %gnu_indirect_function");
+#endif