elfcpp/ChangeLog:
authorCary Coutant <ccoutant@google.com>
Thu, 12 Aug 2010 22:15:00 +0000 (22:15 +0000)
committerCary Coutant <ccoutant@google.com>
Thu, 12 Aug 2010 22:15:00 +0000 (22:15 +0000)
* elfcpp.h (enum SHT): Add SHT_GNU_INCREMENTAL_GOT_PLT.

gold/ChangeLog:

* arm.cc (Target_arm::got_size): Add const.
(Target_arm::got_entry_count): New function.
(Target_arm::plt_entry_count): New function.
(Target_arm::first_plt_entry_offset): New function.
(Target_arm::plt_entry_size): New function.
(Output_data_plt_arm::entry_count): New function.
(Output_data_plt_arm::first_plt_entry_offset): New function.
(Output_data_plt_arm::get_plt_entry_size): New function.
* i386.cc (Target_i386::got_size): Add const.
(Target_i386::got_entry_count): New function.
(Target_i386::plt_entry_count): New function.
(Target_i386::first_plt_entry_offset): New function.
(Target_i386::plt_entry_size): New function.
(Output_data_plt_i386::entry_count): New function.
(Output_data_plt_i386::first_plt_entry_offset): New function.
(Output_data_plt_i386::get_plt_entry_size): New function.
* incremental-dump.cc (dump_incremental_inputs): Adjust call to
find_incremental_inputs_sections.  Dump incremental_got_plt section.
* incremental.cc: Include target.h.
(Sized_incremental_binary::do_find_incremental_inputs_sections): Add
parameter.  Adjust all callers.  Find incremental_got_plt section.
(Incremental_inputs::create_data_sections): Create incremental_got_plt
section.
(Output_section_incremental_inputs::set_final_data_size): Calculate
size of incremental_got_plt section.
(Output_section_incremental_inputs::do_write): Write the
incremental_got_plt section.
(Got_plt_view_info): New struct.
(Local_got_offset_visitor): New class.
(Global_got_offset_visitor): New class.
(Global_symbol_visitor_got_plt): New class.
(Output_section_incremental_inputs::write_got_plt): New function.
* incremental.h (Incremental_binary::find_incremental_inputs_sections):
Add parameter.  Adjust all callers.
(Incremental_binary::do_find_incremental_inputs_sections): Likewise.
(Incremental_inputs::got_plt_section): New function.
(Incremental_inputs::got_plt_section_): New data member.
(Incremental_got_plt_reader): New class.
* layout.cc (Layout::create_incremental_info_sections): Add the
incremental_got_plt section.
* object.h (Got_offset_list::get_list): New function.
(Got offset_list::for_all_got_offsets): New function.
(Sized_relobj::local_got_offset_list): New function.
* powerpc.cc (Target_powerpc::got_size): Add const.
(Target_powerpc::got_entry_count): New function.
(Target_powerpc::plt_entry_count): New function.
(Target_powerpc::first_plt_entry_offset): New function.
(Target_powerpc::plt_entry_size): New function.
(Output_data_plt_powerpc::entry_count): New function.
(Output_data_plt_powerpc::first_plt_entry_offset): New function.
(Output_data_plt_powerpc::get_plt_entry_size): New function.
* sparc.cc (Target_sparc::got_size): Add const.
(Target_sparc::got_entry_count): New function.
(Target_sparc::plt_entry_count): New function.
(Target_sparc::first_plt_entry_offset): New function.
(Target_sparc::plt_entry_size): New function.
(Output_data_plt_sparc::entry_count): New function.
(Output_data_plt_sparc::first_plt_entry_offset): New function.
(Output_data_plt_sparc::get_plt_entry_size): New function.
* symtab.h (Symbol::got_offset_list): New function.
(Symbol_table::for_all_symbols): New function.
* target.h (Sized_target::got_entry_count): New function.
(Sized_target::plt_entry_count): New function.
(Sized_target::plt_entry_size): New function.
* x86_64.cc (Target_x86_64::got_size): Add const.
(Target_x86_64::got_entry_count): New function.
(Target_x86_64::plt_entry_count): New function.
(Target_x86_64::first_plt_entry_offset): New function.
(Target_x86_64::plt_entry_size): New function.
(Output_data_plt_x86_64::entry_count): New function.
(Output_data_plt_x86_64::first_plt_entry_offset): New function.
(Output_data_plt_x86_64::get_plt_entry_size): New function.

13 files changed:
gold/ChangeLog
gold/arm.cc
gold/i386.cc
gold/incremental-dump.cc
gold/incremental.cc
gold/incremental.h
gold/layout.cc
gold/object.h
gold/powerpc.cc
gold/sparc.cc
gold/symtab.h
gold/target.h
gold/x86_64.cc

