diff options
author | Nick Clifton <nickc@redhat.com> | 2019-04-19 10:39:47 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-04-19 10:39:47 +0100 |
commit | 5ce032bdfc60a8f44f6307b2297384c852100f95 (patch) | |
tree | caba4efd415ea2d34cef2332481458b8b8f377db /gas | |
parent | fce9773608d45757dfb26ef7783f37d432ae9a88 (diff) | |
download | binutils-gdb-5ce032bdfc60a8f44f6307b2297384c852100f95.tar.gz |
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.
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 9 | ||||
-rw-r--r-- | gas/config/tc-rx.c | 19 | ||||
-rw-r--r-- | gas/config/tc-rx.h | 11 |
3 files changed, 31 insertions, 8 deletions
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 <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 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) |