This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

config/tls.m4: Use the general dynamic model for the crossed case


Hello,

 My standard toolchain configuration now has TLS support in binutils and 
GCC, but no such support in glibc (I have reasons for such an odd case).  
With such an arrangement I have noticed the test for TLS support used for 
a few libraries distributed with GCC incorrectly considers it present when 
cross-compiling.  Having studied config/tls.m4 I have noticed it is 
apparently a known shortcoming.

 I have a simple proposal to improve this situation.  The problem with the 
test succeeding is the way TLS references are done for standard 
executables.  For such binaries the so called exec TLS access model is 
used, which builds upon the fact the actual location of the TLS is bound 
to the executable referred to from, and GCC resolves TLS references to a 
local operation referring to a thread pointer register (which, depending 
on the architecture, is either a general register reserved in the ABI for 
this purpose or some allocated data store resource accessed in a "magic" 
way).  This operation does not refer to the system C library and therefore 
a failure to support TLS there cannot be discovered at the link time with 
this model.

 There is also another, more generic, access model, called dynamic, that 
is used for shared libraries which, meant to be shared by many 
executables, cannot locally infer the location of the TLS associated with 
the executable they have been called from.  They have to call an external 
function __tls_get_addr() provided by the system C library.  Therefore, if 
the use of the dynamic model is forced, the absence of support for TLS in 
the system C library may be detected.

 Here is an implementation that I did based on the observation above.  It 
has an assumption GCC is being cross-compiled with GCC and GNU binutils 
and not another compiler and/or set of binary utilities.  I think it is a 
reasonable assumption, but if it is not fulfilled, the worst that happens 
is the dynamic TLS access mode is not forced and the test resorts to the 
current implementation.  The dynamic model is forced by using this set of 
compilation options: -fPIC (for the compiler, typically needed for shared 
objects; it also makes the compile use the dynamic rather than exec TLS 
access model) and "-shared -Wl,-z,defs" (for the linker, to actually 
create a shared object and fail if it is not self-contained symbol-wise).  
The "-shared" option is necessary, because the linker is allowed to make a 
link-time optimisation and convert the dynamic model to the exec model if 
it is known the resulting binary will in the end not be shared.

 However, to make sure all these options are actually supported, a link of 
a trivial program is attempted first and if it fails, the actual test is 
done without these options.

 I have successfully tested this change by building a native 
alpha-linux-gnu compiler on an i386-linux-gnu build machine.  It correctly 
detected the lack of TLS support in the host (the alpha-linux-gnu linker 
does perform the link-time optimisation mentioned above), which is 
currently mishandled.  There are some explanatory notes included within 
the patch itself; not such lengthy ones as the above, but they should be 
enough for the casual reader to know what is going on.

2007-10-16  Maciej W. Rozycki  <macro@linux-mips.org>

	* tls.m4 (GCC_CHECK_TLS): Force the use of the general dynamic
	TLS access model when cross-compiling.

libgomp/:
2007-10-16  Maciej W. Rozycki  <macro@linux-mips.org>

	* configure: Regenerate following changes to ../config/tls.m4.

libjava/:
2007-10-16  Maciej W. Rozycki  <macro@linux-mips.org>

	* configure: Regenerate following changes to ../config/tls.m4.

libmudflap/:
2007-10-16  Maciej W. Rozycki  <macro@linux-mips.org>

	* configure: Regenerate following changes to ../config/tls.m4.

 OK to apply?

  Maciej

gcc-4.3.0-20071011-tls.patch
diff -up --recursive --new-file gcc-4.3.0-20071011.macro/config/tls.m4 gcc-4.3.0-20071011/config/tls.m4
--- gcc-4.3.0-20071011.macro/config/tls.m4	2007-10-12 22:23:59.000000000 +0000
+++ gcc-4.3.0-20071011/config/tls.m4	2007-10-12 22:49:48.000000000 +0000
@@ -63,11 +63,38 @@ AC_DEFUN([GCC_CHECK_TLS], [
 	fi
       fi],
       [gcc_cv_have_tls=no],
-      [dnl This is the cross-compiling case. Assume libc supports TLS if the
+      [dnl This is the cross-compiling case.  Attempt to infer whether the
+       dnl C library supports TLS and failing this assume it does if the
        dnl binutils and the compiler do.
-       AC_LINK_IFELSE([__thread int a; int b; int main() { return a = b; }],
-		      [gcc_cv_have_tls=yes], [gcc_cv_have_tls=no])
-      ]
+      chktls_test_CFLAGS=${CFLAGS+set}
+      chktls_save_CFLAGS=$CFLAGS
+      chktls_test_LDFLAGS=${LDFLAGS+set}
+      chktls_save_LDFLAGS=$LDFLAGS
+      dnl Add -fPIC so that the general dynamic model is used as the
+      dnl compiler may support TLS, but __tls_get_addr() may be absent
+      dnl from the C library if not supported there.
+      CFLAGS="$CFLAGS -fPIC"
+      dnl Similarly, ask the linker to build a shared object and forbid
+      dnl unresolved symbol references.  This is so that the linker
+      dnl does not try to convert the object to the local exec model
+      dnl and the lack of __tls_get_addr() is actually seen.
+      LDFLAGS="$LDFLAGS -shared -Wl,-z,defs"
+      dnl First make sure the options are supported though.
+      AC_LINK_IFELSE([int main() { return 0; }],
+	[],
+	[LDFLAGS=$chktls_save_LDFLAGS; CFLAGS=$chktls_save_CFLAGS])
+      AC_LINK_IFELSE([__thread int a; int b; int main() { return a = b; }],
+		     [gcc_cv_have_tls=yes], [gcc_cv_have_tls=no])
+      if test "$chktls_test_LDFLAGS" = set; then
+        LDFLAGS=$chktls_save_LDFLAGS
+      else
+        unset LDFLAGS
+      fi
+      if test "$chktls_test_CFLAGS" = set; then
+        CFLAGS=$chktls_save_CFLAGS
+      else
+        unset CFLAGS
+      fi]
     )])
   if test "$enable_tls $gcc_cv_have_tls" = "yes yes"; then
     AC_DEFINE(HAVE_TLS, 1,


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]