aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2019-04-19 10:39:47 +0100
committerNick Clifton <nickc@redhat.com>2019-04-19 10:39:47 +0100
commit5ce032bdfc60a8f44f6307b2297384c852100f95 (patch)
treecaba4efd415ea2d34cef2332481458b8b8f377db
parentfce9773608d45757dfb26ef7783f37d432ae9a88 (diff)
downloadgdb-5ce032bdfc60a8f44f6307b2297384c852100f95.zip
gdb-5ce032bdfc60a8f44f6307b2297384c852100f95.tar.gz
gdb-5ce032bdfc60a8f44f6307b2297384c852100f95.tar.bz2
RX Assembler: Ensure that the internal limit on the number of relaxation iterations is not larger that the external limit.
PR 24464 * config/tc-rx.h (md_relax_frag): Pass the max_iterations variable to the relaxation function. * config/tc-rx.c (rx_relax_frag): Add new parameter - the maximum number of iterations. Make sure that our internal iteration limit does not exceed this external iteration limit.
-rw-r--r--gas/ChangeLog9
-rw-r--r--gas/config/tc-rx.c19
-rw-r--r--gas/config/tc-rx.h11
3 files changed, 31 insertions, 8 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5488ef2..d49ec4d 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,12 @@
+2019-04-19 Nick Clifton <nickc@redhat.com>
+
+ PR 24464
+ * config/tc-rx.h (md_relax_frag): Pass the max_iterations variable
+ to the relaxation function.
+ * config/tc-rx.c (rx_relax_frag): Add new parameter - the maximum
+ number of iterations. Make sure that our internal iteration limit
+ does not exceed this external iteration limit.
+
2019-04-18 Matthew Fortune <matthew.fortune@mips.com>
* config/tc-mips.c (match_non_zero_reg_operand): Update
diff --git a/gas/config/tc-rx.c b/gas/config/tc-rx.c
index 8688837..6b19f2f 100644
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -740,8 +740,8 @@ typedef struct rx_bytesT
int n_relax;
int link_relax;
fixS *link_relax_fixP;
- char times_grown;
- char times_shrank;
+ unsigned long times_grown;
+ unsigned long times_shrank;
} rx_bytesT;
static rx_bytesT rx_bytes;
@@ -1558,7 +1558,7 @@ rx_next_opcode (fragS *fragP)
fr_subtype to calculate the difference. */
int
-rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
+rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch, unsigned long max_iterations)
{
addressT addr0, sym_addr;
addressT mypc;
@@ -1755,9 +1755,16 @@ rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
/* This prevents infinite loops in align-heavy sources. */
if (newsize < oldsize)
{
- if (fragP->tc_frag_data->times_shrank > 10
- && fragP->tc_frag_data->times_grown > 10)
- newsize = oldsize;
+ /* Make sure that our iteration limit is no bigger than the one being
+ used inside write.c:relax_segment(). Otherwise we can end up
+ iterating for too long, and triggering a fatal error there. See
+ PR 24464 for more details. */
+ unsigned long limit = max_iterations > 10 ? 10 : max_iterations;
+
+ if (fragP->tc_frag_data->times_shrank > limit
+ && fragP->tc_frag_data->times_grown > limit)
+ newsize = oldsize;
+
if (fragP->tc_frag_data->times_shrank < 20)
fragP->tc_frag_data->times_shrank ++;
}
diff --git a/gas/config/tc-rx.h b/gas/config/tc-rx.h
index 09c50f9..69302e5 100644
--- a/gas/config/tc-rx.h
+++ b/gas/config/tc-rx.h
@@ -54,8 +54,15 @@ extern int target_big_endian;
#define md_end rx_md_end
extern void rx_md_end (void);
-#define md_relax_frag rx_relax_frag
-extern int rx_relax_frag (segT, fragS *, long);
+/* Note - the definition of MD_RELAX_FRAG here includes a reference to the
+ MAX_ITERATIONS variable which is defined locally in write.c:relax_segment()
+ but which is not normally passed to target specific relaxing code. This
+ reference is needed however as the number of iterations of the RX relaxing
+ code needs to be constrained by the maximum number of iterations allowed
+ by relax_segment(). See PR 24464 for more details. */
+#define md_relax_frag(SEG, FRAGP, STRETCH) \
+ rx_relax_frag ((SEG), (FRAGP), (STRETCH), max_iterations)
+extern int rx_relax_frag (segT, fragS *, long, unsigned long);
#define TC_FRAG_TYPE struct rx_bytesT *
#define TC_FRAG_INIT(fragp, max_bytes) rx_frag_init (fragp)