Add support for .MIPS.options section.

gold/
        * mips.cc (class Mips_output_section_options): New class.
        (Target_mips::do_make_output_section): New method.
This commit is contained in:
Vladimir Radosavljevic 2017-03-15 15:47:58 -07:00 committed by Cary Coutant
parent c3847462f8
commit 1728969e93
2 changed files with 83 additions and 0 deletions

View File

@ -1,3 +1,8 @@
2017-03-15 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
* mips.cc (class Mips_output_section_options): New class.
(Target_mips::do_make_output_section): New method.
2017-03-15 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
* mips.cc (Mips_relocate_functions::rel26): Don't print relocation

View File

@ -63,6 +63,9 @@ class Target_mips;
template<int size, bool big_endian>
class Mips_output_section_reginfo;
template<int size, bool big_endian>
class Mips_output_section_options;
template<int size, bool big_endian>
class Mips_output_data_la25_stub;
@ -2821,6 +2824,31 @@ class Mips_output_section_reginfo : public Output_section_data
Valtype cprmask4_;
};
// This class handles .MIPS.options output section.
template<int size, bool big_endian>
class Mips_output_section_options : public Output_section
{
public:
Mips_output_section_options(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
Target_mips<size, big_endian>* target)
: Output_section(name, type, flags), target_(target)
{
// After the input sections are written, we only need to update
// ri_gp_value field of ODK_REGINFO entries.
this->set_after_input_sections();
}
protected:
// Write out option section.
void
do_write(Output_file* of);
private:
Target_mips<size, big_endian>* target_;
};
// This class handles .MIPS.abiflags output section.
template<int size, bool big_endian>
@ -3635,6 +3663,18 @@ 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_OPTIONS)
return new Mips_output_section_options<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);
@ -8177,6 +8217,44 @@ Mips_output_section_reginfo<size, big_endian>::do_write(Output_file* of)
of->write_output_view(offset, data_size, view);
}
// Mips_output_section_options methods.
template<int size, bool big_endian>
void
Mips_output_section_options<size, big_endian>::do_write(Output_file* of)
{
off_t offset = this->offset();
const section_size_type oview_size =
convert_to_section_size_type(this->data_size());
unsigned char* view = of->get_output_view(offset, oview_size);
const unsigned char* end = view + oview_size;
while (view + 8 <= end)
{
unsigned char kind = elfcpp::Swap<8, big_endian>::readval(view);
unsigned char sz = elfcpp::Swap<8, big_endian>::readval(view + 1);
if (sz < 8)
{
gold_error(_("Warning: bad `%s' option size %u smaller "
"than its header in output section"),
this->name(), sz);
break;
}
// Only update ri_gp_value (GP register value) field of ODK_REGINFO entry.
if (this->target_->is_output_n64() && kind == elfcpp::ODK_REGINFO)
elfcpp::Swap<size, big_endian>::writeval(view + 32,
this->target_->gp_value());
else if (kind == elfcpp::ODK_REGINFO)
elfcpp::Swap<size, big_endian>::writeval(view + 28,
this->target_->gp_value());
view += sz;
}
of->write_output_view(offset, oview_size, view);
}
// Mips_output_section_abiflags methods.
template<int size, bool big_endian>