This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
i386 and x86_64 TLSDESC relocations to local symbols broken in gold
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Thu, 11 Sep 2008 21:52:47 -0300
- Subject: 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}