From f8c6b621d4ed4cf68f595845f0222530f8d00de0 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Fri, 4 Nov 2022 10:01:52 +0000 Subject: [PATCH] Disable some symbol -> section_symbol + offset translations 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. --- gas/config/tc-aarch64.c | 34 ++++++++++++++++--- .../gas/aarch64/morello-ldst-reloc.d | 12 +++---- gas/testsuite/gas/aarch64/reloc-insn.d | 4 +-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index a1bd6e1a769..c8373b311dd 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 d2fb08ec9d1..2199e90dd90 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 .* : - .*: 90800002 adrp c2, 0 <_start> - .*: R_MORELLO_ADR_GOT_PAGE \.data\+0x10 + .*: 90800002 adrp c2, 10 + .*: 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 0f3b4143d96..8898a88bca0 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 : 19c: deadf00d \.word 0xdeadf00d -- 2.39.2