Fix failure in exception_static_test.
authorCary Coutant <ccoutant@google.com>
Mon, 9 Mar 2015 17:10:29 +0000 (10:10 -0700)
committerCary Coutant <ccoutant@google.com>
Mon, 9 Mar 2015 17:12:06 +0000 (10:12 -0700)
Because the __EH_FRAME_BEGIN__ symbol is provided in an empty .eh_frame
section in crtbeginT.o, if crt1.o has a non-empty .eh_frame section,
we place all optimized .eh_frame sections into the output section ahead
of the __EH_FRAME_BEGIN__ symbol, which breaks EH for statically-linked
binaries.

This patch fixes the problem by delaying the attachment of the optimized
.eh_frame sections to the output section until we see the end marker
section (or to the end of pass 1 if we never see an end marker).

gold/
PR gold/14675
* ehframe.cc (Eh_frame::add_ehframe_input_section): Change return type;
return enum indicating whether .eh_frame section is empty, optimizable,
unrecognized, or an end marker. Adjust explicit instantiations.
* ehframe.h (Eh_frame::Eh_frame_section_disposition): New enum type.
(Eh_frame::add_ehframe_input_section): Change return type.
* gold.cc (queue_middle_tasks): Call Layout::finalize_eh_frame_section.
* layout.cc (Layout::layout_eh_frame): Don't add optimized sections
to the .eh_frame output section until we see the end marker.
(Layout::finalize_eh_frame_section): New.
* layout.h: (Layout::finalize_eh_frame_section): New.

gold/ChangeLog
gold/ehframe.cc
gold/ehframe.h
gold/gold.cc
gold/layout.cc
gold/layout.h

index 24d3560774149cc06bed1817269e81d2f0b564c9..14a8610e35105dd49958590dadce56fc6e5dbbd1 100644 (file)
@@ -1,3 +1,17 @@
+2015-03-09  Cary Coutant  <ccoutant@google.com>
+
+       PR gold/14675
+       * ehframe.cc (Eh_frame::add_ehframe_input_section): Change return type;
+       return enum indicating whether .eh_frame section is empty, optimizable,
+       unrecognized, or an end marker. Adjust explicit instantiations.
+       * ehframe.h (Eh_frame::Eh_frame_section_disposition): New enum type.
+       (Eh_frame::add_ehframe_input_section): Change return type.
+       * gold.cc (queue_middle_tasks): Call Layout::finalize_eh_frame_section.
+       * layout.cc (Layout::layout_eh_frame): Don't add optimized sections
+       to the .eh_frame output section until we see the end marker.
+       (Layout::finalize_eh_frame_section): New.
+       * layout.h: (Layout::finalize_eh_frame_section): New.
+
 2015-03-05  H.J. Lu  <hongjiu.lu@intel.com>
 
        * output.cc (Relobj::initialize_input_to_output_map<size>):
index 711103b482ec1cb5f5a7f4128c737bbcd54a0650..262766ed0af89956e58084ee134947e026b56fa2 100644 (file)
@@ -567,7 +567,7 @@ Eh_frame::skip_leb128(const unsigned char** pp, const unsigned char* pend)
 // section.
 
 template<int size, bool big_endian>
