From 3a44184e641a1a7f6791b65fed802492032d8492 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 7 Jan 2010 21:09:31 +0000 Subject: [PATCH] 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. --- gold/ChangeLog | 17 +++++++++++++++++ gold/layout.cc | 13 ++++++++++++- gold/layout.h | 4 +++- gold/output.cc | 2 +- gold/output.h | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 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 + 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 + * 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::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 : 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 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 // the reloc type. template -class Output_data_reloc_base : public Output_section_data_build +class Output_data_reloc_base : public Output_data_reloc_generic { public: typedef Output_reloc 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. -- 2.7.4