aboutsummaryrefslogtreecommitdiff
path: root/gold/mips.cc
diff options
context:
space:
mode:
authorVladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>2017-03-15 15:47:58 -0700
committerCary Coutant <ccoutant@gmail.com>2017-03-15 16:51:35 -0700
commit1728969e93010862fe0ef7985cabe03a4494a63e (patch)
treea2b23e206f71e41ea41e8d8a320c0a67ce0c22bd /gold/mips.cc
parentc3847462f86778e97222a72378a84182f92c644a (diff)
downloadgdb-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.cc78
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>