diff options
author | Stefan Liebler <stli@linux.vnet.ibm.com> | 2016-10-07 09:56:46 +0200 |
---|---|---|
committer | Stefan Liebler <stli@linux.vnet.ibm.com> | 2016-10-07 10:03:20 +0200 |
commit | 00980d845f8f2ec3ed4ad161a1e5b97704be1929 (patch) | |
tree | 8ec5bf7c144610f5e058ccfa4bd46f1d843bfc9c /sysdeps/powerpc/powerpc32/power4/multiarch | |
parent | 022dfdce000374b60aadfb0a5ed9a5c4c1dbd29b (diff) | |
download | glibc-00980d845f8f2ec3ed4ad161a1e5b97704be1929.tar.gz glibc-00980d845f8f2ec3ed4ad161a1e5b97704be1929.tar.xz glibc-00980d845f8f2ec3ed4ad161a1e5b97704be1929.zip |
Use gcc attribute ifunc in libc_ifunc macro instead of inline assembly due to false debuginfo.
The current s390 ifunc resolver for vector optimized functions and the common libc_ifunc macro in include/libc-symbols.h uses something like that to generate ifunc'ed functions: extern void *__resolve___strlen(unsigned long int dl_hwcap) asm (strlen); asm (".type strlen, %gnu_indirect_function"); This leads to false debug information: objdump --dwarf=info libc.so: ... <1><1e6424>: Abbrev Number: 43 (DW_TAG_subprogram) <1e6425> DW_AT_external : 1 <1e6425> DW_AT_name : (indirect string, offset: 0x1146e): __resolve___strlen <1e6429> DW_AT_decl_file : 1 <1e642a> DW_AT_decl_line : 23 <1e642b> DW_AT_linkage_name: (indirect string, offset: 0x1147a): strlen <1e642f> DW_AT_prototyped : 1 <1e642f> DW_AT_type : <0x1e4ccd> <1e6433> DW_AT_low_pc : 0x998e0 <1e643b> DW_AT_high_pc : 0x16 <1e6443> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <1e6445> DW_AT_GNU_all_call_sites: 1 <1e6445> DW_AT_sibling : <0x1e6459> <2><1e6449>: Abbrev Number: 44 (DW_TAG_formal_parameter) <1e644a> DW_AT_name : (indirect string, offset: 0x1845): dl_hwcap <1e644e> DW_AT_decl_file : 1 <1e644f> DW_AT_decl_line : 23 <1e6450> DW_AT_type : <0x1e4c8d> <1e6454> DW_AT_location : 0x122115 (location list) ... The debuginfo for the ifunc-resolver function contains the DW_AT_linkage_name field, which names the real function name "strlen". If you perform an inferior function call to strlen in lldb, then it fails due to something like that: "error: no matching function for call to 'strlen' candidate function not viable: no known conversion from 'const char [6]' to 'unsigned long' for 1st argument" The unsigned long is the dl_hwcap argument of the resolver function. The strlen function itself has no debufinfo. The s390 ifunc resolver for memset & co uses something like that: asm (".globl FUNC" ".type FUNC, @gnu_indirect_function" ".set FUNC, __resolve_FUNC"); This way the debuginfo for the ifunc-resolver function does not conain the DW_AT_linkage_name field and the real function has no debuginfo, too. Using this strategy for the vector optimized functions leads to some troubles for functions like strnlen. Here we have __strnlen and a weak alias strnlen. The __strnlen function is the ifunc function, which is realized with the asm- statement above. The weak_alias-macro can't be used here due to undefined symbol: gcc ../sysdeps/s390/multiarch/strnlen.c -c ... In file included from <command-line>:0:0: ../sysdeps/s390/multiarch/strnlen.c:28:24: error: ‘strnlen’ aliased to undefined symbol ‘__strnlen’ weak_alias (__strnlen, strnlen) ^ ./../include/libc-symbols.h:111:26: note: in definition of macro ‘_weak_alias’ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); ^ ../sysdeps/s390/multiarch/strnlen.c:28:1: note: in expansion of macro ‘weak_alias’ weak_alias (__strnlen, strnlen) ^ make[2]: *** [build/string/strnlen.o] Error 1 As the __strnlen function is defined with asm-statements the function name __strnlen isn't known by gcc. But the weak alias can also be done with an asm statement to resolve this issue: __asm__ (".weak strnlen\n\t" ".set strnlen,__strnlen\n"); In order to use the weak_alias macro, gcc needs to know the ifunc function. The minimum gcc to build glibc is currently 4.7, which supports attribute((ifunc)). See https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html. It is only supported if gcc is configured with --enable-gnu-indirect-function or gcc supports it by default for at least intel and s390x architecture. This patch uses the old behaviour if gcc support is not available. Usage of attribute ifunc is something like that: __typeof (FUNC) FUNC __attribute__ ((ifunc ("__resolve_FUNC"))); Then gcc produces the same .globl, .type, .set assembler instructions like above. And the debuginfo does not contain the DW_AT_linkage_name field and there is no debuginfo for the real function, too. But in order to get it work, there is also some extra work to do. Currently, the glibc internal symbol on s390x e.g. __GI___strnlen is not the ifunc symbol, but the fallback __strnlen_c symbol. Thus I have to omit the libc_hidden_def macro in strnlen.c (here is the ifunc function __strnlen) because it is already handled in strnlen-c.c (here is __strnlen_c). Due to libc_hidden_proto (__strnlen) in string.h, compiling fails: gcc ../sysdeps/s390/multiarch/strnlen.c -c ... In file included from <command-line>:0:0: ../sysdeps/s390/multiarch/strnlen.c:53:24: error: ‘strnlen’ aliased to undefined symbol ‘__strnlen’ weak_alias (__strnlen, strnlen) ^ ./../include/libc-symbols.h:111:26: note: in definition of macro ‘_weak_alias’ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); ^ ../sysdeps/s390/multiarch/strnlen.c:53:1: note: in expansion of macro ‘weak_alias’ weak_alias (__strnlen, strnlen) ^ make[2]: *** [build/string/strnlen.os] Error 1 I have to redirect the prototypes for __strnlen in string.h and create a copy of the prototype for using as ifunc function: __typeof (__redirect___strnlen) __strnlen __attribute__ ((ifunc ("__resolve_strnlen"))); weak_alias (__strnlen, strnlen) This way there is no trouble with the internal __GI_* symbols. Glibc builds fine with this construct and the debuginfo is "correct". For functions without a __GI_* symbol like memccpy this redirection is not needed. This patch adjusts the common libc_ifunc and libm_ifunc macro to use gcc attribute ifunc. Due to this change, the macro users where the __GI_* symbol does not target the ifunc symbol have to be prepared with the redirection construct. Furthermore a configure check to test gcc support is added. If it is not supported, the old behaviour is used. This patch also prepares the libc_ifunc macro to be useable in s390-ifunc-macro. The s390 ifunc-resolver-functions do have an hwcaps parameter and not all resolvers need the same initialization code. The next patch in this series changes the s390 ifunc macros to use this common one. ChangeLog: * include/libc-symbols.h (__ifunc_resolver): New macro is used by __ifunc* macros. (__ifunc): New macro uses gcc attribute ifunc or inline assembly depending on HAVE_GCC_IFUNC. (libc_ifunc, libm_ifunc): Use __ifunc as base macro. (libc_ifunc_redirected, libc_ifunc_hidden, libm_ifunc_init): New macro. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_finite.c: Redirect ifunced function in header for using as type for ifunc function. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_finitef.c: Likewise. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_isinf.c: Likewise. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_isinff.c: Likewise. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_isnan.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/memcmp.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/memcpy.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/memmove.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/mempcpy.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/memset.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/rawmemchr.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/strchr.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/strlen.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/strncmp.c: Likewise. * sysdeps/powerpc/powerpc32/power4/multiarch/strnlen.c: Likewise. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_finite.c: Likewise. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_finitef.c: Likewise. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isinf.c: Likewise. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isinff.c: Likewise. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnan.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/memcmp.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/mempcpy.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/stpncpy.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strcat.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strchr.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strcmp.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strcpy.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strncmp.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strncpy.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strnlen.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strrchr.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/strstr.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/wcschr.c: Likewise. * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_isnanf.c: Add libc_hidden_def() and use libc_ifunc_hidden() macro instead of libc_ifunc() macro. * sysdeps/powerpc/powerpc64/fpu/multiarch/s_isnanf.c: Likewise. * sysdeps/powerpc/powerpc64/multiarch/stpcpy.c: Likewise.
Diffstat (limited to 'sysdeps/powerpc/powerpc32/power4/multiarch')
10 files changed, 79 insertions, 51 deletions
diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/memcmp.c b/sysdeps/powerpc/powerpc32/power4/multiarch/memcmp.c index c08519c7a1..49d424f6c8 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/memcmp.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/memcmp.c @@ -18,17 +18,19 @@ /* Define multiple versions only for definition in libc. */ #if IS_IN (libc) +# define memcmp __redirect_memcmp # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (memcmp) __memcmp_ppc attribute_hidden; extern __typeof (memcmp) __memcmp_power7 attribute_hidden; +# undef memcmp /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (memcmp, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __memcmp_power7 - : __memcmp_ppc); +libc_ifunc_redirected (__redirect_memcmp, memcmp, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __memcmp_power7 + : __memcmp_ppc); #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/memcpy.c b/sysdeps/powerpc/powerpc32/power4/multiarch/memcpy.c index f379e479a2..1a5da219eb 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/memcpy.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/memcpy.c @@ -20,6 +20,8 @@ DSO. In static binaries we need memcpy before the initialization happened. */ #if defined SHARED && IS_IN (libc) +# undef memcpy +# define memcpy __redirect_memcpy # include <string.h> # include <shlib-compat.h> # include "init-arch.h" @@ -29,17 +31,18 @@ extern __typeof (memcpy) __memcpy_cell attribute_hidden; extern __typeof (memcpy) __memcpy_power6 attribute_hidden; extern __typeof (memcpy) __memcpy_a2 attribute_hidden; extern __typeof (memcpy) __memcpy_power7 attribute_hidden; +# undef memcpy /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (memcpy, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __memcpy_power7 : - (hwcap & PPC_FEATURE_ARCH_2_06) - ? __memcpy_a2 : - (hwcap & PPC_FEATURE_ARCH_2_05) - ? __memcpy_power6 : - (hwcap & PPC_FEATURE_CELL_BE) - ? __memcpy_cell - : __memcpy_ppc); +libc_ifunc_redirected (__redirect_memcpy, memcpy, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __memcpy_power7 + : (hwcap & PPC_FEATURE_ARCH_2_06) + ? __memcpy_a2 + : (hwcap & PPC_FEATURE_ARCH_2_05) + ? __memcpy_power6 + : (hwcap & PPC_FEATURE_CELL_BE) + ? __memcpy_cell + : __memcpy_ppc); #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/memmove.c b/sysdeps/powerpc/powerpc32/power4/multiarch/memmove.c index 417318461b..1dfb5bec0a 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/memmove.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/memmove.c @@ -19,16 +19,18 @@ #if defined SHARED && IS_IN (libc) /* Redefine memmove so that the compiler won't complain about the type mismatch with the IFUNC selector in strong_alias, below. */ +# define memmove __redirect_memmove # include <string.h> # include "init-arch.h" extern __typeof (memmove) __memmove_ppc attribute_hidden; extern __typeof (memmove) __memmove_power7 attribute_hidden; +# undef memmove -libc_ifunc (memmove, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __memmove_power7 - : __memmove_ppc); +libc_ifunc_redirected (__redirect_memmove, memmove, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __memmove_power7 + : __memmove_ppc); #else # include <string/memmove.c> #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/mempcpy.c b/sysdeps/powerpc/powerpc32/power4/multiarch/mempcpy.c index 3c77b5f1bd..3c7c644fe9 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/mempcpy.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/mempcpy.c @@ -17,23 +17,28 @@ <http://www.gnu.org/licenses/>. */ #if IS_IN (libc) +# define mempcpy __redirect_mempcpy +# define __mempcpy __redirect___mempcpy # define NO_MEMPCPY_STPCPY_REDIRECT +/* Omit the mempcpy inline definitions because it would redefine mempcpy. */ +# define _HAVE_STRING_ARCH_mempcpy 1 # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (__mempcpy) __mempcpy_ppc attribute_hidden; extern __typeof (__mempcpy) __mempcpy_power7 attribute_hidden; +# undef mempcpy +# undef __mempcpy /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (__mempcpy, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __mempcpy_power7 - : __mempcpy_ppc); +libc_ifunc_redirected (__redirect___mempcpy, __mempcpy, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __mempcpy_power7 + : __mempcpy_ppc); weak_alias (__mempcpy, mempcpy) -libc_hidden_def (mempcpy) #else # include <string/mempcpy.c> #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/memset.c b/sysdeps/powerpc/powerpc32/power4/multiarch/memset.c index 1d7fc7f2c8..a5c0142dc4 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/memset.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/memset.c @@ -18,6 +18,7 @@ /* Define multiple versions only for definition in libc. */ #if defined SHARED && IS_IN (libc) +# define memset __redirect_memset # include <string.h> # include <shlib-compat.h> # include "init-arch.h" @@ -25,13 +26,14 @@ extern __typeof (memset) __memset_ppc attribute_hidden; extern __typeof (memset) __memset_power6 attribute_hidden; extern __typeof (memset) __memset_power7 attribute_hidden; +# undef memset /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (memset, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __memset_power7 : - (hwcap & PPC_FEATURE_ARCH_2_05) - ? __memset_power6 - : __memset_ppc); +libc_ifunc_redirected (__redirect_memset, memset, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __memset_power7 + : (hwcap & PPC_FEATURE_ARCH_2_05) + ? __memset_power6 + : __memset_ppc); #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/rawmemchr.c b/sysdeps/powerpc/powerpc32/power4/multiarch/rawmemchr.c index f06030eeeb..d72b5df787 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/rawmemchr.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/rawmemchr.c @@ -17,20 +17,21 @@ <http://www.gnu.org/licenses/>. */ #if IS_IN (libc) +# define __rawmemchr __redirect___rawmemchr # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (__rawmemchr) __rawmemchr_ppc attribute_hidden; extern __typeof (__rawmemchr) __rawmemchr_power7 attribute_hidden; +# undef __rawmemchr /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (__rawmemchr, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __rawmemchr_power7 - : __rawmemchr_ppc); - +libc_ifunc_redirected (__redirect___rawmemchr, __rawmemchr, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __rawmemchr_power7 + : __rawmemchr_ppc); weak_alias (__rawmemchr, rawmemchr) #else #include <string/rawmemchr.c> diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/strchr.c b/sysdeps/powerpc/powerpc32/power4/multiarch/strchr.c index 2cfde632cb..c23384f01c 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/strchr.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/strchr.c @@ -18,18 +18,22 @@ /* Define multiple versions only for definition in libc. */ #if defined SHARED && IS_IN (libc) +# define strchr __redirect_strchr +/* Omit the strchr inline definitions because it would redefine strchr. */ +# define __NO_STRING_INLINES # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (strchr) __strchr_ppc attribute_hidden; extern __typeof (strchr) __strchr_power7 attribute_hidden; +# undef strchr /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (strchr, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __strchr_power7 - : __strchr_ppc); +libc_ifunc_redirected (__redirect_strchr, strchr, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __strchr_power7 + : __strchr_ppc); weak_alias (strchr, index) #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/strlen.c b/sysdeps/powerpc/powerpc32/power4/multiarch/strlen.c index af5921a15a..b676b26c15 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/strlen.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/strlen.c @@ -17,15 +17,17 @@ <http://www.gnu.org/licenses/>. */ #if defined SHARED && IS_IN (libc) +# define strlen __redirect_strlen # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (strlen) __strlen_ppc attribute_hidden; extern __typeof (strlen) __strlen_power7 attribute_hidden; +# undef strlen -libc_ifunc (strlen, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __strlen_power7 - : __strlen_ppc); +libc_ifunc_redirected (__redirect_strlen, strlen, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __strlen_power7 + : __strlen_ppc); #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/strncmp.c b/sysdeps/powerpc/powerpc32/power4/multiarch/strncmp.c index 7cc7628091..c384b4c64a 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/strncmp.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/strncmp.c @@ -18,6 +18,9 @@ /* Define multiple versions only for definition in libc. */ #if defined SHARED && IS_IN (libc) +# define strncmp __redirect_strncmp +/* Omit the strncmp inline definitions because it would redefine strncmp. */ +# define __NO_STRING_INLINES # include <string.h> # include <shlib-compat.h> # include "init-arch.h" @@ -25,11 +28,12 @@ extern __typeof (strncmp) __strncmp_ppc attribute_hidden; extern __typeof (strncmp) __strncmp_power4 attribute_hidden; extern __typeof (strncmp) __strncmp_power7 attribute_hidden; +# undef strncmp /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle ifunc symbol properly. */ -libc_ifunc (strncmp, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __strncmp_power7 - : __strncmp_ppc); +libc_ifunc_redirected (__redirect_strncmp, strncmp, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __strncmp_power7 + : __strncmp_ppc); #endif diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/strnlen.c b/sysdeps/powerpc/powerpc32/power4/multiarch/strnlen.c index 8f1e7c9e54..c3681bec46 100644 --- a/sysdeps/powerpc/powerpc32/power4/multiarch/strnlen.c +++ b/sysdeps/powerpc/powerpc32/power4/multiarch/strnlen.c @@ -17,17 +17,20 @@ <http://www.gnu.org/licenses/>. */ #if IS_IN (libc) +# define strnlen __redirect_strnlen +# define __strnlen __redirect___strnlen # include <string.h> # include <shlib-compat.h> # include "init-arch.h" extern __typeof (__strnlen) __strnlen_ppc attribute_hidden; extern __typeof (__strnlen) __strnlen_power7 attribute_hidden; +# undef strnlen +# undef __strnlen -libc_ifunc (__strnlen, - (hwcap & PPC_FEATURE_HAS_VSX) - ? __strnlen_power7 - : __strnlen_ppc); +libc_ifunc_redirected (__redirect___strnlen, __strnlen, + (hwcap & PPC_FEATURE_HAS_VSX) + ? __strnlen_power7 + : __strnlen_ppc); weak_alias (__strnlen, strnlen) -libc_hidden_def (strnlen) #endif |