-bool
+Eh_frame::Eh_frame_section_disposition
 Eh_frame::add_ehframe_input_section(
     Sized_relobj_file<size, big_endian>* object,
     const unsigned char* symbols,
@@ -584,7 +584,7 @@ Eh_frame::add_ehframe_input_section(
                                                            &contents_len,
                                                            false);
   if (contents_len == 0)
-    return false;
+    return EH_EMPTY_SECTION;
 
   // If this is the marker section for the end of the data, then
   // return false to force it to be handled as an ordinary input
@@ -592,7 +592,7 @@ Eh_frame::add_ehframe_input_section(
   // of unrecognized .eh_frame sections.
   if (contents_len == 4
       && elfcpp::Swap<32, big_endian>::readval(pcontents) == 0)
-    return false;
+    return EH_END_MARKER_SECTION;
 
   New_cies new_cies;
   if (!this->do_add_ehframe_input_section(object, symbols, symbols_size,
@@ -609,7 +609,7 @@ Eh_frame::add_ehframe_input_section(
           ++p)
        delete p->first;
 
-      return false;
+      return EH_UNRECOGNIZED_SECTION;
     }
 
   // Now that we know we are using this section, record any new CIEs
@@ -624,7 +624,7 @@ Eh_frame::add_ehframe_input_section(
        this->unmergeable_cie_offsets_.push_back(p->first);
     }
 
-  return true;
+  return EH_OPTIMIZABLE_SECTION;
 }
 
 // The bulk of the implementation of add_ehframe_input_section.
@@ -1206,7 +1206,7 @@ Eh_frame::do_sized_write(unsigned char* oview)
 
 #ifdef HAVE_TARGET_32_LITTLE
 template
-bool
+Eh_frame::Eh_frame_section_disposition
 Eh_frame::add_ehframe_input_section<32, false>(
     Sized_relobj_file<32, false>* object,
     const unsigned char* symbols,
@@ -1220,7 +1220,7 @@ Eh_frame::add_ehframe_input_section<32, false>(
 
 #ifdef HAVE_TARGET_32_BIG
 template
-bool
+Eh_frame::Eh_frame_section_disposition
 Eh_frame::add_ehframe_input_section<32, true>(
     Sized_relobj_file<32, true>* object,
     const unsigned char* symbols,
@@ -1234,7 +1234,7 @@ Eh_frame::add_ehframe_input_section<32, true>(
 
 #ifdef HAVE_TARGET_64_LITTLE
 template
-bool
+Eh_frame::Eh_frame_section_disposition
 Eh_frame::add_ehframe_input_section<64, false>(
     Sized_relobj_file<64, false>* object,
     const unsigned char* symbols,
@@ -1248,7 +1248,7 @@ Eh_frame::add_ehframe_input_section<64, false>(
 
 #ifdef HAVE_TARGET_64_BIG
 template
-bool
+Eh_frame::Eh_frame_section_disposition
 Eh_frame::add_ehframe_input_section<64, true>(
     Sized_relobj_file<64, true>* object,
     const unsigned char* symbols,
index bb47381d18bf372ed3142e25ee48a536fa18617b..e6e21b2673e0e3ba406d33f719f1f34294c4acb7 100644 (file)
@@ -359,6 +359,14 @@ extern bool operator==(const Cie&, const Cie&);
 class Eh_frame : public Output_section_data
 {
  public:
+  enum Eh_frame_section_disposition
+  {
+    EH_EMPTY_SECTION,
+    EH_UNRECOGNIZED_SECTION,
+    EH_OPTIMIZABLE_SECTION,
+    EH_END_MARKER_SECTION
+  };
+
   Eh_frame();
 
   // Record the associated Eh_frame_hdr, if any.
@@ -374,7 +382,7 @@ class Eh_frame : public Output_section_data
   // returns whether the section was incorporated into the .eh_frame
   // data.
   template<int size, bool big_endian>
-  bool
+  Eh_frame_section_disposition
   add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
                            const unsigned char* symbols,
                            section_size_type symbols_size,
index ab15980f867d7a75850f43d7c2c1d525e8bea3a0..e345887ac12956f088f10fe3d6c342c488f017ad 100644 (file)
@@ -492,6 +492,9 @@ queue_middle_tasks(const General_options& options,
   if (timer != NULL)
     timer->stamp(0);
 
+  // Finalize the .eh_frame section.
+  layout->finalize_eh_frame_section();
+
   // Add any symbols named with -u options to the symbol table.
   symtab->add_undefined_symbols_from_command_line(layout);
 
index 7836640a57767f8ce4c67f5d3dee21e712ba2576..14bfda092c55bf7d14115d7afce058b10eb66a11 100644 (file)
@@ -1420,15 +1420,21 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
 
   elfcpp::Elf_Xword orig_flags = os->flags();
 
-  if (!parameters->incremental()
-      && this->eh_frame_data_->add_ehframe_input_section(object,
-                                                        symbols,
-                                                        symbols_size,
-                                                        symbol_names,
-                                                        symbol_names_size,
-                                                        shndx,
-                                                        reloc_shndx,
-                                                        reloc_type))
+  Eh_frame::Eh_frame_section_disposition disp =
+      Eh_frame::EH_UNRECOGNIZED_SECTION;
+  if (!parameters->incremental())
+    {
+      disp = this->eh_frame_data_->add_ehframe_input_section(object,
+                                                            symbols,
+                                                            symbols_size,
+                                                            symbol_names,
+                                                            symbol_names_size,
+                                                            shndx,
+                                                            reloc_shndx,
+                                                            reloc_type);
+    }
+
+  if (disp == Eh_frame::EH_OPTIMIZABLE_SECTION)
     {
       os->update_flags_for_input_section(shdr.get_sh_flags());
 
@@ -1440,35 +1446,49 @@ Layout::layout_eh_frame(Sized_relobj_file<size, big_endian>* object,
          os->set_order(ORDER_RELRO);
        }
 
-      // We found a .eh_frame section we are going to optimize, so now
-      // we can add the set of optimized sections to the output
-      // section.  We need to postpone adding this until we've found a
-      // section we can optimize so that the .eh_frame section in
-      // crtbegin.o winds up at the start of the output section.
-      if (!this->added_eh_frame_data_)
-       {
-         os->add_output_section_data(this->eh_frame_data_);
-         this->added_eh_frame_data_ = true;
-       }
       *off = -1;
+      return os;
     }
-  else
+
+  if (disp == Eh_frame::EH_END_MARKER_SECTION && !this->added_eh_frame_data_)
     {
-      // We couldn't handle this .eh_frame section for some reason.
-      // Add it as a normal section.
-      bool saw_sections_clause = this->script_options_->saw_sections_clause();
-      *off = os->add_input_section(this, object, shndx, ".eh_frame", shdr,
-                                  reloc_shndx, saw_sections_clause);
-      this->have_added_input_section_ = true;
+      // We found the end marker section, so now we can add the set of
+      // optimized sections to the output section.  We need to postpone
+      // adding this until we've found a section we can optimize so that
+      // the .eh_frame section in crtbeginT.o winds up at the start of
+      // the output section.
+      os->add_output_section_data(this->eh_frame_data_);
+      this->added_eh_frame_data_ = true;
+     }
 
-      if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
-         != (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
-       os->set_order(this->default_section_order(os, false));
-    }
+  // We couldn't handle this .eh_frame section for some reason.
+  // Add it as a normal section.
+  bool saw_sections_clause = this->script_options_->saw_sections_clause();
+  *off = os->add_input_section(this, object, shndx, ".eh_frame", shdr,
+                              reloc_shndx, saw_sections_clause);
+  this->have_added_input_section_ = true;
+
+  if ((orig_flags & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR))
+      != (os->flags() & (elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR)))
+    os->set_order(this->default_section_order(os, false));
 
   return os;
 }
 
+void
+Layout::finalize_eh_frame_section()
+{
+  // If we never found an end marker section, we need to add the
+  // optimized eh sections to the output section now.
+  if (!parameters->incremental()
+      && this->eh_frame_section_ != NULL
+      && !this->added_eh_frame_data_)
+    {
+      this->eh_frame_section_->add_output_section_data(this->eh_frame_data_);
+      this->added_eh_frame_data_ = true;
+    }
+}
+
 // Create and return the magic .eh_frame section.  Create
 // .eh_frame_hdr also if appropriate.  OBJECT is the object with the
 // input .eh_frame section; it may be NULL.
index aec0c53be778d890bf8213b58203fac44606f8d7..9039ee8851d93867c1f7aba310fbbf54461c07f2 100644 (file)
@@ -635,6 +635,12 @@ class Layout
                  unsigned int reloc_shndx, unsigned int reloc_type,
                  off_t* offset);
 
+  // After processing all input files, we call this to make sure that
+  // the optimized .eh_frame sections have been added to the output
+  // section.
+  void
+  finalize_eh_frame_section();
+
   // Add .eh_frame information for a PLT.  The FDE must start with a
   // 4-byte PC-relative reference to the start of the PLT, followed by
   // a 4-byte size of PLT.