From patchwork Fri Oct 6 21:15:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 23385 Received: (qmail 12255 invoked by alias); 6 Oct 2017 21:16:07 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 12241 invoked by uid 89); 6 Oct 2017 21:16:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=H*MI:2612 X-HELO: mail-qt0-f177.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=n+TYLXByY86q5jTcC5azLn9RlIZ/oVVyhEaQShuojEo=; b=L2622PLKEy2A6FvGGjHMxoEVogayYJjoBF2avjDit/PVyPz+0Obxj42Oj2qmcluZgs RPV4FdzAN+IZTgR3/rltT8x5HVhFlwzoyDwh2649JRxJc6y6CcpEY+kwuwkCiodOHvf0 WcBPl2o4P53YYCkoOCbgOEu/Mzobeo+Uc8X3Tjc9RmaUReD2oBeL1vCOlqZkfuTKjJE9 s+5aI+stdN8phO28DDAGudBFgpw62mrK81YxRAnUpcBNdOyKLxniVKGdTD6PkW3PoYak mMBAjabk1I9AOBmcl7FlX6TMhyfKEQnP3ZdXCLeUzP4vpJoEpXmpScn2bYN/M25LiANl SlzQ== X-Gm-Message-State: AMCzsaUtrh2dpvod1RgNo6WAaO9oUNYre5NgedGOtfdAxgjuVPXx0rQZ G7qAqnWo/E6XokLoK9QeJrWNCvByDnA= X-Google-Smtp-Source: AOwi7QAiH1Q9r8EEkQILPBvKpx1JAuknOYrcrGBniKZNEoHSTSMQE6mtxSE4GS0Sqkj0BT0u5gh/tA== X-Received: by 10.200.15.83 with SMTP id l19mr4833297qtk.168.1507324561628; Fri, 06 Oct 2017 14:16:01 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 1/2] arm: Implement memcpy ifunc selection in C Date: Fri, 6 Oct 2017 18:15:53 -0300 Message-Id: <1507324554-2612-1-git-send-email-adhemerval.zanella@linaro.org> 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. Checked on armv7-linux-gnueabihf and with a build for arm-linux-gnueabi, arm-linux-gnueabihf with and without multiarch support and with both GCC 7.1 and GCC mainline. * sysdeps/arm/arm-ifunc.h: New file. * sysdeps/arm/armv7/multiarch/ifunc-memcpy.h: Likewise. * sysdeps/arm/armv7/multiarch/memcpy.c: Likewise. * sysdeps/arm/armv7/multiarch/memcpy_arm.S: Likewise. * sysdeps/arm/armv7/multiarch/rtld-memcpy.S: Likewise. * sysdeps/arm/armv7/multiarch/Makefile [$(subdir) = string] (sysdep_routines): Add memcpy_arm. (CFLAGS-.os): New rule. * sysdeps/arm/armv7/multiarch/memcpy.S: Remove file. * sysdeps/generic/symbol-hacks.h: Use mem* alias hacks if not defined NO_MEM_INTERAL_SYM_HACKS. --- ChangeLog | 12 +++++ sysdeps/arm/arm-ifunc.h | 47 ++++++++++++++++++ sysdeps/arm/armv7/multiarch/Makefile | 8 +++- sysdeps/arm/armv7/multiarch/ifunc-memcpy.h | 37 +++++++++++++++ sysdeps/arm/armv7/multiarch/memcpy.S | 76 ------------------------------ sysdeps/arm/armv7/multiarch/memcpy.c | 33 +++++++++++++ sysdeps/arm/armv7/multiarch/memcpy_arm.S | 6 +++ sysdeps/arm/armv7/multiarch/rtld-memcpy.S | 1 + sysdeps/generic/symbol-hacks.h | 3 +- 9 files changed, 145 insertions(+), 78 deletions(-) create mode 100644 sysdeps/arm/arm-ifunc.h create mode 100644 sysdeps/arm/armv7/multiarch/ifunc-memcpy.h delete mode 100644 sysdeps/arm/armv7/multiarch/memcpy.S create mode 100644 sysdeps/arm/armv7/multiarch/memcpy.c create mode 100644 sysdeps/arm/armv7/multiarch/memcpy_arm.S create mode 100644 sysdeps/arm/armv7/multiarch/rtld-memcpy.S 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 + . */ + +#include +#include + +#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 + . */ + +#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 - . */ - -/* Thumb requires excess IT instructions here. */ -#define NO_THUMB -#include -#include - -#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 + . */ + +#if IS_IN (libc) +# define memcpy __redirect_memcpy +# include +# undef memcpy + +# include + +# 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");