PR 11061
authorIan Lance Taylor <ian@airs.com>
Thu, 7 Jan 2010 21:09:31 +0000 (21:09 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 7 Jan 2010 21:09:31 +0000 (21:09 +0000)
* output.h (class Output_reloc) [SHT_RELA]: Add is_relative
function.
(class Output_data_reloc_generic): Define.
(class Output_data_reloc_base): Change base class to
Output_data_reloc_generic.  Change add() method to call
bump_relative_reloc_count for a relative reloc.  Remove
sort_relocs_ field.
* output.cc (Output_data_reloc_base::do_write): Change sort_reloc_
to sort_relocs().
* layout.cc (Layout::add_target_dynamic_tags): Change dyn_rel to
Output_data_reloc_generic*.  Add DT_RELCOUNT/DT_RELACOUNT tag if
appropriate.
* layout.h (class Layout): Update declaration.

gold/ChangeLog
gold/layout.cc
gold/layout.h
gold/output.cc
gold/output.h

index a96d0794f82a6ce47d88543069f9dbea088eb383..928af4cd9d47387f25765cec0b68c285753e40ef 100644 (file)
@@ -1,3 +1,20 @@
+2010-01-07  Ian Lance Taylor  <iant@google.com>
+
+       PR 11061
+       * output.h (class Output_reloc) [SHT_RELA]: Add is_relative
+       function.
+       (class Output_data_reloc_generic): Define.
+       (class Output_data_reloc_base): Change base class to
+       Output_data_reloc_generic.  Change add() method to call
+       bump_relative_reloc_count for a relative reloc.  Remove
+       sort_relocs_ field.
+       * output.cc (Output_data_reloc_base::do_write): Change sort_reloc_
+       to sort_relocs().
+       * layout.cc (Layout::add_target_dynamic_tags): Change dyn_rel to
+       Output_data_reloc_generic*.  Add DT_RELCOUNT/DT_RELACOUNT tag if
+       appropriate.
+       * layout.h (class Layout): Update declaration.
+
 2010-01-07  Ian Lance Taylor  <iant@google.com>
 
        * output.h (class Output_data): Add const version of
index a55020cdea987d532dfd5287d9286493e8beb812..dc7cd13a3cf771264bc563a5c952689df62bcf36 100644 (file)
@@ -3226,7 +3226,8 @@ Layout::create_interp(const Target* target)
 void
 Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
                                const Output_data* plt_rel,
-                               const Output_data* dyn_rel, bool add_debug)
+                               const Output_data_reloc_generic* dyn_rel,
+                               bool add_debug)
 {
   Output_data_dynamic* odyn = this->dynamic_data_;
   if (odyn == NULL)
@@ -3273,6 +3274,16 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
            gold_unreachable();
        }
       odyn->add_constant(rel_tag, rel_size);
+
+      if (parameters->options().combreloc())
+       {
+         size_t c = dyn_rel->relative_reloc_count();
+         if (c > 0)
+           odyn->add_constant((use_rel
+                               ? elfcpp::DT_RELCOUNT
+                               : elfcpp::DT_RELACOUNT),
+                              c);
+       }
     }
 
   if (add_debug && !parameters->options().shared())
index 0b16cdf88a35e149bd9bf6188ae405f7dbcbf90d..15e75484b34e6465984f6deb31ef1abb21a51708 100644 (file)
@@ -51,6 +51,7 @@ class Output_segment_headers;
 class Output_file_header;
 class Output_segment;
 class Output_data;
+class Output_data_reloc_generic;
 class Output_data_dynamic;
 class Output_symtab_xindex;
 class Output_reduced_debug_abbrev_section;
@@ -561,7 +562,8 @@ class Layout
   void
   add_target_dynamic_tags(bool use_rel, const Output_data* plt_got,
                          const Output_data* plt_rel,
-                         const Output_data* dyn_rel, bool add_debug);
+                         const Output_data_reloc_generic* dyn_rel,
+                         bool add_debug);
 
   // Compute and write out the build ID if needed.
   void
