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 Sun, Feb 18, 2007 at 06:54:38PM -0800, H. J. Lu wrote:
> The problem is with rs_leb128 processing. When size needed for
> the new value is 0x3fff is 2 and the old size is 3, growth is -1. Then
> the next time the new value becomes 0x4000 and its size becomes 3. That
> is an infinite loop.
> 
> This patch breaks the infinite loop by growing the size by 1 instead
> of shrinking it by 1 when there are 3 growths after 3 shrinks.
> 

Here is an updated patch. This patch only counts shrink after growth
and vice versa.


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

	PR gas/4029
	* frags.h (frag): Add growth_count and last_growth.

	* write.c (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-18 23:01:43.000000000 -0800
@@ -77,6 +77,11 @@ struct frag {
   unsigned int has_code:1;
   unsigned int insn_addr:6;
 
+  /* 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-17 16:02:34.000000000 -0800
+++ gas/write.c	2007-02-18 23:11:40.000000000 -0800
@@ -2258,7 +2258,44 @@ 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.  */
+		      growth = 1;
+		    }
+		  else
+		    {
+		      fragP->fr_offset = size;
+		      /* We only count shrink after growth and vice
+			 versa.  */
+		      if (growth == 1)
+			{
+			  if (fragP->last_growth == 2)
+			    {
+			      if (fragP->growth_count != 0xf)
+				fragP->growth_count++;
+			    }
+			  else
+			    fragP->growth_count = 0;
+			  fragP->last_growth = 1;
+			}
+		      else if (growth == -1)
+			{
+			  if (fragP->last_growth == 1)
+			    {
+			      if (fragP->growth_count != 0xf)
+				fragP->growth_count++;
+			    }
+			  else
+			    fragP->growth_count = 0;
+			  fragP->last_growth = 2;
+			}
+		      else
+			fragP->last_growth = 0;
+		    }
 		}
 		break;
 


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