* i386.cc (class Target_i386): Add got_tlsdesc_ field.
authorIan Lance Taylor <ian@airs.com>
Mon, 2 Aug 2010 10:07:03 +0000 (10:07 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 2 Aug 2010 10:07:03 +0000 (10:07 +0000)
(Target_i386::Target_i386):: Initialize got_tlsdesc_.
(Target_i386::got_tlsdesc_section): New function.
(Target_i386::got_section): Create space for GOT entries for
TLSDESC relocations.
(Target_i386::Scan::local): Use TLSDESC GOT for unoptimized
R_386_TLS_GOTDESC.
(Target_i386::Scan::global): Likewise.
(Target_i386::Relocate::relocate_tls): Adjust GOT offset when
using TLSDESC GOT.
* x86_64.cc (class Target_x86_64): Add got_tlsdesc_ field.
(Target_x86_64::Target_x86_64):: Initialize got_tlsdesc_.
(Target_x86_64::got_tlsdesc_section): New function.
(Target_x86_64::got_section): Create space for GOT entries for
TLSDESC relocations.
(Target_x86_64::Scan::local): Use TLSDESC GOT for unoptimized
R_386_TLS_GOTDESC.
(Target_x86_64::Scan::global): Likewise.
(Target_x86_64::Relocate::relocate_tls): Adjust GOT offset when
using TLSDESC GOT.

gold/ChangeLog
gold/i386.cc
gold/x86_64.cc

index f0062d5478f9a34912efee4f57dce720f10e7ad8..2a5a2891e7bc81d840d2829aee12225f8a74afa5 100644 (file)
@@ -1,3 +1,26 @@
+2010-08-02  Ian Lance Taylor  <iant@google.com>
+
+       * i386.cc (class Target_i386): Add got_tlsdesc_ field.
+       (Target_i386::Target_i386):: Initialize got_tlsdesc_.
+       (Target_i386::got_tlsdesc_section): New function.
+       (Target_i386::got_section): Create space for GOT entries for
+       TLSDESC relocations.
+       (Target_i386::Scan::local): Use TLSDESC GOT for unoptimized
+       R_386_TLS_GOTDESC.
+       (Target_i386::Scan::global): Likewise.
+       (Target_i386::Relocate::relocate_tls): Adjust GOT offset when
+       using TLSDESC GOT.
+       * x86_64.cc (class Target_x86_64): Add got_tlsdesc_ field.
+       (Target_x86_64::Target_x86_64):: Initialize got_tlsdesc_.
+       (Target_x86_64::got_tlsdesc_section): New function.
+       (Target_x86_64::got_section): Create space for GOT entries for
+       TLSDESC relocations.
+       (Target_x86_64::Scan::local): Use TLSDESC GOT for unoptimized
+       R_386_TLS_GOTDESC.
+       (Target_x86_64::Scan::global): Likewise.
+       (Target_x86_64::Relocate::relocate_tls): Adjust GOT offset when
+       using TLSDESC GOT.
+
 2010-08-02  Ian Lance Taylor  <iant@google.com>
 
        * testsuite/final_layout.sh: Use dc to convert from hex to
index 19728c521d3bca3b6de8922c54a8d3d31eeea65e..ce07588f088a8156ed13340c49aa90e052f153b3 100644 (file)
@@ -1,6 +1,6 @@
 // i386.cc -- i386 target support for gold.
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -59,8 +59,9 @@ class Target_i386 : public Target_freebsd<32, false>
 
   Target_i386()
     : Target_freebsd<32, false>(&i386_info),
-      got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL),
-      rel_dyn_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
+      got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL),
+      global_offset_table_(NULL), rel_dyn_(NULL),
+      copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
   { }
 
@@ -385,6 +386,14 @@ class Target_i386 : public Target_freebsd<32, false>
     return this->got_plt_;
   }
 
+  // Get the GOT section for TLSDESC entries.
+  Output_data_got<32, false>*
+  got_tlsdesc_section() const
+  {
+    gold_assert(this->got_tlsdesc_ != NULL);
+    return this->got_tlsdesc_;
+  }
+
   // Create a PLT entry for a global symbol.
   void
   make_plt_entry(Symbol_table*, Layout*, Symbol*);
@@ -447,6 +456,8 @@ class Target_i386 : public Target_freebsd<32, false>
   Output_data_plt_i386* plt_;
   // The GOT PLT section.
   Output_data_space* got_plt_;
