aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elfxx-mips.c17
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/testsuite/ld-mips-elf/jal-global-overflow-0.d20
-rw-r--r--ld/testsuite/ld-mips-elf/jal-global-overflow-1.d8
-rw-r--r--ld/testsuite/ld-mips-elf/jal-global-overflow.s37
-rw-r--r--ld/testsuite/ld-mips-elf/jal-local-overflow-0.d6
-rw-r--r--ld/testsuite/ld-mips-elf/jal-local-overflow-1.d8
-rw-r--r--ld/testsuite/ld-mips-elf/jal-local-overflow.s35
-rw-r--r--ld/testsuite/ld-mips-elf/mips-elf.exp6
10 files changed, 146 insertions, 8 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4ce81a6..fa83823 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+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
+ local non-section symbols and enable overflow detection.
+
2016-05-28 Alan Modra <amodra@gmail.com>
* aoutx.h: Adjust linker callback calls throughout file,
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 5143fcb..d519090 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -5247,6 +5247,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
/* TRUE if the symbol referred to by this relocation is a local
symbol. */
bfd_boolean local_p, was_local_p;
+ /* TRUE if the symbol referred to by this relocation is a section
+ symbol. */
+ bfd_boolean section_p = FALSE;
/* TRUE if the symbol referred to by this relocation is "_gp_disp". */
bfd_boolean gp_disp_p = FALSE;
/* TRUE if the symbol referred to by this relocation is
@@ -5302,12 +5305,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
+ section_p = ELF_ST_TYPE (sym->st_info) == STT_SECTION;
+
symbol = sec->output_section->vma + sec->output_offset;
- if (ELF_ST_TYPE (sym->st_info) != STT_SECTION
- || (sec->flags & SEC_MERGE))
+ if (!section_p || (sec->flags & SEC_MERGE))
symbol += sym->st_value;
- if ((sec->flags & SEC_MERGE)
- && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ if ((sec->flags & SEC_MERGE) && section_p)
{
addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend);
addend -= symbol;
@@ -5773,9 +5776,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
/* Shift is 2, unusually, for microMIPS JALX. */
shift = (!*cross_mode_jump_p && r_type == R_MICROMIPS_26_S1) ? 1 : 2;
- if (was_local_p)
- value = addend | ((p + 4) & (0xfc000000 << shift));
- else if (howto->partial_inplace)
+ if (howto->partial_inplace && !section_p)
value = _bfd_mips_elf_sign_extend (addend, 26 + shift);
else
value = addend;
@@ -5787,7 +5788,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
return bfd_reloc_outofrange;
value >>= shift;
- if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak)
+ if (was_local_p || h->root.root.type != bfd_link_hash_undefweak)
overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift));
value &= howto->dst_mask;
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index fde9553..13fb745 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+2016-05-28 Maciej W. Rozycki <macro@imgtec.com>
+
+ * testsuite/ld-mips-elf/jal-global-overflow-0.d: New test.
+ * testsuite/ld-mips-elf/jal-global-overflow-1.d: New test.
+ * testsuite/ld-mips-elf/jal-local-overflow-0.d: New test.
+ * testsuite/ld-mips-elf/jal-local-overflow-1.d: New test.
+ * testsuite/ld-mips-elf/jal-global-overflow.s: New test source.
+ * testsuite/ld-mips-elf/jal-local-overflow.s: New test source.
+ * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
+
2016-05-28 Alan Modra <amodra@gmail.com>
* ldmain.c (multiple_definition, multiple_common, add_to_set,
diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d b/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d
new file mode 100644
index 0000000..f02bfea
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d
@@ -0,0 +1,20 @@
+#name: MIPS JAL to global symbol overflow 0
+#source: jal-global-overflow.s
+#as: -EB -32
+#ld: -EB -Ttext 0x20000000 -e 0x20000000
+#objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0c001000 jal 20004000 <bar>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 0c000800 jal 20002000 <foo>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
+[0-9a-f]+ <[^>]*> 0c000800 jal 20002000 <foo>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+[0-9a-f]+ <[^>]*> 0c001000 jal 20004000 <bar>
+[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero
+ \.\.\.
diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d b/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d
new file mode 100644
index 0000000..da6e750
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d
@@ -0,0 +1,8 @@
+#name: MIPS JAL to global symbol overflow 1
+#source: jal-global-overflow.s
+#as: -EB -32
+#ld: -EB -Ttext 0x1fffd000 -e 0x1fffd000
+#error: \A[^\n]*: In function `foo':\n
+#error: \(\.text\+0x2000\): relocation truncated to fit: R_MIPS_26 against `abar'\n
+#error: [^\n]*: In function `bar':\n
+#error: \(\.text\+0x4000\): relocation truncated to fit: R_MIPS_26 against `afoo'\Z
diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow.s b/ld/testsuite/ld-mips-elf/jal-global-overflow.s
new file mode 100644
index 0000000..a67d0bf
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-global-overflow.s
@@ -0,0 +1,37 @@
+ .text
+ .set noreorder
+ .org 0x2000
+
+ .align 4
+ .globl foo
+ .ent foo
+foo:
+ jal abar - 8
+ nor $0, $0
+
+ .globl afoo
+ .aent afoo
+afoo:
+ jal afoo - 8
+ nor $0, $0
+ .end foo
+
+ .org 0x4000
+
+ .align 4
+ .globl bar
+ .ent bar
+bar:
+ jal afoo - 8
+ nor $0, $0
+
+ .globl abar
+ .aent abar
+abar:
+ jal abar - 8
+ nor $0, $0
+ .end bar
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+ .align 4, 0
+ .space 16
diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d b/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d
new file mode 100644
index 0000000..592b2ae
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d
@@ -0,0 +1,6 @@
+#name: MIPS JAL to local symbol overflow 0
+#source: jal-local-overflow.s
+#as: -EB -32
+#ld: -EB -Ttext 0x20000000 -e 0x20000000
+#objdump: -dr --prefix-addresses --show-raw-insn
+#dump: jal-global-overflow-0.d
diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d b/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d
new file mode 100644
index 0000000..869df0e
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d
@@ -0,0 +1,8 @@
+#name: MIPS JAL to local symbol overflow 1
+#source: jal-local-overflow.s
+#as: -EB -32
+#ld: -EB -Ttext 0x1fffd000 -e 0x1fffd000
+#error: \A[^\n]*: In function `foo':\n
+#error: \(\.text\+0x2000\): relocation truncated to fit: R_MIPS_26 against `.text'\n
+#error: [^\n]*: In function `bar':\n
+#error: \(\.text\+0x4000\): relocation truncated to fit: R_MIPS_26 against `.text'\Z
diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow.s b/ld/testsuite/ld-mips-elf/jal-local-overflow.s
new file mode 100644
index 0000000..9b22f67
--- /dev/null
+++ b/ld/testsuite/ld-mips-elf/jal-local-overflow.s
@@ -0,0 +1,35 @@
+ .text
+ .set noreorder
+ .org 0x2000
+
+ .align 4
+ .globl foo
+ .ent foo
+foo:
+ jal abar - 8
+ nor $0, $0
+
+ .aent afoo
+afoo:
+ jal afoo - 8
+ nor $0, $0
+ .end foo
+
+ .org 0x4000
+
+ .align 4
+ .globl bar
+ .ent bar
+bar:
+ jal afoo - 8
+ nor $0, $0
+
+ .aent abar
+abar:
+ jal abar - 8
+ nor $0, $0
+ .end bar
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+ .align 4, 0
+ .space 16
diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp
index 3fa151a..f8c8b09 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf.exp
@@ -493,6 +493,12 @@ if {$linux_gnu} {
run_dump_test "jaloverflow"
run_dump_test "jaloverflow-2"
+
+run_dump_test "jal-global-overflow-0" [list [list ld $abi_ldflags(o32)]]
+run_dump_test "jal-global-overflow-1" [list [list ld $abi_ldflags(o32)]]
+run_dump_test "jal-local-overflow-0" [list [list ld $abi_ldflags(o32)]]
+run_dump_test "jal-local-overflow-1" [list [list ld $abi_ldflags(o32)]]
+
run_dump_test "undefweak-overflow" [list [list as $abi_asflags(o32)] \
[list ld $abi_ldflags(o32)]]