From: Jan Beulich Date: Fri, 10 Jan 2025 07:42:41 +0000 (+0100) Subject: aarch64: re-work PR gas/27217 fix again X-Git-Tag: binutils-2_44~211 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e18fc11e47b91961ef4254323abad2a522725af2;p=thirdparty%2Fbinutils-gdb.git aarch64: re-work PR gas/27217 fix again Commit c1723a8118f0 ("Arm64: re-work PR gas/27217 fix") really was only a band-aid; Nick's original solution to the problem was technically preferable, yet didn't work when . came into play. Undo most of that change, now that expr_defer expression parsing mode latches dot as is desired here. Also add testing for the . case, which I should have done already back at the time. --- diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 3046d3d8b5e..47d9e93fd16 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -662,18 +662,25 @@ static bool in_aarch64_get_expression = false; #define ALLOW_ABSENT false #define REJECT_ABSENT true +/* Fifth argument to aarch64_get_expression. */ +#define NORMAL_RESOLUTION false + /* Return TRUE if the string pointed by *STR is successfully parsed as an valid expression; *EP will be filled with the information of such an expression. Otherwise return FALSE. If ALLOW_IMMEDIATE_PREFIX is true then skip a '#' at the start. - If REJECT_ABSENT is true then trat missing expressions as an error. */ + If REJECT_ABSENT is true then trat missing expressions as an error. + If DEFER_RESOLUTION is true, then do not resolve expressions against + constant symbols. Necessary if the expression is part of a fixup + that uses a reloc that must be emitted. */ static bool aarch64_get_expression (expressionS * ep, char ** str, bool allow_immediate_prefix, - bool reject_absent) + bool reject_absent, + bool defer_resolution) { char *save_in; segT seg; @@ -693,7 +700,10 @@ aarch64_get_expression (expressionS * ep, save_in = input_line_pointer; input_line_pointer = *str; in_aarch64_get_expression = true; - seg = expression (ep); + if (defer_resolution) + seg = deferred_expression (ep); + else + seg = expression (ep); in_aarch64_get_expression = false; if (ep->X_op == O_illegal || (reject_absent && ep->X_op == O_absent)) @@ -1159,7 +1169,8 @@ parse_index_expression (char **str, int64_t *imm) { expressionS exp; - aarch64_get_expression (&exp, str, GE_NO_PREFIX, REJECT_ABSENT); + aarch64_get_expression (&exp, str, GE_NO_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION); if (exp.X_op != O_constant) { first_error (_("constant expression required")); @@ -2542,7 +2553,8 @@ parse_immediate_expression (char **str, expressionS *exp, return false; } - aarch64_get_expression (exp, str, GE_OPT_PREFIX, REJECT_ABSENT); + aarch64_get_expression (exp, str, GE_OPT_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION); if (exp->X_op == O_absent) { @@ -2776,7 +2788,8 @@ parse_big_immediate (char **str, int64_t *imm, aarch64_reg_type reg_type) return false; } - aarch64_get_expression (&inst.reloc.exp, &ptr, GE_OPT_PREFIX, REJECT_ABSENT); + aarch64_get_expression (&inst.reloc.exp, &ptr, GE_OPT_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION); if (inst.reloc.exp.X_op == O_constant) *imm = inst.reloc.exp.X_add_number; @@ -3673,7 +3686,8 @@ parse_shift (char **str, aarch64_opnd_info *operand, enum parse_shift_mode mode) p++; exp_has_prefix = 1; } - aarch64_get_expression (&exp, &p, GE_NO_PREFIX, ALLOW_ABSENT); + aarch64_get_expression (&exp, &p, GE_NO_PREFIX, ALLOW_ABSENT, + NORMAL_RESOLUTION); } if (kind == AARCH64_MOD_MUL_VL) /* For consistency, give MUL VL the same shift amount as an implicit @@ -3737,7 +3751,7 @@ parse_shifter_operand_imm (char **str, aarch64_opnd_info *operand, /* Accept an immediate expression. */ if (! aarch64_get_expression (&inst.reloc.exp, &p, GE_OPT_PREFIX, - REJECT_ABSENT)) + REJECT_ABSENT, NORMAL_RESOLUTION)) return false; /* Accept optional LSL for arithmetic immediate values. */ @@ -3896,7 +3910,8 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand, /* Next, we parse the expression. */ if (! aarch64_get_expression (&inst.reloc.exp, str, GE_NO_PREFIX, - REJECT_ABSENT)) + REJECT_ABSENT, + aarch64_force_reloc (entry->add_type) == 1)) return false; /* Record the relocation type (use the ADD variant here). */ @@ -4091,7 +4106,8 @@ parse_address_main (char **str, aarch64_opnd_info *operand, } /* #:: */ - if (! aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT)) + if (! aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT, + aarch64_force_reloc (ty) == 1)) { set_syntax_error (_("invalid relocation expression")); return false; @@ -4107,7 +4123,8 @@ parse_address_main (char **str, aarch64_opnd_info *operand, /* =immediate; need to generate the literal in the literal pool. */ inst.gen_lit_pool = 1; - if (!aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT)) + if (!aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION)) { set_syntax_error (_("invalid address")); return false; @@ -4221,7 +4238,8 @@ parse_address_main (char **str, aarch64_opnd_info *operand, /* We now have the group relocation table entry corresponding to the name in the assembler source. Next, we parse the expression. */ - if (! aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT)) + if (! aarch64_get_expression (exp, &p, GE_NO_PREFIX, REJECT_ABSENT, + aarch64_force_reloc (entry->ldst_type) == 1)) { set_syntax_error (_("invalid relocation expression")); return false; @@ -4234,7 +4252,8 @@ parse_address_main (char **str, aarch64_opnd_info *operand, } else { - if (! aarch64_get_expression (exp, &p, GE_OPT_PREFIX, REJECT_ABSENT)) + if (! aarch64_get_expression (exp, &p, GE_OPT_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION)) { set_syntax_error (_("invalid expression in the address")); return false; @@ -4290,7 +4309,8 @@ parse_address_main (char **str, aarch64_opnd_info *operand, operand->addr.offset.regno = reg->number; operand->addr.offset.is_reg = 1; } - else if (! aarch64_get_expression (exp, &p, GE_OPT_PREFIX, REJECT_ABSENT)) + else if (! aarch64_get_expression (exp, &p, GE_OPT_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION)) { /* [Xn],#expr */ set_syntax_error (_("invalid expression in the address")); @@ -4418,7 +4438,8 @@ parse_half (char **str, int *internal_fixup_p) else *internal_fixup_p = 1; - if (! aarch64_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, REJECT_ABSENT)) + if (! aarch64_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, REJECT_ABSENT, + aarch64_force_reloc (inst.reloc.type) == 1)) return false; *str = p; @@ -4460,7 +4481,8 @@ parse_adrp (char **str) inst.reloc.type = BFD_RELOC_AARCH64_ADR_HI21_PCREL; inst.reloc.pc_rel = 1; - if (! aarch64_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, REJECT_ABSENT)) + if (! aarch64_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, REJECT_ABSENT, + aarch64_force_reloc (inst.reloc.type) == 1)) return false; *str = p; return true; @@ -7222,7 +7244,8 @@ parse_operands (char *str, const aarch64_opcode *opcode) goto failure; str = saved; po_misc_or_fail (aarch64_get_expression (&inst.reloc.exp, &str, - GE_OPT_PREFIX, REJECT_ABSENT)); + GE_OPT_PREFIX, REJECT_ABSENT, + NORMAL_RESOLUTION)); /* The MOV immediate alias will be fixed up by fix_mov_imm_insn later. fix_mov_imm_insn will try to determine a machine instruction (MOVZ, MOVN or ORR) for it and will issue an error @@ -9604,8 +9627,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) /* Note whether this will delete the relocation. */ - if (fixP->fx_addsy == 0 && !fixP->fx_pcrel - && aarch64_force_reloc (fixP->fx_r_type) <= 0) + if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) fixP->fx_done = 1; /* Process the relocations. */ diff --git a/gas/testsuite/gas/aarch64/pr27217.d b/gas/testsuite/gas/aarch64/pr27217.d index ddbfb3229d3..8dc355b3f28 100644 --- a/gas/testsuite/gas/aarch64/pr27217.d +++ b/gas/testsuite/gas/aarch64/pr27217.d @@ -10,8 +10,19 @@ Disassembly of section \.text: 0+000 <.*>: [ ]+0:[ ]+90000000[ ]+adrp[ ]+x0, [0-9]*[ ]+<.*> -[ ]+0:[ ]+R_AARCH64(|_P32)_ADR_PREL_PG_HI21[ ]+\*ABS\*\+0x12345678 +[ ]+0:[ ]+R_AARCH64(|_P32)_ADR_PREL_PG_HI21[ ]+bar [ ]+4:[ ]+91000000[ ]+add[ ]+x0, x0, #0x0 -[ ]+4:[ ]+R_AARCH64(|_P32)_ADD_ABS_LO12_NC[ ]+\*ABS\*\+0x12345678 +[ ]+4:[ ]+R_AARCH64(|_P32)_ADD_ABS_LO12_NC[ ]+bar [ ]+8:[ ]+d65f03c0[ ]+ret +#... +0+010 <.*>: +[ ]+10:[ ]+90000000[ ]+adrp[ ]+x0, [0-9]*[ ]+<.*> +[ ]+10:[ ]+R_AARCH64(|_P32)_ADR_PREL_PG_HI21[ ]+\.text\+0x10 +[ ]+14:[ ]+91000000[ ]+add[ ]+x0, x0, #0x0 +[ ]+14:[ ]+R_AARCH64(|_P32)_ADD_ABS_LO12_NC[ ]+\.text\+0x10 +[ ]+18:[ ]+90000001[ ]+adrp[ ]+x1, [0-9]*[ ]+<.*> +[ ]+18:[ ]+R_AARCH64(|_P32)_ADR_PREL_PG_HI21[ ]+\.text\+0x1c +[ ]+1c:[ ]+91000021[ ]+add[ ]+x1, x1, #0x0 +[ ]+1c:[ ]+R_AARCH64(|_P32)_ADD_ABS_LO12_NC[ ]+\.text\+0x1c +[ ]+20:[ ]+d65f03c0[ ]+ret #pass diff --git a/gas/testsuite/gas/aarch64/pr27217.s b/gas/testsuite/gas/aarch64/pr27217.s index 8cb92309f35..08aa64bb3d2 100644 --- a/gas/testsuite/gas/aarch64/pr27217.s +++ b/gas/testsuite/gas/aarch64/pr27217.s @@ -13,4 +13,13 @@ foo: add x0, x0, :lo12:bar ret .size foo, .-foo - .ident "GCC: (GNU) 10.2.1 20201030 (RTEMS 6, RSB " + + .p2align 4 + .type dot, %function +dot: + adrp x0, . + add x0, x0, :lo12:. - 4 + adrp x1, . + 4 + add x1, x1, :lo12:. + ret + .size dot, .-dot