This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: PR gas/4029: relax_segment can't stabilize .gcc_except_table
- From: "H. J. Lu" <hjl at lucon dot org>
- To: binutils at sources dot redhat dot com
- Date: Sun, 18 Feb 2007 23:19:27 -0800
- Subject: Re: PATCH: PR gas/4029: relax_segment can't stabilize .gcc_except_table
- References: <20070219025438.GA10913@lucon.org>
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;