This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: Enable IFUNC in libc.a


Hi,

In libc.a, before __libc_csu_init, we can't call any IFUNC functions.
This patch adds <direct-symbols.h> and include it in files where IFUNC
functions are called before __libc_csu_init. The __GI__ version of those
functions will be called instead.

Tested on Linux/ia32 and Linux/x86-64.


H.J.
---
2009-08-21  H.J. Lu  <hongjiu.lu@intel.com>

	* elf/dl-load.c: Include <direct-symbols.h>.

	* stdlib/getenv.c: Include <direct-symbols.h> if NOT_IN_libc
	isn't defined.
	* string/strsep.c: Likewise.

	* sysdeps/generic/direct-symbols.h: Here.  New.
	* sysdeps/i386/i686/multiarch/direct-symbols.h: Likewise.
	* sysdeps/x86_64/multiarch/direct-symbols.h: Likewise.

	* sysdeps/i386/i686/multiarch/strcspn.S: Enable strpbrk for libc.a.

	* sysdeps/i386/i686/multiarch/strlen.S: Enable strlen for libc.a.

	* sysdeps/x86_64/multiarch/strcmp.S: Enable strncmp for libc.a.

	* sysdeps/x86_64/multiarch/strcspn.S: Enable strpbrk for libc.a.

	* sysdeps/x86_64/multiarch/strlen.S: Enabled for libc.a.

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0b896d9..817a918 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -36,6 +36,7 @@
 #include <stackinfo.h>
 #include <caller.h>
 #include <sysdep.h>
+#include <direct-symbols.h>
 
 #include <dl-dst.h>
 
diff --git a/stdlib/getenv.c b/stdlib/getenv.c
index 6cdfe2b..547294a 100644
--- a/stdlib/getenv.c
+++ b/stdlib/getenv.c
@@ -23,6 +23,9 @@
 #include <string.h>
 #include <unistd.h>
 
+#ifndef NOT_IN_libc
+# include <direct-symbols.h>
+#endif
 
 /* Return the value of the environment variable NAME.  This implementation
    is tuned a bit in that it assumes no environment variable has an empty
diff --git a/string/strsep.c b/string/strsep.c
index e5342f7..741fc69 100644
--- a/string/strsep.c
+++ b/string/strsep.c
@@ -18,6 +18,10 @@
 
 #include <string.h>
 
+#ifndef NOT_IN_libc
+# include <direct-symbols.h>
+#endif
+
 #undef __strsep
 #undef strsep
 
diff --git a/sysdeps/generic/direct-symbols.h b/sysdeps/generic/direct-symbols.h
new file mode 100644
index 0000000..9369261
--- /dev/null
+++ b/sysdeps/generic/direct-symbols.h
@@ -0,0 +1,8 @@
+#define __direct_asmname(name) \
+  __direct_asmname1 (__USER_LABEL_PREFIX__, name)
+#define __direct_asmname1(prefix, name) __direct_asmname2(prefix, name)
+#define __direct_asmname2(prefix, name) #prefix name
+#define libc_direct_proto(name, attrs...) \
+  __direct_proto (name, __GI_##name, ##attrs)
+#define __direct_proto(name, internal, attrs...) \
+  extern __typeof (name) name __asm__ (__direct_asmname (#internal));
diff --git a/sysdeps/i386/i686/multiarch/direct-symbols.h b/sysdeps/i386/i686/multiarch/direct-symbols.h
new file mode 100644
index 0000000..1120d72
--- /dev/null
+++ b/sysdeps/i386/i686/multiarch/direct-symbols.h
@@ -0,0 +1,9 @@
+#if defined USE_MULTIARCH && !defined SHARED && !defined NOT_IN_libc
+
+#include <sysdeps/generic/direct-symbols.h>
+#include <string.h>
+
+libc_direct_proto (strlen)
+libc_direct_proto (strpbrk)
+
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strcspn.S b/sysdeps/i386/i686/multiarch/strcspn.S
index 73e7eb4..8e82195 100644
--- a/sysdeps/i386/i686/multiarch/strcspn.S
+++ b/sysdeps/i386/i686/multiarch/strcspn.S
@@ -38,10 +38,8 @@
 #endif
 #endif
 
-/* Define multiple versions only for the definition in libc.  Don't
-   define multiple versions for strpbrk in static library since we
-   need strpbrk before the initialization happened.  */
-#if (defined SHARED || !defined USE_AS_STRPBRK) && !defined NOT_IN_libc
+/* Define multiple versions only for the definition in libc.  */
+#ifndef NOT_IN_libc
 # ifdef SHARED
 	.section	.gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
 	.globl	__i686.get_pc_thunk.bx
