* output.h (Output_data_got::add_global_tls, add_local_tls,
authorAlan Modra <amodra@gmail.com>
Mon, 10 Sep 2012 23:05:54 +0000 (23:05 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 10 Sep 2012 23:05:54 +0000 (23:05 +0000)
add_local_tls_pair): New functions.
(Output_data_got::add_local_pair_with_rel): Remove second
reloc param.  Expand comment.
(Output_data_got::Got_entry): Rename use_plt_offset_ to
use_plt_or_tls_offset_, similarly for constructor param.
(Output_data_got::Got_entry::write): Add got_index param.
* output.cc (Output_data_got::add_global_tls, add_local_tls,
add_local_tls_pair): New functions.
(Output_data_got::Got_entry::write): Handle tls symbols
with use_plt_or_tls_offset_ set specially.
(Output_data_got::add_local_pair_with_rel): Only one reloc.
(Output_data_got::do_write): Replace iterator with index, pass
index to entry write function.
* target.h (Target::tls_offset_for_local, tls_offset_for_global,
do_tls_offset_for_local, do_tls_offset_for_global): New functions.
* arm.cc (Target_arm::Scan::local): Update add_local_pair_with_rel
call.
* i386.cc (Target_i386::Scan::local): Likewise.
* sparc.cc (Target_sparc::Scan::local): Likewise.
* x86_64.cc (Target_x86_64::Scan::local): Likewise.
* powerpc.cc (Target_powerpc::do_tls_offset_for_local,
do_tls_offset_for_global): New functions.
(Target_powerpc::Scan::local): Correct TLS relocations and got
entry values.
(Target_powerpc::Scan::global): Don't emit unnecessary
dynamic relocations on TLS GOT entries.

gold/ChangeLog
gold/arm.cc
gold/i386.cc
gold/output.cc
gold/output.h
gold/powerpc.cc
gold/sparc.cc
gold/target.h
gold/x86_64.cc

index c7488efe88c6cc308d5160e34e294a9440287216..e6ee0d6b3e74a3731d97430141962a26e0f7178a 100644 (file)
@@ -1,3 +1,33 @@
+2012-09-11  Alan Modra  <amodra@gmail.com>
+
+       * output.h (Output_data_got::add_global_tls, add_local_tls,
+       add_local_tls_pair): New functions.
+       (Output_data_got::add_local_pair_with_rel): Remove second
+       reloc param.  Expand comment.
+       (Output_data_got::Got_entry): Rename use_plt_offset_ to
+       use_plt_or_tls_offset_, similarly for constructor param.
+       (Output_data_got::Got_entry::write): Add got_index param.
+       * output.cc (Output_data_got::add_global_tls, add_local_tls,
+       add_local_tls_pair): New functions.
+       (Output_data_got::Got_entry::write): Handle tls symbols
+       with use_plt_or_tls_offset_ set specially.
+       (Output_data_got::add_local_pair_with_rel): Only one reloc.
+       (Output_data_got::do_write): Replace iterator with index, pass
+       index to entry write function.
+       * target.h (Target::tls_offset_for_local, tls_offset_for_global,
+       do_tls_offset_for_local, do_tls_offset_for_global): New functions.
+       * arm.cc (Target_arm::Scan::local): Update add_local_pair_with_rel
+       call.
+       * i386.cc (Target_i386::Scan::local): Likewise.
+       * sparc.cc (Target_sparc::Scan::local): Likewise.
+       * x86_64.cc (Target_x86_64::Scan::local): Likewise.
+       * powerpc.cc (Target_powerpc::do_tls_offset_for_local,
+       do_tls_offset_for_global): New functions.
+       (Target_powerpc::Scan::local): Correct TLS relocations and got
+       entry values.
+       (Target_powerpc::Scan::global): Don't emit unnecessary
+       dynamic relocations on TLS GOT entries.
+
 2012-09-10  Matthias Klose  <doko@ubuntu.com>
 
        * config.in: Disable sanity check for kfreebsd.
index fc7d9811d450a5718d70fa9ac414ae475ea57027..351c6fe1484cd75825399bd9e1520534cc22cd2c 100644 (file)
@@ -8068,7 +8068,7 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
                  got->add_local_pair_with_rel(object, r_sym, shndx,
                                               GOT_TYPE_TLS_PAIR,
                                               target->rel_dyn_section(layout),
-                                              elfcpp::R_ARM_TLS_DTPMOD32, 0);
+                                              elfcpp::R_ARM_TLS_DTPMOD32);
                else
                  got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR,
                                                      object, r_sym);
