]> Git Repo - binutils.git/blobdiff - gold/i386.cc
elfcpp/ChangeLog:
[binutils.git] / gold / i386.cc
index 19728c521d3bca3b6de8922c54a8d3d31eeea65e..b27296769a7dd825332852f2ca296f8e0035d1d1 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 <[email protected]>.
 
 // 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)
   { }
 
@@ -184,12 +185,33 @@ class Target_i386 : public Target_freebsd<32, false>
 
   // Return the size of the GOT section.
   section_size_type
-  got_size()
+  got_size() const
   {
     gold_assert(this->got_ != NULL);
     return this->got_->data_size();
   }
 
+  // Return the number of entries in the GOT.
+  unsigned int
+  got_entry_count() const
+  {
+    if (this->got_ == NULL)
+      return 0;
+    return this->got_size() / 4;
+  }
+
+  // Return the number of entries in the PLT.
+  unsigned int
+  plt_entry_count() const;
+
+  // Return the offset of the first non-reserved PLT entry.
+  unsigned int
+  first_plt_entry_offset() const;
+
+  // Return the size of each PLT entry.
+  unsigned int
+  plt_entry_size() const;
+
  private:
   // The class which scans relocations.
   struct Scan
@@ -385,6 +407,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*);
@@ -432,6 +462,9 @@ class Target_i386 : public Target_freebsd<32, false>
   static const Target::Target_info i386_info;
 
   // The types of GOT entries needed for this platform.
+  // These values are exposed to the ABI in an incremental link.
+  // Do not renumber existing values without changing the version
+  // number of the .gnu_incremental_inputs section.
   enum Got_type
   {
     GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
@@ -447,6 +480,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.
@@ -497,14 +532,14 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout)
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_WRITE),
-                                     this->got_, false, true, true, false);
+                                     this->got_, ORDER_RELRO_LAST, true);
 
       this->got_plt_ = new Output_data_space(4, "** GOT PLT");
       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_WRITE),
-                                     this->got_plt_, false, false, false,
-                                     true);
+                                     this->got_plt_, ORDER_NON_RELRO_FIRST,
+                                     false);
 
       // The first three entries are reserved.
       this->got_plt_->set_current_data_size(3 * 4);
@@ -521,6 +556,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_,
+                                     ORDER_NON_RELRO_FIRST, false);
     }
 
   return this->got_;
@@ -536,8 +580,8 @@ Target_i386::rel_dyn_section(Layout* layout)
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-                                     elfcpp::SHF_ALLOC, this->rel_dyn_, true,
-                                     false, false, false);
+                                     elfcpp::SHF_ALLOC, this->rel_dyn_,
+                                     ORDER_DYNAMIC_RELOCS, false);
     }
   return this->rel_dyn_;
 }
@@ -564,6 +608,21 @@ class Output_data_plt_i386 : public Output_section_data
   Reloc_section*
   rel_tls_desc(Layout*);
 
+  // Return the number of PLT entries.
+  unsigned int
+  entry_count() const
+  { return this->count_; }
+
+  // Return the offset of the first non-reserved PLT entry.
+  static unsigned int
+  first_plt_entry_offset()
+  { return plt_entry_size; }
+
+  // Return the size of a PLT entry.
+  static unsigned int
+  get_plt_entry_size()
+  { return plt_entry_size; }
+
  protected:
   void
   do_adjust_output_section(Output_section* os);
@@ -619,8 +678,8 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-                                 elfcpp::SHF_ALLOC, this->rel_, true,
-                                 false, false, false);
+                                 elfcpp::SHF_ALLOC, this->rel_,
+                                 ORDER_DYNAMIC_PLT_RELOCS, false);
 }
 
 void
@@ -672,7 +731,7 @@ Output_data_plt_i386::rel_tls_desc(Layout* layout)
       this->tls_desc_rel_ = new Reloc_section(false);
       layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
                                      elfcpp::SHF_ALLOC, this->tls_desc_rel_,
-                                     true, false, false, false);
+                                     ORDER_DYNAMIC_PLT_RELOCS, false);
       gold_assert(this->tls_desc_rel_->output_section() ==
                  this->rel_->output_section());
     }
@@ -823,12 +882,38 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym)
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
                                      (elfcpp::SHF_ALLOC
                                       | elfcpp::SHF_EXECINSTR),
-                                     this->plt_, false, false, false, false);
+                                     this->plt_, ORDER_PLT, false);
     }
 
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+unsigned int
+Target_i386::plt_entry_count() const
+{
+  if (this->plt_ == NULL)
+    return 0;
+  return this->plt_->entry_count();
+}
+
+// Return the offset of the first non-reserved PLT entry.
+
+unsigned int
+Target_i386::first_plt_entry_offset() const
+{
+  return Output_data_plt_i386::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+unsigned int
+Target_i386::plt_entry_size() const
+{
+  return Output_data_plt_i386::get_plt_entry_size();
+}
+
 // Get the section to use for TLS_DESC relocations.
 
 Target_i386::Reloc_section*
@@ -1117,9 +1202,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 +1590,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 +2139,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)
            {
This page took 0.029528 seconds and 4 git commands to generate.