Fix problems emitting MIPS .reginfo section.
authorVladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
Fri, 10 Jun 2016 22:32:33 +0000 (15:32 -0700)
committerCary Coutant <ccoutant@gmail.com>
Fri, 10 Jun 2016 22:37:19 +0000 (15:37 -0700)
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.

gold/ChangeLog
gold/mips.cc

index 5171ad0a99b925446e84ee54a5afce9706781992..9552d5501264a4e5894f1e937bcb49d6e55eb80d 100644 (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
index e8a639b982833bf662dd485d0aee23e17f707a37..59ce88e30988412ef91e866d66023d423f88ac3a 100644 (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);
+
+      Output_section* os =
+        layout->add_output_section_data(".reginfo", elfcpp::SHT_MIPS_REGINFO,
+                                        elfcpp::SHF_ALLOC, reginfo_section,
+                                        ORDER_INVALID, false);
 
-      gprmask |= relobj->gprmask();
-      cprmask1 |= relobj->cprmask1();
-      cprmask2 |= relobj->cprmask2();
-      cprmask3 |= relobj->cprmask3();
-      cprmask4 |= relobj->cprmask4();
+      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