index c77f2d7cc1bc38d330795d3063545bd417b521ae..47814f02511ce27d26613992a1854d794b32a9bb 100644 (file)
@@ -1,3 +1,78 @@
+2010-08-12  Cary Coutant  <ccoutant@google.com>
+
+       * arm.cc (Target_arm::got_size): Add const.
+       (Target_arm::got_entry_count): New function.
+       (Target_arm::plt_entry_count): New function.
+       (Target_arm::first_plt_entry_offset): New function.
+       (Target_arm::plt_entry_size): New function.
+       (Output_data_plt_arm::entry_count): New function.
+       (Output_data_plt_arm::first_plt_entry_offset): New function.
+       (Output_data_plt_arm::get_plt_entry_size): New function.
+       * i386.cc (Target_i386::got_size): Add const.
+       (Target_i386::got_entry_count): New function.
+       (Target_i386::plt_entry_count): New function.
+       (Target_i386::first_plt_entry_offset): New function.
+       (Target_i386::plt_entry_size): New function.
+       (Output_data_plt_i386::entry_count): New function.
+       (Output_data_plt_i386::first_plt_entry_offset): New function.
+       (Output_data_plt_i386::get_plt_entry_size): New function.
+       * incremental-dump.cc (dump_incremental_inputs): Adjust call to
+       find_incremental_inputs_sections.  Dump incremental_got_plt section.
+       * incremental.cc: Include target.h.
+       (Sized_incremental_binary::do_find_incremental_inputs_sections): Add
+       parameter.  Adjust all callers.  Find incremental_got_plt section.
+       (Incremental_inputs::create_data_sections): Create incremental_got_plt
+       section.
+       (Output_section_incremental_inputs::set_final_data_size): Calculate
+       size of incremental_got_plt section.
+       (Output_section_incremental_inputs::do_write): Write the
+       incremental_got_plt section.
+       (Got_plt_view_info): New struct.
+       (Local_got_offset_visitor): New class.
+       (Global_got_offset_visitor): New class.
+       (Global_symbol_visitor_got_plt): New class.
+       (Output_section_incremental_inputs::write_got_plt): New function.
+       * incremental.h (Incremental_binary::find_incremental_inputs_sections):
+       Add parameter.  Adjust all callers.
+       (Incremental_binary::do_find_incremental_inputs_sections): Likewise.
+       (Incremental_inputs::got_plt_section): New function.
+       (Incremental_inputs::got_plt_section_): New data member.
+       (Incremental_got_plt_reader): New class.
+       * layout.cc (Layout::create_incremental_info_sections): Add the
+       incremental_got_plt section.
+       * object.h (Got_offset_list::get_list): New function.
+       (Got offset_list::for_all_got_offsets): New function.
+       (Sized_relobj::local_got_offset_list): New function.
+       * powerpc.cc (Target_powerpc::got_size): Add const.
+       (Target_powerpc::got_entry_count): New function.
+       (Target_powerpc::plt_entry_count): New function.
+       (Target_powerpc::first_plt_entry_offset): New function.
+       (Target_powerpc::plt_entry_size): New function.
+       (Output_data_plt_powerpc::entry_count): New function.
+       (Output_data_plt_powerpc::first_plt_entry_offset): New function.
+       (Output_data_plt_powerpc::get_plt_entry_size): New function.
+       * sparc.cc (Target_sparc::got_size): Add const.
+       (Target_sparc::got_entry_count): New function.
+       (Target_sparc::plt_entry_count): New function.
+       (Target_sparc::first_plt_entry_offset): New function.
+       (Target_sparc::plt_entry_size): New function.
+       (Output_data_plt_sparc::entry_count): New function.
+       (Output_data_plt_sparc::first_plt_entry_offset): New function.
+       (Output_data_plt_sparc::get_plt_entry_size): New function.
+       * symtab.h (Symbol::got_offset_list): New function.
+       (Symbol_table::for_all_symbols): New function.
+       * target.h (Sized_target::got_entry_count): New function.
+       (Sized_target::plt_entry_count): New function.
+       (Sized_target::plt_entry_size): New function.
+       * x86_64.cc (Target_x86_64::got_size): Add const.
+       (Target_x86_64::got_entry_count): New function.
+       (Target_x86_64::plt_entry_count): New function.
+       (Target_x86_64::first_plt_entry_offset): New function.
+       (Target_x86_64::plt_entry_size): New function.
+       (Output_data_plt_x86_64::entry_count): New function.
+       (Output_data_plt_x86_64::first_plt_entry_offset): New function.
+       (Output_data_plt_x86_64::get_plt_entry_size): New function.
+
 2010-08-12  Cary Coutant  <ccoutant@google.com>
 
        * archive.cc: Include incremental.h.
index 51ce38c2ddc33f002238658c1ed17b1bba3d3206..123f896e9d33c7451fe6c15088a1a669264d7090 100644 (file)
@@ -2342,12 +2342,33 @@ class Target_arm : public Sized_target<32, big_endian>
 
   // 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->has_got_section())
+      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;
+
   // Map platform-specific reloc types
   static unsigned int
   get_real_reloc_type (unsigned int r_type);
@@ -2816,6 +2837,9 @@ class Target_arm : public Sized_target<32, big_endian>
   static const Target::Target_info arm_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
@@ -7111,6 +7135,21 @@ class Output_data_plt_arm : public Output_section_data
   rel_plt() const
   { return this->rel_; }
 
+  // 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 sizeof(first_plt_entry); }
+
+  // Return the size of a PLT entry.
+  static unsigned int
+  get_plt_entry_size()
+  { return sizeof(plt_entry); }
+
  protected:
   void
   do_adjust_output_section(Output_section* os);
@@ -7326,6 +7365,35 @@ Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout,
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+template<bool big_endian>
+unsigned int
+Target_arm<big_endian>::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.
+
+template<bool big_endian>
+unsigned int
+Target_arm<big_endian>::first_plt_entry_offset() const
+{
+  return Output_data_plt_arm<big_endian>::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<bool big_endian>
+unsigned int
+Target_arm<big_endian>::plt_entry_size() const
+{
+  return Output_data_plt_arm<big_endian>::get_plt_entry_size();
+}
+
 // Get the section to use for TLS_DESC relocations.
 
 template<bool big_endian>
index b4040c198cd769c6aa7ed04a2604e99418400ce2..b27296769a7dd825332852f2ca296f8e0035d1d1 100644 (file)
@@ -185,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
@@ -441,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
@@ -584,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);
@@ -849,6 +888,32 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym)
   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*
