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 /sysdeps | |
parent | 809fdf0d23ddb683eb60672465d7a39d02ef272b (diff) | |
download | glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.zip glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.tar.gz glibc-90e5dd482fc4708d559fbec9740104470ffdb9df.tar.bz2 |
[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.
Diffstat (limited to 'sysdeps')
-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 |
10 files changed, 149 insertions, 1 deletions
diff --git a/sysdeps/arm/Makefile b/sysdeps/arm/Makefile index daaf4aa..a138048 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 d79ef76..953ef44 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 d66500b..fdc52c0 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 899b256..c5ffc93 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 0000000..36ae999 --- /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 0000000..2cb8f8c --- /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 0000000..36ae999 --- /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 0000000..2cb8f8c --- /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 0000000..730f1ba --- /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 0000000..a2d7eaf --- /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; +} |