binutils-2.24-aarch64-fix-ie-relax.patch: fix GD to IE relaxation under register pressure

split some fixes out, so it's easier to see what's backported
This commit is contained in:
Kyle McMartin 2014-08-22 11:52:55 -04:00
parent 404956d0f6
commit 422f7b7960
5 changed files with 276 additions and 73 deletions

View File

@ -0,0 +1,103 @@
commit 67428c4aa56d4183d0f531e0d752040745a94423
Author: Will Newton <will.newton@linaro.org>
Date: Mon Nov 25 11:07:07 2013 +0000
bfd/elfnn-aarch64.c: Fix miscalculation of GOTPLT offset for ifunc syms.
The .got.plt header size was not being correctly taken into account
when calculating the offset for relocations against ifunc symbols.
bfd/ChangeLog:
2013-11-26 Will Newton <will.newton@linaro.org>
* elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Ensure
PLT_INDEX is calculated using correct header size.
ld/testsuite/ChangeLog:
2013-11-26 Will Newton <will.newton@linaro.org>
* ld-aarch64/aarch64-elf.exp: Add ifunc-21 test.
* ld-aarch64/ifunc-21.d: New file.
* ld-aarch64/ifunc-21.s: Likewise.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 6bc414e..3cd3a18 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -3589,7 +3589,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
if (globals->root.splt != NULL)
{
- plt_index = h->plt.offset / globals->plt_entry_size - 1;
+ plt_index = ((h->plt.offset - globals->plt_header_size) /
+ globals->plt_entry_size);
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = globals->root.sgotplt;
}
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 5c150dd..a6b3ea2 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -155,3 +155,4 @@ run_dump_test "ifunc-18b"
run_dump_test "ifunc-19a"
run_dump_test "ifunc-19b"
run_dump_test "ifunc-20"
+run_dump_test "ifunc-21"
diff --git a/ld/testsuite/ld-aarch64/ifunc-21.d b/ld/testsuite/ld-aarch64/ifunc-21.d
new file mode 100644
index 0000000..fa139b2
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-21.d
@@ -0,0 +1,31 @@
+#source: ifunc-21.s
+#ld: -shared -z nocombreloc
+#objdump: -d -s -j .got.plt -j .text
+#target: aarch64*-*-*
+
+# Ensure the .got.plt slot used is correct
+
+.*: file format elf64-(little|big)aarch64
+
+Contents of section .text:
+ 02a0 .*
+Contents of section .got.plt:
+ 103a8 0+ 0+ 0+ 0+ .*
+ 103b8 0+ 0+ [0-9a-f]+ 0+ .*
+
+Disassembly of section .text:
+
+0+2a0 <ifunc>:
+ 2a0: d65f03c0 ret
+
+0+2a4 <bar>:
+ 2a4: 90000080 adrp x0, 10000 <.*>
+ 2a8: f941e000 ldr x0, \[x0,#960\]
+ 2ac: d65f03c0 ret
+
+Disassembly of section .got.plt:
+
+.*:
+.*
+.*
+.*
diff --git a/ld/testsuite/ld-aarch64/ifunc-21.s b/ld/testsuite/ld-aarch64/ifunc-21.s
new file mode 100644
index 0000000..a1563dc
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-21.s
@@ -0,0 +1,13 @@
+ .text
+ .type ifunc, @gnu_indirect_function
+ .hidden ifunc
+ifunc:
+ ret
+ .size ifunc, .-ifunc
+ .type bar, @function
+ .globl bar
+bar:
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ ret
+ .size bar, .-bar

View File

@ -0,0 +1,40 @@
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

View File

@ -0,0 +1,118 @@
commit 14d96265dd8fd934d868c0b8e1991e2fefbe9fc8
Author: Will Newton <will.newton@linaro.org>
Date: Mon Nov 25 14:44:59 2013 +0000
bfd/elfnn-aarch64.c: Handle static links with ifunc correctly.
The code for handling GOT references to ifunc symbols in static links
was missing.
bfd/ChangeLog:
2013-11-26 Will Newton <will.newton@linaro.org>
* elfnn-aarch64.c (elfNN_aarch64_finish_dynamic_symbol):
Handle STT_GNU_IFUNC symbols correctly in static links.
ld/testsuite/ChangeLog:
2013-11-26 Will Newton <will.newton@linaro.org>
* ld-aarch64/aarch64-elf.exp: Add ifunc-22.
* ld-aarch64/ifunc-22.d: New file.
* ld-aarch64/ifunc-22.s: Likewise.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 3cd3a18..9053635 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -6824,7 +6824,34 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
+ htab->root.sgot->output_offset
+ (h->got.offset & ~(bfd_vma) 1));
- if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+ if (h->def_regular
+ && h->type == STT_GNU_IFUNC)
+ {
+ if (info->shared)
+ {
+ /* Generate R_AARCH64_GLOB_DAT. */
+ goto do_glob_dat;
+ }
+ else
+ {
+ asection *plt;
+
+ if (!h->pointer_equality_needed)
+ abort ();
+
+ /* For non-shared object, we can't use .got.plt, which
+ contains the real function address if we need pointer
+ equality. We load the GOT entry with the PLT entry. */
+ plt = htab->root.splt ? htab->root.splt : htab->root.iplt;
+ bfd_put_NN (output_bfd, (plt->output_section->vma
+ + plt->output_offset
+ + h->plt.offset),
+ htab->root.sgot->contents
+ + (h->got.offset & ~(bfd_vma) 1));
+ return TRUE;
+ }
+ }
+ else if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
{
if (!h->def_regular)
return FALSE;
@@ -6837,6 +6864,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
}
else
{
+do_glob_dat:
BFD_ASSERT ((h->got.offset & 1) == 0);
bfd_put_NN (output_bfd, (bfd_vma) 0,
htab->root.sgot->contents + h->got.offset);
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index a6b3ea2..692bf34 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -156,3 +156,4 @@ run_dump_test "ifunc-19a"
run_dump_test "ifunc-19b"
run_dump_test "ifunc-20"
run_dump_test "ifunc-21"
+run_dump_test "ifunc-22"
diff --git a/ld/testsuite/ld-aarch64/ifunc-22.d b/ld/testsuite/ld-aarch64/ifunc-22.d
new file mode 100644
index 0000000..f28b039
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-22.d
@@ -0,0 +1,11 @@
+#source: ifunc-22.s
+#objdump: -s -j .got
+#ld: -static
+#target: aarch64*-*-*
+
+# Ensure GOT is populated correctly in static link
+
+.*: file format elf64-(little|big)aarch64
+
+Contents of section \.got:
+ 4100f0 00000000 00000000 d0004000 00000000 ..........@.....
diff --git a/ld/testsuite/ld-aarch64/ifunc-22.s b/ld/testsuite/ld-aarch64/ifunc-22.s
new file mode 100644
index 0000000..69a87bb
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/ifunc-22.s
@@ -0,0 +1,14 @@
+ .text
+ .type ifunc, @gnu_indirect_function
+ .global ifunc
+ifunc:
+ ret
+ .size ifunc, .-ifunc
+ .type _start, @function
+ .globl _start
+_start:
+ adrp x0, :got:ifunc
+ ldr x0, [x0, #:got_lo12:ifunc]
+ .size _start, .-_start
+ .data
+ .xword ifunc

View File

@ -19,75 +19,3 @@
struct elf_aarch64_local_symbol
{
*************** elfNN_aarch64_final_link_relocate (reloc
*** 3589,3595 ****
if (globals->root.splt != NULL)
{
! plt_index = h->plt.offset / globals->plt_entry_size - 1;
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = globals->root.sgotplt;
}
--- 3589,3596 ----
if (globals->root.splt != NULL)
{
! plt_index = ((h->plt.offset - globals->plt_header_size) /
! globals->plt_entry_size);
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = globals->root.sgotplt;
}
*************** elfNN_aarch64_finish_dynamic_symbol (bfd
*** 6823,6829 ****
+ htab->root.sgot->output_offset
+ (h->got.offset & ~(bfd_vma) 1));
! if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
{
if (!h->def_regular)
return FALSE;
--- 6824,6857 ----
+ htab->root.sgot->output_offset
+ (h->got.offset & ~(bfd_vma) 1));
! if (h->def_regular
! && h->type == STT_GNU_IFUNC)
! {
! if (info->shared)
! {
! /* Generate R_AARCH64_GLOB_DAT. */
! goto do_glob_dat;
! }
! else
! {
! asection *plt;
!
! if (!h->pointer_equality_needed)
! abort ();
!
! /* For non-shared object, we can't use .got.plt, which
! contains the real function address if we need pointer
! equality. We load the GOT entry with the PLT entry. */
! plt = htab->root.splt ? htab->root.splt : htab->root.iplt;
! bfd_put_NN (output_bfd, (plt->output_section->vma
! + plt->output_offset
! + h->plt.offset),
! htab->root.sgot->contents
! + (h->got.offset & ~(bfd_vma) 1));
! return TRUE;
! }
! }
! else if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
{
if (!h->def_regular)
return FALSE;
*************** elfNN_aarch64_finish_dynamic_symbol (bfd
*** 6836,6841 ****
--- 6864,6870 ----
}
else
{
+ do_glob_dat:
BFD_ASSERT ((h->got.offset & 1) == 0);
bfd_put_NN (output_bfd, (bfd_vma) 0,
htab->root.sgot->contents + h->got.offset);

View File

@ -19,7 +19,7 @@
Summary: A GNU collection of binary utilities
Name: %{?cross}binutils%{?_with_debug:-debug}
Version: 2.24
Release: 22%{?dist}
Release: 23%{?dist}
License: GPLv3+
Group: Development/Tools
URL: http://sources.redhat.com/binutils
@ -68,6 +68,9 @@ Patch23: binutils-2.24-aarch64-ld-shared-non-PIC-xfail.patch
Patch24: binutils-2.24-weak-sym-merge.patch
Patch25: binutils-2.24-indirect-chain.patch
Patch26: binutils-2.24-aarch64-fix-final_link_relocate.patch
Patch27: binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch
Patch28: binutils-2.24-aarch64-fix-static-ifunc.patch
Patch29: binutils-2.24-aarch64-fix-ie-relax.patch
Provides: bundled(libiberty)
@ -198,6 +201,9 @@ using libelf instead of BFD.
%patch24 -p0 -b .weak-sym-merge~
%patch25 -p0 -b .indirect-chain~
%patch26 -p1 -b .aa64-final-link~
%patch27 -p1 -b .aa64-1~
%patch28 -p1 -b .aa64-2~
%patch29 -p1 -b .aa64-3~
# We cannot run autotools as there is an exact requirement of autoconf-2.59.
@ -511,6 +517,14 @@ exit 0
%endif # %{isnative}
%changelog
* Fri Aug 22 2014 Kyle McMartin <kmcmarti@redhat.com> - 2.24-23
- binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch
binutils-2.24-aarch64-fix-static-ifunc.patch, split elfnn-aarch64 patches
into upstream git commits, to make it easier to figure out what's
backported already
- binutils-2.24-aarch64-fix-ie-relax.patch: add fix for gd to ie relaxation
when target register is >16 (pretty unlikely, but...)
* Thu Aug 21 2014 Kyle McMartin <kmcmarti@redhat.com> - 2.24-22
- bfd/elfnn-aarch64.c: use correct offsets in final_link_relocate
Resolves: BZ #1126199