diff --git a/sysdeps/i386/i686/multiarch/strlen.S b/sysdeps/i386/i686/multiarch/strlen.S
index 0c1e864..f7f1ddd 100644
--- a/sysdeps/i386/i686/multiarch/strlen.S
+++ b/sysdeps/i386/i686/multiarch/strlen.S
@@ -21,10 +21,9 @@
 #include <sysdep.h>
 #include <ifunc-defines.h>
 
-/* Define multiple versions only for the definition in libc and for the
-   DSO.  In static binaries, we need strlen before the initialization
-   happened.  */
-#if defined SHARED && !defined NOT_IN_libc
+/* Define multiple versions only for the definition in libc.  */
+#ifndef NOT_IN_libc
+# ifdef SHARED
 	.section	.gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
 	.globl	__i686.get_pc_thunk.bx
 	.hidden	__i686.get_pc_thunk.bx
@@ -54,6 +53,19 @@ ENTRY(strlen)
 	cfi_restore (ebx)
 	ret
 END(strlen)
+# else
+ENTRY(strlen)
+	.type	strlen, @gnu_indirect_function
+END(strlen)
+	cmpl	$0, KIND_OFFSET+__cpu_features
+	jne	1f
+	call	__init_cpu_features
+1:	leal	__strlen_ia32, %eax
+	testl	$(1<<26), CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_EDX_OFFSET+__cpu_features
+	jz	2f
+	leal	__strlen_sse2, %eax
+2:	ret
+# endif
 
 #define CFI_POP(REG)						\
   cfi_adjust_cfa_offset (-4);					\
diff --git a/sysdeps/x86_64/multiarch/direct-symbols.h b/sysdeps/x86_64/multiarch/direct-symbols.h
new file mode 100644
index 0000000..cbec3c0
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/direct-symbols.h
@@ -0,0 +1,10 @@
+#if defined USE_MULTIARCH && !defined SHARED && !defined NOT_IN_libc
+
+#include <sysdeps/generic/direct-symbols.h>
+#include <string.h>
+
+libc_direct_proto (strlen)
+libc_direct_proto (strncmp)
+libc_direct_proto (strpbrk)
+
+#endif
diff --git a/sysdeps/x86_64/multiarch/strcmp.S b/sysdeps/x86_64/multiarch/strcmp.S
index 05adf1e..e6db48b 100644
--- a/sysdeps/x86_64/multiarch/strcmp.S
+++ b/sysdeps/x86_64/multiarch/strcmp.S
@@ -52,10 +52,8 @@
 #define LABEL(l) L(l)
 #endif
 
-/* Define multiple versions only for the definition in libc.  Don't
-   define multiple versions for strncmp in static library since we
-   need strncmp before the initialization happened.  */
-#if (defined SHARED || !defined USE_AS_STRNCMP) && !defined NOT_IN_libc
+/* Define multiple versions only for the definition in libc.  */
+#ifndef NOT_IN_libc
 	.text
 ENTRY(STRCMP)
 	.type	STRCMP, @gnu_indirect_function
diff --git a/sysdeps/x86_64/multiarch/strcspn.S b/sysdeps/x86_64/multiarch/strcspn.S
index cc75ab7..7da0b49 100644
--- a/sysdeps/x86_64/multiarch/strcspn.S
+++ b/sysdeps/x86_64/multiarch/strcspn.S
@@ -38,10 +38,8 @@
 #endif
 #endif
 
-/* Define multiple versions only for the definition in libc.  Don't
-   define multiple versions for strpbrk in static library since we
-   need strpbrk before the initialization happened.  */
-#if (defined SHARED || !defined USE_AS_STRPBRK) && !defined NOT_IN_libc
+/* Define multiple versions only for the definition in libc.  */
+#ifndef NOT_IN_libc
 	.text
 ENTRY(STRCSPN)
 	.type	STRCSPN, @gnu_indirect_function
diff --git a/sysdeps/x86_64/multiarch/strlen.S b/sysdeps/x86_64/multiarch/strlen.S
index 4342c6c..1381b16 100644
--- a/sysdeps/x86_64/multiarch/strlen.S
+++ b/sysdeps/x86_64/multiarch/strlen.S
@@ -22,10 +22,8 @@
 #include <ifunc-defines.h>
 
 
-/* Define multiple versions only for the definition in libc and for
-   the DSO.  In static binaries we need strlen before the initialization
-   happened.  */
-#if defined SHARED && !defined NOT_IN_libc
+/* Define multiple versions only for the definition in libc.   */
+#ifndef NOT_IN_libc
 	.text
 ENTRY(strlen)
 	.type	strlen, @gnu_indirect_function


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]