MIPS/BFD: Correctly handle `bfd_reloc_outofrange' with branches
authorMaciej W. Rozycki <macro@imgtec.com>
Sat, 28 May 2016 09:57:58 +0000 (10:57 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Sat, 28 May 2016 09:59:45 +0000 (10:59 +0100)
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) <bfd_reloc_outofrange>: 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
bfd/elfxx-mips.c
ld/ChangeLog
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/unaligned-branch.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-branch.s [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-text.s [new file with mode: 0644]

index fa83823..726e4c3 100644 (file)
@@ -1,5 +1,11 @@
 2016-05-28  Maciej W. Rozycki  <macro@imgtec.com>
 
+       * elfxx-mips.c (b_reloc_p): New function.
+       (_bfd_mips_elf_relocate_section) <bfd_reloc_outofrange>: Handle
+       branch relocations.
+
+2016-05-28  Maciej W. Rozycki  <macro@imgtec.com>
+
        * elfxx-mips.c (mips_elf_calculate_relocation): <R_MIPS16_26>
        <R_MIPS_26, R_MICROMIPS_26_S1>: Drop the region bits of the
        reloc location from calculation, treat the addend as signed with
index d519090..e2f4749 100644 (file)
@@ -2216,6 +2216,15 @@ jal_reloc_p (int r_type)
 }
 
 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)
 {
   return (r_type == R_MIPS_PC18_S3
@@ -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)
index 238b25f..1b99a43 100644 (file)
@@ -1,5 +1,12 @@
 2016-05-28  Maciej W. Rozycki  <macro@imgtec.com>
 
+       * 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  <macro@imgtec.com>
+
        * testsuite/ld-mips-elf/unaligned-syms.s: Rename to...
        * testsuite/ld-mips-elf/unaligned-data.s: ... this.
        * testsuite/ld-mips-elf/unaligned-ldpc-0.d: Adjust accordingly.
index f8c8b09..61a119e 100644 (file)
@@ -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 (file)
index 0000000..54894b6
--- /dev/null
@@ -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 (file)
index 0000000..8fef3bb
--- /dev/null
@@ -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 (file)
index 0000000..4b3aa38
--- /dev/null
@@ -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