This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH COMMITTED: Fix debug info for TLS variables
- From: Ian Lance Taylor <iant at google dot com>
- To: binutils at sourceware dot org
- Date: Fri, 16 May 2008 14:00:26 -0700
- Subject: PATCH COMMITTED: Fix debug info for TLS variables
gold was generating incorrect debug information for TLS variables.
The debug information for TLS variables uses the same relocation types
as for code. The problem is that in some cases we can optimize the
code relocations, but we must never optimized the debug relocations.
I committed this patch to fix the problem for i386 and x86_64. This
looks at the preceding relocations to see whether it can optimize the
relocations. If there is no relocation to get the address of the TLS
block, then we assume that we are not in a regular code section, and
we should not optimize the relocation.
I don't know whether this problem occurs on SPARC.
I also don't know how to write a good test case for this. It's easy
to see if you run gdb--just try to print the value of a TLS variable
defined in an object which is linked into an executable. Any
suggestions for a way to test for this without running gdb?
Ian
2008-05-16 Ian Lance Taylor <iant@google.com>
* i386.cc (Target_i386::Relocate::relocate_tls): Set dynamic type
for TLS_GOTDESC and TLS_DESC_CALL. Only optimize TLS_LDO_32 if we
know the dynamic type.
* x86_64.cc (Target_x86_64::Relocate): Add saw_tls_block_reloc_
field. Initialize it in constructor.
(Target_x86_64::Relocate::relocate_tls): Record that we saw a TLS
block reloc for TLSGD, GOTPC32_TLSDESC, TLSDESC_CALL, and TLSLD.
Only optimize DTPOFF32 and DTPOFF64 if we have seen a TLS block
reloc.
Index: i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.74
diff -u -p -u -r1.74 i386.cc
--- i386.cc 6 May 2008 05:03:15 -0000 1.74
+++ i386.cc 16 May 2008 20:43:29 -0000
@@ -1843,6 +1843,7 @@ Target_i386::Relocate::relocate_tls(cons
case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_386_TLS_DESC_CALL:
+ this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -1927,7 +1928,8 @@ Target_i386::Relocate::relocate_tls(cons
// This reloc can appear in debugging sections, in which case we
// won't see the TLS_LDM reloc. The local_dynamic_type field
// tells us this.
- if (optimized_type == tls::TLSOPT_TO_LE)
+ if (optimized_type == tls::TLSOPT_TO_LE
+ && this->local_dynamic_type_ != LOCAL_DYNAMIC_NONE)
{
gold_assert(tls_segment != NULL);
value -= tls_segment->memsz();
Index: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.67
diff -u -p -u -r1.67 x86_64.cc
--- x86_64.cc 16 May 2008 15:27:49 -0000 1.67
+++ x86_64.cc 16 May 2008 20:43:29 -0000
@@ -197,7 +197,7 @@ class Target_x86_64 : public Sized_targe
{
public:
Relocate()
- : skip_call_tls_get_addr_(false)
+ : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false)
{ }
~Relocate()
@@ -288,6 +288,12 @@ class Target_x86_64 : public Sized_targe
// This is set if we should skip the next reloc, which should be a
// PLT32 reloc against ___tls_get_addr.
bool skip_call_tls_get_addr_;
+
+ // This is set if we see a relocation which could load the address
+ // of the TLS block. Whether we see such a relocation determines
+ // how we handle the R_X86_64_DTPOFF32 relocation, which is used
+ // in debugging sections.
+ bool saw_tls_block_reloc_;
};
// A class which returns the size required for a relocation type,
@@ -1897,6 +1903,7 @@ Target_x86_64::Relocate::relocate_tls(co
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -1947,6 +1954,7 @@ Target_x86_64::Relocate::relocate_tls(co
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -2000,6 +2008,7 @@ Target_x86_64::Relocate::relocate_tls(co
break;
case elfcpp::R_X86_64_TLSLD: // Local-dynamic
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
@@ -2026,14 +2035,25 @@ Target_x86_64::Relocate::relocate_tls(co
case elfcpp::R_X86_64_DTPOFF32:
gold_assert(tls_segment != NULL);
if (optimized_type == tls::TLSOPT_TO_LE)
- value -= tls_segment->memsz();
+ {
+ // This relocation type is used in debugging information.
+ // In that case we need to not optimize the value. If we
+ // haven't seen a TLSLD reloc, then we assume we should not
+ // optimize this reloc.
+ if (this->saw_tls_block_reloc_)
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela32(view, value, 0);
break;
case elfcpp::R_X86_64_DTPOFF64:
gold_assert(tls_segment != NULL);
if (optimized_type == tls::TLSOPT_TO_LE)
- value -= tls_segment->memsz();
+ {
+ // See R_X86_64_DTPOFF32, just above, for why we test this.
+ if (this->saw_tls_block_reloc_)
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela64(view, value, 0);
break;