aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog17
-rw-r--r--gold/layout.cc13
-rw-r--r--gold/layout.h4
-rw-r--r--gold/output.cc2
-rw-r--r--gold/output.h52
5 files changed, 79 insertions, 9 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index a96d079..928af4c 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,22 @@
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
output_section and do_output_section.
(class Output_section_data): Add const version of
diff --git a/gold/layout.cc b/gold/layout.cc
index a55020c..dc7cd13 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -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())
diff --git a/gold/layout.h b/gold/layout.h
index 0b16cdf..15e7548 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -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
diff --git a/gold/output.cc b/gold/output.cc
index 63ab98c..b9ded6e 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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(),
diff --git a/gold/output.h b/gold/output.h
index 18e0a9e..796575a 100644
--- a/gold/output.h
+++ b/gold/output.h
@@ -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.