diff options
author | Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com> | 2017-03-15 15:47:58 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@gmail.com> | 2017-03-15 16:51:35 -0700 |
commit | 1728969e93010862fe0ef7985cabe03a4494a63e (patch) | |
tree | a2b23e206f71e41ea41e8d8a320c0a67ce0c22bd /gold/mips.cc | |
parent | c3847462f86778e97222a72378a84182f92c644a (diff) | |
download | gdb-1728969e93010862fe0ef7985cabe03a4494a63e.zip gdb-1728969e93010862fe0ef7985cabe03a4494a63e.tar.gz gdb-1728969e93010862fe0ef7985cabe03a4494a63e.tar.bz2 |
Add support for .MIPS.options section.
gold/
* mips.cc (class Mips_output_section_options): New class.
(Target_mips::do_make_output_section): New method.
Diffstat (limited to 'gold/mips.cc')
-rw-r--r-- | gold/mips.cc | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/gold/mips.cc b/gold/mips.cc index c62ced3..4ea2e1d 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -64,6 +64,9 @@ 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; template<int size, bool big_endian> @@ -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> |