index 98555cdb14622a9c77c17888f90a5ac6effa3e14..68fba5ca1e1b24288c5257fcc6682907f2202b3c 100644 (file)
@@ -79,6 +79,7 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   unsigned int inputs_shndx;
   unsigned int isymtab_shndx;
   unsigned int irelocs_shndx;
+  unsigned int igot_plt_shndx;
   unsigned int istrtab_shndx;
   typedef Incremental_binary::Location Location;
   typedef Incremental_binary::View View;
@@ -88,7 +89,8 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   // Find the .gnu_incremental_inputs, _symtab, _relocs, and _strtab sections.
 
   t = inc->find_incremental_inputs_sections(&inputs_shndx, &isymtab_shndx,
-                                           &irelocs_shndx, &istrtab_shndx);
+                                           &irelocs_shndx, &igot_plt_shndx,
+                                           &istrtab_shndx);
   if (!t)
     {
       fprintf(stderr, "%s: %s: no .gnu_incremental_inputs section\n", argv0,
@@ -134,9 +136,7 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   printf("\nInput files:\n");
   for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
     {
-      typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
-      typename Inputs_reader::Incremental_input_entry_reader input_file =
-         incremental_inputs.input_file(i);
+      Entry_reader input_file = incremental_inputs.input_file(i);
 
       const char* objname = input_file.filename();
       if (objname == NULL)
@@ -203,10 +203,6 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   printf("\nInput sections:\n");
   for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
     {
-      typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
-      typedef typename Inputs_reader::Incremental_input_entry_reader
-          Entry_reader;
-
       Entry_reader input_file(incremental_inputs.input_file(i));
 
       if (input_file.type() != INCREMENTAL_INPUT_OBJECT
@@ -241,10 +237,6 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   printf("\nGlobal symbols per input file:\n");
   for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
     {
-      typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
-      typedef typename Inputs_reader::Incremental_input_entry_reader
-          Entry_reader;
-
       Entry_reader input_file(incremental_inputs.input_file(i));
 
       if (input_file.type() != INCREMENTAL_INPUT_OBJECT
@@ -374,6 +366,54 @@ dump_incremental_inputs(const char* argv0, const char* filename,
       isym_p += 4;
     }
 
+  // Get a view of the .gnu_incremental_got_plt section.
+
+  Location igot_plt_location(elf_file.section_contents(igot_plt_shndx));
+  View igot_plt_view(inc->view(igot_plt_location));
+
+  Incremental_got_plt_reader<big_endian> igot_plt(igot_plt_view.data());
+  unsigned int ngot = igot_plt.get_got_entry_count();
+  unsigned int nplt = igot_plt.get_plt_entry_count();
+  
+  printf("\nGOT entries:\n");
+  for (unsigned int i = 0; i < ngot; ++i)
+    {
+      unsigned int got_type = igot_plt.get_got_type(i);
+      unsigned int got_desc = igot_plt.get_got_desc(i);
+      printf("[%d] type %02x, ", i, got_type & 0x7f);
+      if (got_type == 0x7f)
+       printf("reserved");
+      else if (got_type & 0x80)
+       {
+         Entry_reader input_file = incremental_inputs.input_file(got_desc);
+         const char* objname = input_file.filename();
+         printf("local: %s (%d)", objname, got_desc);
+       }
+      else
+       {
+         sym_p = symtab_view.data() + got_desc * sym_size;
+         elfcpp::Sym<size, big_endian> sym(sym_p);
+         const char* symname;
+         if (!strtab.get_c_string(sym.get_st_name(), &symname))
+           symname = "<unknown>";
+         printf("global %s (%d)", symname, got_desc);
+       }
+      printf("\n");
+    }
+
+  printf("\nPLT entries:\n");
+  for (unsigned int i = 0; i < nplt; ++i)
+    {
+      unsigned int plt_desc = igot_plt.get_plt_desc(i);
+      printf("[%d] ", i);
+      sym_p = symtab_view.data() + plt_desc * sym_size;
+      elfcpp::Sym<size, big_endian> sym(sym_p);
+      const char* symname;
+      if (!strtab.get_c_string(sym.get_st_name(), &symname))
+       symname = "<unknown>";
+      printf("%s (%d)\n", symname, plt_desc);
+    }
+
   printf("\nUnused archive symbols:\n");
   for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
     {
index b279c72ead39fba5cd1570c52e9359a953b2d03b..b2ec781d896dd8fd59593604fe01da22df6438f1 100644 (file)
@@ -32,6 +32,7 @@
 #include "archive.h"
 #include "output.h"
 #include "target-select.h"
+#include "target.h"
 
 namespace gold {
 
@@ -88,6 +89,10 @@ class Output_section_incremental_inputs : public Output_section_data
   write_symtab(unsigned char* pov, unsigned int* global_syms,
               unsigned int global_sym_count);
 
+  // Write the contents of the .gnu_incremental_got_plt section.
+  void
+  write_got_plt(unsigned char* pov, off_t view_size);
+
   // Typedefs for writing the data to the output sections.
   typedef elfcpp::Swap<size, big_endian> Swap;
   typedef elfcpp::Swap<16, big_endian> Swap16;
@@ -153,6 +158,7 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
     unsigned int* p_inputs_shndx,
     unsigned int* p_symtab_shndx,
     unsigned int* p_relocs_shndx,
+    unsigned int* p_got_plt_shndx,
     unsigned int* p_strtab_shndx)
 {
   unsigned int inputs_shndx =
@@ -174,6 +180,13 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
   if (this->elf_file_.section_link(relocs_shndx) != inputs_shndx)
     return false;
 
+  unsigned int got_plt_shndx =
+      this->elf_file_.find_section_by_type(elfcpp::SHT_GNU_INCREMENTAL_GOT_PLT);
+  if (got_plt_shndx == elfcpp::SHN_UNDEF)  // Not found.
+    return false;
+  if (this->elf_file_.section_link(got_plt_shndx) != inputs_shndx)
+    return false;
+
   unsigned int strtab_shndx = this->elf_file_.section_link(inputs_shndx);
   if (strtab_shndx == elfcpp::SHN_UNDEF
       || strtab_shndx > this->elf_file_.shnum()
@@ -186,6 +199,8 @@ Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_sections(
     *p_symtab_shndx = symtab_shndx;
   if (p_relocs_shndx != NULL)
     *p_relocs_shndx = relocs_shndx;
+  if (p_got_plt_shndx != NULL)
+    *p_got_plt_shndx = got_plt_shndx;
   if (p_strtab_shndx != NULL)
     *p_strtab_shndx = strtab_shndx;
   return true;
@@ -202,10 +217,12 @@ Sized_incremental_binary<size, big_endian>::do_check_inputs(
   unsigned int inputs_shndx;
   unsigned int symtab_shndx;
   unsigned int relocs_shndx;
+  unsigned int plt_got_shndx;
   unsigned int strtab_shndx;
 
   if (!do_find_incremental_inputs_sections(&inputs_shndx, &symtab_shndx,
-                                          &relocs_shndx, &strtab_shndx))
+                                          &relocs_shndx, &plt_got_shndx,
+                                          &strtab_shndx))
     {
       explain_no_incremental(_("no incremental data from previous build"));
       return false;
@@ -555,6 +572,7 @@ Incremental_inputs::create_data_sections(Symbol_table* symtab)
     }
   this->symtab_section_ = new Output_data_space(4, "** incremental_symtab");
   this->relocs_section_ = new Output_data_space(4, "** incremental_relocs");
+  this->got_plt_section_ = new Output_data_space(4, "** incremental_got_plt");
 }
 
 // Return the sh_entsize value for the .gnu_incremental_relocs section.
@@ -657,6 +675,16 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
   // Set the size of the .gnu_incremental_relocs section.
   inputs->relocs_section()->set_current_data_size(inputs->get_reloc_count()
                                                  * rel_size);
+
+  // Set the size of the .gnu_incremental_got_plt section.
+  Sized_target<size, big_endian>* target =
+    parameters->sized_target<size, big_endian>();
+  unsigned int got_count = target->got_entry_count();
+  unsigned int plt_count = target->plt_entry_count();
+  unsigned int got_plt_size = 8;  // GOT entry count, PLT entry count.
+  got_plt_size = (got_plt_size + got_count + 3) & ~3;  // GOT type array.
+  got_plt_size += got_count * 4 + plt_count * 4;  // GOT array, PLT array.
+  inputs->got_plt_section()->set_current_data_size(got_plt_size);
 }
 
 // Write the contents of the .gnu_incremental_inputs and
@@ -711,8 +739,16 @@ Output_section_incremental_inputs<size, big_endian>::do_write(Output_file* of)
 
   delete[] global_syms;
 
+  // Write the .gnu_incremental_got_plt section.
+  const off_t got_plt_off = inputs->got_plt_section()->offset();
+  const off_t got_plt_size = inputs->got_plt_section()->data_size();
+  unsigned char* const got_plt_view = of->get_output_view(got_plt_off,
+                                                         got_plt_size);
+  this->write_got_plt(got_plt_view, got_plt_size);
+
   of->write_output_view(off, oview_size, oview);
   of->write_output_view(symtab_off, symtab_size, symtab_view);
+  of->write_output_view(got_plt_off, got_plt_size, got_plt_view);
 }
 
 // Write the section header: version, input file count, offset of command line
@@ -936,6 +972,195 @@ Output_section_incremental_inputs<size, big_endian>::write_symtab(
     }
 }
 
+// This struct holds the view information needed to write the
+// .gnu_incremental_got_plt section.
+
+struct Got_plt_view_info
+{
+  // Start of the GOT type array in the output view.
+  unsigned char* got_type_p;
+  // Start of the GOT descriptor array in the output view.
+  unsigned char* got_desc_p;
+  // Start of the PLT descriptor array in the output view.
+  unsigned char* plt_desc_p;
+  // Number of GOT entries.
+  unsigned int got_count;
+  // Number of PLT entries.
+  unsigned int plt_count;
+  // Offset of the first non-reserved PLT entry (this is a target-dependent value).
+  unsigned int first_plt_entry_offset;
+  // Size of a PLT entry (this is a target-dependent value).
+  unsigned int plt_entry_size;
+  // Value to write in the GOT descriptor array.  For global symbols,
+  // this is the global symbol table index; for local symbols, it is
+  // the offset of the input file entry in the .gnu_incremental_inputs
+  // section.
+  unsigned int got_descriptor;
+};
+
+// Functor class for processing a GOT offset list for local symbols.
+// Writes the GOT type and symbol index into the GOT type and descriptor
+// arrays in the output section.
+
+template<int size, bool big_endian>
+class Local_got_offset_visitor
+{
+ public:
+  Local_got_offset_visitor(struct Got_plt_view_info& info)
+    : info_(info)
+  { }
+
+  void
+  operator()(unsigned int got_type, unsigned int got_offset)
+  {
+    unsigned int got_index = got_offset / this->got_entry_size_;
+    gold_assert(got_index < this->info_.got_count);
+    // We can only handle GOT entry types in the range 0..0x7e
+    // because we use a byte array to store them, and we use the
+    // high bit to flag a local symbol.
+    gold_assert(got_type < 0x7f);
+    this->info_.got_type_p[got_index] = got_type | 0x80;
+    unsigned char* pov = this->info_.got_desc_p + got_index * 4;
+    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.got_descriptor);
+  }
+
+ private:
+  static const unsigned int got_entry_size_ = size / 8;
+  struct Got_plt_view_info& info_;
+};
+
+// Functor class for processing a GOT offset list.  Writes the GOT type
+// and symbol index into the GOT type and descriptor arrays in the output
+// section.
+
+template<int size, bool big_endian>
+class Global_got_offset_visitor
+{
+ public:
+  Global_got_offset_visitor(struct Got_plt_view_info& info)
+    : info_(info)
+  { }
+
+  void
+  operator()(unsigned int got_type, unsigned int got_offset)
+  {
+    unsigned int got_index = got_offset / this->got_entry_size_;
+    gold_assert(got_index < this->info_.got_count);
+    // We can only handle GOT entry types in the range 0..0x7e
+    // because we use a byte array to store them, and we use the
+    // high bit to flag a local symbol.
+    gold_assert(got_type < 0x7f);
+    this->info_.got_type_p[got_index] = got_type;
+    unsigned char* pov = this->info_.got_desc_p + got_index * 4;
+    elfcpp::Swap<32, big_endian>::writeval(pov, this->info_.got_descriptor);
+  }
+
+ private:
+  static const unsigned int got_entry_size_ = size / 8;
+  struct Got_plt_view_info& info_;
+};
+
+// Functor class for processing the global symbol table.  Processes the
+// GOT offset list for the symbol, and writes the symbol table index
+// into the PLT descriptor array in the output section.
+
+template<int size, bool big_endian>
+class Global_symbol_visitor_got_plt
+{
+ public:
+  Global_symbol_visitor_got_plt(struct Got_plt_view_info& info)
+    : info_(info)
+  { }
+
+  void
+  operator()(const Sized_symbol<size>* sym)
+  {
+    typedef Global_got_offset_visitor<size, big_endian> Got_visitor;
+    const Got_offset_list* got_offsets = sym->got_offset_list();
+    if (got_offsets != NULL)
+      {
+        info_.got_descriptor = sym->symtab_index();
+       got_offsets->for_all_got_offsets(Got_visitor(info_));
+      }
+    if (sym->has_plt_offset())
+      {
+       unsigned int plt_index =
+           ((sym->plt_offset() - this->info_.first_plt_entry_offset)
+            / this->info_.plt_entry_size);
+       gold_assert(plt_index < this->info_.plt_count);
+       unsigned char* pov = this->info_.plt_desc_p + plt_index * 4;
+       elfcpp::Swap<32, big_endian>::writeval(pov, sym->symtab_index());
+      }
+  }
+
+ private:
+  struct Got_plt_view_info& info_;
+};
+
+// Write the contents of the .gnu_incremental_got_plt section.
+
+template<int size, bool big_endian>
+void
+Output_section_incremental_inputs<size, big_endian>::write_got_plt(
+    unsigned char* pov,
+    off_t view_size)
+{
+  Sized_target<size, big_endian>* target =
+    parameters->sized_target<size, big_endian>();
+
+  // Set up the view information for the functors.
+  struct Got_plt_view_info view_info;
+  view_info.got_count = target->got_entry_count();
+  view_info.plt_count = target->plt_entry_count();
+  view_info.first_plt_entry_offset = target->first_plt_entry_offset();
+  view_info.plt_entry_size = target->plt_entry_size();
+  view_info.got_type_p = pov + 8;
+  view_info.got_desc_p = (view_info.got_type_p
+                         + ((view_info.got_count + 3) & ~3));
+  view_info.plt_desc_p = view_info.got_desc_p + view_info.got_count * 4;
+
+  gold_assert(pov + view_size ==
+             view_info.plt_desc_p + view_info.plt_count * 4);
+
+  // Write the section header.
+  Swap32::writeval(pov, view_info.got_count);
+  Swap32::writeval(pov + 4, view_info.plt_count);
+
+  // Initialize the GOT type array to 0xff (reserved).
+  memset(view_info.got_type_p, 0xff, view_info.got_count);
+
+  // Write the incremental GOT descriptors for local symbols.
+  for (Incremental_inputs::Input_list::const_iterator p =
+          this->inputs_->input_files().begin();
+       p != this->inputs_->input_files().end();
+       ++p)
+    {
+      if ((*p)->type() != INCREMENTAL_INPUT_OBJECT
+         && (*p)->type() != INCREMENTAL_INPUT_ARCHIVE_MEMBER)
+       continue;
+      Incremental_object_entry* entry = (*p)->object_entry();
+      gold_assert(entry != NULL);
+      const Sized_relobj<size, big_endian>* obj =
+          static_cast<Sized_relobj<size, big_endian>*>(entry->object());
+      gold_assert(obj != NULL);
+      unsigned int nsyms = obj->local_symbol_count();
+      for (unsigned int i = 0; i < nsyms; i++)
+        {
+          const Got_offset_list* got_offsets = obj->local_got_offset_list(i);
+          if (got_offsets != NULL)
+            {
+             typedef Local_got_offset_visitor<size, big_endian> Got_visitor;
+             view_info.got_descriptor = (*p)->get_offset();
+             got_offsets->for_all_got_offsets(Got_visitor(view_info));
+           }
+       }
+    }
+
+  // Write the incremental GOT and PLT descriptors for global symbols.
+  typedef Global_symbol_visitor_got_plt<size, big_endian> Symbol_visitor;
+  symtab_->for_all_symbols<size, Symbol_visitor>(Symbol_visitor(view_info));
+}
+
 // Instantiate the templates we need.
 
 #ifdef HAVE_TARGET_32_LITTLE
index 6fb1a324e74ec91e99ccd41ef13061dd2ae0b569..c1f3c990894cbd06d02a737a10bc1f7c4f399b54 100644 (file)
@@ -131,10 +131,12 @@ class Incremental_binary
   find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
                                   unsigned int* p_symtab_shndx,
                                   unsigned int* p_relocs_shndx,
+                                  unsigned int* p_got_plt_shndx,
                                   unsigned int* p_strtab_shndx)
   {
     return do_find_incremental_inputs_sections(p_inputs_shndx, p_symtab_shndx,
-                                              p_relocs_shndx, p_strtab_shndx);
+                                              p_relocs_shndx, p_got_plt_shndx,
+                                              p_strtab_shndx);
   }
 
   // Check the .gnu_incremental_inputs section to see whether an incremental
@@ -153,6 +155,7 @@ class Incremental_binary
   do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
                                      unsigned int* p_symtab_shndx,
                                      unsigned int* p_relocs_shndx,
+                                     unsigned int* p_got_plt_shndx,
                                      unsigned int* p_strtab_shndx) = 0;
 
   // Check the .gnu_incremental_inputs section to see whether an incremental
@@ -182,6 +185,7 @@ class Sized_incremental_binary : public Incremental_binary
   do_find_incremental_inputs_sections(unsigned int* p_inputs_shndx,
                                      unsigned int* p_symtab_shndx,
                                      unsigned int* p_relocs_shndx,
+                                     unsigned int* p_got_plt_shndx,
                                      unsigned int* p_strtab_shndx);
 
   virtual bool
@@ -577,6 +581,11 @@ class Incremental_inputs
   relocs_section() const
   { return this->relocs_section_; }
 
+  // Return the .gnu_incremental_got_plt section.
+  Output_data_space*
+  got_plt_section() const
+  { return this->got_plt_section_; }
+
   // Return the .gnu_incremental_strtab stringpool.
   Stringpool*
   get_stringpool() const
@@ -635,6 +644,9 @@ class Incremental_inputs
   // The .gnu_incremental_relocs section.
   Output_data_space* relocs_section_;
 
+  // The .gnu_incremental_got_plt section.
+  Output_data_space* got_plt_section_;
+
   // Total count of incremental relocations.  Updated during Scan_relocs
   // phase at the completion of each object file.
   unsigned int reloc_count_;
@@ -889,7 +901,7 @@ class Incremental_symtab_reader
   { }
 
   // Return the list head for symbol table entry N.
-  unsigned int get_list_head(unsigned int n)
+  unsigned int get_list_head(unsigned int n) const
   { return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4 * n); }
 
  private:
@@ -918,28 +930,28 @@ class Incremental_relocs_reader
 
   // Return the relocation type for relocation entry at offset OFF.
   unsigned int
-  get_r_type(unsigned int off)
+  get_r_type(unsigned int off) const
   {
     return elfcpp::Swap<32, big_endian>::readval(this->p_ + off);
   }
 
   // Return the output section index for relocation entry at offset OFF.
   unsigned int
-  get_r_shndx(unsigned int off)
+  get_r_shndx(unsigned int off) const
   {
     return elfcpp::Swap<32, big_endian>::readval(this->p_ + off + 4);
   }
 
   // Return the output section offset for relocation entry at offset OFF.
   Address
-  get_r_offset(unsigned int off)
+  get_r_offset(unsigned int off) const
   {
     return elfcpp::Swap<size, big_endian>::readval(this->p_ + off + 8);
   }
 
   // Return the addend for relocation entry at offset OFF.
   Addend
-  get_r_addend(unsigned int off)
+  get_r_addend(unsigned int off) const
   {
     return elfcpp::Swap<size, big_endian>::readval(this->p_ + off + 8
                                                   + this->field_size);
@@ -950,6 +962,65 @@ class Incremental_relocs_reader
   const unsigned char* p_;
 };
 
+// Reader class for the .gnu_incremental_got_plt section.
+
+template<bool big_endian>
+class Incremental_got_plt_reader
+{
+ public:
+  Incremental_got_plt_reader(const unsigned char* p) : p_(p)
+  {
+    this->got_count_ = elfcpp::Swap<32, big_endian>::readval(p);
+    this->got_desc_p_ = p + 8 + ((this->got_count_ + 3) & ~3);
+    this->plt_desc_p_ = this->got_desc_p_ + this->got_count_ * 4;
+  }
+
+  // Return the GOT entry count.
+  unsigned int
+  get_got_entry_count() const
+  {
+    return this->got_count_;
+  }
+
+  // Return the PLT entry count.
+  unsigned int
+  get_plt_entry_count() const
+  {
+    return elfcpp::Swap<32, big_endian>::readval(this->p_ + 4);
+  }
+
+  // Return the GOT type for GOT entry N.
+  unsigned int
+  get_got_type(unsigned int n)
+  {
+    return this->p_[8 + n];
+  }
+
+  // Return the GOT descriptor for GOT entry N.
+  unsigned int
+  get_got_desc(unsigned int n)
+  {
+    return elfcpp::Swap<32, big_endian>::readval(this->got_desc_p_ + n * 4);
+  }
+
+  // Return the PLT descriptor for PLT entry N.
+  unsigned int
+  get_plt_desc(unsigned int n)
+  {
+    return elfcpp::Swap<32, big_endian>::readval(this->plt_desc_p_ + n * 4);
+  }
+
+ private:
+  // Base address of the .gnu_incremental_got_plt section.
+  const unsigned char* p_;
+  // GOT entry count.
+  unsigned int got_count_;
+  // Base address of the GOT descriptor array.
+  const unsigned char* got_desc_p_;
+  // Base address of the PLT descriptor array.
+  const unsigned char* plt_desc_p_;
+};
+
 } // End namespace gold.
 
 #endif // !defined(GOLD_INCREMENTAL_H)