index 63ab98c96b6789de0a75c61d034716150b1de020..b9ded6e07f4cfde6da4524b9067c30578b817dbb 100644 (file)
@@ -1049,7 +1049,7 @@ Output_data_reloc_base<sh_type, dynamic, size, big_endian>::do_write(
   const off_t oview_size = this->data_size();
   unsigned char* const oview = of->get_output_view(off, oview_size);
 
-  if (this->sort_relocs_)
+  if (this->sort_relocs())
     {
       gold_assert(dynamic);
       std::sort(this->relocs_.begin(), this->relocs_.end(),
index 18e0a9e639326c06b2610f4893375b7ea4a08ab2..796575a32505bff376be5951572047a5385b1f1d 100644 (file)
@@ -1237,6 +1237,11 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     : rel_(os, type, relobj, shndx, address), addend_(addend)
   { }
 
+  // Return TRUE if this is a RELATIVE relocation.
+  bool
+  is_relative() const
+  { return this->rel_.is_relative(); }
+
   // Write the reloc entry to an output view.
   void
   write(unsigned char* pov) const;
@@ -1263,6 +1268,43 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   Addend addend_;
 };
 
+// Output_data_reloc_generic is a non-template base class for
+// Output_data_reloc_base.  This gives the generic code a way to hold
+// a pointer to a reloc section.
+
+class Output_data_reloc_generic : public Output_section_data_build
+{
+ public:
+  Output_data_reloc_generic(int size, bool sort_relocs)
+    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
+      relative_reloc_count_(0), sort_relocs_(sort_relocs)
+  { }
+
+  // Return the number of relative relocs in this section.
+  size_t
+  relative_reloc_count() const
+  { return this->relative_reloc_count_; }
+
+  // Whether we should sort the relocs.
+  bool
+  sort_relocs() const
+  { return this->sort_relocs_; }
+
+ protected:
+  // Note that we've added another relative reloc.
+  void
+  bump_relative_reloc_count()
+  { ++this->relative_reloc_count_; }
+
+ private:
+  // The number of relative relocs added to this section.  This is to
+  // support DT_RELCOUNT.
+  size_t relative_reloc_count_;
+  // Whether to sort the relocations when writing them out, to make
+  // the dynamic linker more efficient.
+  bool sort_relocs_;
+};
+
 // Output_data_reloc is used to manage a section containing relocs.
 // SH_TYPE is either elfcpp::SHT_REL or elfcpp::SHT_RELA.  DYNAMIC
 // indicates whether this is a dynamic relocation or a normal
@@ -1271,7 +1313,7 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 // the reloc type.
 
 template<int sh_type, bool dynamic, int size, bool big_endian>
-class Output_data_reloc_base : public Output_section_data_build
+class Output_data_reloc_base : public Output_data_reloc_generic
 {
  public:
   typedef Output_reloc<sh_type, dynamic, size, big_endian> Output_reloc_type;
@@ -1281,8 +1323,7 @@ class Output_data_reloc_base : public Output_section_data_build
 
   // Construct the section.
   Output_data_reloc_base(bool sort_relocs)
-    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
-      sort_relocs_(sort_relocs)
+    : Output_data_reloc_generic(size, sort_relocs)
   { }
 
  protected:
@@ -1311,6 +1352,8 @@ class Output_data_reloc_base : public Output_section_data_build
     this->relocs_.push_back(reloc);
     this->set_current_data_size(this->relocs_.size() * reloc_size);
     od->add_dynamic_reloc();
+    if (reloc.is_relative())
+      this->bump_relative_reloc_count();
   }
 
  private:
@@ -1326,9 +1369,6 @@ class Output_data_reloc_base : public Output_section_data_build
 
   // The relocations in this section.
   Relocs relocs_;
-  // Whether to sort the relocations when writing them out, to make
-  // the dynamic linker more efficient.
-  bool sort_relocs_;
 };
 
 // The class which callers actually create.