From: Siddhesh Poyarekar Date: Fri, 11 Sep 2020 03:48:10 +0000 (+0530) Subject: [Morello] Add interworking and range extension veneers X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=50e192f0f26433193ae7f82cbc7ec98109e4fb8f;p=thirdparty%2Fbinutils-gdb.git [Morello] Add interworking and range extension veneers Add veneers to branch from A64 to C64 and vice versa and for range extension from C64 to C64. The veneers are named as __foo_a64c64_veneer, __foo_c64a64_veneer or simply __foo_veneer (where foo is the target function) based on whether the branch is from A64 to C64, the other way around or for extended range. A64 to C64 needs an additional BX since the ADRP in the veneer does not generate a valid capability without the switch using BX. As a result, the addendum LSB is no longer important for A64 -> C64 switch, but we keep it anyway so that we can use the same veneer for long range C64 to C64 branches. bfd/ChangeLog: 2020-10-20 Siddhesh Poyarekar * elfnn-aarch64.c (STUB_ENTRY_NAME): Add format specifier for veneer type. (C64_MAX_ADRP_IMM, C64_MIN_ADRP_IMM): New macros. (aarch64_branch_reloc_p, c64_valid_for_adrp_p, aarch64_interwork_stub): New functions. (aarch64_c64_branch_stub, c64_aarch64_branch_stub): New stubs. (elf_aarch64_stub_type): New members. (aarch64_type_of_stub): Support C64 stubs. (aarch64_lookup_stub_type_suffix): New function. (elfNN_aarch64_stub_name): Use it. (elfNN_aarch64_get_stub_entry): Add stub_type argument. Adjust callers. Support C64 stubs. (aarch64_build_one_stub): Likewise. (aarch64_size_one_stub): Likewise. (elfNN_aarch64_size_stubs): Likewise. (elfNN_aarch64_build_stubs): Save and return error if stub building failed. (elfNN_aarch64_final_link_relocate): Emit stubs based on whether source and target of a branch are different. (aarch64_map_one_stub): Emit mapping symbol for C64 stubs. ld/ChangeLog: 2020-10-20 Siddhesh Poyarekar * testsuite/ld-aarch64/aarch64-elf.exp: Add test. * testsuite/ld-aarch64/morello-stubs-static.d: New file. * testsuite/ld-aarch64/morello-stubs.d: New file. * testsuite/ld-aarch64/morello-stubs.ld: New file. * testsuite/ld-aarch64/morello-stubs.s: New file. The jump targets have limited range (i.e. limited by ADRP range) and hence cannot be used for very long jumps. The linker will throw an error for such out of range jumps. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6648a26cc3e..54abe00f310 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,26 @@ +2020-10-20 Siddhesh Poyarekar + + * elfnn-aarch64.c (STUB_ENTRY_NAME): Add format specifier for + veneer type. + (C64_MAX_ADRP_IMM, C64_MIN_ADRP_IMM): New macros. + (aarch64_branch_reloc_p, c64_valid_for_adrp_p, + aarch64_interwork_stub): New functions. + (aarch64_c64_branch_stub, c64_aarch64_branch_stub): New stubs. + (elf_aarch64_stub_type): New members. + (aarch64_type_of_stub): Support C64 stubs. + (aarch64_lookup_stub_type_suffix): New function. + (elfNN_aarch64_stub_name): Use it. + (elfNN_aarch64_get_stub_entry): Add stub_type argument. + Adjust callers. Support C64 stubs. + (aarch64_build_one_stub): Likewise. + (aarch64_size_one_stub): Likewise. + (elfNN_aarch64_size_stubs): Likewise. + (elfNN_aarch64_build_stubs): Save and return error if stub + building failed. + (elfNN_aarch64_final_link_relocate): Emit stubs based on + whether source and target of a branch are different. + (aarch64_map_one_stub): Emit mapping symbol for C64 stubs. + 2020-10-20 Siddhesh Poyarekar * elfnn-aarch64.c (elfNN_c64_small_plt0_entry, diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index c926dba170b..bd7da1610a7 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -2584,7 +2584,7 @@ elfNN_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, The entry_names are used to do simple name mangling on the stubs. Given a function name, and its type, the stub can be found. The name can be changed. The only requirement is the %s be present. */ -#define STUB_ENTRY_NAME "__%s_veneer" +#define STUB_ENTRY_NAME "__%s%s_veneer" /* The name of the dynamic interpreter. This is put in the .interp section. */ @@ -2598,6 +2598,26 @@ elfNN_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, #define AARCH64_MAX_ADRP_IMM ((1 << 20) - 1) #define AARCH64_MIN_ADRP_IMM (-(1 << 20)) +#define C64_MAX_ADRP_IMM ((1 << 19) - 1) +#define C64_MIN_ADRP_IMM (-(1 << 19)) + +static bfd_boolean +aarch64_branch_reloc_p (unsigned int r_type) +{ + switch (r_type) + { + case MORELLO_R (JUMP26): + case MORELLO_R (CALL26): + case AARCH64_R (JUMP26): + case AARCH64_R (CALL26): + return TRUE; + + default: break; + } + + return FALSE; +} + static int aarch64_valid_for_adrp_p (bfd_vma value, bfd_vma place) { @@ -2605,6 +2625,13 @@ aarch64_valid_for_adrp_p (bfd_vma value, bfd_vma place) return offset <= AARCH64_MAX_ADRP_IMM && offset >= AARCH64_MIN_ADRP_IMM; } +static bfd_boolean +c64_valid_for_adrp_p (bfd_vma value, bfd_vma place) +{ + bfd_signed_vma offset = (bfd_signed_vma) (PG (value) - PG (place)) >> 12; + return offset <= C64_MAX_ADRP_IMM && offset >= C64_MIN_ADRP_IMM; +} + static int aarch64_valid_branch_p (bfd_vma value, bfd_vma place) { @@ -2650,6 +2677,25 @@ static const uint32_t aarch64_erratum_843419_stub[] = 0x14000000, /* b