This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gold commit] PR gold/17639: Fix corrupted .eh_frame section with LTO and --gc-sections


When --gc-sections is turned on during an LTO link, the .eh_frame sections
from deferred files are processed before those from the replacement files.
As a result, the section end-cap from crtendS.o is placed ahead of
the .eh_frame data from the replacement files. This patch fixes the bug
by skipping the layout of the deferred sections during GC pass 2.


2014-11-25  Cary Coutant  <ccoutant@google.com>

gold/
	PR gold/17639
	* object.cc (Sized_relobj_file): Initialize is_deferred_layout_.
	(Sized_relobj_file::do_layout): Handle deferred sections properly
	during GC pass 1. Don't add reloc sections to deferred list twice.
	* object.h (Sized_relobj_file::is_deferred_layout): New function.
	(Sized_relobj_file::is_deferred_layout_): New data member.


diff --git a/gold/object.cc b/gold/object.cc
index 6ab84ce..e357ddf 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -430,6 +430,7 @@ Sized_relobj_file<size, big_endian>::Sized_relobj_file(
     kept_comdat_sections_(),
     has_eh_frame_(false),
     discarded_eh_frame_shndx_(-1U),
+    is_deferred_layout_(false),
     deferred_layout_(),
     deferred_layout_relocs_(),
     compressed_sections_()
@@ -1430,6 +1431,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
     {
       parameters->options().plugins()->add_deferred_layout_object(this);
       this->deferred_layout_.reserve(num_sections_to_defer);
+      this->is_deferred_layout_ = true;
     }
 
   // Whether we've seen a .note.GNU-stack section.
@@ -1590,10 +1592,13 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 	{
 	  if (is_pass_one)
 	    {
-	      out_sections[i] = reinterpret_cast<Output_section*>(1);
+	      if (this->is_deferred_layout())
+		out_sections[i] = reinterpret_cast<Output_section*>(2);
+	      else
+		out_sections[i] = reinterpret_cast<Output_section*>(1);
 	      out_section_offsets[i] = invalid_address;
 	    }
-	  else if (should_defer_layout)
+	  else if (this->is_deferred_layout())
 	    this->deferred_layout_.push_back(Deferred_layout(i, name,
 							     pshdrs,
 							     reloc_shndx[i],
@@ -1658,11 +1663,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 	}
 
       // Defer layout here if input files are claimed by plugins.  When gc
-      // is turned on this function is called twice.  For the second call
-      // should_defer_layout should be false.
-      if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+      // is turned on this function is called twice; we only want to do this
+      // on the first pass.
+      if (!is_pass_two
+          && this->is_deferred_layout()
+          && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
 	{
-	  gold_assert(!is_pass_two);
 	  this->deferred_layout_.push_back(Deferred_layout(i, name,
 							   pshdrs,
 							   reloc_shndx[i],
@@ -1764,6 +1770,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       Output_section* data_section = out_sections[data_shndx];
       if (data_section == reinterpret_cast<Output_section*>(2))
 	{
+	  if (is_pass_two)
+	    continue;
 	  // The layout for the data section was deferred, so we need
 	  // to defer the relocation section, too.
 	  const char* name = pnames + shdr.get_sh_name();
diff --git a/gold/object.h b/gold/object.h
index 754b1d2..cf45ec5 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -2202,6 +2202,10 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
 			    Symbol_value<size>* lv_out,
 			    const Symbol_table* symtab);
 
+  // Return true if the layout for this object was deferred.
+  bool is_deferred_layout() const
+  { return this->is_deferred_layout_; }
+
  protected:
   typedef typename Sized_relobj<size, big_endian>::Output_sections
       Output_sections;
@@ -2740,6 +2744,9 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   // If this object has a GNU style .eh_frame section that is discarded in
   // output, record the index here.  Otherwise it is -1U.
   unsigned int discarded_eh_frame_shndx_;
+  // True if the layout of this object was deferred, waiting for plugin
+  // replacement files.
+  bool is_deferred_layout_;
   // The list of sections whose layout was deferred.
   std::vector<Deferred_layout> deferred_layout_;
   // The list of relocation sections whose layout was deferred.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]