* 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.
This commit is contained in:
Ian Lance Taylor 2010-01-07 21:09:31 +00:00
parent 71a72a8462
commit 3a44184e64
5 changed files with 79 additions and 9 deletions

View 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

View 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())

View 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

View 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(),

View 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.