diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 55bf288a754..08d1141d4dd 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -8139,6 +8139,14 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, input_section, (uint64_t) rel->r_offset, howto->name, name); } + if (r_symndx + && h + && IS_AARCH64_TLS_RELOC (bfd_r_type) + && h->root.type == bfd_link_hash_undefweak) + /* We have already warned about these in aarch64_check_relocs, + so just skip over them. */ + continue; + /* We relax only if we can see that there can be a valid transition from a reloc type to another. We call elfNN_aarch64_final_link_relocate unless we're completely @@ -8947,11 +8955,13 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, for (rel = relocs; rel < rel_end; rel++) { struct elf_link_hash_entry *h; - unsigned int r_symndx; + unsigned int r_symndx, r_type; bfd_reloc_code_real_type bfd_r_type; Elf_Internal_Sym *isym; r_symndx = ELFNN_R_SYM (rel->r_info); + r_type = ELFNN_R_TYPE (rel->r_info); + bfd_r_type = elfNN_aarch64_bfd_reloc_from_type (abfd, r_type); if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { @@ -8994,6 +9004,26 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, h = (struct elf_link_hash_entry *) h->root.u.i.link; } + /* Ignore TLS relocations against weak undef symbols and warn about them. + The behaviour of weak TLS variables is not well defined. Since making + these well behaved is not a priority for Morello, we simply ignore + TLS relocations against such symbols here to avoid the linker crashing + on these and to enable making progress in other areas. */ + if (r_symndx + && h + && IS_AARCH64_TLS_RELOC (bfd_r_type) + && h->root.type == bfd_link_hash_undefweak) + { + int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; + _bfd_error_handler (_("%pB(%pA+%#" PRIx64 "): ignoring TLS relocation " + "%s against undef weak symbol %s"), + abfd, sec, + (uint64_t) rel->r_offset, + elfNN_aarch64_howto_table[howto_index].name, + h->root.root.string); + continue; + } + /* Could be done earlier, if h were already available. */ bfd_r_type = aarch64_tls_transition (abfd, info, rel, h, r_symndx); diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 228cfe224c5..893c869f1a3 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -457,4 +457,5 @@ run_dump_test "bti-pac-plt-2" run_dump_test "bti-warn" run_dump_test "weak-tls" +run_dump_test "morello-weak-tls" run_dump_test "undef-tls" diff --git a/ld/testsuite/ld-aarch64/morello-weak-tls.d b/ld/testsuite/ld-aarch64/morello-weak-tls.d new file mode 100644 index 00000000000..20f5cb1b889 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-weak-tls.d @@ -0,0 +1,6 @@ +#source: morello-weak-tls.s +#ld: +#warning:.*: ignoring TLS relocation R_MORELLO_TLSDESC_ADR_PAGE20 against undef weak symbol x +#warning:.*: ignoring TLS relocation R_MORELLO_TLSDESC_LD128_LO12 against undef weak symbol x +#warning:.*: ignoring TLS relocation R_AARCH64_TLSDESC_ADD_LO12 against undef weak symbol x +#warning:.*: ignoring TLS relocation R_MORELLO_TLSDESC_CALL against undef weak symbol x diff --git a/ld/testsuite/ld-aarch64/morello-weak-tls.s b/ld/testsuite/ld-aarch64/morello-weak-tls.s new file mode 100644 index 00000000000..a40d84b8546 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-weak-tls.s @@ -0,0 +1,36 @@ + .arch morello+crc+c64 + .file "t.c" + .text + .align 2 + .global _start + .type _start, %function +_start: +.LFB0: + .cfi_startproc + stp c29, c30, [csp, -32]! + .cfi_def_cfa_offset 32 + .cfi_offset 29, -32 + .cfi_offset 30, -16 + mov c29, csp + mrs c2, ctpidr_el0 + nop + adrp c0, :tlsdesc:x + ldr c1, [c0, #:tlsdesc_lo12:x] + add c0, c0, :tlsdesc_lo12:x + .tlsdesccall x + blr c1 + scbnds c0, c0, x1 + mov w1, 1 + str w1, [c0] + nop + ldp c29, c30, [csp], 32 + .cfi_restore 30 + .cfi_restore 29 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +.LFE0: + .size _start, .-_start + .weak x + .ident "GCC: (GNU) 11.0.0 20200826 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/ld/testsuite/ld-aarch64/weak-tls.d b/ld/testsuite/ld-aarch64/weak-tls.d index a8269406892..60d7d9122c0 100644 --- a/ld/testsuite/ld-aarch64/weak-tls.d +++ b/ld/testsuite/ld-aarch64/weak-tls.d @@ -1,8 +1,6 @@ #source: weak-tls.s #ld: -e0 --emit-relocs -#objdump: -dr -#... -#error:.*: warning: Weak TLS is implementation defined and may not work as expected.* -#error:.*: warning: Weak TLS is implementation defined and may not work as expected.* -#error:.*: in function `get':.* -#error:.*: relocation truncated to fit: R_AARCH64_TLSLD_ADD_DTPREL_LO12 against undefined symbol `dtl'.* +#warning:.*: ignoring TLS relocation .* against undef weak symbol tls +#warning:.*: ignoring TLS relocation .* against undef weak symbol tls +#warning:.*: ignoring TLS relocation .* against undef weak symbol dtl +#warning:.*: ignoring TLS relocation .* against undef weak symbol dtl