about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2014-06-20 20:08:03 +0100
committerMaciej W. Rozycki <macro@codesourcery.com>2014-06-20 20:22:42 +0100
commit90e5dd482fc4708d559fbec9740104470ffdb9df (patch)
tree0e1cf5705463c270c44330e0b8b4660004dc55e6 /sysdeps
parent809fdf0d23ddb683eb60672465d7a39d02ef272b (diff)
downloadglibc-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.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/arm/Makefile20
-rw-r--r--sysdeps/arm/configure36
-rw-r--r--sysdeps/arm/configure.ac13
-rw-r--r--sysdeps/arm/dl-machine.h5
-rw-r--r--sysdeps/arm/tst-armtlsdescextlazy.c1
-rw-r--r--sysdeps/arm/tst-armtlsdescextlazymod.c1
-rw-r--r--sysdeps/arm/tst-armtlsdescextnow.c1
-rw-r--r--sysdeps/arm/tst-armtlsdescextnowmod.c1
-rw-r--r--sysdeps/arm/tst-armtlsdescloc.c28
-rw-r--r--sysdeps/arm/tst-armtlsdesclocmod.c44
10 files changed, 149 insertions, 1 deletions
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;
+}