From 99aefae6818be07a77739e0366121f2032916d9c Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 28 May 2016 10:57:58 +0100 Subject: [PATCH] MIPS/BFD: Correctly handle `bfd_reloc_outofrange' with branches Fix internal errors like: ld: BFD (GNU Binutils) 2.26.51.20160526 internal error, aborting at .../bfd/elfxx-mips.c:10278 in _bfd_mips_elf_relocate_section ld: Please report this bug. triggered by the `bfd_reloc_outofrange' condition on branch relocations. bfd/ * elfxx-mips.c (b_reloc_p): New function. (_bfd_mips_elf_relocate_section) : Handle branch relocations. ld/ * testsuite/ld-mips-elf/unaligned-branch.d: New test. * testsuite/ld-mips-elf/unaligned-branch.s: New test source. * testsuite/ld-mips-elf/unaligned-text.s: New test source. * testsuite/ld-mips-elf/mips-elf.exp: Run the new test. --- bfd/ChangeLog | 6 ++++++ bfd/elfxx-mips.c | 11 ++++++++++ ld/ChangeLog | 7 +++++++ ld/testsuite/ld-mips-elf/mips-elf.exp | 2 ++ ld/testsuite/ld-mips-elf/unaligned-branch.d | 23 +++++++++++++++++++++ ld/testsuite/ld-mips-elf/unaligned-branch.s | 21 +++++++++++++++++++ ld/testsuite/ld-mips-elf/unaligned-text.s | 15 ++++++++++++++ 7 files changed, 85 insertions(+) create mode 100644 ld/testsuite/ld-mips-elf/unaligned-branch.d create mode 100644 ld/testsuite/ld-mips-elf/unaligned-branch.s create mode 100644 ld/testsuite/ld-mips-elf/unaligned-text.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fa83823d889..726e4c3ff8f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2016-05-28 Maciej W. Rozycki + + * elfxx-mips.c (b_reloc_p): New function. + (_bfd_mips_elf_relocate_section) : Handle + branch relocations. + 2016-05-28 Maciej W. Rozycki * elfxx-mips.c (mips_elf_calculate_relocation): diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index d519090dc15..e2f47499e93 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -2215,6 +2215,15 @@ jal_reloc_p (int r_type) || r_type == R_MICROMIPS_26_S1); } +static inline bfd_boolean +b_reloc_p (int r_type) +{ + return (r_type == R_MIPS_PC26_S2 + || r_type == R_MIPS_PC21_S2 + || r_type == R_MIPS_PC16 + || r_type == R_MIPS_GNU_REL16_S2); +} + static inline bfd_boolean aligned_pcrel_reloc_p (int r_type) { @@ -10261,6 +10270,8 @@ _bfd_mips_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info, msg = NULL; if (jal_reloc_p (howto->type)) msg = _("JALX to a non-word-aligned address"); + else if (b_reloc_p (howto->type)) + msg = _("Branch to a non-instruction-aligned address"); else if (aligned_pcrel_reloc_p (howto->type)) msg = _("PC-relative load from unaligned address"); if (msg) diff --git a/ld/ChangeLog b/ld/ChangeLog index 238b25f866f..1b99a438ac8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +2016-05-28 Maciej W. Rozycki + + * testsuite/ld-mips-elf/unaligned-branch.d: New test. + * testsuite/ld-mips-elf/unaligned-branch.s: New test source. + * testsuite/ld-mips-elf/unaligned-text.s: New test source. + * testsuite/ld-mips-elf/mips-elf.exp: Run the new test. + 2016-05-28 Maciej W. Rozycki * testsuite/ld-mips-elf/unaligned-syms.s: Rename to... diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index f8c8b09bda0..61a119e39a9 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -199,6 +199,8 @@ if $has_newabi { [list [list ld $abi_ldflags(n32)]] } +run_dump_test "unaligned-branch" [list [list ld $abi_ldflags(o32)]] + run_dump_test "unaligned-lwpc-0" [list [list ld $abi_ldflags(o32)]] run_dump_test "unaligned-lwpc-1" [list [list ld $abi_ldflags(o32)]] run_dump_test "unaligned-ldpc-0" [list [list ld $abi_ldflags(o32)]] diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch.d b/ld/testsuite/ld-mips-elf/unaligned-branch.d new file mode 100644 index 00000000000..54894b68bdd --- /dev/null +++ b/ld/testsuite/ld-mips-elf/unaligned-branch.d @@ -0,0 +1,23 @@ +#name: MIPS branch to unaligned symbol +#source: unaligned-branch.s +#source: unaligned-text.s +#as: -EB -32 -mips32r6 +#ld: -EB -Ttext 0x10000000 -e 0x10000000 +#error: \A[^\n]*: In function `foo':\n +#error: \(\.text\+0x14\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x1c\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x24\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x28\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x30\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x38\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x3c\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x44\): Branch to a non-instruction-aligned address\n +#error: [^\n]*: In function `foo':\n +#error: \(\.text\+0x4c\): Branch to a non-instruction-aligned address\Z diff --git a/ld/testsuite/ld-mips-elf/unaligned-branch.s b/ld/testsuite/ld-mips-elf/unaligned-branch.s new file mode 100644 index 00000000000..8fef3bb0b5d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/unaligned-branch.s @@ -0,0 +1,21 @@ + .text + .align 4 + .globl foo + .ent foo +foo: + b bar0 + beqzc $2, bar0 + bc bar0 + b bar1 + beqzc $2, bar1 + bc bar1 + b bar2 + beqzc $2, bar2 + bc bar2 + b bar3 + beqzc $2, bar3 + bc bar3 + b bar4 + beqzc $2, bar4 + bc bar4 + .end foo diff --git a/ld/testsuite/ld-mips-elf/unaligned-text.s b/ld/testsuite/ld-mips-elf/unaligned-text.s new file mode 100644 index 00000000000..4b3aa38ad9c --- /dev/null +++ b/ld/testsuite/ld-mips-elf/unaligned-text.s @@ -0,0 +1,15 @@ + .macro sym n:req + .if \n + .globl bar\@ + .type bar\@, @object +bar\@ : + .byte 0 + .size bar\@, . - bar\@ + sym \n - 1 + .endif + .endm + + .text + .align 4 + .space 32 + sym 16