aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-xtensa.c26
-rw-r--r--ld/ChangeLog9
-rw-r--r--ld/testsuite/ld-xtensa/relax-diff1.d6
-rw-r--r--ld/testsuite/ld-xtensa/relax-diff1.s18
-rw-r--r--ld/testsuite/ld-xtensa/relax-ndiff.d6
-rw-r--r--ld/testsuite/ld-xtensa/relax-ndiff.s20
-rw-r--r--ld/testsuite/ld-xtensa/xtensa.exp2
8 files changed, 83 insertions, 11 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 31e8526..25453b3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2020-04-29 Max Filippov <jcmvbkbc@gmail.com>
+
+ * elf32-xtensa.c (relax_section): Don't negate diff_value for
+ XTENSA_NDIFF relocations. Don't add sign bits whe diff_value
+ equals 0. Report overflow when the result has negative sign but
+ all significant bits are zero.
+
2020-04-29 Gunther Nikl <gnikl@justmail.de>
* aoutx.h (swap_std_reloc_out): Special case 64 bit relocations.
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index fded42d..4327b02 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -9670,37 +9670,44 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
switch (r_type)
{
case R_XTENSA_DIFF8:
+ diff_mask = 0x7f;
diff_value =
bfd_get_signed_8 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
+ diff_mask = 0x7fff;
diff_value =
bfd_get_signed_16 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
+ diff_mask = 0x7fffffff;
diff_value =
bfd_get_signed_32 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_PDIFF8:
case R_XTENSA_NDIFF8:
+ diff_mask = 0xff;
diff_value =
bfd_get_8 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_PDIFF16:
case R_XTENSA_NDIFF16:
+ diff_mask = 0xffff;
diff_value =
bfd_get_16 (abfd, &contents[old_source_offset]);
break;
case R_XTENSA_PDIFF32:
case R_XTENSA_NDIFF32:
+ diff_mask = 0xffffffff;
diff_value =
bfd_get_32 (abfd, &contents[old_source_offset]);
break;
}
if (r_type >= R_XTENSA_NDIFF8
- && r_type <= R_XTENSA_NDIFF32)
- diff_value = -diff_value;
+ && r_type <= R_XTENSA_NDIFF32
+ && diff_value)
+ diff_value |= ~diff_mask;
new_end_offset = offset_with_removed_text_map
(&target_relax_info->action_list,
@@ -9710,43 +9717,40 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info)
switch (r_type)
{
case R_XTENSA_DIFF8:
- diff_mask = 0x7f;
bfd_put_signed_8 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF16:
- diff_mask = 0x7fff;
bfd_put_signed_16 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_DIFF32:
- diff_mask = 0x7fffffff;
bfd_put_signed_32 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_PDIFF8:
case R_XTENSA_NDIFF8:
- diff_mask = 0xff;
bfd_put_8 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_PDIFF16:
case R_XTENSA_NDIFF16:
- diff_mask = 0xffff;
bfd_put_16 (abfd, diff_value,
&contents[old_source_offset]);
break;
case R_XTENSA_PDIFF32:
case R_XTENSA_NDIFF32:
- diff_mask = 0xffffffff;
bfd_put_32 (abfd, diff_value,
&contents[old_source_offset]);
break;
}
- /* Check for overflow. Sign bits must be all zeroes or all ones */
- if ((diff_value & ~diff_mask) != 0 &&
- (diff_value & ~diff_mask) != (-1 & ~diff_mask))
+ /* Check for overflow. Sign bits must be all zeroes or
+ all ones. When sign bits are all ones diff_value
+ may not be zero. */
+ if (((diff_value & ~diff_mask) != 0
+ && (diff_value & ~diff_mask) != ~diff_mask)
+ || (diff_value && (bfd_vma) diff_value == ~diff_mask))
{
(*link_info->callbacks->reloc_dangerous)
(link_info, _("overflow after relaxation"),
diff --git a/ld/ChangeLog b/ld/ChangeLog
index ae587df..43825ee 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,12 @@
+2020-04-29 Max Filippov <jcmvbkbc@gmail.com>
+
+ * testsuite/ld-xtensa/relax-diff1.d: New test definition.
+ * testsuite/ld-xtensa/relax-diff1.s: New test source.
+ * testsuite/ld-xtensa/relax-ndiff.d: New test definition.
+ * testsuite/ld-xtensa/relax-ndiff.s: New test source.
+ * testsuite/ld-xtensa/xtensa.exp: (relax-diff1)
+ (relax-ndiff): New tests.
+
2020-04-29 Stephen Casner <casner@acm.org>
PR 25829
diff --git a/ld/testsuite/ld-xtensa/relax-diff1.d b/ld/testsuite/ld-xtensa/relax-diff1.d
new file mode 100644
index 0000000..900b55b
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/relax-diff1.d
@@ -0,0 +1,6 @@
+#as: --text-section-literals
+#ld:
+#objdump: -s
+#...
+ 410154 06fa0006 fffa.*
+#...
diff --git a/ld/testsuite/ld-xtensa/relax-diff1.s b/ld/testsuite/ld-xtensa/relax-diff1.s
new file mode 100644
index 0000000..6cc8e2b
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/relax-diff1.s
@@ -0,0 +1,18 @@
+ .globl _start
+ .globl _ResetVector
+ .text
+_ResetVector:
+_start:
+ .literal_position
+ movi a2, 0x12345678
+ movi a2, 0x12345678
+1:
+ .space 250
+2:
+ .space 65530
+3:
+ .align 4
+ .byte 1b - 2b
+ .byte 2b - 1b
+ .short 2b - 3b
+ .short 3b - 2b
diff --git a/ld/testsuite/ld-xtensa/relax-ndiff.d b/ld/testsuite/ld-xtensa/relax-ndiff.d
new file mode 100644
index 0000000..2a1cfd3
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/relax-ndiff.d
@@ -0,0 +1,6 @@
+#as: --text-section-literals
+#ld:
+#objdump: -s
+#...
+ 400074 fffffff6 0000000a fff6000a f60a.*
+#...
diff --git a/ld/testsuite/ld-xtensa/relax-ndiff.s b/ld/testsuite/ld-xtensa/relax-ndiff.s
new file mode 100644
index 0000000..4e4176b
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/relax-ndiff.s
@@ -0,0 +1,20 @@
+ .globl _start
+ .globl _ResetVector
+ .text
+_ResetVector:
+_start:
+ .literal_position
+ movi a2, 0x12345678
+ movi a2, 0x12345678
+1:
+ .space 10
+2:
+ .space 10
+3:
+ .align 4
+ .word 1b - 2b
+ .word 3b - 2b
+ .short 1b - 2b
+ .short 3b - 2b
+ .byte 1b - 2b
+ .byte 3b - 2b
diff --git a/ld/testsuite/ld-xtensa/xtensa.exp b/ld/testsuite/ld-xtensa/xtensa.exp
index de39887..5334bc6 100644
--- a/ld/testsuite/ld-xtensa/xtensa.exp
+++ b/ld/testsuite/ld-xtensa/xtensa.exp
@@ -27,7 +27,9 @@ run_dump_test "call_overflow"
run_dump_test "coalesce"
run_dump_test "diff_overflow"
run_dump_test "lcall"
+run_dump_test "relax-diff1"
run_dump_test "relax-loc"
+run_dump_test "relax-ndiff"
run_dump_test "relax-static-pie"
run_dump_test "relax-static-local-pie"