~sourceware/binutils-gdb

f3ecc5c84e9806a10435f4fc8b43b66b6e2bb877 — Alex Coplan 4 months ago 8b0ba11
ld: Ignore TLS relocs against weak undef symbols

The behaviour of weak undef thread-local variables is not well defined.
TLS relocations against weak undef symbols are not handled properly by
the linker, and in some cases cause the linker to crash (notably when
linking glibc for purecap Morello). This patch simply ignores these and
emits a warning to that effect. This is a compromise to enable progress
for Morello.

bfd/ChangeLog:

2022-01-17  Alex Coplan  <alex.coplan@arm.com>

	* elfnn-aarch64.c (elfNN_aarch64_relocate_section): Skip over TLS
	relocations against weak undef symbols.
	(elfNN_aarch64_check_relocs): Likewise, but also warn.

ld/ChangeLog:

2022-01-17  Alex Coplan  <alex.coplan@arm.com>

	* testsuite/ld-aarch64/aarch64-elf.exp: Add morello-weak-tls test.
	* testsuite/ld-aarch64/morello-weak-tls.d: New test.
	* testsuite/ld-aarch64/morello-weak-tls.s: New test.
	* testsuite/ld-aarch64/weak-tls.d: Update test wrt new behaviour.
M bfd/ChangeLog => bfd/ChangeLog +6 -0
@@ 1,3 1,9 @@
2022-01-17  Alex Coplan  <alex.coplan@arm.com>

	* elfnn-aarch64.c (elfNN_aarch64_relocate_section): Skip over TLS
	relocations against weak undef symbols.
	(elfNN_aarch64_check_relocs): Likewise, but also warn.

2021-05-25  Luis Machado  <luis.machado@arm.com>

	* elf-bfd.h (elfcore_write_aarch_morello): New prototype.

M bfd/elfnn-aarch64.c => bfd/elfnn-aarch64.c +31 -1
@@ 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);


M ld/ChangeLog => ld/ChangeLog +7 -0
@@ 1,3 1,10 @@
2022-01-17  Alex Coplan  <alex.coplan@arm.com>

	* testsuite/ld-aarch64/aarch64-elf.exp: Add morello-weak-tls test.
	* testsuite/ld-aarch64/morello-weak-tls.d: New test.
	* testsuite/ld-aarch64/morello-weak-tls.s: New test.
	* testsuite/ld-aarch64/weak-tls.d: Update test wrt new behaviour.

2020-10-20  Siddhesh Poyarekar  <siddesh.poyarekar@arm.com>

	* testsuite/ld-aarch64/morello-tlsdesc.s: New file.

M ld/testsuite/ld-aarch64/aarch64-elf.exp => ld/testsuite/ld-aarch64/aarch64-elf.exp +1 -0
@@ 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"

A ld/testsuite/ld-aarch64/morello-weak-tls.d => ld/testsuite/ld-aarch64/morello-weak-tls.d +6 -0
@@ 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

A ld/testsuite/ld-aarch64/morello-weak-tls.s => ld/testsuite/ld-aarch64/morello-weak-tls.s +36 -0
@@ 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

M ld/testsuite/ld-aarch64/weak-tls.d => ld/testsuite/ld-aarch64/weak-tls.d +4 -6
@@ 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