index eb1322ae6affdfd82cb38ecdcdf6349ad9436ce0..1dd41f3df28f4aa0e8cba54d0b34a81c7ed9a30d 100644 (file)
@@ -2342,6 +2342,15 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
   incremental_relocs_os->add_output_section_data(incr->relocs_section());
   incremental_relocs_os->set_entsize(incr->relocs_entsize());
 
+  // Add the .gnu_incremental_got_plt section.
+  const char *incremental_got_plt_name =
+    this->namepool_.add(".gnu_incremental_got_plt", false, NULL);
+  Output_section* incremental_got_plt_os =
+    this->make_output_section(incremental_got_plt_name,
+                             elfcpp::SHT_GNU_INCREMENTAL_GOT_PLT, 0,
+                             ORDER_INVALID, false);
+  incremental_got_plt_os->add_output_section_data(incr->got_plt_section());
+
   // Add the .gnu_incremental_strtab section.
   const char *incremental_strtab_name =
     this->namepool_.add(".gnu_incremental_strtab", false, NULL);
@@ -2355,10 +2364,12 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
   incremental_inputs_os->set_after_input_sections();
   incremental_symtab_os->set_after_input_sections();
   incremental_relocs_os->set_after_input_sections();
+  incremental_got_plt_os->set_after_input_sections();
 
   incremental_inputs_os->set_link_section(incremental_strtab_os);
   incremental_symtab_os->set_link_section(incremental_inputs_os);
   incremental_relocs_os->set_link_section(incremental_inputs_os);
