From 5b5ab3a7859cefe23e8a2bdb2175b9ec383c60fe Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Aug 26 2014 19:27:18 +0000 Subject: 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 --- diff --git a/binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch b/binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch new file mode 100644 index 0000000..64a1d9c --- /dev/null +++ b/binutils-2.24-aarch64-fix-gotplt-offset-ifunc.patch @@ -0,0 +1,103 @@ +commit 67428c4aa56d4183d0f531e0d752040745a94423 +Author: Will Newton +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 + + * 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 + + * 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 : ++ 2a0: d65f03c0 ret ++ ++0+2a4 : ++ 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 diff --git a/binutils-2.24-aarch64-fix-ie-relax.patch b/binutils-2.24-aarch64-fix-ie-relax.patch new file mode 100644 index 0000000..d9157ea --- /dev/null +++ b/binutils-2.24-aarch64-fix-ie-relax.patch @@ -0,0 +1,40 @@ +commit 44f814ce5066f10a3bed29c45d10e0d38f4fa433 +Author: Marcus Shawcroft +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 diff --git a/binutils-2.24-aarch64-fix-static-ifunc.patch b/binutils-2.24-aarch64-fix-static-ifunc.patch new file mode 100644 index 0000000..296f162 --- /dev/null +++ b/binutils-2.24-aarch64-fix-static-ifunc.patch @@ -0,0 +1,118 @@ +commit 14d96265dd8fd934d868c0b8e1991e2fefbe9fc8 +Author: Will Newton +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 + + * 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 + + * 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 diff --git a/binutils-2.24-elfnn-aarch64.patch b/binutils-2.24-elfnn-aarch64.patch index 2491e0f..469387b 100644 --- a/binutils-2.24-elfnn-aarch64.patch +++ b/binutils-2.24-elfnn-aarch64.patch @@ -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); diff --git a/binutils.spec b/binutils.spec index 4d58e4a..cfc1bdb 100644 --- a/binutils.spec +++ b/binutils.spec @@ -66,6 +66,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) @@ -196,6 +199,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. @@ -506,6 +512,18 @@ exit 0 %endif # %{isnative} %changelog +* Fri Aug 22 2014 Kyle McMartin +- 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 +- bfd/elfnn-aarch64.c: use correct offsets in final_link_relocate + Resolves: BZ #1126199 + * Tue Aug 26 2014 Nick Clifton - 2.24-20 - Import patch from mainline to fix indirect symbol resolution. Resolves: BZ #1123714