From 37a5888387413a4b787468eff710eefebe134201 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 25 Oct 2019 19:46:24 +1030 Subject: PR25125, relaxation chooses wrong branch size The patch I made for PR12049 didn't test for a "negative" branch properly. "if (target < address)" ought to have been "if (target < address + fragP->fr_fix)". Rather than making that change, this patch adds fragP->fr_fix into address earlier. The patch also avoids running into a bad interaction with the m68k md_prepare_relax_scan by returning zero growth immediately, since the adjusted target expression would result in a zero "aim". PR gas/25125 PR gas/12049 * write.c (relax_frag): Correct calculation of delta for positive branches where "stretch" would make the branch negative. Return zero immediately in that case. Correct TC_PCREL_ADJUST comment. --- gas/ChangeLog | 9 +++++++++ gas/write.c | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index ac2e3d7..8b78037 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,12 @@ +2019-10-25 Alan Modra + + PR gas/25125 + PR gas/12049 + * write.c (relax_frag): Correct calculation of delta for + positive branches where "stretch" would make the branch + negative. Return zero immediately in that case. Correct + TC_PCREL_ADJUST comment. + 2019-10-16 Alan Modra * config/tc-xtensa.c (xg_order_trampoline_chain_entry): Don't diff --git a/gas/write.c b/gas/write.c index 9b5ae6f..8f7786e 100644 --- a/gas/write.c +++ b/gas/write.c @@ -2497,7 +2497,7 @@ relax_frag (segT segment, fragS *fragP, long stretch) const relax_typeS *table; target = fragP->fr_offset; - address = fragP->fr_address; + address = fragP->fr_address + fragP->fr_fix; table = TC_GENERIC_RELAX_TABLE; this_state = fragP->fr_subtype; start_type = this_type = table + this_state; @@ -2537,13 +2537,13 @@ relax_frag (segT segment, fragS *fragP, long stretch) negative. Don't allow this in case the negative reach is large enough to require a larger branch instruction. */ else if (target < address) - target = fragP->fr_next->fr_address + stretch; + return 0; } } - aim = target - address - fragP->fr_fix; + aim = target - address; #ifdef TC_PCREL_ADJUST - /* Currently only the ns32k family needs this. */ + /* Currently only the ns32k and arc needs this. */ aim += TC_PCREL_ADJUST (fragP); #endif -- cgit v1.1