+  incremental_got_plt_os->set_link_section(incremental_inputs_os);
 }
 
 // Return whether SEG1 should be before SEG2 in the output file.  This
index 99ceabfb448734ffbfbaf31faa45eb164d89babf..94ad64312e1a78b27876983bb11d6da8e806af74 100644 (file)
@@ -1479,6 +1479,26 @@ class Got_offset_list
     return -1U;
   }
 
+  // Return a pointer to the list, or NULL if the list is empty.
+  const Got_offset_list*
+  get_list() const
+  {
+    if (this->got_type_ == -1U)
+      return NULL;
+    return this;
+  }
+
+  // Loop over all GOT offset entries, applying the function F to each.
+  template<typename F>
+  void
+  for_all_got_offsets(F f) const
+  {
+    if (this->got_type_ == -1U)
+      return;
+    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+      f(g->got_type_, g->got_offset_);
+  }
+
  private:
   unsigned int got_type_;
   unsigned int got_offset_;
@@ -1661,6 +1681,17 @@ class Sized_relobj : public Relobj
       }
   }
 
+  // Return the GOT offset list for the local symbol SYMNDX.
+  const Got_offset_list*
+  local_got_offset_list(unsigned int symndx) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    if (p == this->local_got_offsets_.end())
+      return NULL;
+    return p->second;
+  }
+
   // Get the offset of input section SHNDX within its output section.
   // This is -1 if the input section requires a special mapping, such
   // as a merge section.  The output section can be found in the
