From 1728969e93010862fe0ef7985cabe03a4494a63e Mon Sep 17 00:00:00 2001 From: Vladimir Radosavljevic Date: Wed, 15 Mar 2017 15:47:58 -0700 Subject: [PATCH] Add support for .MIPS.options section. gold/ * mips.cc (class Mips_output_section_options): New class. (Target_mips::do_make_output_section): New method. --- gold/ChangeLog | 5 ++++ gold/mips.cc | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/gold/ChangeLog b/gold/ChangeLog index a36faa1d06..140114e207 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,8 @@ +2017-03-15 Vladimir Radosavljevic + + * mips.cc (class Mips_output_section_options): New class. + (Target_mips::do_make_output_section): New method. + 2017-03-15 Vladimir Radosavljevic * mips.cc (Mips_relocate_functions::rel26): Don't print relocation diff --git a/gold/mips.cc b/gold/mips.cc index c62ced3ef6..4ea2e1d9fe 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -63,6 +63,9 @@ class Target_mips; template class Mips_output_section_reginfo; +template +class Mips_output_section_options; + template 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 +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* 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* target_; +}; + // This class handles .MIPS.abiflags output section. template @@ -3635,6 +3663,18 @@ class Target_mips : public Sized_target const elfcpp::Ehdr&) { 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(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::do_write(Output_file* of) of->write_output_view(offset, data_size, view); } +// Mips_output_section_options methods. + +template +void +Mips_output_section_options::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::writeval(view + 32, + this->target_->gp_value()); + else if (kind == elfcpp::ODK_REGINFO) + elfcpp::Swap::writeval(view + 28, + this->target_->gp_value()); + + view += sz; + } + + of->write_output_view(offset, oview_size, view); +} + // Mips_output_section_abiflags methods. template -- 2.34.1