41 lines
1.6 KiB
Diff
41 lines
1.6 KiB
Diff
|
commit 44f814ce5066f10a3bed29c45d10e0d38f4fa433
|
||
|
Author: Marcus Shawcroft <marcus.shawcroft@arm.com>
|
||
|
Date: Tue Apr 15 17:46:07 2014 +0100
|
||
|
|
||
|
[AArch64] Fix off by one error in instruction relaxation mask.
|
||
|
|
||
|
The AArch64 TLSDESC to IE relaxation code uses a bit mask intended to
|
||
|
ensure that destination register in a relaxed ldr instruction is
|
||
|
always X0. The mask has an off by one error resulting in the most
|
||
|
significant bit of the destination register being retained in the
|
||
|
relaxed instruction. The issue generally appears when the compiler
|
||
|
emits TLS accesses code under high register pressure resulting in a
|
||
|
broken code sequence.
|
||
|
|
||
|
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
|
||
|
index 42c83fb..8503419 100644
|
||
|
--- a/bfd/elfnn-aarch64.c
|
||
|
+++ b/bfd/elfnn-aarch64.c
|
||
|
@@ -3957,7 +3957,7 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
|
||
|
ldr xd, [x0, #:tlsdesc_lo12:var] => ldr x0, [x0, #:gottprel_lo12:var]
|
||
|
*/
|
||
|
insn = bfd_getl32 (contents + rel->r_offset);
|
||
|
- insn &= 0xfffffff0;
|
||
|
+ insn &= 0xffffffe0;
|
||
|
bfd_putl32 (insn, contents + rel->r_offset);
|
||
|
return bfd_reloc_continue;
|
||
|
}
|
||
|
diff --git a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
|
||
|
index c20690c..38b3721 100644
|
||
|
--- a/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
|
||
|
+++ b/ld/testsuite/ld-aarch64/tls-relax-gdesc-ie.s
|
||
|
@@ -4,7 +4,7 @@ var:
|
||
|
.word 2
|
||
|
.text
|
||
|
adrp x0, :tlsdesc:var
|
||
|
- ldr x1, [x0, #:tlsdesc_lo12:var]
|
||
|
+ ldr x17, [x0, #:tlsdesc_lo12:var]
|
||
|
add x0, x0, :tlsdesc_lo12:var
|
||
|
.tlsdesccall var
|
||
|
blr x1
|