From abd242a90836b535b2f98be634e16c70012a3c5d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Oct 2011 00:32:25 +0000 Subject: [PATCH] Fix sparc TLS call relaxation when the delay slot sets up %o0. bfd/ PR binutils/13301 * elfxx-sparc.c (sparc_elf_find_reloc_at_ofs): New function. (_bfd_sparc_elf_relocate_section): Always move the __tls_get_addr call delay slot instruction forward 4 bytes when performing relaxation. gold/ PR binutils/13301 * sparc.cc (Target_sparc::Relocate::reloc_adjust_addr_): New member to track relocation locations that have moved during TLS reloc optimizations. (Target_sparc::Relocate::Relocate): Initialize to NULL. (Target_sparc::Relocate::relocate): Adjust view down by 4 bytes if it matches reloc_adjust_addr_. (Target_sparc::Relocate::relocate_tls): Always move the __tls_get_addr call delay slot instruction forward 4 bytes when performing relaxation. ld/testsuite/ * ld-sparc/tlssunbin32.dd: Update for TLS call relaxation fix for PR 13301. * ld-sparc/tlssunbin64.dd: Likewise. * ld-sparc/tlssunpic32.dd: Likewise. * ld-sparc/tlssunpic64.dd: Likewise. --- bfd/ChangeLog | 8 +++++++ bfd/elfxx-sparc.c | 36 +++++++++++++++++++++++++++- gold/ChangeLog | 13 ++++++++++ gold/sparc.cc | 17 +++++++++++-- ld/testsuite/ChangeLog | 8 +++++++ ld/testsuite/ld-sparc/tlssunbin32.dd | 8 +++---- ld/testsuite/ld-sparc/tlssunbin64.dd | 8 +++---- ld/testsuite/ld-sparc/tlssunpic32.dd | 16 ++++++------- ld/testsuite/ld-sparc/tlssunpic64.dd | 16 ++++++------- 9 files changed, 103 insertions(+), 27 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8f9b9be753e..3a0c0eb3709 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2011-10-18 David S. Miller + + PR binutils/13301 + * elfxx-sparc.c (sparc_elf_find_reloc_at_ofs): New function. + (_bfd_sparc_elf_relocate_section): Always move the __tls_get_addr + call delay slot instruction forward 4 bytes when performing + relaxation. + 2011-10-17 Alan Modra PR ld/12975 diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c index 438b7f5b887..9a151247d1b 100644 --- a/bfd/elfxx-sparc.c +++ b/bfd/elfxx-sparc.c @@ -1830,6 +1830,20 @@ _bfd_sparc_elf_gc_mark_hook (asection *sec, return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); } +static Elf_Internal_Rela * +sparc_elf_find_reloc_at_ofs (Elf_Internal_Rela *rel, + Elf_Internal_Rela *relend, + bfd_vma offset) +{ + while (rel < relend) + { + if (rel->r_offset == offset) + return rel; + rel++; + } + return NULL; +} + /* Update the got entry reference counts for the section being removed. */ bfd_boolean _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info, @@ -3676,6 +3690,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, if (! info->shared || (r_type == R_SPARC_TLS_GD_CALL && tls_type == GOT_TLS_IE)) { + Elf_Internal_Rela *rel2; bfd_vma insn; if (!info->shared && (h == NULL || h->dynindx == -1)) @@ -3711,7 +3726,26 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd, continue; } - bfd_put_32 (output_bfd, 0x9001c008, contents + rel->r_offset); + /* We cannot just overwrite the delay slot instruction, + as it might be what puts the %o0 argument to + __tls_get_addr into place. So we have to transpose + the delay slot with the add we patch in. */ + insn = bfd_get_32 (input_bfd, contents + rel->r_offset + 4); + bfd_put_32 (output_bfd, insn, + contents + rel->r_offset); + bfd_put_32 (output_bfd, 0x9001c008, + contents + rel->r_offset + 4); + + rel2 = rel; + while ((rel2 = sparc_elf_find_reloc_at_ofs (rel2 + 1, relend, + rel->r_offset + 4)) + != NULL) + { + /* If the instruction we moved has a relocation attached to + it, adjust the offset so that it will apply to the correct + instruction. */ + rel2->r_offset -= 4; + } continue; } diff --git a/gold/ChangeLog b/gold/ChangeLog index 61ad6cdd33f..153eead12b0 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2011-10-18 David S. Miller + + PR binutils/13301 + * sparc.cc (Target_sparc::Relocate::reloc_adjust_addr_): New + member to track relocation locations that have moved during TLS + reloc optimizations. + (Target_sparc::Relocate::Relocate): Initialize to NULL. + (Target_sparc::Relocate::relocate): Adjust view down by 4 + bytes if it matches reloc_adjust_addr_. + (Target_sparc::Relocate::relocate_tls): Always move the + __tls_get_addr call delay slot instruction forward 4 bytes when + performing relaxation. + 2011-10-18 Cary Coutant * output.cc (posix_fallocate): Return 0 on success, errno on failure. diff --git a/gold/sparc.cc b/gold/sparc.cc index 1d2cbad319d..12e1dee1d64 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -265,7 +265,7 @@ class Target_sparc : public Sized_target { public: Relocate() - : ignore_gd_add_(false) + : ignore_gd_add_(false), reloc_adjust_addr_(NULL) { } ~Relocate() @@ -302,6 +302,9 @@ class Target_sparc : public Sized_target // Ignore the next relocation which should be R_SPARC_TLS_GD_ADD bool ignore_gd_add_; + + // If we hit a reloc at this view address, adjust it back by 4 bytes. + unsigned char *reloc_adjust_addr_; }; // A class which returns the size required for a relocation type, @@ -2622,6 +2625,8 @@ Target_sparc::Relocate::relocate( return false; } } + if (this->reloc_adjust_addr_ == view) + view -= 4; typedef Sparc_relocate_functions Reloc; @@ -3101,7 +3106,15 @@ Target_sparc::Relocate::relocate_tls( wv += 1; this->ignore_gd_add_ = true; } - + else + { + // Even if the delay slot isn't the TLS_GD_ADD + // instruction, we still have to handle the case + // where it sets up %o0 in some other way. + elfcpp::Swap<32, true>::writeval(wv, val); + wv += 1; + this->reloc_adjust_addr_ = view + 4; + } // call __tls_get_addr --> add %g7, %o0, %o0 elfcpp::Swap<32, true>::writeval(wv, 0x9001c008); break; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 6bf48c5b97f..791250803db 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-10-18 David S. Miller + + * ld-sparc/tlssunbin32.dd: Update for TLS call relaxation fix + for PR 13301. + * ld-sparc/tlssunbin64.dd: Likewise. + * ld-sparc/tlssunpic32.dd: Likewise. + * ld-sparc/tlssunpic64.dd: Likewise. + 2011-10-18 Jie Zhang Julian Brown diff --git a/ld/testsuite/ld-sparc/tlssunbin32.dd b/ld/testsuite/ld-sparc/tlssunbin32.dd index 37c1d042809..c31d1909a57 100644 --- a/ld/testsuite/ld-sparc/tlssunbin32.dd +++ b/ld/testsuite/ld-sparc/tlssunbin32.dd @@ -27,8 +27,8 @@ Disassembly of section .text: +11034: 01 00 00 00 nop * +11038: d0 05 c0 12 ld \[ %l7 \+ %l2 \], %o0 +1103c: 01 00 00 00 nop * - +11040: 90 01 c0 08 add %g7, %o0, %o0 - +11044: 01 00 00 00 nop * + +11040: 01 00 00 00 nop * + +11044: 90 01 c0 08 add %g7, %o0, %o0 +11048: 01 00 00 00 nop * +1104c: 01 00 00 00 nop * +11050: 01 00 00 00 nop * @@ -36,8 +36,8 @@ Disassembly of section .text: +11058: 11 00 00 00 sethi %hi\(0\), %o0 +1105c: 92 02 20 08 add %o0, 8, %o1 ! 8 <.*> +11060: d0 05 c0 09 ld \[ %l7 \+ %o1 \], %o0 - +11064: 90 01 c0 08 add %g7, %o0, %o0 - +11068: 01 00 00 00 nop * + +11064: 01 00 00 00 nop * + +11068: 90 01 c0 08 add %g7, %o0, %o0 +1106c: 01 00 00 00 nop * +11070: 01 00 00 00 nop * +11074: 01 00 00 00 nop * diff --git a/ld/testsuite/ld-sparc/tlssunbin64.dd b/ld/testsuite/ld-sparc/tlssunbin64.dd index 0585ae6e280..cd7db1c55fd 100644 --- a/ld/testsuite/ld-sparc/tlssunbin64.dd +++ b/ld/testsuite/ld-sparc/tlssunbin64.dd @@ -27,8 +27,8 @@ Disassembly of section .text: +101034: 01 00 00 00 nop * +101038: d0 5d c0 12 ldx \[ %l7 \+ %l2 \], %o0 +10103c: 01 00 00 00 nop * - +101040: 90 01 c0 08 add %g7, %o0, %o0 - +101044: 01 00 00 00 nop * + +101040: 01 00 00 00 nop * + +101044: 90 01 c0 08 add %g7, %o0, %o0 +101048: 01 00 00 00 nop * +10104c: 01 00 00 00 nop * +101050: 01 00 00 00 nop * @@ -36,8 +36,8 @@ Disassembly of section .text: +101058: 11 00 00 00 sethi %hi\(0\), %o0 +10105c: 92 02 20 10 add %o0, 0x10, %o1 ! 10 <.*> +101060: d0 5d c0 09 ldx \[ %l7 \+ %o1 \], %o0 - +101064: 90 01 c0 08 add %g7, %o0, %o0 - +101068: 01 00 00 00 nop * + +101064: 01 00 00 00 nop * + +101068: 90 01 c0 08 add %g7, %o0, %o0 +10106c: 01 00 00 00 nop * +101070: 01 00 00 00 nop * +101074: 01 00 00 00 nop * diff --git a/ld/testsuite/ld-sparc/tlssunpic32.dd b/ld/testsuite/ld-sparc/tlssunpic32.dd index c34d514ac1e..558977114d5 100644 --- a/ld/testsuite/ld-sparc/tlssunpic32.dd +++ b/ld/testsuite/ld-sparc/tlssunpic32.dd @@ -37,8 +37,8 @@ Disassembly of section .text: +1058: 11 00 00 00 sethi %hi\(0\), %o0 +105c: 92 02 20 3c add %o0, 0x3c, %o1 ! 3c <.*> +1060: d0 05 c0 09 ld \[ %l7 \+ %o1 \], %o0 - +1064: 90 01 c0 08 add %g7, %o0, %o0 - +1068: 01 00 00 00 nop * + +1064: 01 00 00 00 nop * + +1068: 90 01 c0 08 add %g7, %o0, %o0 +106c: 01 00 00 00 nop * +1070: 01 00 00 00 nop * +1074: 01 00 00 00 nop * @@ -55,8 +55,8 @@ Disassembly of section .text: +10a0: 11 00 00 00 sethi %hi\(0\), %o0 +10a4: 90 02 20 0c add %o0, 0xc, %o0 ! c <.*> +10a8: d0 05 c0 08 ld \[ %l7 \+ %o0 \], %o0 - +10ac: 90 01 c0 08 add %g7, %o0, %o0 - +10b0: 01 00 00 00 nop * + +10ac: 01 00 00 00 nop * + +10b0: 90 01 c0 08 add %g7, %o0, %o0 +10b4: 01 00 00 00 nop * +10b8: 01 00 00 00 nop * +10bc: 01 00 00 00 nop * @@ -73,8 +73,8 @@ Disassembly of section .text: +10e8: 11 00 00 00 sethi %hi\(0\), %o0 +10ec: 90 02 20 48 add %o0, 0x48, %o0 ! 48 <.*> +10f0: d0 05 c0 08 ld \[ %l7 \+ %o0 \], %o0 - +10f4: 90 01 c0 08 add %g7, %o0, %o0 - +10f8: 01 00 00 00 nop * + +10f4: 01 00 00 00 nop * + +10f8: 90 01 c0 08 add %g7, %o0, %o0 +10fc: 01 00 00 00 nop * +1100: 01 00 00 00 nop * +1104: 01 00 00 00 nop * @@ -91,8 +91,8 @@ Disassembly of section .text: +1130: 11 00 00 00 sethi %hi\(0\), %o0 +1134: 90 02 20 24 add %o0, 0x24, %o0 ! 24 <.*> +1138: d0 05 c0 08 ld \[ %l7 \+ %o0 \], %o0 - +113c: 90 01 c0 08 add %g7, %o0, %o0 - +1140: 01 00 00 00 nop * + +113c: 01 00 00 00 nop * + +1140: 90 01 c0 08 add %g7, %o0, %o0 +1144: 01 00 00 00 nop * +1148: 01 00 00 00 nop * +114c: 01 00 00 00 nop * diff --git a/ld/testsuite/ld-sparc/tlssunpic64.dd b/ld/testsuite/ld-sparc/tlssunpic64.dd index 0b41b6858f4..5e94858182d 100644 --- a/ld/testsuite/ld-sparc/tlssunpic64.dd +++ b/ld/testsuite/ld-sparc/tlssunpic64.dd @@ -37,8 +37,8 @@ Disassembly of section .text: +1058: 11 00 00 00 sethi %hi\(0\), %o0 +105c: 92 02 20 78 add %o0, 0x78, %o1 ! 78 <.*> +1060: d0 5d c0 09 ldx \[ %l7 \+ %o1 \], %o0 - +1064: 90 01 c0 08 add %g7, %o0, %o0 - +1068: 01 00 00 00 nop * + +1064: 01 00 00 00 nop * + +1068: 90 01 c0 08 add %g7, %o0, %o0 +106c: 01 00 00 00 nop * +1070: 01 00 00 00 nop * +1074: 01 00 00 00 nop * @@ -55,8 +55,8 @@ Disassembly of section .text: +10a0: 11 00 00 00 sethi %hi\(0\), %o0 +10a4: 90 02 20 18 add %o0, 0x18, %o0 ! 18 <.*> +10a8: d0 5d c0 08 ldx \[ %l7 \+ %o0 \], %o0 - +10ac: 90 01 c0 08 add %g7, %o0, %o0 - +10b0: 01 00 00 00 nop * + +10ac: 01 00 00 00 nop * + +10b0: 90 01 c0 08 add %g7, %o0, %o0 +10b4: 01 00 00 00 nop * +10b8: 01 00 00 00 nop * +10bc: 01 00 00 00 nop * @@ -73,8 +73,8 @@ Disassembly of section .text: +10e8: 11 00 00 00 sethi %hi\(0\), %o0 +10ec: 90 02 20 90 add %o0, 0x90, %o0 ! 90 <.*> +10f0: d0 5d c0 08 ldx \[ %l7 \+ %o0 \], %o0 - +10f4: 90 01 c0 08 add %g7, %o0, %o0 - +10f8: 01 00 00 00 nop * + +10f4: 01 00 00 00 nop * + +10f8: 90 01 c0 08 add %g7, %o0, %o0 +10fc: 01 00 00 00 nop * +1100: 01 00 00 00 nop * +1104: 01 00 00 00 nop * @@ -91,8 +91,8 @@ Disassembly of section .text: +1130: 11 00 00 00 sethi %hi\(0\), %o0 +1134: 90 02 20 48 add %o0, 0x48, %o0 ! 48 <.*> +1138: d0 5d c0 08 ldx \[ %l7 \+ %o0 \], %o0 - +113c: 90 01 c0 08 add %g7, %o0, %o0 - +1140: 01 00 00 00 nop * + +113c: 01 00 00 00 nop * + +1140: 90 01 c0 08 add %g7, %o0, %o0 +1144: 01 00 00 00 nop * +1148: 01 00 00 00 nop * +114c: 01 00 00 00 nop * -- 2.30.2