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]

Re: PATCH: PR gas/4029: relax_segment can't stabilize .gcc_except_table


On Fri, Feb 23, 2007 at 12:05:54AM +1030, Alan Modra wrote:
> On Sun, Feb 18, 2007 at 11:19:27PM -0800, H. J. Lu wrote:
> > +		  if (growth == -1
> > +		      && fragP->growth_count == 0xf)
> > +		    {
> > +		      /* There are 15 growths after shrinks. To break
> > +			 the infinite loop, we grow the size by 1 instead
> > +			 of shrinking it by 1.  */
> > +		      growth = 1;
> > +		    }
> 
> HJ, how can this possibly work?  If you arbitrarily change the growth,
> then all following frags will have their address set incorrectly.
> At least, that's what is seems like to me.  Hmm, I suppose you might
> have found something that works for one specific case of following
> frag types, but I don't think this can be correct in general.
> 

It works because the size of rs_leb128 depends on its value. When
its value changes due to relaxation, its size may increase or decrease.
You can change its size which will change addresses of all following
frags. In turn, it will change the value of rs_leb128. I added
an assert to cvt_frag_to_fill to make sure that rs_leb128 size matches
its value.


H.J.
---
2007-02-19  H.J. Lu  <hongjiu.lu@intel.com>

	PR gas/4029
	* frags.h (LAST_GROWTH_NONE): New.
	(LAST_GROWTH_INCREASE): Likewise.
	(LAST_GROWTH_SHRINK): Likewise.
	(frag): Add growth_count and last_growth.

	* write.c (cvt_frag_to_fill): Check size of rs_leb128.
	(relax_segment): Break infinite loop for rs_leb128.

--- gas/frags.h.relax	2006-04-18 02:58:26.000000000 -0700
+++ gas/frags.h	2007-02-23 23:01:43.000000000 -0800
@@ -77,6 +77,14 @@ struct frag {
   unsigned int has_code:1;
   unsigned int insn_addr:6;
 
+#define LAST_GROWTH_NONE	0
+#define LAST_GROWTH_INCREASE	1
+#define LAST_GROWTH_SHRINK	2
+  /* Remember previous growths/shrinks to avoid infinite loop during
+     relaxation.  */
+  unsigned int growth_count: 4;
+  unsigned int last_growth: 2;
+
   /* What state is my tail in? */
   relax_stateT fr_type;
   relax_substateT fr_subtype;
--- gas/write.c.relax	2007-02-22 01:43:45.000000000 -0800
+++ gas/write.c	2007-02-23 23:07:03.000000000 -0800
@@ -448,6 +448,7 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNU
 	size = output_leb128 (fragP->fr_literal + fragP->fr_fix, value,
 			      fragP->fr_subtype);
 
+	assert (size == fragP->fr_offset);
 	fragP->fr_fix += size;
 	fragP->fr_type = rs_fill;
 	fragP->fr_var = 0;
@@ -2208,7 +2209,48 @@ relax_segment (struct frag *segment_frag
 		  value = resolve_symbol_value (fragP->fr_symbol);
 		  size = sizeof_leb128 (value, fragP->fr_subtype);
 		  growth = size - fragP->fr_offset;
-		  fragP->fr_offset = size;
+		  if (growth == -1
+		      && fragP->growth_count == 0xf)
+		    {
+		      /* There are 15 growths after shrinks. To break
+			 the infinite loop, we grow the size by 1
+			 instead of shrinking it by 1.  See testcase in
+			 PR gas/4029.  */
+		      growth = 1;
+		    }
+		  else
+		    {
+		      fragP->fr_offset = size;
+		      /* We only count shrink after growth and vice
+			 versa.  */
+		      if (growth == 1)
+			{
+			  if (fragP->last_growth == LAST_GROWTH_SHRINK)
+			    {
+			      if (fragP->growth_count != 0xf)
+				fragP->growth_count++;
+			    }
+			  else
+			    fragP->growth_count = 0;
+			  fragP->last_growth = LAST_GROWTH_INCREASE;
+			}
+		      else if (growth == -1)
+			{
+			  if (fragP->last_growth == LAST_GROWTH_INCREASE)
+			    {
+			      if (fragP->growth_count != 0xf)
+				fragP->growth_count++;
+			    }
+			  else
+			    fragP->growth_count = 0;
+			  fragP->last_growth = LAST_GROWTH_SHRINK;
+			}
+		      else
+			{
+			  fragP->growth_count = 0;
+			  fragP->last_growth = LAST_GROWTH_NONE;
+			}
+		    }
 		}
 		break;
 


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