+  // The GOT section for TLSDESC relocations.
+  Output_data_got<32, false>* got_tlsdesc_;
   // The _GLOBAL_OFFSET_TABLE_ symbol.
   Symbol* global_offset_table_;
   // The dynamic reloc section.
@@ -521,6 +532,15 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
                                      elfcpp::STB_LOCAL,
                                      elfcpp::STV_HIDDEN, 0,
                                      false, false);
+
+      // If there are any TLSDESC relocations, they get GOT entries in
+      // .got.plt after the jump slot entries.
+      this->got_tlsdesc_ = new Output_data_got<32, false>();
+      layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+                                     (elfcpp::SHF_ALLOC
+                                      | elfcpp::SHF_WRITE),
+                                     this->got_tlsdesc_, false, false, false,
+                                     true);
     }
 
   return this->got_;
@@ -1117,9 +1137,13 @@ Target_i386::Scan::local(Symbol_table* symtab,
            target->define_tls_base_symbol(symtab, layout);
             if (optimized_type == tls::TLSOPT_NONE)
               {
-                // Create a double GOT entry with an R_386_TLS_DESC reloc.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
+                // Create a double GOT entry with an R_386_TLS_DESC
+                // reloc.  The R_386_TLS_DESC reloc is resolved
+                // lazily, so the GOT entry needs to be in an area in
+                // .got.plt, not .got.  Call got_section to make sure
+                // the section has been created.
+               target->got_section(symtab, layout);
+                Output_data_got<32, false>* got = target->got_tlsdesc_section();
                 unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
                if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
                  {
@@ -1501,9 +1525,13 @@ Target_i386::Scan::global(Symbol_table* symtab,
            target->define_tls_base_symbol(symtab, layout);
             if (optimized_type == tls::TLSOPT_NONE)
               {
-                // Create a double GOT entry with an R_386_TLS_DESC reloc.
-                Output_data_got<32, false>* got
-                    = target->got_section(symtab, layout);
+                // Create a double GOT entry with an R_386_TLS_DESC
+                // reloc.  The R_386_TLS_DESC reloc is resolved
+                // lazily, so the GOT entry needs to be in an area in
+                // .got.plt, not .got.  Call got_section to make sure
+                // the section has been created.
+               target->got_section(symtab, layout);
+                Output_data_got<32, false>* got = target->got_tlsdesc_section();
                Reloc_section* rt = target->rel_tls_desc_section(layout);
                 got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
                                              elfcpp::R_386_TLS_DESC, 0);
@@ -2046,18 +2074,27 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
           unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
                                    ? GOT_TYPE_TLS_NOFFSET
                                    : GOT_TYPE_TLS_DESC);
-          unsigned int got_offset;
+          unsigned int got_offset = 0;
+         if (r_type == elfcpp::R_386_TLS_GOTDESC
+             && optimized_type == tls::TLSOPT_NONE)
+           {
+             // We created GOT entries in the .got.tlsdesc portion of
+             // the .got.plt section, but the offset stored in the
+             // symbol is the offset within .got.tlsdesc.
+             got_offset = (target->got_size()
+                           + target->got_plt_section()->data_size());
+           }
           if (gsym != NULL)
             {
               gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type) - target->got_size();
+              got_offset += gsym->got_offset(got_type) - target->got_size();
             }
           else
             {
               unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
               gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = (object->local_got_offset(r_sym, got_type)
-                           - target->got_size());
+              got_offset += (object->local_got_offset(r_sym, got_type)
+                            - target->got_size());
             }
           if (optimized_type == tls::TLSOPT_TO_IE)
            {
index 2a5cecbf44e1094888d890c7c61fb1df9c15571e..54f07db9701f6550c35e42ec64ee4605815eeae7 100644 (file)
@@ -1,6 +1,6 @@
 // x86_64.cc -- x86_64 target support for gold.
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -64,8 +64,9 @@ class Target_x86_64 : public Target_freebsd<64, false>
 
   Target_x86_64()
     : Target_freebsd<64, false>(&x86_64_info),
-      got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL),
-      rela_dyn_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
+      got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL),
+      global_offset_table_(NULL), rela_dyn_(NULL),
+      copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
       got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
       tls_base_symbol_defined_(false)
   { }
@@ -403,6 +404,14 @@ class Target_x86_64 : public Target_freebsd<64, false>
     return this->got_plt_;
   }
 