index b7f16ebd6d359fd83d7e9e6f3c0b830da445d1c7..91611a13396243b5f869ecdc89bd25a26413c155 100644 (file)
@@ -1874,7 +1874,7 @@ Target_i386::Scan::local(Symbol_table* symtab,
                  got->add_local_pair_with_rel(object, r_sym, shndx,
                                               GOT_TYPE_TLS_PAIR,
                                               target->rel_dyn_section(layout),
-                                              elfcpp::R_386_TLS_DTPMOD32, 0);
+                                              elfcpp::R_386_TLS_DTPMOD32);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);
index 664e408bb1e98b8c2ae36897501e1ed2ee02f714..d75579b6152b5e574508cf5de315390ce0773cf6 100644 (file)
@@ -1369,7 +1369,9 @@ Output_data_group<size, big_endian>::do_write(Output_file* of)
 
 template<int size, bool big_endian>
 void
-Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
+Output_data_got<size, big_endian>::Got_entry::write(
+    unsigned int got_indx,
+    unsigned char* pov) const
 {
   Valtype val = 0;
 
@@ -1381,7 +1383,7 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
        // link-time value, which will be relocated dynamically by a
        // RELATIVE relocation.
        Symbol* gsym = this->u_.gsym;
-       if (this->use_plt_offset_ && gsym->has_plt_offset())
+       if (this->use_plt_or_tls_offset_ && gsym->has_plt_offset())
          val = (parameters->target().plt_address_for_global(gsym)
                 + gsym->plt_offset());
        else
@@ -1392,6 +1394,9 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
            // as small as possible.
            sgsym = static_cast<Sized_symbol<size>*>(gsym);
            val = sgsym->value();
+           if (this->use_plt_or_tls_offset_ && gsym->type() == elfcpp::STT_TLS)
+             val += parameters->target().tls_offset_for_global(gsym,
+                                                               got_indx);
          }
       }
       break;
@@ -1409,19 +1414,24 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
 
     default:
       {
-       const Relobj* object = this->u_.object;
+       const Sized_relobj_file<size, big_endian>* object
+         = static_cast<Sized_relobj_file<size, big_endian>*>(this->u_.object);
         const unsigned int lsi = this->local_sym_index_;
-       if (!this->use_plt_offset_)
-         {
-           uint64_t lval = object->local_symbol_value(lsi, 0);
-           val = convert_types<Valtype, uint64_t>(lval);
-         }
-       else
+       bool is_tls = object->local_symbol(lsi)->is_tls_symbol();
+       if (this->use_plt_or_tls_offset_ && !is_tls)
          {
            uint64_t plt_address =
              parameters->target().plt_address_for_local(object, lsi);
            val = plt_address + object->local_plt_offset(lsi);
          }
+       else
+         {
+           uint64_t lval = object->local_symbol_value(lsi, 0);
+           val = convert_types<Valtype, uint64_t>(lval);
+           if (this->use_plt_or_tls_offset_ && is_tls)
+             val += parameters->target().tls_offset_for_local(object, lsi,
+                                                              got_indx);
+         }
       }
       break;
     }
@@ -1566,8 +1576,10 @@ Output_data_got<size, big_endian>::add_local_with_rel(
 }
 
 // Add a pair of entries for a local symbol to the GOT, and add
-// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
-// If R_TYPE_2 == 0, add the second entry with no relocation.
+// a dynamic relocation of type R_TYPE using the section symbol of
+// the output section to which input section SHNDX maps, on the first.
+// The first got entry will have a value of zero, the second the
+// value of the local symbol.
 template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::add_local_pair_with_rel(
@@ -1576,8 +1588,7 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
     unsigned int shndx,
     unsigned int got_type,
     Output_data_reloc_generic* rel_dyn,
-    unsigned int r_type_1,
-    unsigned int r_type_2)
+    unsigned int r_type)
 {
   if (object->local_has_got_offset(symndx, got_type))
     return;
@@ -1587,11 +1598,30 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
                               Got_entry(object, symndx, false));
   object->set_local_got_offset(symndx, got_type, got_offset);
   Output_section* os = object->output_section(shndx);
