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]

gold patch committed: Handle LDO_32 following LDM


On i386, the R_386_TLS_LDO_32 relocation is handled in two different
ways, depending upon whether it is being applied to an instruction or
to debugging information.  Gold makes that determination based on
whether it has seen a R_386_TLS_LDM reloc in the same section.
Unfortunately, in some cases, instruction scheduling can cause the
LDO_32 relocation to precede the LDM relocation.  In that case, gold
will make the wrong decision.

I committed this patch to fix the problem by keeping track of each
LDO_32 relocation processed for the section.  If an LDM relocation is
seen, the linker goes back and adjusts the preceding LDO_32
relocations.

The GNU linker makes this decision based on whether the section is
executable or not.  That information is not readily available for
gold.

Ian


2009-10-06  Ian Lance Taylor  <iant@google.com>

	* i386.cc (class Target_i386::Relocate): Add ldo_addrs_ field.
	(Target_i386::Relocate::relocate_tls): Call fix_up_ldo before
	changing local_dynamic_type_ from LOCAL_DYNAMIC_NONE.  When
	handling R_386_TLS_LDO_32, if local_dynamic_type_ is NONE, push
	the address on ldo_addrs_.
	(Target_i386::Relocate::fix_up_ldo): New function.


Index: i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.89
diff -p -u -r1.89 i386.cc
--- i386.cc	1 Oct 2009 00:58:38 -0000	1.89
+++ i386.cc	6 Oct 2009 21:29:15 -0000
@@ -212,7 +212,7 @@ class Target_i386 : public Target_freebs
    public:
     Relocate()
       : skip_call_tls_get_addr_(false),
-	local_dynamic_type_(LOCAL_DYNAMIC_NONE)
+	local_dynamic_type_(LOCAL_DYNAMIC_NONE), ldo_addrs_()
     { }
 
     ~Relocate()
@@ -307,6 +307,10 @@ class Target_i386 : public Target_freebs
 		 unsigned char* view,
 		 section_size_type view_size);
 
+    // Fix up LDO_32 relocations we've already seen.
+    void
+    fix_up_ldo(const Relocate_info<32, false>*);
+
     // We need to keep track of which type of local dynamic relocation
     // we have seen, so that we can optimize R_386_TLS_LDO_32 correctly.
     enum Local_dynamic_type
@@ -322,6 +326,8 @@ class Target_i386 : public Target_freebs
     // The type of local dynamic relocation we have seen in the section
     // being relocated, if any.
     Local_dynamic_type local_dynamic_type_;
+    // A list of LDO_32 offsets, in case we find LDM after LDO_32.
+    std::vector<unsigned char*> ldo_addrs_;
   };
 
   // A class which returns the size required for a relocation type,
@@ -1922,6 +1928,8 @@ Target_i386::Relocate::relocate_tls(cons
 
     case elfcpp::R_386_TLS_GOTDESC:      // Global-dynamic (from ~oliva url)
     case elfcpp::R_386_TLS_DESC_CALL:
+      if (this->local_dynamic_type_ == LOCAL_DYNAMIC_NONE)
+	this->fix_up_ldo(relinfo);
       this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
       if (optimized_type == tls::TLSOPT_TO_LE)
         {
@@ -1980,6 +1988,8 @@ Target_i386::Relocate::relocate_tls(cons
 				   "TLS relocations"));
 	  break;
 	}
+      else if (this->local_dynamic_type_ == LOCAL_DYNAMIC_NONE)
+	this->fix_up_ldo(relinfo);
       this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
       if (optimized_type == tls::TLSOPT_TO_LE)
 	{
@@ -2013,6 +2023,11 @@ Target_i386::Relocate::relocate_tls(cons
           gold_assert(tls_segment != NULL);
           value -= tls_segment->memsz();
 	}
+      else
+	{
+	  // We may see the LDM later.
+	  this->ldo_addrs_.push_back(view);
+	}
       Relocate_functions<32, false>::rel32(view, value);
       break;
 
@@ -2419,6 +2434,24 @@ Target_i386::Relocate::tls_ie_to_le(cons
   Relocate_functions<32, false>::rel32(view, value);
 }
 
+// If we see an LDM reloc after we handled any LDO_32 relocs, fix up
+// the LDO_32 relocs.
+
+void
+Target_i386::Relocate::fix_up_ldo(const Relocate_info<32, false>* relinfo)
+{
+  if (this->ldo_addrs_.empty())
+    return;
+  Output_segment* tls_segment = relinfo->layout->tls_segment();
+  gold_assert(tls_segment != NULL);
+  elfcpp::Elf_types<32>::Elf_Addr value = - tls_segment->memsz();
+  for (std::vector<unsigned char*>::const_iterator p = this->ldo_addrs_.begin();
+       p != this->ldo_addrs_.end();
+       ++p)
+    Relocate_functions<32, false>::rel32(*p, value);
+  this->ldo_addrs_.clear();
+}
+
 // Relocate section data.
 
 void

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