This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
PATCH: Enable IFUNC in libc.a
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 21 Aug 2009 13:28:10 -0700
- Subject: PATCH: Enable IFUNC in libc.a
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
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