+  // Get the GOT section for TLSDESC entries.
+  Output_data_got<64, false>*
+  got_tlsdesc_section() const
+  {
+    gold_assert(this->got_tlsdesc_ != NULL);
+    return this->got_tlsdesc_;
+  }
+
   // Create the PLT section.
   void
   make_plt_section(Symbol_table* symtab, Layout* layout);
@@ -486,6 +495,8 @@ class Target_x86_64 : public Target_freebsd<64, false>
   Output_data_plt_x86_64* plt_;
   // The GOT PLT section.
   Output_data_space* got_plt_;
+  // The GOT section for TLSDESC relocations.
+  Output_data_got<64, false>* got_tlsdesc_;
   // The _GLOBAL_OFFSET_TABLE_ symbol.
   Symbol* global_offset_table_;
   // The dynamic reloc section.
@@ -574,6 +585,15 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
                                      elfcpp::STB_LOCAL,
                                      elfcpp::STV_HIDDEN, 0,
                                      false, false);
+
+      // If there are any TLSDESC relocations, they get GOT entries in
+      // .got.plt after the jump slot entries.
+      this->got_tlsdesc_ = new Output_data_got<64, false>();
+      layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+                                     (elfcpp::SHF_ALLOC
+                                      | elfcpp::SHF_WRITE),
+                                     this->got_tlsdesc_, false, false, false,
+                                     true);
     }
 
   return this->got_;
@@ -1306,9 +1326,13 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
                // Create reserved PLT and GOT entries for the resolver.
                target->reserve_tlsdesc_entries(symtab, layout);
 
-               // Generate a double GOT entry with an R_X86_64_TLSDESC reloc.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
+               // Generate a double GOT entry with an
+               // R_X86_64_TLSDESC reloc.  The R_X86_64_TLSDESC reloc
+               // is resolved lazily, so the GOT entry needs to be in
+               // an area in .got.plt, not .got.  Call got_section to
+               // make sure the section has been created.
+               target->got_section(symtab, layout);
+                Output_data_got<64, false>* got = target->got_tlsdesc_section();
                 unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
                if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
                  {
@@ -1687,9 +1711,13 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
                // Create reserved PLT and GOT entries for the resolver.
                target->reserve_tlsdesc_entries(symtab, layout);
 
-               // Create a double GOT entry with an R_X86_64_TLSDESC reloc.
-                Output_data_got<64, false>* got
-                    = target->got_section(symtab, layout);
+               // Create a double GOT entry with an R_X86_64_TLSDESC
+               // reloc.  The R_X86_64_TLSDESC reloc is resolved
+               // lazily, so the GOT entry needs to be in an area in
+               // .got.plt, not .got.  Call got_section to make sure
+               // the section has been created.
+               target->got_section(symtab, layout);
+                Output_data_got<64, false>* got = target->got_tlsdesc_section();
                Reloc_section *rt = target->rela_tlsdesc_section(layout);
                 got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
                                                elfcpp::R_X86_64_TLSDESC, 0);
@@ -2229,18 +2257,27 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
           unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
                                    ? GOT_TYPE_TLS_OFFSET
                                    : GOT_TYPE_TLS_DESC);
-          unsigned int got_offset;
+          unsigned int got_offset = 0;
+         if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
+             && optimized_type == tls::TLSOPT_NONE)
+           {
+             // We created GOT entries in the .got.tlsdesc portion of
+             // the .got.plt section, but the offset stored in the
+             // symbol is the offset within .got.tlsdesc.
+             got_offset = (target->got_size()
+                           + target->got_plt_section()->data_size());
+           }
           if (gsym != NULL)
             {
               gold_assert(gsym->has_got_offset(got_type));
-              got_offset = gsym->got_offset(got_type) - target->got_size();
+              got_offset += gsym->got_offset(got_type) - target->got_size();
             }
           else
             {
               unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
               gold_assert(object->local_has_got_offset(r_sym, got_type));
-              got_offset = (object->local_got_offset(r_sym, got_type)
-                            - target->got_size());
+              got_offset += (object->local_got_offset(r_sym, got_type)
+                            - target->got_size());
             }
           if (optimized_type == tls::TLSOPT_TO_IE)
             {