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]

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;
 

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