From: Nick Clifton Date: Fri, 19 Apr 2019 09:39:47 +0000 (+0100) Subject: RX Assembler: Ensure that the internal limit on the number of relaxation iterations... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5ce032bdfc60a8f44f6307b2297384c852100f95;p=binutils-gdb.git 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 5488ef21dfe..d49ec4d9278 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2019-04-19 Nick Clifton + + 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 * 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 8688837b319..6b19f2f3971 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 09c50f94718..69302e565b7 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)