-  rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
+  rel_dyn->add_output_section_generic(os, r_type, this, got_offset, 0);
+}
 
-  if (r_type_2 != 0)
-    rel_dyn->add_output_section_generic(os, r_type_2, this,
-                                       got_offset + size / 8, 0);
+// Add a pair of entries for a local symbol to the GOT, and add
+// a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
+// The first got entry will have a value of zero, the second the
+// value of the local symbol offset by Target::tls_offset_for_local.
+template<int size, bool big_endian>
+void
+Output_data_got<size, big_endian>::add_local_tls_pair(
+    Relobj* object,
+    unsigned int symndx,
+    unsigned int got_type,
+    Output_data_reloc_generic* rel_dyn,
+    unsigned int r_type)
+{
+  if (object->local_has_got_offset(symndx, got_type))
+    return;
+
+  unsigned int got_offset
+    = this->add_got_entry_pair(Got_entry(),
+                              Got_entry(object, symndx, true));
+  object->set_local_got_offset(symndx, got_type, got_offset);
+  rel_dyn->add_local_generic(object, 0, r_type, this, got_offset, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1634,11 +1664,9 @@ Output_data_got<size, big_endian>::do_write(Output_file* of)
   unsigned char* const oview = of->get_output_view(off, oview_size);
 
   unsigned char* pov = oview;
-  for (typename Got_entries::const_iterator p = this->entries_.begin();
-       p != this->entries_.end();
-       ++p)
+  for (unsigned int i = 0; i < this->entries_.size(); ++i)
     {
-      p->write(pov);
+      this->entries_[i].write(i, pov);
       pov += add;
     }
 
index 14c5aac32ddf5a3206d91db1007e8bfc81ff40f1..d5bcc27ddb5e6c187c45f357e751dcfab470840d 100644 (file)
@@ -2246,6 +2246,12 @@ class Output_data_got : public Output_data_got_base
   bool
   add_global_plt(Symbol* gsym, unsigned int got_type);
 
+  // Like add_global, but for a TLS symbol where the value will be
+  // offset using Target::tls_offset_for_global
+  bool
+  add_global_tls(Symbol* gsym, unsigned int got_type)
+  { return add_global_plt(gsym, got_type); }
+
   // Add an entry for a global symbol to the GOT, and add a dynamic
   // relocation of type R_TYPE for the GOT entry.
   void
@@ -2270,6 +2276,12 @@ class Output_data_got : public Output_data_got_base
   bool
   add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
 
+  // Like add_local, but for a TLS symbol where the value will be
+  // offset using Target::tls_offset_for_local
+  bool
+  add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type)
+  { return add_local_plt(object, sym_index, got_type); }
+
   // Add an entry for a local symbol to the GOT, and add a dynamic
   // relocation of type R_TYPE for the GOT entry.
   void
@@ -2278,12 +2290,25 @@ class Output_data_got : public Output_data_got_base
                     unsigned int r_type);
 
   // Add a pair of entries for a local symbol to the GOT, and add
-  // dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
+  // a dynamic relocation of type R_TYPE using the section symbol of
+  // the output section to which input section SHNDX maps, on the first.
+  // The first got entry will have a value of zero, the second the
+  // value of the local symbol.
   void
   add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
                          unsigned int shndx, unsigned int got_type,
                          Output_data_reloc_generic* rel_dyn,
-                          unsigned int r_type_1, unsigned int r_type_2);
+                          unsigned int r_type);
+
+  // Add a pair of entries for a local symbol to the GOT, and add
+  // a dynamic relocation of type R_TYPE using STN_UNDEF on the first.
+  // The first got entry will have a value of zero, the second the
+  // value of the local symbol offset by Target::tls_offset_for_local.
+  void
+  add_local_tls_pair(Relobj* object, unsigned int sym_index,
+                    unsigned int got_type,
+                    Output_data_reloc_generic* rel_dyn,
+                    unsigned int r_type);
 
   // Add a constant to the GOT.  This returns the offset of the new
   // entry from the start of the GOT.
