#include <ldsodefs.h>
+/* The code checks if _rtld_global_ro was realocated before trying to access
+ the dl_hwcap field. The assembly is to make the compiler not optimize the
+ test (&_rtld_global_ro != NULL), which is always true in ISO C (but not
+ in that case since _rtld_global_ro might not been realocated yet.). */
+#if defined(SHARED) && !defined(IS_IN_rtld)
+# define __GLRO(value) \
+ ({ volatile void **__p = (volatile void**)(&_rtld_global_ro); \
+ unsigned long int __ret; \
+ asm ("# x in %0" : "+r" (__p)); \
+ __ret = (__p) ? GLRO(value) : 0; \
+ __ret; })
+#else
+# define __GLRO(value) GLRO(value)
+#endif
+
# define INIT_ARCH() \
- unsigned long int hwcap = GLRO(dl_hwcap);
+ unsigned long int hwcap = __GLRO(dl_hwcap);
+++ /dev/null
-/* Copyright (C) 2013 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 <sysdep.h>
-#include <rtld-global-offsets.h>
-
-/* Define multiple versions only for the definition in libc. */
-#ifndef NOT_IN_libc
- .text
-ENTRY(__strnlen)
- .type __strnlen, @gnu_indirect_function
-# ifdef PIC
- mflr r6
- cfi_register (lr,r6)
- SETUP_GOT_ACCESS (r5,got_label)
- addis r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@ha
- addi r5,r5,_GLOBAL_OFFSET_TABLE_-got_label@l
- mtlr r6
- cfi_same_value (lr)
-# ifdef SHARED
- lwz r6,_rtld_global_ro@got(r5)
- /* If _rtld_global_ro is not initialized use the default ppc32
- implementation. */
- cmplwi r6,0
- beq L(ppc32)
- lwz r6,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+4(r6)
-# else
- lwz r6,_dl_hwcap@got(r5)
- lwz r6,4(r6)
-# endif
-# else /* PIC */
- lis r6,(_dl_hwcap+4)@ha
- lwz r6,(_dl_hwcap+4)@l(r6)
-# endif
- andi. r7,r6,PPC_FEATURE_HAS_VSX
- bne L(power7)
-L(ppc32):
-# ifdef PIC
- lwz r3,__strnlen_ppc32@got(r5)
-# else
- lis r3,__strnlen_ppc32@ha
- lwz r3,__strnlen_ppc32@l(r3)
-# endif
- blr
-L(power7):
-# ifdef PIC
- lwz r3,__strnlen_power7@got(r5)
-# else
- lis r3,__strnlen_power7@ha
- lwz r3,__strnlen_power7@l(r3)
-# endif
- blr
-END(__strnlen)
-
-weak_alias (__strnlen, strnlen)
-#endif
--- /dev/null
+/* Multiple versions of strnlen.
+ Copyright (C) 2013 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/>. */
+
+#ifndef NOT_IN_libc
+# include <string.h>
+# include <shlib-compat.h>
+# include "init-arch.h"
+
+extern __typeof (__strnlen) __strnlen_ppc32 attribute_hidden;
+extern __typeof (__strnlen) __strnlen_power7 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+ ifunc symbol properly. */
+libc_ifunc (__strnlen,
+ (hwcap & PPC_FEATURE_HAS_VSX)
+ ? __strnlen_power7
+ : __strnlen_ppc32);
+
+weak_alias (__strnlen, strnlen);
+libc_hidden_def (strnlen)
+#endif