diff options
author | Maciej W. Rozycki <macro@codesourcery.com> | 2014-06-20 20:08:03 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@codesourcery.com> | 2014-06-20 20:22:42 +0100 |
commit | 90e5dd482fc4708d559fbec9740104470ffdb9df (patch) | |
tree | 0e1cf5705463c270c44330e0b8b4660004dc55e6 | |
parent | 809fdf0d23ddb683eb60672465d7a39d02ef272b (diff) | |
download | glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.tar.gz glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.tar.xz glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.zip |
[BZ #17075] ARM: Fix immediate calculation of R_ARM_TLS_DESC
This fixes the calculation of R_ARM_TLS_DESC relocations for lazy global symbol references, i.e. created with `-z lazy' in effect with the static linker, where immediate resolution is requested with LD_BIND_NOW.
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | sysdeps/arm/Makefile | 20 | ||||
-rw-r--r-- | sysdeps/arm/configure | 36 | ||||
-rw-r--r-- | sysdeps/arm/configure.ac | 13 | ||||
-rw-r--r-- | sysdeps/arm/dl-machine.h | 5 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdescextlazy.c | 1 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdescextlazymod.c | 1 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdescextnow.c | 1 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdescextnowmod.c | 1 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdescloc.c | 28 | ||||
-rw-r--r-- | sysdeps/arm/tst-armtlsdesclocmod.c | 44 |
12 files changed, 178 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog index 84f07d2048..fbbd5d2689 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,31 @@ +2014-06-20 Maciej W. Rozycki <macro@codesourcery.com> + + [BZ #17075] + * sysdeps/arm/dl-machine.h (elf_machine_rel) <R_ARM_TLS_DESC>: + Fix calculation of the symbol's value. + * sysdeps/arm/tst-armtlsdescloc.c: New file. + * sysdeps/arm/tst-armtlsdesclocmod.c: New file. + * sysdeps/arm/tst-armtlsdescextnow.c: New file. + * sysdeps/arm/tst-armtlsdescextlazymod.c: New file. + * sysdeps/arm/tst-armtlsdescextlazy.c: New file. + * sysdeps/arm/tst-armtlsdescextnowmod.c: New file. + * sysdeps/arm/Makefile (tests): Add `tst-armtlsdesc', + `tst-armtlsdescextnow' and `tst-armtlsdescextlazy'. + (modules-names): Add `tst-armtlsdescmod', + `tst-armtlsdescextlazymod' and `tst-armtlsdescextnowmod'. + (CPPFLAGS-tst-armtlsdescextnowmod.c): New variable. + (CPPFLAGS-tst-armtlsdescextlazymod.c): Likewise. + (CFLAGS-tst-armtlsdesclocmod.c): Likewise. + (CFLAGS-tst-armtlsdescextnowmod.c): Likewise. + (CFLAGS-tst-armtlsdescextlazymod.c): Likewise. + (LDFLAGS-tst-armtlsdescextnowmod.so): Likewise. + ($(objpfx)tst-armtlsdescloc): New dependency. + ($(objpfx)tst-armtlsdescextnow): Likewise. + ($(objpfx)tst-armtlsdescextlazy): Likewise. + * sysdeps/arm/configure.ac: Add a check for tools' GNU descriptor + TLS scheme support. + * sysdeps/arm/configure: Regenerate. + 2014-06-20 Joseph Myers <joseph@codesourcery.com> * include/fcntl.h (__atfct_seterrno): Remove prototype. diff --git a/NEWS b/NEWS index 9c2ba43ab4..170aed2edb 100644 --- a/NEWS +++ b/NEWS @@ -20,7 +20,7 @@ Version 2.20 16854, 16876, 16877, 16878, 16882, 16885, 16888, 16890, 16912, 16915, 16916, 16917, 16922, 16927, 16928, 16932, 16943, 16958, 16965, 16966, 16967, 16977, 16978, 16984, 16990, 16996, 17009, 17022, 17031, 17042, - 17048, 17058, 17062, 17069. + 17048, 17058, 17062, 17069, 17075. * Optimized strchr implementation for AArch64. Contributed by ARM Ltd. diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile index daaf4aa922..a1380487b1 100644 --- a/sysdeps/arm/Makefile +++ b/sysdeps/arm/Makefile @@ -11,6 +11,26 @@ $(objpfx)libgcc-stubs.a: $(objpfx)aeabi_unwind_cpp_pr1.os $(build-extra-lib) lib-noranlib: $(objpfx)libgcc-stubs.a + +ifeq ($(build-shared),yes) +ifeq ($(have-arm-tls-desc),yes) +tests += tst-armtlsdescloc tst-armtlsdescextnow tst-armtlsdescextlazy +modules-names += tst-armtlsdesclocmod +modules-names += tst-armtlsdescextlazymod tst-armtlsdescextnowmod +CPPFLAGS-tst-armtlsdescextnowmod.c += -Dstatic= +CPPFLAGS-tst-armtlsdescextlazymod.c += -Dstatic= +CFLAGS-tst-armtlsdesclocmod.c += -mtls-dialect=gnu2 +CFLAGS-tst-armtlsdescextnowmod.c += -mtls-dialect=gnu2 +CFLAGS-tst-armtlsdescextlazymod.c += -mtls-dialect=gnu2 +LDFLAGS-tst-armtlsdescextnowmod.so += -Wl,-z,now +tst-armtlsdescloc-ENV = LD_BIND_NOW=1 +tst-armtlsdescextnow-ENV = LD_BIND_NOW=1 +tst-armtlsdescextlazy-ENV = LD_BIND_NOW=1 +$(objpfx)tst-armtlsdescloc: $(objpfx)tst-armtlsdesclocmod.so +$(objpfx)tst-armtlsdescextnow: $(objpfx)tst-armtlsdescextnowmod.so +$(objpfx)tst-armtlsdescextlazy: $(objpfx)tst-armtlsdescextlazymod.so +endif +endif endif ifeq ($(subdir),csu) diff --git a/sysdeps/arm/configure b/sysdeps/arm/configure index d79ef76ec9..953ef4406d 100644 --- a/sysdeps/arm/configure +++ b/sysdeps/arm/configure @@ -203,3 +203,39 @@ else config_vars="$config_vars default-abi = soft" fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the build tools support the GNU descriptor TLS scheme" >&5 +$as_echo_n "checking whether the build tools support the GNU descriptor TLS scheme... " >&6; } +if ${libc_cv_arm_tls_desc+:} false; then : + $as_echo_n "(cached) " >&6 +else + old_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -mtls-dialect=gnu2" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +asm (".word\tfoo(tlsdesc)"); +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libc_cv_arm_tls_desc=yes +else + libc_cv_arm_tls_desc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$old_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_arm_tls_desc" >&5 +$as_echo "$libc_cv_arm_tls_desc" >&6; } +if test $libc_cv_arm_tls_desc = yes; then + config_vars="$config_vars +have-arm-tls-desc = yes" +else + config_vars="$config_vars +have-arm-tls-desc = no" +fi diff --git a/sysdeps/arm/configure.ac b/sysdeps/arm/configure.ac index d66500b3fd..fdc52c0408 100644 --- a/sysdeps/arm/configure.ac +++ b/sysdeps/arm/configure.ac @@ -44,3 +44,16 @@ if test $libc_cv_arm_pcs_vfp = yes; then else LIBC_CONFIG_VAR([default-abi], [soft]) fi + +AC_CACHE_CHECK([whether the build tools support the GNU descriptor TLS scheme], + [libc_cv_arm_tls_desc], + [old_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -mtls-dialect=gnu2" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([asm (".word\tfoo(tlsdesc)");], [])], + [libc_cv_arm_tls_desc=yes], [libc_cv_arm_tls_desc=no]) + CFLAGS="$old_CFLAGS"]) +if test $libc_cv_arm_tls_desc = yes; then + LIBC_CONFIG_VAR([have-arm-tls-desc], [yes]) +else + LIBC_CONFIG_VAR([have-arm-tls-desc], [no]) +fi diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index 899b2568f3..c5ffc9304c 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -452,7 +452,10 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, else # endif { - value = sym->st_value + td->argument.value; + if (ELF32_R_SYM (reloc->r_info) == STN_UNDEF) + value = td->argument.value; + else + value = sym->st_value; # ifndef RTLD_BOOTSTRAP # ifndef SHARED diff --git a/sysdeps/arm/tst-armtlsdescextlazy.c b/sysdeps/arm/tst-armtlsdescextlazy.c new file mode 100644 index 0000000000..36ae9994f7 --- /dev/null +++ b/sysdeps/arm/tst-armtlsdescextlazy.c @@ -0,0 +1 @@ +#include "tst-armtlsdescloc.c" diff --git a/sysdeps/arm/tst-armtlsdescextlazymod.c b/sysdeps/arm/tst-armtlsdescextlazymod.c new file mode 100644 index 0000000000..2cb8f8c853 --- /dev/null +++ b/sysdeps/arm/tst-armtlsdescextlazymod.c @@ -0,0 +1 @@ +#include "tst-armtlsdesclocmod.c" diff --git a/sysdeps/arm/tst-armtlsdescextnow.c b/sysdeps/arm/tst-armtlsdescextnow.c new file mode 100644 index 0000000000..36ae9994f7 --- /dev/null +++ b/sysdeps/arm/tst-armtlsdescextnow.c @@ -0,0 +1 @@ +#include "tst-armtlsdescloc.c" diff --git a/sysdeps/arm/tst-armtlsdescextnowmod.c b/sysdeps/arm/tst-armtlsdescextnowmod.c new file mode 100644 index 0000000000..2cb8f8c853 --- /dev/null +++ b/sysdeps/arm/tst-armtlsdescextnowmod.c @@ -0,0 +1 @@ +#include "tst-armtlsdesclocmod.c" diff --git a/sysdeps/arm/tst-armtlsdescloc.c b/sysdeps/arm/tst-armtlsdescloc.c new file mode 100644 index 0000000000..730f1ba442 --- /dev/null +++ b/sysdeps/arm/tst-armtlsdescloc.c @@ -0,0 +1,28 @@ +/* ARM immediate binding GNU TLS descriptor relocation test. + Copyright (C) 2014 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/>. */ + +int getfoo (void); + +int +do_test (void) +{ + return getfoo (); +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/arm/tst-armtlsdesclocmod.c b/sysdeps/arm/tst-armtlsdesclocmod.c new file mode 100644 index 0000000000..a2d7eaf96e --- /dev/null +++ b/sysdeps/arm/tst-armtlsdesclocmod.c @@ -0,0 +1,44 @@ +/* DSO used for ARM immediate binding GNU TLS descriptor relocation test. + Copyright (C) 2014 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/>. */ + +static int __thread bar = 1; +static int __thread foo; + +int +getfoo (void) +{ + return foo; +} + +void +setfoo (int i) +{ + foo = 1; +} + +int +getbar (void) +{ + return bar; +} + +void +setbar (int i) +{ + bar = 1; +} |