summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamar Christina <tamar.christina@arm.com>2019-08-22 11:35:35 +0100
committerTamar Christina <tamar.christina@arm.com>2019-08-28 09:35:10 +0100
commit6795dba28d531a17a0800d532d555653415702bb (patch)
treec8a407cc04c5fabe7a3b091408f60c8e947825f0
parent8f254d8183a0c35d46fea419c67b52c89271f478 (diff)
downloadbinutils-gdb-6795dba28d531a17a0800d532d555653415702bb.tar.gz
AArch64: Fix LD crash on weak and undefined TLS symbols. (PR/24602).
This patch fixes a few linker crashes due to TLS code reaching an assert when it shouldn't. The first scenario is with weak TLS symbols that remain weak during linking. In this case the mid-end would not have seen a TLS symbol and so wouldn't have allocated the TLS section. We currently assert here and the linker crashes with a not very useful message. This patch changes this to return the value 0 for the TLS symbol in question emulating what lld and gold and other BFD targets do. However because weak TLS is implementation defined and we don't define any behavior for it I also emit a warning to the user to inform them of such. Secondly when a strong TLS reference is undefined. The linker crashes even after it correctly reported that there is an undefined reference. This changes it so that it gracefully exits and reports a useful error. bfd/ChangeLog: PR ld/24601 * elfnn-aarch64.c (aarch64_relocate): Handle weak TLS and undefined TLS. Also Pass input_bfd to _bfd_aarch64_elf_resolve_relocation. * elfxx-aarch64.c (_bfd_aarch64_elf_resolve_relocation): Use it. * elfxx-aarch64.h (_bfd_aarch64_elf_resolve_relocation): Emit warning for weak TLS. ld/ChangeLog: PR ld/24601 * testsuite/ld-aarch64/aarch64-elf.exp (undef-tls, weak-tls): New. * testsuite/ld-aarch64/undef-tls.d: New test. * testsuite/ld-aarch64/undef-tls.s: New test. * testsuite/ld-aarch64/weak-tls.d: New test. * testsuite/ld-aarch64/weak-tls.s: New test. (cherry picked from commit 652afeef247770b22c44ca292d1f4c65be40a696)
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elfnn-aarch64.c83
-rw-r--r--bfd/elfxx-aarch64.c15
-rw-r--r--bfd/elfxx-aarch64.h4
-rw-r--r--ld/ChangeLog12
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp3
-rw-r--r--ld/testsuite/ld-aarch64/undef-tls.d17
-rw-r--r--ld/testsuite/ld-aarch64/undef-tls.s13
-rw-r--r--ld/testsuite/ld-aarch64/weak-tls.d8
-rw-r--r--ld/testsuite/ld-aarch64/weak-tls.s16
10 files changed, 160 insertions, 23 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index d21a1a61809..d53d12d6a4c 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2019-08-28 Tamar Christina <tamar.christina@arm.com>
+
+ Backport from mainline.
+ 2019-08-22 Tamar Christina <tamar.christina@arm.com>
+
+ PR ld/24601
+ * elfnn-aarch64.c (aarch64_relocate): Handle weak TLS and undefined TLS.
+ Also Pass input_bfd to _bfd_aarch64_elf_resolve_relocation.
+ * elfxx-aarch64.c (_bfd_aarch64_elf_resolve_relocation): Use it.
+ * elfxx-aarch64.h (_bfd_aarch64_elf_resolve_relocation): Emit warning
+ for weak TLS.
+
2019-07-08 Alan Modra <amodra@gmail.com>
PR 24785
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 1dbd0184ce2..af53d3a5087 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -2896,7 +2896,8 @@ aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
+ offset);
r_type = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
- value = _bfd_aarch64_elf_resolve_relocation (r_type, place, value, 0, FALSE);
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, r_type, place,
+ value, 0, FALSE);
return _bfd_aarch64_elf_put_addend (input_bfd,
input_section->contents + offset, r_type,
howto, value) == bfd_reloc_ok;
@@ -5383,7 +5384,8 @@ bad_ifunc_reloc:
/* FALLTHROUGH */
case BFD_RELOC_AARCH64_CALL26:
case BFD_RELOC_AARCH64_JUMP26:
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
signed_addend,
weak_undef_p);
return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type,
@@ -5460,7 +5462,8 @@ bad_ifunc_reloc:
addend = (globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
addend, weak_undef_p);
return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type, howto, value);
case BFD_RELOC_AARCH64_ADD_LO12:
@@ -5638,7 +5641,8 @@ bad_ifunc_reloc:
signed_addend = 0;
}
}
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
signed_addend, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
@@ -5698,7 +5702,8 @@ bad_ifunc_reloc:
case BFD_RELOC_AARCH64_MOVW_G2_S:
case BFD_RELOC_AARCH64_MOVW_G3:
case BFD_RELOC_AARCH64_TSTBR14:
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
signed_addend, weak_undef_p);
break;
@@ -5743,7 +5748,8 @@ bad_ifunc_reloc:
if (aarch64_relocation_aginst_gp_p (bfd_r_type))
addend = (globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
addend, weak_undef_p);
}
else
@@ -5790,7 +5796,8 @@ bad_ifunc_reloc:
if (aarch64_relocation_aginst_gp_p (bfd_r_type))
addend = base_got->output_section->vma + base_got->output_offset;
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
addend, weak_undef_p);
}
@@ -5827,7 +5834,8 @@ bad_ifunc_reloc:
+ globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
0, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
@@ -5840,7 +5848,8 @@ bad_ifunc_reloc:
return bfd_reloc_notsupported;
value = symbol_got_offset (input_bfd, h, r_symndx);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
0, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
@@ -5861,10 +5870,26 @@ bad_ifunc_reloc:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
- signed_addend - dtpoff_base (info),
- weak_undef_p);
- break;
+ {
+ if (!(weak_undef_p || elf_hash_table (info)->tls_sec))
+ {
+ int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: TLS relocation %s against undefined symbol `%s'"),
+ input_bfd, elfNN_aarch64_howto_table[howto_index].name,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
+
+ bfd_vma def_value
+ = weak_undef_p ? 0 : signed_addend - dtpoff_base (info);
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
+ def_value, weak_undef_p);
+ break;
+ }
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
@@ -5882,11 +5907,27 @@ bad_ifunc_reloc:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
- signed_addend - tpoff_base (info),
- weak_undef_p);
- *unresolved_reloc_p = FALSE;
- break;
+ {
+ if (!(weak_undef_p || elf_hash_table (info)->tls_sec))
+ {
+ int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: TLS relocation %s against undefined symbol `%s'"),
+ input_bfd, elfNN_aarch64_howto_table[howto_index].name,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
+
+ bfd_vma def_value
+ = weak_undef_p ? 0 : signed_addend - tpoff_base (info);
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
+ def_value, weak_undef_p);
+ *unresolved_reloc_p = FALSE;
+ break;
+ }
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
@@ -5901,7 +5942,8 @@ bad_ifunc_reloc:
+ globals->root.sgotplt->output_offset
+ globals->sgotplt_jump_table_size);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
0, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
@@ -5919,7 +5961,8 @@ bad_ifunc_reloc:
value -= (globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
- value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
0, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c
index 32a9d972824..0bda59e380a 100644
--- a/bfd/elfxx-aarch64.c
+++ b/bfd/elfxx-aarch64.c
@@ -395,10 +395,12 @@ _bfd_aarch64_elf_put_addend (bfd *abfd,
}
bfd_vma
-_bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
+_bfd_aarch64_elf_resolve_relocation (bfd *input_bfd,
+ bfd_reloc_code_real_type r_type,
bfd_vma place, bfd_vma value,
bfd_vma addend, bfd_boolean weak_undef_p)
{
+ bfd_boolean tls_reloc = TRUE;
switch (r_type)
{
case BFD_RELOC_AARCH64_NONE:
@@ -446,6 +448,8 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G2_S:
case BFD_RELOC_AARCH64_MOVW_G3:
+ tls_reloc = FALSE;
+ /* fall-through. */
case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
@@ -466,6 +470,15 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ /* Weak Symbols and TLS relocations are implementation defined. For this
+ case we choose to emit 0. */
+ if (weak_undef_p && tls_reloc)
+ {
+ _bfd_error_handler (_("%pB: warning: Weak TLS is implementation "
+ "defined and may not work as expected"),
+ input_bfd);
+ value = place;
+ }
value = value + addend;
break;
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index 1f9ce09675f..02e91d216fd 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -40,8 +40,8 @@ _bfd_aarch64_elf_put_addend (bfd *, bfd_byte *, bfd_reloc_code_real_type,
reloc_howto_type *, bfd_signed_vma);
extern bfd_vma
-_bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type, bfd_vma, bfd_vma,
- bfd_vma, bfd_boolean);
+_bfd_aarch64_elf_resolve_relocation (bfd *, bfd_reloc_code_real_type, bfd_vma,
+ bfd_vma, bfd_vma, bfd_boolean);
extern bfd_boolean
_bfd_aarch64_elf_grok_prstatus (bfd *, Elf_Internal_Note *);
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a05684b00da..bed4af2e74d 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,15 @@
+2019-08-28 Tamar Christina <tamar.christina@arm.com>
+
+ Backport from mainline.
+ 2019-08-22 Tamar Christina <tamar.christina@arm.com>
+
+ PR ld/24601
+ * testsuite/ld-aarch64/aarch64-elf.exp (undef-tls, weak-tls): New.
+ * testsuite/ld-aarch64/undef-tls.d: New test.
+ * testsuite/ld-aarch64/undef-tls.s: New test.
+ * testsuite/ld-aarch64/weak-tls.d: New test.
+ * testsuite/ld-aarch64/weak-tls.s: New test.
+
2019-08-16 Alan Modra <amodra@gmail.com>
* emultempl/ppc32elf.em (ppc_before_allocation): Force running
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index cac44585c0a..f9d6d3cbd7b 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -393,3 +393,6 @@ set aarch64elflinktests {
}
run_ld_link_tests $aarch64elflinktests
+
+run_dump_test "weak-tls"
+run_dump_test "undef-tls"
diff --git a/ld/testsuite/ld-aarch64/undef-tls.d b/ld/testsuite/ld-aarch64/undef-tls.d
new file mode 100644
index 00000000000..8b43ca4c1de
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/undef-tls.d
@@ -0,0 +1,17 @@
+#source: undef-tls.s
+#ld: -e0 --emit-relocs
+#objdump: -dr
+#...
+#error:.*: in function `get':.*
+#error:.*: undefined reference to `tls'.*
+#error:.*: TLS relocation R_AARCH64_TLSLE_ADD_TPREL_HI12 against undefined symbol `tls'.*
+#error:.*: dangerous relocation: unsupported relocation.*
+#error:.*: undefined reference to `tls'.*
+#error:.*: TLS relocation R_AARCH64_TLSLE_ADD_TPREL_LO12_NC against undefined symbol `tls'.*
+#error:.*: dangerous relocation: unsupported relocation.*
+#error:.*: undefined reference to `dtl'.*
+#error:.*: TLS relocation R_AARCH64_TLSLD_ADD_DTPREL_HI12 against undefined symbol `dtl'.*
+#error:.*: dangerous relocation: unsupported relocation.*
+#error:.*: undefined reference to `dtl'.*
+#error:.*: TLS relocation R_AARCH64_TLSLD_ADD_DTPREL_LO12 against undefined symbol `dtl'.*
+#error:.*: dangerous relocation: unsupported relocation.*
diff --git a/ld/testsuite/ld-aarch64/undef-tls.s b/ld/testsuite/ld-aarch64/undef-tls.s
new file mode 100644
index 00000000000..6d57afbb540
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/undef-tls.s
@@ -0,0 +1,13 @@
+ .global get
+ .type get, %function
+get:
+.LFB0:
+ mrs x0, tpidr_el0
+ add x0, x0, #:tprel_hi12:tls, lsl #12
+ add x0, x0, #:tprel_lo12_nc:tls
+ add x0, x0, #:dtprel_hi12:dtl
+ add x0, x0, #:dtprel_lo12:dtl
+ ret
+.LFE0:
+ .size get, .-get
+
diff --git a/ld/testsuite/ld-aarch64/weak-tls.d b/ld/testsuite/ld-aarch64/weak-tls.d
new file mode 100644
index 00000000000..a8269406892
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-tls.d
@@ -0,0 +1,8 @@
+#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'.*
diff --git a/ld/testsuite/ld-aarch64/weak-tls.s b/ld/testsuite/ld-aarch64/weak-tls.s
new file mode 100644
index 00000000000..3520a85589c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/weak-tls.s
@@ -0,0 +1,16 @@
+ .global get
+ .type get, %function
+ .global dtl
+ .weak dtl
+get:
+.LFB0:
+ mrs x0, tpidr_el0
+ add x0, x0, #:tprel_hi12:tls, lsl #12
+ add x0, x0, #:tprel_lo12_nc:tls
+ add x0, x0, #:dtprel_hi12:dtl
+ add x0, x0, #:dtprel_lo12:dtl
+ ret
+.LFE0:
+ .size get, .-get
+ .weak tls
+