This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

i386 and x86_64 TLSDESC relocations to local symbols broken in gold


Hi,

I finally got 'round to investigating how _TLS_MODULE_BASE_ could
possibly be working on gold, since it hadn't been fixed along the
lines of the fix that I installed in bfd on 2008-07-28.  Turns out it
doesn't, and it's even more broken than I'd expected.

I found out it generates bad TLSDESC relocations in dynamic libraries,
referencing local symbols.  The relocations that used to refer to
local symbols are adjusted to refer to .tdata or .tbss symbols, but
this doesn't work: the value of these section symbols is not an offset
into the TLS segment like regular TLS symbols, but rather an absolute
offset within the executable, so the computations are all way off.

BFD generates an *ABS*+<dtpoff> relocation for these cases, as
expected.  I guess I should mention this in the specs...  Ideally,
libc run-time should be able to cope with section symbols, but it
doesn't, and I'm not sure how easy it would be to add this.

Furthermore, symbols that are not at offset zero in their sections are
getting what should have been the addend of the relocation in place at
the GOT entry, rather than in the addend field of the relocation, as
expected for a RELA relocation.  I'm pretty sure this will cause the
addend to be completely disregarded at run-time, even if the other
problems above are fixed.

FTR, all tls*gnu2* testcases in the gold testsuite pass when the
bfd-based linker is used to link them, but tls_shared_gnu2_test fails
because of errors WRT local variables.

Anyhow, here's the patch that fixes the first of the 3 problems.  I'm
not sure when I'm going to be able to get back to the other two;
pretty please beat me to it :-)

for  gold/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* options.h (General_options::output_is_executable): New.
	(General_options::output_is_pie): New.
	* i386.cc (Target_i386::define_tls_base_symbol): Use SEGMENT_START
	for shared libraries.
	* x86_64.cc (Target_x86_64::define_tls_base_symbol): Likewise.

Index: gold/options.h
===================================================================
--- gold/options.h.orig	2008-09-11 21:48:44.000000000 -0300
+++ gold/options.h	2008-09-11 21:49:30.000000000 -0300
@@ -862,6 +862,20 @@ class General_options
   output_is_position_independent() const
   { return this->shared(); }
 
+  // Return true if the output is something that can be exec()ed, such
+  // as a static executable, or a position-dependent or
+  // position-independent executable, but not a dynamic library or an
+  // object file.
+  bool
+  output_is_executable() const
+  { return !this->shared() || this->output_is_pie(); }
+
+  // Return true if the output is a position-independent executable.
+  // This is currently not support.
+  bool
+  output_is_pie() const
+  { return false; }
+
   // This would normally be static(), and defined automatically, but
   // since static is a keyword, we need to come up with our own name.
   bool
Index: gold/i386.cc
===================================================================
--- gold/i386.cc.orig	2008-09-11 21:49:30.000000000 -0300
+++ gold/i386.cc	2008-09-11 21:49:30.000000000 -0300
@@ -747,12 +747,16 @@ Target_i386::define_tls_base_symbol(Symb
   Output_segment* tls_segment = layout->tls_segment();
   if (tls_segment != NULL)
     {
+      bool is_exec = parameters->options().output_is_executable();
       symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL,
 				       tls_segment, 0, 0,
 				       elfcpp::STT_TLS,
 				       elfcpp::STB_LOCAL,
 				       elfcpp::STV_HIDDEN, 0,
-				       Symbol::SEGMENT_END, true);
+				       is_exec
+				       ? Symbol::SEGMENT_END
+				       : Symbol::SEGMENT_START,
+				       true);
     }
   this->tls_base_symbol_defined_ = true;
 }
Index: gold/x86_64.cc
===================================================================
--- gold/x86_64.cc.orig	2008-09-11 21:49:30.000000000 -0300
+++ gold/x86_64.cc	2008-09-11 21:49:30.000000000 -0300
@@ -807,12 +807,16 @@ Target_x86_64::define_tls_base_symbol(Sy
   Output_segment* tls_segment = layout->tls_segment();
   if (tls_segment != NULL)
     {
+      bool is_exec = parameters->options().output_is_executable();
       symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL,
 				       tls_segment, 0, 0,
 				       elfcpp::STT_TLS,
 				       elfcpp::STB_LOCAL,
 				       elfcpp::STV_HIDDEN, 0,
-				       Symbol::SEGMENT_END, true);
+				       is_exec
+				       ? Symbol::SEGMENT_END
+				       : Symbol::SEGMENT_START,
+				       true);
     }
   this->tls_base_symbol_defined_ = true;
 }
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}
FSFLA Board Member       ÂSÃ Libre! => http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}

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