index 88bc378c5fffd0d580af9fe9673a63857c5964e8..aca75f286db9d15e5971ba44c97c3c12d0db52ae 100644 (file)
@@ -1,6 +1,6 @@
 // powerpc.cc -- powerpc target support for gold.
 
-// Copyright 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>
 //        and David Edelsohn <edelsohn@gnu.org>
 
@@ -151,12 +151,33 @@ class Target_powerpc : public Sized_target<size, big_endian>
 
   // 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() / (size / 8);
+  }
+
+  // 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.
@@ -321,6 +342,9 @@ class Target_powerpc : public Sized_target<size, big_endian>
   static Target::Target_info powerpc_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
@@ -808,6 +832,21 @@ class Output_data_plt_powerpc : public Output_section_data
     return this->rel_;
   }
 
+  // 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 4 * base_plt_entry_size; }
+
+  // Return the size of a PLT entry.
+  static unsigned int
+  get_plt_entry_size()
+  { return base_plt_entry_size; }
+
  protected:
   void do_adjust_output_section(Output_section* os);
 
@@ -993,6 +1032,35 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+template<int size, bool big_endian>
+unsigned int
+Target_powerpc<size, big_endian>::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.
+
+template<int size, bool big_endian>
+unsigned int
+Target_powerpc<size, big_endian>::first_plt_entry_offset() const
+{
+  return Output_data_plt_powerpc<size, big_endian>::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_powerpc<size, big_endian>::plt_entry_size() const
+{
+  return Output_data_plt_powerpc<size, big_endian>::get_plt_entry_size();
+}
+
 // Create a GOT entry for the TLS module index.
 
 template<int size, bool big_endian>
index 1635f33cdbfc6c013481e86a33e8a656dd3af20b..2f8ef7a43ec21a9ac3a4fdd54237c206f30d7837 100644 (file)
@@ -1,6 +1,6 @@
 // sparc.cc -- sparc target support for gold.
 
-// Copyright 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
 // Written by David S. Miller <davem@davemloft.net>.
 
 // This file is part of gold.
@@ -161,12 +161,33 @@ class Target_sparc : public Sized_target<size, big_endian>
 
   // 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() / (size / 8);
+  }
+
+  // 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.
@@ -343,6 +364,9 @@ class Target_sparc : public Sized_target<size, big_endian>
   static Target::Target_info sparc_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
