Now that we internally handle a set LSB as part of a C64 STT_FUNC value throughout the assembler rather than as something that is just introduced by the linker, relocations to code labels now may or may not include that LSB.
GAS checks that the target of an AARCH64 BRANCH19, TSTBR14, CALL26, or JUMP26 relocation is aligned, since all uses should point to an instruction and all instructions should be aligned. Now that we are including the LSB in the value of STT_FUNC C64 symbols, the relevant MORELLO_* relocations do not also satisfy this alignment behaviour. When these relocations target a location generated from an STT_FUNC C64 symbol, their value includes that LSB.
This behaviour is not relevant to the user since these relocations lose the bottom 2 bits of the value they target. It does however match the specification of the relocations in the ABI document, which includes the `C` bit. This fix avoids requiring that this LSB is unset when in `md_apply_fix`. For extra robustness we also assert that when setting this LSB on the symbol in the first place it was not set to begin with.
A downside is that if the LSB is set on non-function symbols the user will not be warned about that. Any method to handle that would always need to determine which expressions should include this LSB and which shouldn't, which would be difficult to make perfect. On top of that, the relevant code would either have to duplicate the code in `fixup_segment` that resolves an expression into a single value, or record another bit in the `TC_FIX_TYPE` structure just for this warning.
This seems like more complexity than the extra warning is worth.
We add two tests since `objdump` shows the resulting disassembly but `readelf` shows the LSB getting set on the relevant functions.
############### Attachment also inlined for ease of reply ###############
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 4b66d542191263fbef4ff6f82957848c3fe2708f..765996c624f9b646317f33c7cc07d51ab359e6b4 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -7710,7 +7710,10 @@ aarch64_frob_label (symbolS * sym)
AARCH64_SET_C64 (sym, IS_C64); if (AARCH64_IS_C64 (sym) && S_IS_FUNCTION (sym)) - *symbol_X_add_number (sym) += 1; + { + gas_assert ((*symbol_X_add_number (sym) & 1) == 0); + *symbol_X_add_number (sym) += 1; + }
dwarf2_emit_label (sym); } @@ -8500,6 +8503,15 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; int scale; unsigned flags = fixP->fx_addnumber; + /* We check alignment for relocations of this kind. These relocations could + be applied on a C64 STT_FUNC symbol and hence may have the LSB set on + `*valP`, their AARCH64 counterparts can not be applied on such symbols and + hence should never have the LSB set on their value. */ + valueT alignment_mask = (fixP->fx_r_type == BFD_RELOC_MORELLO_BRANCH19 + || fixP->fx_r_type == BFD_RELOC_MORELLO_TSTBR14 + || fixP->fx_r_type == BFD_RELOC_MORELLO_CALL26 + || fixP->fx_r_type == BFD_RELOC_MORELLO_JUMP26) + ? 2 : 3;
DEBUG_TRACE ("\n\n"); DEBUG_TRACE ("~~~~~~~~~~~~~~~~~~~~~~~~~"); @@ -8609,7 +8621,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) case BFD_RELOC_MORELLO_BRANCH19: if (fixP->fx_done || !seg->use_rela_p) { - if (value & 3) + if (value & alignment_mask) as_bad_where (fixP->fx_file, fixP->fx_line, _("conditional branch target not word aligned")); if (signed_overflow (value, 21)) @@ -8625,7 +8637,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) case BFD_RELOC_AARCH64_TSTBR14: if (fixP->fx_done || !seg->use_rela_p) { - if (value & 3) + if (value & alignment_mask) as_bad_where (fixP->fx_file, fixP->fx_line, _("conditional branch target not word aligned")); if (signed_overflow (value, 16)) @@ -8643,7 +8655,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) case BFD_RELOC_AARCH64_JUMP26: if (fixP->fx_done || !seg->use_rela_p) { - if (value & 3) + if (value & alignment_mask) as_bad_where (fixP->fx_file, fixP->fx_line, _("branch target not word aligned")); if (signed_overflow (value, 28)) diff --git a/gas/testsuite/gas/aarch64/morello-lsb-relocs.d b/gas/testsuite/gas/aarch64/morello-lsb-relocs.d new file mode 100644 index 0000000000000000000000000000000000000000..226801b23a8a9061d466dbfcdc220b9eb279a25e --- /dev/null +++ b/gas/testsuite/gas/aarch64/morello-lsb-relocs.d @@ -0,0 +1,46 @@ +#as: -march=armv8-a+c64 +#objdump: -drt + +.*.o: file format .* + +SYMBOL TABLE: +0000000000000000 l d .text 0000000000000000 .text +0000000000000000 l d .data 0000000000000000 .data +0000000000000000 l d .bss 0000000000000000 .bss +000000000000000c l F .text 0000000000000000 a +000000000000000c l .text 0000000000000000 altlabel +000000000000000c g F .text 0000000000000000 f +0000000000000000 *UND* 0000000000000000 x + + + +Disassembly of section .text: + +0000000000000000 <f-0xc>: + ... + +000000000000000c <f>: + c: 14000000 b 0 <x> + c: R_MORELLO_JUMP26 x + 10: 14000000 b c <f> + 10: R_MORELLO_JUMP26 f + 14: 17fffffe b c <f> + 18: 17fffffd b c <f> + 1c: 5400000d b.le 0 <x> + 1c: R_MORELLO_CONDBR19 x + 20: 5400000d b.le c <f> + 20: R_MORELLO_CONDBR19 f + 24: 54ffff4d b.le c <f> + 28: 54ffff2d b.le c <f> + 2c: 36080001 tbz w1, #1, 0 <x> + 2c: R_MORELLO_TSTBR14 x + 30: 36080001 tbz w1, #1, c <f> + 30: R_MORELLO_TSTBR14 f + 34: 360ffec1 tbz w1, #1, c <f> + 38: 360ffea1 tbz w1, #1, c <f> + 3c: 94000000 bl 0 <x> + 3c: R_MORELLO_CALL26 x + 40: 94000000 bl c <f> + 40: R_MORELLO_CALL26 f + 44: 97fffff2 bl c <f> + 48: 97fffff1 bl c <f> diff --git a/gas/testsuite/gas/aarch64/morello-lsb-relocs.s b/gas/testsuite/gas/aarch64/morello-lsb-relocs.s new file mode 100644 index 0000000000000000000000000000000000000000..227b023e220386e4630e869ca4f62e7b4e7ff410 --- /dev/null +++ b/gas/testsuite/gas/aarch64/morello-lsb-relocs.s @@ -0,0 +1,32 @@ + .text + // Just to make it a bit clearer to humans reading the tests that we + // use the address of `f` and `altlabel` in some places. Otherwise + // when reading the disassembly you just see `0` and it's not 100% + // clear that we're using the address vs using a dummy value for later. + .zero 12 + .p2align 2 + .globl f + .type f,@function + .type a,@function +f: // This function is global, so relocations will remain in the + // object file. +a: // This function is local, so the relocation on the ADR + // instruction will be relaxed to a value. +altlabel: // This label does not have function type, so will not have the + // LSB set. + b x + b f + b a + b altlabel + b.le x + b.le f + b.le a + b.le altlabel + tbz x1, 1, x + tbz x1, 1, f + tbz x1, 1, a + tbz x1, 1, altlabel + bl x + bl f + bl a + bl altlabel diff --git a/gas/testsuite/gas/aarch64/morello-lsb-relocs2.d b/gas/testsuite/gas/aarch64/morello-lsb-relocs2.d new file mode 100644 index 0000000000000000000000000000000000000000..aa99c58a70c4e1a104525fef1d8eb997a346ad06 --- /dev/null +++ b/gas/testsuite/gas/aarch64/morello-lsb-relocs2.d @@ -0,0 +1,28 @@ +#as: -march=morello+c64 +#readelf: --relocs --syms +#source: morello-lsb-relocs.s + + +Relocation section '.rela.text' at offset 0x198 contains 8 entries: + Offset Info Type Sym. Value Sym. Name + Addend +00000000000c 00090000e002 R_MORELLO_JUMP26 0000000000000000 x + 0 +000000000010 00080000e002 R_MORELLO_JUMP26 000000000000000d f + 0 +00000000001c 00090000e001 R_MORELLO_CONDBR1 0000000000000000 x + 0 +000000000020 00080000e001 R_MORELLO_CONDBR1 000000000000000d f + 0 +00000000002c 00090000e000 R_MORELLO_TSTBR14 0000000000000000 x + 0 +000000000030 00080000e000 R_MORELLO_TSTBR14 000000000000000d f + 0 +00000000003c 00090000e003 R_MORELLO_CALL26 0000000000000000 x + 0 +000000000040 00080000e003 R_MORELLO_CALL26 000000000000000d f + 0 + +Symbol table '.symtab' contains 10 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 SECTION LOCAL DEFAULT 1 + 2: 0000000000000000 0 SECTION LOCAL DEFAULT 3 + 3: 0000000000000000 0 SECTION LOCAL DEFAULT 4 + 4: 0000000000000000 0 NOTYPE LOCAL DEFAULT 1 $d + 5: 000000000000000c 0 NOTYPE LOCAL DEFAULT 1 $c + 6: 000000000000000d 0 FUNC LOCAL DEFAULT 1 a + 7: 000000000000000c 0 NOTYPE LOCAL DEFAULT 1 altlabel + 8: 000000000000000d 0 FUNC GLOBAL DEFAULT 1 f + 9: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND x