This is the mail archive of the binutils-cvs@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]

[binutils-gdb/binutils-2_27-branch] PR gold/20529 - relaxing loop never ends.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cd54b50e7b5ac662ca52d636c01dfaa506cdb07b

commit cd54b50e7b5ac662ca52d636c01dfaa506cdb07b
Author: Han Shen <shenhan@google.com>
Date:   Fri Aug 26 15:50:15 2016 -0700

    PR gold/20529 - relaxing loop never ends.
    
    	* powerpc.cc (Stub_table::min_size_threshold_): New member to
    	limit size.
    	(Stub_table::set_min_size_threshold): New member function.
    	(Stub_table::set_address_and_size): Add code to only allow size
    	increase.
    	(Target_powerpc::do_relax): Add code to record last size.

Diff:
---
 gold/ChangeLog  | 12 ++++++++++++
 gold/powerpc.cc | 27 ++++++++++++++++++++++++---
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index f5005ef..e551591 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,15 @@
+2017-02-22  Alan Modra  <amodra@gmail.com>
+
+	Apply from master
+	2016-08-26  Han Shen  <shenhan@google.com>
+	PR gold/20529 - relaxing loop never ends.
+	* powerpc.cc (Stub_table::min_size_threshold_): New member to
+	limit size.
+	(Stub_table::set_min_size_threshold): New member function.
+	(Stub_table::set_address_and_size): Add code to only allow size
+	increase.
+	(Target_powerpc::do_relax): Add code to record last size.
+
 2016-09-26  Cary Coutant  <ccoutant@gmail.com>
 
 	PR gold/20238
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 60530ba..c269ae0 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -2982,7 +2982,13 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
 	      Stub_table<size, big_endian>* stub_table
 		= static_cast<Stub_table<size, big_endian>*>(
 		    i->relaxed_input_section());
-	      off += stub_table->set_address_and_size(os, off);
+	      Address stub_table_size = stub_table->set_address_and_size(os, off);
+	      off += stub_table_size;
+	      // After a few iterations, set current stub table size
+	      // as min size threshold, so later stub tables can only
+	      // grow in size.
+	      if (pass >= 4)
+		stub_table->set_min_size_threshold(stub_table_size);
 	    }
 	  else
 	    off += i->data_size();
@@ -3634,8 +3640,8 @@ class Stub_table : public Output_relaxed_input_section
       targ_(targ), plt_call_stubs_(), long_branch_stubs_(),
       orig_data_size_(owner->current_data_size()),
       plt_size_(0), last_plt_size_(0),
-      branch_size_(0), last_branch_size_(0), eh_frame_added_(false),
-      need_save_res_(false)
+      branch_size_(0), last_branch_size_(0), min_size_threshold_(0),
+      eh_frame_added_(false), need_save_res_(false)
   {
     this->set_output_section(output_section);
 
@@ -3726,6 +3732,11 @@ class Stub_table : public Output_relaxed_input_section
       off = align_address(off, this->stub_align());
     // Include original section size and alignment padding in size
     my_size += off - start_off;
+    // Ensure new size is always larger than min size
+    // threshold. Alignment requirement is included in "my_size", so
+    // increase "my_size" does not invalidate alignment.
+    if (my_size < this->min_size_threshold_)
+      my_size = this->min_size_threshold_;
     this->reset_address_and_file_offset();
     this->set_current_data_size(my_size);
     this->set_address_and_file_offset(os->address() + start_off,
@@ -3751,6 +3762,9 @@ class Stub_table : public Output_relaxed_input_section
   plt_size() const
   { return this->plt_size_; }
 
+  void set_min_size_threshold(Address min_size)
+  { this->min_size_threshold_ = min_size; }
+
   bool
   size_update()
   {
@@ -4015,6 +4029,13 @@ class Stub_table : public Output_relaxed_input_section
   section_size_type orig_data_size_;
   // size of stubs
   section_size_type plt_size_, last_plt_size_, branch_size_, last_branch_size_;
+  // Some rare cases cause (PR/20529) fluctuation in stub table
+  // size, which leads to an endless relax loop. This is to be fixed
+  // by, after the first few iterations, allowing only increase of
+  // stub table size. This variable sets the minimal possible size of
+  // a stub table, it is zero for the first few iterations, then
+  // increases monotonically.
+  Address min_size_threshold_;
   // Whether .eh_frame info has been created for this stub section.
   bool eh_frame_added_;
   // Set if this stub group needs a copy of out-of-line register


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