Fix problems emitting MIPS .reginfo section.

gold/
	* mips.cc (Mips_relobj::Mips_relobj): Initialize
	has_reginfo_section_.
	(Mips_relobj::has_reginfo_section_): New data member.
	(Mips_relobj::has_reginfo_section): New method.
	(class Mips_output_section_reginfo): Change base class to
	Output_section_data, and set masks of the output .reginfo section
	in constructor.
	(Mips_output_section_reginfo::as_mips_output_section_reginfo):
	Remove.
	(Mips_output_section_reginfo::set_masks): Likewise.
	(Mips_output_section_reginfo::set_final_data_size): Likewise.
	(Mips_output_section_reginfo::do_print_to_mapfile): New method.
	(Target_mips::do_make_output_section): Remove.
	(Mips_relobj::do_read_symbols): Set has_reginfo_section_ to true
	if the object contains a .reginfo section.
	(Target_mips::do_finalize_sections): Create a .reginfo output
	section if needed.
This commit is contained in:
Vladimir Radosavljevic 2016-06-10 15:32:33 -07:00 committed by Cary Coutant
parent 695bfa52cc
commit 82e498727a
2 changed files with 80 additions and 81 deletions

View file

@ -1,3 +1,23 @@
2016-06-10 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
* mips.cc (Mips_relobj::Mips_relobj): Initialize
has_reginfo_section_.
(Mips_relobj::has_reginfo_section_): New data member.
(Mips_relobj::has_reginfo_section): New method.
(class Mips_output_section_reginfo): Change base class to
Output_section_data, and set masks of the output .reginfo section
in constructor.
(Mips_output_section_reginfo::as_mips_output_section_reginfo):
Remove.
(Mips_output_section_reginfo::set_masks): Likewise.
(Mips_output_section_reginfo::set_final_data_size): Likewise.
(Mips_output_section_reginfo::do_print_to_mapfile): New method.
(Target_mips::do_make_output_section): Remove.
(Mips_relobj::do_read_symbols): Set has_reginfo_section_ to true
if the object contains a .reginfo section.
(Target_mips::do_finalize_sections): Create a .reginfo output
section if needed.
2016-06-09 Artemiy Volkov <artemiyv@acm.org>
* mips.cc (Mips_output_data_got::do_write): Add missing template

View file

