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] [GOLD] correct grouping of stubs


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

commit 57f6d32deafcfec43bef5e963e12aacc0783a1e4
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Aug 30 11:58:05 2016 +0930

    [GOLD] correct grouping of stubs
    
    This patch rewrites the rather obscure can_add_to_stub_group, fixing
    a problem with the handling of sections containing conditional
    external branches.  When a section group contains any such section,
    the group size needs to be limited to a much smaller size than groups
    with only non-conditional external branches.
    
    	PR 20523
    	* powerpc.cc (class Stub_control): Add has14_.  Comment owner_.
    	(Stub_control::can_add_to_stub_group): Correct grouping of
    	sections containing 14-bit external branches.  When returning
    	false, set state_ to reflect the fact that we have one section
    	for the next group.  Rewrite most of function for clarity.
    	Add and expand comments.
    	(Target_powerpc::do_relax): Print stub group size retry in hex.

Diff:
---
 gold/ChangeLog  |  11 ++++++
 gold/powerpc.cc | 103 ++++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/gold/ChangeLog b/gold/ChangeLog
index f01188e..0ea09f9 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,14 @@
+2016-08-30  Alan Modra  <amodra@gmail.com>
+
+	PR 20523
+	* powerpc.cc (class Stub_control): Add has14_.  Comment owner_.
+	(Stub_control::can_add_to_stub_group): Correct grouping of
+	sections containing 14-bit external branches.  When returning
+	false, set state_ to reflect the fact that we have one section
+	for the next group.  Rewrite most of function for clarity.
+	Add and expand comments.
+	(Target_powerpc::do_relax): Print stub group size retry in hex.
+
 2016-08-26  Han Shen  <shenhan@google.com>
 
 	PR gold/20529 - relaxing loop never ends.
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index c269ae0..d0dd672 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -2441,7 +2441,7 @@ class Stub_control
     : state_(NO_GROUP), stub_group_size_(abs(size)),
       stub14_group_size_(abs(size) >> 10),
       stubs_always_before_branch_(size < 0),
-      suppress_size_errors_(no_size_errors),
+      suppress_size_errors_(no_size_errors), has14_(false),
       group_end_addr_(0), owner_(NULL), output_section_(NULL)
   {
   }
@@ -2482,21 +2482,23 @@ class Stub_control
   uint32_t stub14_group_size_;
   bool stubs_always_before_branch_;
   bool suppress_size_errors_;
+  bool has14_;
   uint64_t group_end_addr_;
+  // owner_ and output_section_ specify the section to which stubs are
+  // attached.  The stubs are placed at the end of this section.
   const Output_section::Input_section* owner_;
   Output_section* output_section_;
 };
 
 // Return true iff input section can be handled by current stub
