Message ID | 1507324554-2612-1-git-send-email-adhemerval.zanella@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | [1/2] arm: Implement memcpy ifunc selection in C | expand |
On Fri, 6 Oct 2017, Adhemerval Zanella wrote: > This patch refactor ARM memcpy ifunc selector to a C implementation. > No functional change is expected, including ifunc resolution rules. > > To avoid build issues with mainline GCC which set no default gnu > indirect function support for ARM (--enable-gnu-indirect-function) > two fixes are added: > > 1. The new macro arm_libc_ifunc_hidden_def is redefined using > direct asm assembly directives instead of function attributes. > This avoid the incompatbile types for a symbol and its alias. > > 2. A new macro NO_MEM_INTERAL_SYM_HACKS is added on symbol-hacks > and defined on arm ifunc objects. It avoids the symbol > definition loop because compiler might emit the hacks for first > fix before the ifunc function definition itself. As a general principle, I don't think we should be checking in workarounds for defects in unreleased GCC versions (this is not specific to this particular issue - it means more generally that if you see a warning building with mainline GCC, you need to consider whether that warning is buggy before applying glibc changes to avoid the warning). That is, we should fix the default in GCC mainline and then propose glibc changes that do not involve such workarounds. (Arguably the default should be to support the attribute for all architectures, to avoid future issues when new architectures gain binutils support for IFUNCs after the GCC 8 release.) -- Joseph S. Myers joseph@codesourcery.com
On 06/10/2017 20:05, Joseph Myers wrote: > On Fri, 6 Oct 2017, Adhemerval Zanella wrote: > >> This patch refactor ARM memcpy ifunc selector to a C implementation. >> No functional change is expected, including ifunc resolution rules. >> >> To avoid build issues with mainline GCC which set no default gnu >> indirect function support for ARM (--enable-gnu-indirect-function) >> two fixes are added: >> >> 1. The new macro arm_libc_ifunc_hidden_def is redefined using >> direct asm assembly directives instead of function attributes. >> This avoid the incompatbile types for a symbol and its alias. >> >> 2. A new macro NO_MEM_INTERAL_SYM_HACKS is added on symbol-hacks >> and defined on arm ifunc objects. It avoids the symbol >> definition loop because compiler might emit the hacks for first >> fix before the ifunc function definition itself. > > As a general principle, I don't think we should be checking in workarounds > for defects in unreleased GCC versions (this is not specific to this > particular issue - it means more generally that if you see a warning > building with mainline GCC, you need to consider whether that warning is > buggy before applying glibc changes to avoid the warning). > > That is, we should fix the default in GCC mainline and then propose glibc > changes that do not involve such workarounds. (Arguably the default > should be to support the attribute for all architectures, to avoid future > issues when new architectures gain binutils support for IFUNCs after the > GCC 8 release.) There are two different issues here: 1. My understanding if for 1. is for gcc mainline we are aiming to *not* support glibc builds support for gnu indirection function (--enable-gnu-indirect-function). I think this is too restrictive and since it is possible to support glibc build whether gcc has it supports should not prevent this specific support on glibc. 2. The 2. is indeed a workaround for mainline issue and I agree we should avoid pushing fixes for this issues on glibc. I will work on it.
> That is, we should fix the default in GCC mainline and then propose glibc > changes that do not involve such workarounds. (Arguably the default > should be to support the attribute for all architectures, to avoid future > issues when new architectures gain binutils support for IFUNCs after the > GCC 8 release.) Is there a patch for this to mainline gcc - my quick searches did not find anything ? I see no reason for not defaulting to this on linux / glibc configurations in mainline gcc taking care not to break things for people who use musl or bionic. We've had ifuncs on aarch32 glibc / binutils for a few years now IIRC so I'm happy to review a patch on gcc-patches if someone can point me at it or propose a patch .... regards Ramana > > -- > Joseph S. Myers > joseph@codesourcery.com
On Mon, 9 Oct 2017, Adhemerval Zanella wrote: > There are two different issues here: > > 1. My understanding if for 1. is for gcc mainline we are aiming to *not* > support glibc builds support for gnu indirection function > (--enable-gnu-indirect-function). I think this is too restrictive and > since it is possible to support glibc build whether gcc has it supports > should not prevent this specific support on glibc. I believe the goal should be to phase out support for multiarch glibc built by compilers without ifunc attribute support for that architecture. (Meaning the configure test for multiarch support would end up requiring the attribute support, say once we require GCC >= 8 to build glibc.) Using the attribute gives better debug info, and we want to avoid having too many arbitrarily different ways to build glibc. -- Joseph S. Myers joseph@codesourcery.com
On Mon, 9 Oct 2017, Ramana Radhakrishnan wrote: > > That is, we should fix the default in GCC mainline and then propose glibc > > changes that do not involve such workarounds. (Arguably the default > > should be to support the attribute for all architectures, to avoid future > > issues when new architectures gain binutils support for IFUNCs after the > > GCC 8 release.) > > Is there a patch for this to mainline gcc - my quick searches did not > find anything ? I see no reason for not defaulting to this on linux / > glibc configurations in mainline gcc taking care not to break things > for people who use musl or bionic. We've had ifuncs on aarch32 glibc / > binutils for a few years now IIRC so I'm happy to review a patch on > gcc-patches if someone can point me at it or propose a patch .... My view is that we should default to having the support in GCC for all architectures with glibc, whether or not binutils/ABI support exists right now, to avoid unnecessarily requiring a GCC update as well as binutils/glibc ones to use it when support is added on a new architecture. But that would be most friendly to users if the assembler then rejects IFUNC creation in the absence of ABI/linker support. -- Joseph S. Myers joseph@codesourcery.com
On 09/10/2017 09:00, Joseph Myers wrote: > On Mon, 9 Oct 2017, Adhemerval Zanella wrote: > >> There are two different issues here: >> >> 1. My understanding if for 1. is for gcc mainline we are aiming to *not* >> support glibc builds support for gnu indirection function >> (--enable-gnu-indirect-function). I think this is too restrictive and >> since it is possible to support glibc build whether gcc has it supports >> should not prevent this specific support on glibc. > > I believe the goal should be to phase out support for multiarch glibc > built by compilers without ifunc attribute support for that architecture. > (Meaning the configure test for multiarch support would end up requiring > the attribute support, say once we require GCC >= 8 to build glibc.) > Using the attribute gives better debug info, and we want to avoid having > too many arbitrarily different ways to build glibc. > I agree with you, but currently glibc build just fail with gcc mainline without ifunc attribute support for such architectures. What about to add a configure test for glibc master to check for such failure on configure (mismatch alias for ifunc resolvers)?
On 09/10/2017 08:59, Ramana Radhakrishnan wrote: >> That is, we should fix the default in GCC mainline and then propose glibc >> changes that do not involve such workarounds. (Arguably the default >> should be to support the attribute for all architectures, to avoid future >> issues when new architectures gain binutils support for IFUNCs after the >> GCC 8 release.) > > Is there a patch for this to mainline gcc - my quick searches did not > find anything ? I see no reason for not defaulting to this on linux / > glibc configurations in mainline gcc taking care not to break things > for people who use musl or bionic. We've had ifuncs on aarch32 glibc / > binutils for a few years now IIRC so I'm happy to review a patch on > gcc-patches if someone can point me at it or propose a patch .... I will on on it, the patch should be simple enough as the one for sparc [1]. [1] https://gcc.gnu.org/ml/gcc-patches/2017-09/msg01779.html
On Mon, 9 Oct 2017, Adhemerval Zanella wrote: > I agree with you, but currently glibc build just fail with gcc mainline > without ifunc attribute support for such architectures. What about to > add a configure test for glibc master to check for such failure on > configure (mismatch alias for ifunc resolvers)? Some such check would be reasonable, once GCC has been changed for ARM. To be clear, with GCC 7 and before it's reasonable to build IFUNCs using the versions of the C macros that get types and debug info wrong. With GCC 8 and later, IFUNCs built in C need to use the ifunc attribute to avoid the errors about types (and we'd like to phase out IFUNCs implemented in assembly). So if you get the error for mismatched types, and don't have ifunc attribute support, that should be considered a case where multiarch support should be disabled by configure, just like if the assembler or linker support are missing. -- Joseph S. Myers joseph@codesourcery.com
On 09/10/2017 09:44, Adhemerval Zanella wrote: > > > On 09/10/2017 08:59, Ramana Radhakrishnan wrote: >>> That is, we should fix the default in GCC mainline and then propose glibc >>> changes that do not involve such workarounds. (Arguably the default >>> should be to support the attribute for all architectures, to avoid future >>> issues when new architectures gain binutils support for IFUNCs after the >>> GCC 8 release.) >> >> Is there a patch for this to mainline gcc - my quick searches did not >> find anything ? I see no reason for not defaulting to this on linux / >> glibc configurations in mainline gcc taking care not to break things >> for people who use musl or bionic. We've had ifuncs on aarch32 glibc / >> binutils for a few years now IIRC so I'm happy to review a patch on >> gcc-patches if someone can point me at it or propose a patch .... > > I will on on it, the patch should be simple enough as the one for > sparc [1]. > > [1] https://gcc.gnu.org/ml/gcc-patches/2017-09/msg01779.html > Patch for ARM sent for review [1]. [1] https://gcc.gnu.org/ml/gcc-patches/2017-10/msg00521.html
diff --git a/sysdeps/arm/arm-ifunc.h b/sysdeps/arm/arm-ifunc.h new file mode 100644 index 0000000..f7d3473 --- /dev/null +++ b/sysdeps/arm/arm-ifunc.h @@ -0,0 +1,47 @@ +/* Common definition for ifunc resolvers. Linux/ARM version. + This file is part of the GNU C Library. + Copyright (C) 2017 Free Software Foundation, Inc. + + 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 <ifunc-init.h> + +#define INIT_ARCH() + +#define arm_libc_ifunc_redirected(redirected_name, name, expr) \ + __ifunc (redirected_name, name, expr(hwcap), int hwcap, INIT_ARCH) + +#if defined SHARED +# ifdef HAVE_GCC_IFUNC +# define arm_libc_ifunc_hidden_def(redirect_name, name) \ + __hidden_ver1 (name, __GI_##name, redirect_name) \ + __attribute__ ((visibility ("hidden"))) +# else +/* GCC 8 without support for ifunc issues an error when trying to + alias symbols with different prototypes (in this case the redirect + one which have the same as the function implementation and the + ifunc resolver). The macro below avoid it by issuing the required + alias directly. */ +# define arm_libc_ifunc_hidden_def(redirect_name, name) \ + _arm_ifunc_hidden_ver (__GI_##name, name) +# define _arm_ifunc_hidden_ver(local, name) \ + asm (".globl " #local ";" \ + ".hidden " #local ";" \ + #local "=" #name) +# endif +#else +# define arm_libc_ifunc_hidden_def(redirect_name, name) +#endif diff --git a/sysdeps/arm/armv7/multiarch/Makefile b/sysdeps/arm/armv7/multiarch/Makefile index 9e1e61c..24c5e5a 100644 --- a/sysdeps/arm/armv7/multiarch/Makefile +++ b/sysdeps/arm/armv7/multiarch/Makefile @@ -1,3 +1,9 @@ ifeq ($(subdir),string) -sysdep_routines += memcpy_neon memcpy_vfp memchr_neon +sysdep_routines += memcpy_neon memcpy_vfp memchr_neon memcpy_arm + +# For ifunc resolvers compiler might place the alias from generic +# symbol-hacks.h before the resolver implementation itself. This +# causes definition loops and the macro below suppress the alias +# definition. +CFLAGS-.os += -DNO_MEM_INTERAL_SYM_HACKS endif diff --git a/sysdeps/arm/armv7/multiarch/ifunc-memcpy.h b/sysdeps/arm/armv7/multiarch/ifunc-memcpy.h new file mode 100644 index 0000000..78cef2a --- /dev/null +++ b/sysdeps/arm/armv7/multiarch/ifunc-memcpy.h @@ -0,0 +1,37 @@ +/* Common definition for memcpy resolver. + Copyright (C) 2017 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/>. */ + +#ifdef __SOFTFP__ +__typeof (REDIRECT_NAME) OPTIMIZE (arm) attribute_hidden; +#endif +__typeof (REDIRECT_NAME) OPTIMIZE (vfp) attribute_hidden; +__typeof (REDIRECT_NAME) OPTIMIZE (neon) attribute_hidden; + +static inline void * +IFUNC_SELECTOR (int hwcap) +{ + if (hwcap & HWCAP_ARM_NEON) + return OPTIMIZE (neon); +#ifdef __SOFTFP__ + if (hwcap & HWCAP_ARM_VFP) + return OPTIMIZE (vfp); + return OPTIMIZE (arm); +#else + return OPTIMIZE (vfp); +#endif +} diff --git a/sysdeps/arm/armv7/multiarch/memcpy.S b/sysdeps/arm/armv7/multiarch/memcpy.S deleted file mode 100644 index 8a53bda..0000000 --- a/sysdeps/arm/armv7/multiarch/memcpy.S +++ /dev/null @@ -1,76 +0,0 @@ -/* Multiple versions of memcpy - All versions must be listed in ifunc-impl-list.c. - Copyright (C) 2013-2017 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/>. */ - -/* Thumb requires excess IT instructions here. */ -#define NO_THUMB -#include <sysdep.h> -#include <rtld-global-offsets.h> - -#if IS_IN (libc) -/* Under __ARM_NEON__, memcpy_neon.S defines the name memcpy. */ -# ifndef __ARM_NEON__ - .text -ENTRY(memcpy) - .type memcpy, %gnu_indirect_function -# ifdef __SOFTFP__ - ldr r1, .Lmemcpy_arm - tst r0, #HWCAP_ARM_VFP - ldrne r1, .Lmemcpy_vfp -# else - ldr r1, .Lmemcpy_vfp -# endif - tst r0, #HWCAP_ARM_NEON - ldrne r1, .Lmemcpy_neon -1: - add r0, r1, pc - DO_RET(lr) - -# ifdef __SOFTFP__ -.Lmemcpy_arm: - .long C_SYMBOL_NAME(__memcpy_arm) - 1b - PC_OFS -# endif -.Lmemcpy_neon: - .long C_SYMBOL_NAME(__memcpy_neon) - 1b - PC_OFS -.Lmemcpy_vfp: - .long C_SYMBOL_NAME(__memcpy_vfp) - 1b - PC_OFS - -END(memcpy) - -libc_hidden_builtin_def (memcpy) -#endif /* Not __ARM_NEON__. */ - -/* These versions of memcpy are defined not to clobber any VFP or NEON - registers so they must always call the ARM variant of the memcpy code. */ -strong_alias (__memcpy_arm, __aeabi_memcpy) -strong_alias (__memcpy_arm, __aeabi_memcpy4) -strong_alias (__memcpy_arm, __aeabi_memcpy8) -libc_hidden_def (__memcpy_arm) - -#undef libc_hidden_builtin_def -#define libc_hidden_builtin_def(name) -#undef weak_alias -#define weak_alias(x, y) -#undef libc_hidden_def -#define libc_hidden_def(name) - -#define memcpy __memcpy_arm - -#endif - -#include "memcpy_impl.S" diff --git a/sysdeps/arm/armv7/multiarch/memcpy.c b/sysdeps/arm/armv7/multiarch/memcpy.c new file mode 100644 index 0000000..7ef6714 --- /dev/null +++ b/sysdeps/arm/armv7/multiarch/memcpy.c @@ -0,0 +1,33 @@ +/* Multiple versions of memcpy. + All versions must be listed in ifunc-impl-list.c. + Copyright (C) 2017 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/>. */ + +#if IS_IN (libc) +# define memcpy __redirect_memcpy +# include <string.h> +# undef memcpy + +# include <arm-ifunc.h> + +# define SYMBOL_NAME memcpy +# include "ifunc-memcpy.h" + +arm_libc_ifunc_redirected (__redirect_memcpy, memcpy, IFUNC_SELECTOR); + +arm_libc_ifunc_hidden_def (__redirect_memcpy, memcpy); +#endif diff --git a/sysdeps/arm/armv7/multiarch/memcpy_arm.S b/sysdeps/arm/armv7/multiarch/memcpy_arm.S new file mode 100644 index 0000000..37565cd --- /dev/null +++ b/sysdeps/arm/armv7/multiarch/memcpy_arm.S @@ -0,0 +1,6 @@ +#define memcpy __memcpy_arm +#include "memcpy_impl.S" + +strong_alias (__memcpy_arm, __aeabi_memcpy) +strong_alias (__memcpy_arm, __aeabi_memcpy4) +strong_alias (__memcpy_arm, __aeabi_memcpy8) diff --git a/sysdeps/arm/armv7/multiarch/rtld-memcpy.S b/sysdeps/arm/armv7/multiarch/rtld-memcpy.S new file mode 100644 index 0000000..0190edc --- /dev/null +++ b/sysdeps/arm/armv7/multiarch/rtld-memcpy.S @@ -0,0 +1 @@ +#include <./sysdeps/arm/armv7/multiarch/memcpy_impl.S> diff --git a/sysdeps/generic/symbol-hacks.h b/sysdeps/generic/symbol-hacks.h index d614c09..589585a 100644 --- a/sysdeps/generic/symbol-hacks.h +++ b/sysdeps/generic/symbol-hacks.h @@ -1,6 +1,7 @@ /* Some compiler optimizations may transform loops into memset/memmove calls and without proper declaration it may generate PLT calls. */ -#if !defined __ASSEMBLER__ && IS_IN (libc) && defined SHARED +#if !defined __ASSEMBLER__ && IS_IN (libc) && defined SHARED \ + && !defined(NO_MEM_INTERAL_SYM_HACKS) asm ("memmove = __GI_memmove"); asm ("memset = __GI_memset"); asm ("memcpy = __GI_memcpy");