@ -1544,10 +1544,11 @@ class Mips_relobj : public Sized_relobj_file<size, big_endian>
processor_specific_flags_(0), local_symbol_is_mips16_(),
local_symbol_is_micromips_(), mips16_stub_sections_(),
local_non_16bit_calls_(), local_16bit_calls_(), local_mips16_fn_stubs_(),
local_mips16_call_stubs_(), gp_(0), got_info_(NULL),
section_is_mips16_fn_stub_(), section_is_mips16_call_stub_(),
section_is_mips16_call_fp_stub_(), pdr_shndx_(-1U), gprmask_(0),
cprmask1_(0), cprmask2_(0), cprmask3_(0), cprmask4_(0)
local_mips16_call_stubs_(), gp_(0), has_reginfo_section_(false),
got_info_(NULL), section_is_mips16_fn_stub_(),
section_is_mips16_call_stub_(), section_is_mips16_call_fp_stub_(),
pdr_shndx_(-1U), gprmask_(0), cprmask1_(0), cprmask2_(0), cprmask3_(0),
cprmask4_(0)
{
this->is_pic_ = (ehdr.get_e_flags() & elfcpp::EF_MIPS_PIC) != 0;
this->is_n32_ = elfcpp::abi_n32(ehdr.get_e_flags());
@ -1783,6 +1784,11 @@ class Mips_relobj : public Sized_relobj_file<size, big_endian>
void
discard_mips16_stub_sections(Symbol_table* symtab);
// Return whether there is a .reginfo section.
bool
has_reginfo_section() const
{ return this->has_reginfo_section_; }
// Return gprmask from the .reginfo section of this object.
Valtype
gprmask() const
@ -1861,6 +1867,8 @@ class Mips_relobj : public Sized_relobj_file<size, big_endian>
bool is_pic_ : 1;
// Whether the object uses N32 ABI.
bool is_n32_ : 1;
// Whether the object contains a .reginfo section.
bool has_reginfo_section_ : 1;
// The Mips_got_info for this object.
Mips_got_info<size, big_endian>* got_info_;
@ -2713,40 +2721,25 @@ class Mips_output_data_mips_stubs : public Output_section_data
// This class handles Mips .reginfo output section.
template<int size, bool big_endian>
class Mips_output_section_reginfo : public Output_section
class Mips_output_section_reginfo : public Output_section_data
{
typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
public:
Mips_output_section_reginfo(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
Target_mips<size, big_endian>* target)
: Output_section(name, type, flags), target_(target), gprmask_(0),
cprmask1_(0), cprmask2_(0), cprmask3_(0), cprmask4_(0)
Mips_output_section_reginfo(Target_mips<size, big_endian>* target,
Valtype gprmask, Valtype cprmask1,
Valtype cprmask2, Valtype cprmask3,
Valtype cprmask4)
: Output_section_data(24, 4, true), target_(target),
gprmask_(gprmask), cprmask1_(cprmask1), cprmask2_(cprmask2),
cprmask3_(cprmask3), cprmask4_(cprmask4)
{ }
// Downcast a base pointer to a Mips_output_section_reginfo pointer.
static Mips_output_section_reginfo<size, big_endian>*
as_mips_output_section_reginfo(Output_section* os)
{ return static_cast<Mips_output_section_reginfo<size, big_endian>*>(os); }
// Set masks of the output .reginfo section.
void
set_masks(Valtype gprmask, Valtype cprmask1, Valtype cprmask2,
Valtype cprmask3, Valtype cprmask4)
{
this->gprmask_ = gprmask;
this->cprmask1_ = cprmask1;
this->cprmask2_ = cprmask2;
this->cprmask3_ = cprmask3;
this->cprmask4_ = cprmask4;
}
protected:
// Set the final data size.
// Write to a map file.
void
set_final_data_size()
{ this->set_data_size(24); }
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _(".reginfo")); }
// Write out reginfo section.
void
@ -3545,18 +3538,6 @@ class Target_mips : public Sized_target<size, big_endian>
const elfcpp::Ehdr<size, !big_endian>&)
{ gold_unreachable(); }
// Make an output section.
Output_section*
do_make_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
{
if (type == elfcpp::SHT_MIPS_REGINFO)
return new Mips_output_section_reginfo<size, big_endian>(name, type,
flags, this);
else
return new Output_section(name, type, flags);
}
// Adjust ELF file header.
void
do_adjust_elf_header(unsigned char* view, int len);
@ -6400,6 +6381,7 @@ Mips_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
if (shdr.get_sh_type() == elfcpp::SHT_MIPS_REGINFO)
{
this->has_reginfo_section_ = true;
// Read the gp value that was used to create this object. We need the
// gp value while processing relocs. The .reginfo section is not used
// in the 64-bit MIPS ELF ABI.
@ -8609,6 +8591,13 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
}
}
Valtype gprmask = 0;
Valtype cprmask1 = 0;
Valtype cprmask2 = 0;
Valtype cprmask3 = 0;
Valtype cprmask4 = 0;
bool has_reginfo_section = false;
// Merge processor-specific flags.
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
@ -8617,6 +8606,17 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
Mips_relobj<size, big_endian>* relobj =
Mips_relobj<size, big_endian>::as_mips_relobj(*p);
// Merge .reginfo contents of input objects.
if (relobj->has_reginfo_section())
{
has_reginfo_section = true;
gprmask |= relobj->gprmask();
cprmask1 |= relobj->cprmask1();
cprmask2 |= relobj->cprmask2();
cprmask3 |= relobj->cprmask3();
cprmask4 |= relobj->cprmask4();
}
Input_file::Format format = relobj->input_file()->format();
if (format == Input_file::FORMAT_ELF)
{
@ -8663,24 +8663,26 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
this->merge_processor_specific_flags(dynobj->name(), in_flags, true);
}
// Merge .reginfo contents of input objects.
Valtype gprmask = 0;
Valtype cprmask1 = 0;
Valtype cprmask2 = 0;
Valtype cprmask3 = 0;
Valtype cprmask4 = 0;
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
++p)
if (has_reginfo_section && !parameters->options().gc_sections())
{
Mips_relobj<size, big_endian>* relobj =
Mips_relobj<size, big_endian>::as_mips_relobj(*p);
// Create .reginfo output section.
Mips_output_section_reginfo<size, big_endian>* reginfo_section =
new Mips_output_section_reginfo<size, big_endian>(this, gprmask,
cprmask1, cprmask2,
cprmask3, cprmask4);
gprmask |= relobj->gprmask();
cprmask1 |= relobj->cprmask1();
cprmask2 |= relobj->cprmask2();
cprmask3 |= relobj->cprmask3();
cprmask4 |= relobj->cprmask4();
Output_section* os =
layout->add_output_section_data(".reginfo", elfcpp::SHT_MIPS_REGINFO,
elfcpp::SHF_ALLOC, reginfo_section,
ORDER_INVALID, false);
if (!parameters->options().relocatable() && os != NULL)
{
Output_segment* reginfo_segment =
layout->make_output_segment(elfcpp::PT_MIPS_REGINFO,
elfcpp::PF_R);
reginfo_segment->add_output_section_to_nonload(os, elfcpp::PF_R);
}
}
if (this->plt_ != NULL)
@ -8751,29 +8753,6 @@ Target_mips<size, big_endian>::do_finalize_sections(Layout* layout,
if (!parameters->options().relocatable())
layout->make_output_segment(elfcpp::PT_NULL, 0);
for (Layout::Section_list::const_iterator p = layout->section_list().begin();
p != layout->section_list().end();
++p)
{
if ((*p)->type() == elfcpp::SHT_MIPS_REGINFO)
{
Mips_output_section_reginfo<size, big_endian>* reginfo =
Mips_output_section_reginfo<size, big_endian>::
as_mips_output_section_reginfo(*p);
reginfo->set_masks(gprmask, cprmask1, cprmask2, cprmask3, cprmask4);
if (!parameters->options().relocatable())
{
Output_segment* reginfo_segment =
layout->make_output_segment(elfcpp::PT_MIPS_REGINFO,
elfcpp::PF_R);
reginfo_segment->add_output_section_to_nonload(reginfo,
elfcpp::PF_R);
}
}
}
// Fill in some more dynamic tags.
// TODO(sasa): Add more dynamic tags.
const Reloc_section* rel_plt = (this->plt_ == NULL