@@ -2342,18 +2367,20 @@ class Output_data_got : public Output_data_got_base
    public:
     // Create a zero entry.
     Got_entry()
-      : local_sym_index_(RESERVED_CODE), use_plt_offset_(false)
+      : local_sym_index_(RESERVED_CODE), use_plt_or_tls_offset_(false)
     { this->u_.constant = 0; }
 
     // Create a global symbol entry.
-    Got_entry(Symbol* gsym, bool use_plt_offset)
-      : local_sym_index_(GSYM_CODE), use_plt_offset_(use_plt_offset)
+    Got_entry(Symbol* gsym, bool use_plt_or_tls_offset)
+      : local_sym_index_(GSYM_CODE),
+       use_plt_or_tls_offset_(use_plt_or_tls_offset)
     { this->u_.gsym = gsym; }
 
     // Create a local symbol entry.
     Got_entry(Relobj* object, unsigned int local_sym_index,
-             bool use_plt_offset)
-      : local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset)
+             bool use_plt_or_tls_offset)
+      : local_sym_index_(local_sym_index),
+       use_plt_or_tls_offset_(use_plt_or_tls_offset)
     {
       gold_assert(local_sym_index != GSYM_CODE
                  && local_sym_index != CONSTANT_CODE
@@ -2365,12 +2392,12 @@ class Output_data_got : public Output_data_got_base
     // Create a constant entry.  The constant is a host value--it will
     // be swapped, if necessary, when it is written out.
     explicit Got_entry(Valtype constant)
-      : local_sym_index_(CONSTANT_CODE), use_plt_offset_(false)
+      : local_sym_index_(CONSTANT_CODE), use_plt_or_tls_offset_(false)
     { this->u_.constant = constant; }
 
     // Write the GOT entry to an output view.
     void
-    write(unsigned char* pov) const;
+    write(unsigned int got_indx, unsigned char* pov) const;
 
    private:
     enum
@@ -2393,7 +2420,8 @@ class Output_data_got : public Output_data_got_base
     // for a global symbol, or CONSTANT_CODE for a constant.
     unsigned int local_sym_index_ : 31;
     // Whether to use the PLT offset of the symbol if it has one.
-    bool use_plt_offset_ : 1;
+    // For TLS symbols, whether to offset the symbol value.
+    bool use_plt_or_tls_offset_ : 1;
   };
 
   typedef std::vector<Got_entry> Got_entries;
index f9a14cead1e41fe8af5d754fad3d2d06651a556b..31f5ddf752f760a583f03679d2e3ca3416d4ba2e 100644 (file)
@@ -270,6 +270,18 @@ class Target_powerpc : public Sized_target<size, big_endian>
   uint64_t
   do_dynsym_value(const Symbol*) const;
 
+  // Return the offset to use for the GOT_INDX'th got entry which is
+  // for a local tls symbol specified by OBJECT, SYMNDX.
+  int64_t
+  do_tls_offset_for_local(const Relobj* object,
+                         unsigned int symndx,
+                         unsigned int got_indx) const;
+
+  // Return the offset to use for the GOT_INDX'th got entry which is
+  // for global tls symbol GSYM.
+  int64_t
+  do_tls_offset_for_global(Symbol* gsym, unsigned int got_indx) const;
+
   // Relocate a section.
   void
   relocate_section(const Relocate_info<size, big_endian>*,
@@ -2349,7 +2361,7 @@ Target_powerpc<size, big_endian>::Scan::local(
     Output_section* output_section,
     const elfcpp::Rela<size, big_endian>& reloc,
     unsigned int r_type,
-    const elfcpp::Sym<size, big_endian>& lsym)
+    const elfcpp::Sym<size, big_endian>& /* lsym */)
 {
   Powerpc_relobj<size, big_endian>* ppc_object
     = static_cast<Powerpc_relobj<size, big_endian>*>(object);
@@ -2523,16 +2535,9 @@ Target_powerpc<size, big_endian>::Scan::local(
            Output_data_got_powerpc<size, big_endian>* got
              = target->got_section(symtab, layout);
            unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-           unsigned int shndx = lsym.get_st_shndx();
-           bool is_ordinary;
-           shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
-           gold_assert(is_ordinary);
-           got->add_local_pair_with_rel(object, r_sym,
-                                        shndx,
-                                        GOT_TYPE_TLSGD,
-                                        target->rela_dyn_section(layout),
-                                        elfcpp::R_POWERPC_DTPMOD,
-                                        elfcpp::R_POWERPC_DTPREL);
+           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+           got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD,
+                                   rela_dyn, elfcpp::R_POWERPC_DTPMOD);
          }
        else if (tls_type == tls::TLSOPT_TO_LE)
          {
@@ -2574,9 +2579,7 @@ Target_powerpc<size, big_endian>::Scan::local(
        Output_data_got_powerpc<size, big_endian>* got
          = target->got_section(symtab, layout);
        unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-       got->add_local_with_rel(object, r_sym, GOT_TYPE_DTPREL,
-                               target->rela_dyn_section(layout),
-                               elfcpp::R_POWERPC_DTPREL);
+       got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL);
       }
       break;
 
@@ -2591,9 +2594,7 @@ Target_powerpc<size, big_endian>::Scan::local(
            Output_data_got_powerpc<size, big_endian>* got
              = target->got_section(symtab, layout);
            unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
-           got->add_local_with_rel(object, r_sym, GOT_TYPE_TPREL,
-                                   target->rela_dyn_section(layout),
-                                   elfcpp::R_POWERPC_TPREL);
+           got->add_local_tls(object, r_sym, GOT_TYPE_TPREL);
          }
        else if (tls_type == tls::TLSOPT_TO_LE)
          {
@@ -2913,9 +2914,15 @@ Target_powerpc<size, big_endian>::Scan::global(
       {
        Output_data_got_powerpc<size, big_endian>* got
          = target->got_section(symtab, layout);
-       got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
-                                target->rela_dyn_section(layout),
-                                elfcpp::R_POWERPC_DTPREL);
+       if (!gsym->final_value_is_known()
+           && (gsym->is_from_dynobj()
+               || gsym->is_undefined()
+               || gsym->is_preemptible()))
+         got->add_global_with_rel(gsym, GOT_TYPE_DTPREL,
+                                  target->rela_dyn_section(layout),
+                                  elfcpp::R_POWERPC_DTPREL);
+       else
+         got->add_global_tls(gsym, GOT_TYPE_DTPREL);
       }
       break;
 
@@ -2930,9 +2937,15 @@ Target_powerpc<size, big_endian>::Scan::global(
          {
            Output_data_got_powerpc<size, big_endian>* got
              = target->got_section(symtab, layout);
-           got->add_global_with_rel(gsym, GOT_TYPE_TPREL,
-                                    target->rela_dyn_section(layout),
-                                    elfcpp::R_POWERPC_TPREL);
+           if (!gsym->final_value_is_known()
+               && (gsym->is_from_dynobj()
+                   || gsym->is_undefined()
+                   || gsym->is_preemptible()))
+             got->add_global_with_rel(gsym, GOT_TYPE_TPREL,
+                                      target->rela_dyn_section(layout),
+                                      elfcpp::R_POWERPC_TPREL);
+           else
+             got->add_global_tls(gsym, GOT_TYPE_TPREL);
          }
        else if (tls_type == tls::TLSOPT_TO_LE)
          {
@@ -4421,6 +4434,69 @@ Target_powerpc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
     gold_unreachable();
 }
 
+// Return the offset to use for the GOT_INDX'th got entry which is
+// for a local tls symbol specified by OBJECT, SYMNDX.
+template<int size, bool big_endian>
+int64_t
+Target_powerpc<size, big_endian>::do_tls_offset_for_local(
+    const Relobj* object,
+    unsigned int symndx,
+    unsigned int got_indx) const
+{
+  const Powerpc_relobj<size, big_endian>* ppc_object
+    = static_cast<const Powerpc_relobj<size, big_endian>*>(object);
+  if (ppc_object->local_symbol(symndx)->is_tls_symbol())
+    {
+      for (Got_type got_type = GOT_TYPE_TLSGD;
+          got_type <= GOT_TYPE_TPREL;
+          got_type = Got_type(got_type + 1))
+       if (ppc_object->local_has_got_offset(symndx, got_type))
+         {
+           unsigned int off = ppc_object->local_got_offset(symndx, got_type);
+           if (got_type == GOT_TYPE_TLSGD)
+             off += size / 8;
+           if (off == got_indx * (size / 8))
+             {
+               if (got_type == GOT_TYPE_TPREL)
+                 return -tp_offset;
+               else
+                 return -dtp_offset;
+             }
+         }
+    }
+  gold_unreachable();
+}
+
+// Return the offset to use for the GOT_INDX'th got entry which is
+// for global tls symbol GSYM.
+template<int size, bool big_endian>
+int64_t
+Target_powerpc<size, big_endian>::do_tls_offset_for_global(
+    Symbol* gsym,
+    unsigned int got_indx) const
+{
+  if (gsym->type() == elfcpp::STT_TLS)
+    {
+      for (Got_type got_type = GOT_TYPE_TLSGD;
+          got_type <= GOT_TYPE_TPREL;
+          got_type = Got_type(got_type + 1))
+       if (gsym->has_got_offset(got_type))
+         {
+           unsigned int off = gsym->got_offset(got_type);
+           if (got_type == GOT_TYPE_TLSGD)
+             off += size / 8;
+           if (off == got_indx * (size / 8))
+             {
+               if (got_type == GOT_TYPE_TPREL)
+                 return -tp_offset;
+               else
+                 return -dtp_offset;
+             }
+         }
+    }
+  gold_unreachable();
+}
+
 // The selector for powerpc object files.
 
 template<int size, bool big_endian>
index f8c59ec56e2755a997301c32b07ec9ca0b6bc605..04a88bf21bea5939ce1774f50aacda0cf844b3ee 100644 (file)
@@ -2429,8 +2429,7 @@ Target_sparc<size, big_endian>::Scan::local(
                                               target->rela_dyn_section(layout),
                                               (size == 64
                                                ? elfcpp::R_SPARC_TLS_DTPMOD64
-                                               : elfcpp::R_SPARC_TLS_DTPMOD32),
-                                              0);
+                                               : elfcpp::R_SPARC_TLS_DTPMOD32));
                if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
                  generate_tls_call(symtab, layout, target);
              }
