aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfnn-aarch64.c
diff options
context:
space:
mode:
authorSiddhesh Poyarekar <siddesh.poyarekar@arm.com>2020-05-19 11:07:52 +0100
committerNick Clifton <nickc@redhat.com>2020-05-19 11:07:52 +0100
commit7e05773767820b441b23a16628b55c98cb1aef46 (patch)
tree76a372538e574c4de9168c05126acc4908be6f81 /bfd/elfnn-aarch64.c
parent607b483327fdfc75fb193870b3c4e7445ce3f64d (diff)
downloadgdb-7e05773767820b441b23a16628b55c98cb1aef46.zip
gdb-7e05773767820b441b23a16628b55c98cb1aef46.tar.gz
gdb-7e05773767820b441b23a16628b55c98cb1aef46.tar.bz2
[PATCH v3] aarch64: Emit jump slot for conditional branch to undefined symbols
The linker silently writes out a conditional branch to 0 if the target symbol in R_AARCH64_CONDBR19 or R_AARCH64_TSTBR14 relocations is undefined. Emit a PLT instead so that behaviour is the same for these relocations as the llvm linker. The special behaviour for undefined weak symbols, where conditional branches to such symbols result in a branch unto themselves, has been retained. This is because the weak-undefined.s test explicitly checks for that, leading me to conclude that it's expected behaviour. bfd * elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Club BFD_RELOC_AARCH64_BRANCH19 and BFD_RELOC_AARCH64_TSTBR14 cases with BFD_RELOC_AARCH64_JUMP26. (elfNN_aarch64_check_relocs): Likewise. ld * testsuite/ld-aarch64/aarch64-elf.exp: New test emit-relocs-560. * testsuite/ld-aarch64/emit-relocs-560.d: New file. * testsuite/ld-aarch64/emit-relocs-560.s: New file.
Diffstat (limited to 'bfd/elfnn-aarch64.c')
-rw-r--r--bfd/elfnn-aarch64.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4bb5707..02df893 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -5494,6 +5494,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
bfd_vma orig_value = value;
bfd_boolean resolved_to_zero;
bfd_boolean abs_symbol_p;
+ bfd_boolean via_plt_p;
globals = elf_aarch64_hash_table (info);
@@ -5515,6 +5516,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
: bfd_is_und_section (sym_sec));
abs_symbol_p = h != NULL && bfd_is_abs_symbol (&h->root);
+ via_plt_p = (globals->root.splt != NULL && h != NULL
+ && h->plt.offset != (bfd_vma) - 1);
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
it here if it is defined in a non-shared object. */
@@ -5850,12 +5853,23 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
value += signed_addend;
break;
+ case BFD_RELOC_AARCH64_BRANCH19:
+ case BFD_RELOC_AARCH64_TSTBR14:
+ /* A conditional branch to an undefined weak symbol is converted to a
+ branch to itself. */
+ if (weak_undef_p && !via_plt_p)
+ {
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
+ signed_addend,
+ weak_undef_p);
+ break;
+ }
+ /* Fall through. */
case BFD_RELOC_AARCH64_CALL26:
case BFD_RELOC_AARCH64_JUMP26:
{
asection *splt = globals->root.splt;
- bfd_boolean via_plt_p =
- splt != NULL && h != NULL && h->plt.offset != (bfd_vma) - 1;
/* A call to an undefined weak symbol is converted to a jump to
the next instruction unless a PLT entry will be created.
@@ -5943,7 +5957,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
case BFD_RELOC_AARCH64_32:
#endif
case BFD_RELOC_AARCH64_ADD_LO12:
- case BFD_RELOC_AARCH64_BRANCH19:
case BFD_RELOC_AARCH64_LDST128_LO12:
case BFD_RELOC_AARCH64_LDST16_LO12:
case BFD_RELOC_AARCH64_LDST32_LO12:
@@ -5959,7 +5972,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G2_S:
case BFD_RELOC_AARCH64_MOVW_G3:
- case BFD_RELOC_AARCH64_TSTBR14:
value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
place, value,
signed_addend, weak_undef_p);
@@ -8022,6 +8034,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
break;
}
+ case BFD_RELOC_AARCH64_BRANCH19:
+ case BFD_RELOC_AARCH64_TSTBR14:
case BFD_RELOC_AARCH64_CALL26:
case BFD_RELOC_AARCH64_JUMP26:
/* If this is a local symbol then we resolve it