@@ -1100,6 +1124,21 @@ class Output_data_plt_sparc : public Output_section_data
     return this->rel_;
   }
 
+  // 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 4 * base_plt_entry_size; }
+
+  // Return the size of a PLT entry.
+  static unsigned int
+  get_plt_entry_size()
+  { return base_plt_entry_size; }
+
  protected:
   void do_adjust_output_section(Output_section* os);
 
@@ -1415,6 +1454,35 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::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.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::first_plt_entry_offset() const
+{
+  return Output_data_plt_sparc<size, big_endian>::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+template<int size, bool big_endian>
+unsigned int
+Target_sparc<size, big_endian>::plt_entry_size() const
+{
+  return Output_data_plt_sparc<size, big_endian>::get_plt_entry_size();
+}
+
 // Create a GOT entry for the TLS module index.
 
 template<int size, bool big_endian>
index 4e5b7b05ab95db4dc02fe3bb6a1cc811008f7d63..8ccbca9a4107398876bdf3f2e0e4fdacd7daf923 100644 (file)
@@ -409,6 +409,11 @@ class Symbol
   set_got_offset(unsigned int got_type, unsigned int got_offset)
   { this->got_offsets_.set_offset(got_type, got_offset); }
 
+  // Return the GOT offset list.
+  const Got_offset_list*
+  got_offset_list() const
+  { return this->got_offsets_.get_list(); }
+
   // Return whether this symbol has an entry in the PLT section.
   bool
   has_plt_offset() const
@@ -1489,6 +1494,20 @@ class Symbol_table
   write_section_symbol(const Output_section*, Output_symtab_xindex*,
                       Output_file*, off_t) const;
 
+  // Loop over all symbols, applying the function F to each.
+  template<int size, typename F>
+  void
+  for_all_symbols(F f) const
+  {
+    for (Symbol_table_type::const_iterator p = this->table_.begin();
+         p != this->table_.end();
+         ++p)
+      {
+       Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
+       f(sym);
+      }
+  }
+
   // Dump statistical information to stderr.
   void
   print_stats() const;
index 9f9c4f9dfab7308603f35ac9da179fbdc168c483..6ab31d05c599a5453267d021fd7e9bfec33c3083 100644 (file)
@@ -1,6 +1,6 @@
 // target.h -- target support for gold   -*- C++ -*-
 
-// 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.
@@ -732,6 +732,38 @@ class Sized_target : public Target
                               unsigned char* /* preloc_out*/)
   { gold_unreachable(); }
  