-// group.
+// group.  Sections are presented to this function in reverse order,
+// so the first section is the tail of the group.
 
 bool
 Stub_control::can_add_to_stub_group(Output_section* o,
 				    const Output_section::Input_section* i,
 				    bool has14)
 {
-  uint32_t group_size
-    = has14 ? this->stub14_group_size_ : this->stub_group_size_;
   bool whole_sec = o->order() == ORDER_INIT || o->order() == ORDER_FINI;
   uint64_t this_size;
   uint64_t start_addr = o->address();
@@ -2510,46 +2512,81 @@ Stub_control::can_add_to_stub_group(Output_section* o,
       start_addr += i->relobj()->output_section_offset(i->shndx());
       this_size = i->data_size();
     }
+
+  uint32_t group_size
+    = has14 ? this->stub14_group_size_ : this->stub_group_size_;
   uint64_t end_addr = start_addr + this_size;
-  bool toobig = this_size > group_size;
 
-  if (toobig && !this->suppress_size_errors_)
+  if (this_size > group_size && !this->suppress_size_errors_)
     gold_warning(_("%s:%s exceeds group size"),
 		 i->relobj()->name().c_str(),
 		 i->relobj()->section_name(i->shndx()).c_str());
 
-  if (this->state_ != HAS_STUB_SECTION
-      && (!whole_sec || this->output_section_ != o)
-      && (this->state_ == NO_GROUP
-	  || this->group_end_addr_ - end_addr < group_size))
-    {
-      this->owner_ = i;
-      this->output_section_ = o;
-    }
+  this->has14_ = this->has14_ || has14;
+  group_size = this->has14_ ? this->stub14_group_size_ : this->stub_group_size_;
 
-  if (this->state_ == NO_GROUP)
+  if (this->state_ == HAS_STUB_SECTION)
     {
-      this->state_ = FINDING_STUB_SECTION;
-      this->group_end_addr_ = end_addr;
-    }
-  else if (this->group_end_addr_ - start_addr < group_size)
-    ;
-  // Adding this section would make the group larger than GROUP_SIZE.
-  else if (this->state_ == FINDING_STUB_SECTION
-	   && !this->stubs_always_before_branch_
-	   && !toobig)
-    {
-      // But wait, there's more!  Input sections up to GROUP_SIZE
-      // bytes before the stub table can be handled by it too.
-      this->state_ = HAS_STUB_SECTION;
-      this->group_end_addr_ = end_addr;
+      // Can we add this section, which is before the stubs, to the
+      // group?
+      if (this->group_end_addr_ - start_addr <= group_size)
+	return true;
     }
   else
     {
-      this->state_ = NO_GROUP;
-      return false;
+      // Stubs are added at the end of "owner_".
+      // The current section can always be the stub owner, except when
+      // whole_sec is true and the current section isn't the last of
+      // the pasted sections.  (This restriction for the whole_sec
+      // case is just to simplify the corner case mentioned in
+      // group_sections.)
+      // Note that "owner_" itself is not necessarily part of the
+      // group of sections served by these stubs!
+      if (!whole_sec || this->output_section_ != o)
+	{
+	  this->owner_ = i;
+	  this->output_section_ = o;
+	}
+
+      if (this->state_ == FINDING_STUB_SECTION)
+	{
+	  if (this->group_end_addr_ - start_addr <= group_size)
+	    return true;
+	  // The group after the stubs has reached maximum size.
+	  // Now see about adding sections before the stubs to the
+	  // group.  If the current section has a 14-bit branch and
+	  // the group after the stubs exceeds stub14_group_size_
+	  // (because they didn't have 14-bit branches), don't add
+	  // sections before the stubs:  The size of stubs for such a
+	  // large group may exceed the reach of a 14-bit branch.
+	  if (!this->stubs_always_before_branch_
+	      && this_size <= group_size
+	      && this->group_end_addr_ - end_addr <= group_size)
+	    {
+	      this->state_ = HAS_STUB_SECTION;
+	      this->group_end_addr_ = end_addr;
+	      return true;
+	    }
+	}
+      else if (this->state_ == NO_GROUP)
+	{
+	  // Only here on very first use of Stub_control
+	  this->state_ = FINDING_STUB_SECTION;
+	  this->group_end_addr_ = end_addr;
+	  return true;
+	}
+      else
+	gold_unreachable();
     }
-  return true;
+
+  // The section fails to fit in the current group.  Set up a few
+  // things for the next group.  owner_ and output_section_ will be
+  // set later after we've retrieved those values for the current
+  // group.
+  this->state_ = FINDING_STUB_SECTION;
+  this->has14_ = has14;
+  this->group_end_addr_ = end_addr;
+  return false;
 }
 
 // Look over all the input sections, deciding where to place stubs.
@@ -2887,7 +2924,7 @@ Target_powerpc<size, big_endian>::do_relax(int pass,
 	}
       this->stub_tables_.clear();
       this->stub_group_size_ = this->stub_group_size_ / 4 * 3;
-      gold_info(_("%s: stub group size is too large; retrying with %d"),
+      gold_info(_("%s: stub group size is too large; retrying with %#x"),
 		program_name, this->stub_group_size_);
       this->group_sections(layout, task, true);
     }


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