We're disabling transformations of relocations against symbols like this in the assembler when the relocation is against something in the GOT and when the relocation is against something which generates a capability.
For entries in the GOT we disable this transformation since the GNU bfd linker relies on indexing into its internal representation of the GOT using symbols and does not distiinguish between entries using the same symbol but different offsets. Hence transforming multiple symbols into the same section symbol with different offsets would mean that at least one will get an incorrect value.
Relocations which require the static linker to emit dynamic relocations in order to generate capabilities (CAPINIT and capability relocations into the GOT) require symbol information so that the dynamic linker can put correct permissions and bounds on those relocations.
NOTE: We get to use an existing testcase for this change, but it showed up something strange about objdump. One `adrp` instruction has changed in the output so that it shows as pointing to a different location. This happens to be an `objdump` quirk. Objdump looks at the relocation associated with an address and attempts to include that relocation when determining what address to print out. This mechanism has two problems, one is that objdump does not account for the offset in that relocation (only the symbol). Another is that on an object file (i.e. not a final executable) the virtual memory address of all sections is zero. These combined mean that the vma is miscalculated, and the translation from vma to symbol is not injective. In other words: the extra change in morello-ldst-reloc.d on top of switching the relocation symbols is in order to account for an objdump bug and not a problem with this gas change.
############### Attachment also inlined for ease of reply ###############
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index a1bd6e1a769d968ed0bdb2b3dca7bc87732cc498..c8373b311dd14f3c53ce4099ab1ffee28d360e8a 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -9382,13 +9382,37 @@ check_mapping_symbols (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, bfd_boolean aarch64_fix_adjustable (struct fix *fixP) { - /* We need size information of the target symbols to initialise - capabilities. */ - if (fixP->fx_r_type == BFD_RELOC_MORELLO_CAPINIT) - return FALSE; - switch (fixP->fx_r_type) { + /* The AArch64 GNU bfd linker can not handle 'symbol + offset' entries in the + GOT (it internally uses a symbol to reference a GOT slot). Hence we can't + emit any "section symbol + offset" relocations for the GOT. */ + case BFD_RELOC_AARCH64_GOT_LD_PREL19: + case BFD_RELOC_AARCH64_ADR_GOT_PAGE: + case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: + case BFD_RELOC_AARCH64_LD_GOT_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_LO12_NC: + return FALSE; + + /* We need size information of the target symbols to initialise + capabilities. */ + case BFD_RELOC_MORELLO_CAPINIT: + case BFD_RELOC_MORELLO_ADR_GOT_PAGE: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: + return FALSE; + /* We need to retain symbol information when jumping between A64 and C64 states or between two C64 functions. In the C64 -> C64 situation it's really only a corner case that breaks when symbols get replaced with diff --git a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d index d2fb08ec9d13c28e6fa70f12c8f49f88fc37f34f..2199e90dd9091367ff6b8f237fa806ab642386ca 100644 --- a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d +++ b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d @@ -21,13 +21,13 @@ Disassembly of section .text: .*: R_AARCH64_ADD_ABS_LO12_NC ptr
.* <f1>: - .*: 90800002 adrp c2, 0 <_start> - .*: R_MORELLO_ADR_GOT_PAGE .data+0x10 + .*: 90800002 adrp c2, 10 <add> + .*: R_MORELLO_ADR_GOT_PAGE cap .*: c2400042 ldr c2, [c2] - .*: R_MORELLO_LD128_GOT_LO12_NC .data+0x10 + .*: R_MORELLO_LD128_GOT_LO12_NC cap .*: 82600042 ldr c2, [x2] - .*: R_MORELLO_LD128_GOT_LO12_NC .data+0x20 + .*: R_MORELLO_LD128_GOT_LO12_NC ptr .*: f9400042 ldr x2, [c2] - .*: R_AARCH64_LD64_GOT_LO12_NC .data+0x20 + .*: R_AARCH64_LD64_GOT_LO12_NC ptr .*: 82600c42 ldr x2, [x2] - .*: R_AARCH64_LD64_GOT_LO12_NC .data+0x20 + .*: R_AARCH64_LD64_GOT_LO12_NC ptr diff --git a/gas/testsuite/gas/aarch64/reloc-insn.d b/gas/testsuite/gas/aarch64/reloc-insn.d index 0f3b4143d964ed08ef1d435fd518a7e2b13a80f8..8898a88bca0fe8f8e2755741c9d466636bf4aaff 100644 --- a/gas/testsuite/gas/aarch64/reloc-insn.d +++ b/gas/testsuite/gas/aarch64/reloc-insn.d @@ -157,9 +157,9 @@ Disassembly of section .text: 18c: 39400001 ldrb w1, [x0] 190: d65f03c0 ret 194: f94001bc ldr x28, [x13] - 194: R_AARCH64_LD64_GOTPAGE_LO15 .data + 194: R_AARCH64_LD64_GOTPAGE_LO15 dummy 198: f9400000 ldr x0, [x0] - 198: R_AARCH64_LD64_GOTOFF_LO15 .data + 198: R_AARCH64_LD64_GOTOFF_LO15 dummy
000000000000019c <llit>: 19c: deadf00d .word 0xdeadf00d
gnu-morello@op-lists.linaro.org