* i386.cc (class Target_i386::Relocate): Add ldo_addrs_ field.
authorIan Lance Taylor <ian@airs.com>
Tue, 6 Oct 2009 21:36:00 +0000 (21:36 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 6 Oct 2009 21:36:00 +0000 (21:36 +0000)
(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.

gold/ChangeLog
gold/i386.cc

index 48401799e5eb1f6f20869ec5346dfefc13510e92..eab140b161000bd16f46cfa8cb9b70bf8c3cc083 100644 (file)
@@ -1,3 +1,12 @@
+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.
+
 2009-10-06   Rafael Espindola  <espindola@google.com>
 
        * plugin.cc (add_input_library): New.
index 27e1cc91b5ef757c032fe9e4628952604bb7c607..0c4376187445474f79e480179e61080c00ef7b06 100644 (file)
@@ -212,7 +212,7 @@ class Target_i386 : public Target_freebsd<32, false>
    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_freebsd<32, false>
                 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_freebsd<32, false>
     // 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(const Relocate_info<32, false>* relinfo,
 
     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(const Relocate_info<32, false>* relinfo,
                                   "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(const Relocate_info<32, false>* relinfo,
           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(const Relocate_info<32, false>* relinfo,
   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