index effde151a7ab62eebbbdfaee3bf992839ea41cec..65c15fce028a0f0b679d42d5c254ddb2109b99e7 100644 (file)
@@ -270,6 +270,20 @@ class Target
   plt_address_for_local(const Relobj* object, unsigned int symndx) const
   { return this->do_plt_address_for_local(object, symndx); }
 
+  // Return the offset to use for the GOT_INDX'th got entry which is
+  // for a local tls symbol specified by OBJECT, SYMNDX.
+  int64_t
+  tls_offset_for_local(const Relobj* object,
+                      unsigned int symndx,
+                      unsigned int got_indx) const
+  { return do_tls_offset_for_local(object, symndx, got_indx); }
+
+  // Return the offset to use for the GOT_INDX'th got entry which is
+  // for global tls symbol GSYM.
+  int64_t
+  tls_offset_for_global(Symbol* gsym, unsigned int got_indx) const
+  { return do_tls_offset_for_global(gsym, got_indx); }
+
   // Return whether this target can use relocation types to determine
   // if a function's address is taken.
   bool
@@ -546,6 +560,14 @@ class Target
   do_plt_address_for_local(const Relobj*, unsigned int) const
   { gold_unreachable(); }
 
+  virtual int64_t
+  do_tls_offset_for_local(const Relobj*, unsigned int, unsigned int) const
+  { gold_unreachable(); }
+
+  virtual int64_t
+  do_tls_offset_for_global(Symbol*, unsigned int) const
+  { gold_unreachable(); }
+
   // Virtual function which may be overriden by the child class.
   virtual bool
   do_can_check_for_function_pointers() const
index a15b6ae331144f84b85be820d85ff4deafcda149..1712beb21771a04da6e13018a171f00d29c04721 100644 (file)
@@ -2477,7 +2477,7 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
                                               shndx,
                                               GOT_TYPE_TLS_PAIR,
                                               target->rela_dyn_section(layout),
-                                              elfcpp::R_X86_64_DTPMOD64, 0);
+                                              elfcpp::R_X86_64_DTPMOD64);
              }
            else if (optimized_type != tls::TLSOPT_TO_LE)
              unsupported_reloc_local(object, r_type);