+  // Return the number of entries in the GOT.  This is only used for
+  // laying out the incremental link info sections.  A target needs
+  // to implement this to support incremental linking.
+
+  virtual unsigned int
+  got_entry_count() const
+  { gold_unreachable(); }
+
+  // Return the number of entries in the PLT.  This is only used for
+  // laying out the incremental link info sections.  A target needs
+  // to implement this to support incremental linking.
+
+  virtual unsigned int
+  plt_entry_count() const
+  { gold_unreachable(); }
+
+  // Return the offset of the first non-reserved PLT entry.  This is
+  // only used for laying out the incremental link info sections.
+  // A target needs to implement this to support incremental linking.
+
+  virtual unsigned int
+  first_plt_entry_offset() const
+  { gold_unreachable(); }
+
+  // Return the size of each PLT entry.  This is only used for
+  // laying out the incremental link info sections.  A target needs
+  // to implement this to support incremental linking.
+
+  virtual unsigned int
+  plt_entry_size() const
+  { gold_unreachable(); }
+
  protected:
   Sized_target(const Target::Target_info* pti)
     : Target(pti)
index bfa494c33dcd92adb5400d2db58ad146be7d0ba7..df46f2b9771b13dfe9368481add688863b2b1ba9 100644 (file)
@@ -197,12 +197,33 @@ class Target_x86_64 : public Target_freebsd<64, 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() / 8;
+  }
+
+  // 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;
+
   // Add a new reloc argument, returning the index in the vector.
   size_t
   add_tlsdesc_info(Sized_relobj<64, false>* object, unsigned int r_sym)
@@ -466,6 +487,10 @@ class Target_x86_64 : public Target_freebsd<64, false>
   // general Target structure.
   static const Target::Target_info x86_64_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
@@ -659,6 +684,21 @@ class Output_data_plt_x86_64 : public Output_section_data
   Reloc_section*
   rela_tlsdesc(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);
@@ -960,6 +1000,32 @@ Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
   this->plt_->add_entry(gsym);
 }
 
+// Return the number of entries in the PLT.
+
+unsigned int
+Target_x86_64::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_x86_64::first_plt_entry_offset() const
+{
+  return Output_data_plt_x86_64::first_plt_entry_offset();
+}
+
+// Return the size of each PLT entry.
+
+unsigned int
+Target_x86_64::plt_entry_size() const
+{
+  return Output_data_plt_x86_64::get_plt_entry_size();
+}
+
 // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
 
 void
This page took 0.04754 seconds and 4 git commands to generate.