This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
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 18:54:38 -0800
- Subject: PATCH: PR gas/4029: relax_segment can't stabilize .gcc_except_table
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.
H.J.
----
2007-02-19 H.J. Lu <hongjiu.lu@intel.com>
PR gas/4029
* frags.h (frag): Add growths and shrinks.
* 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 18:51:23.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 growths: 2;
+ unsigned int shrinks: 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 18:49:43.000000000 -0800
@@ -2258,7 +2258,26 @@ 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->growths == 0x3
+ && fragP->shrinks == 0x3)
+ {
+ /* There are 3 growths after 3 shrinks. To break
+ infinite loop, we grow the size by 1 instead of
+ shrink it by 1. */
+ growth = 1;
+ }
+ else
+ {
+ fragP->fr_offset = size;
+ if (growth == -1 && fragP->shrinks != 0x3)
+ fragP->shrinks++;
+ /* Start counting growth after the first shrink. */
+ if (fragP->shrinks
+ && growth == 1
+ && fragP->growths != 3)
+ fragP->growths++;
+ }
}
break;