This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix PR 24564 - link fails for some rcalls/rjmps with wraparound


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=338ba75534fbfeb64d7009f29a89f25826a1f4d2

commit 338ba75534fbfeb64d7009f29a89f25826a1f4d2
Author: Senthil Kumar Selvaraj <senthilkumar.selvaraj@microchip.com>
Date:   Thu May 16 17:16:36 2019 +0530

    Fix PR 24564 - link fails for some rcalls/rjmps with wraparound
    
    The current code to compute relative distance in the wrap around case does not
    handle the edge case of the target (after adjusting for implicit PC increment)
    being exactly half of the wrap around distance. This patch fixes that and adds a
    testcase.
    
    The range for a forward relative jump call is 4096 bytes ((2 * 2047) + (2 bytes
    for the implicit PC increment)). If the target of the jump is at a distance of
    4098 bytes, it is out of range for a forward jump - however, a backward jump can
    still reach that address if pmem-wrap-around is 8192.
    
    Assume address 0 has rjmp to address 4098. With a wrap around of 8192 and
    *without* adjusting for the implicit PC increment of 2 bytes, rjmp .-4096 will
    jump to address 4096 (wrap around at 8192 and decreasing addresses from then
    on). Adjusting 2 bytes for the implicit PC increment, the actual target is 4098.
    
    avr_relative_distance_considering_wrap_around though, does the wrap around only
    if the passed in distance is less than half of the wrap around distance. In this
    case, it is exactly equal to half (original distance 4098, adjusted distance of
    4096 and wraparound of 8192), and the bypassed wrap around causes the reloc
    overflow error.
    
    Fix by wrapping around even if adjusted distance is equal to half of wrap around
    distance.

Diff:
---
 bfd/ChangeLog                                   |  6 ++++++
 bfd/elf32-avr.c                                 |  2 +-
 ld/ChangeLog                                    |  6 ++++++
 ld/testsuite/ld-avr/wraparound-range-boundary.d | 17 +++++++++++++++++
 ld/testsuite/ld-avr/wraparound-range-boundary.s |  6 ++++++
 5 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e463fed..0d7eda4 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2019-05-21  Senthil Kumar Selvaraj  <senthilkumar.selvaraj@microchip.com>
+
+	PR ld/24564
+	* bfd/elf32-avr.c (avr_relative_distance_considering_wrap_around):
+	Wrap around even if distance equals avr_pc_wrap_around.
+
 2019-05-20  Nick Clifton  <nickc@redhat.com>
 
 	* po/fr.po: Updated French translation.
diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c
index d6842a0..f8a843e 100644
--- a/bfd/elf32-avr.c
+++ b/bfd/elf32-avr.c
@@ -910,7 +910,7 @@ avr_relative_distance_considering_wrap_around (unsigned int distance)
   unsigned int wrap_around_mask = avr_pc_wrap_around - 1;
   int dist_with_wrap_around = distance & wrap_around_mask;
 
-  if (dist_with_wrap_around > ((int) (avr_pc_wrap_around >> 1)))
+  if (dist_with_wrap_around >= ((int) (avr_pc_wrap_around >> 1)))
     dist_with_wrap_around -= avr_pc_wrap_around;
 
   return dist_with_wrap_around;
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 594a304..20be135 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,9 @@
+2019-05-21  Senthil Kumar Selvaraj  <senthilkumar.selvaraj@microchip.com>
+
+	PR ld/24564
+	* testsuite/ld-avr/wraparound-range-boundary.d: New test.
+	* testsuite/ld-avr/wraparound-range-boundary.s: New test.
+
 2019-05-20  Faraz Shahbazker  <fshahbazker@wavecomp.com>
 
 	PR 14798
diff --git a/ld/testsuite/ld-avr/wraparound-range-boundary.d b/ld/testsuite/ld-avr/wraparound-range-boundary.d
new file mode 100644
index 0000000..83c12f5
--- /dev/null
+++ b/ld/testsuite/ld-avr/wraparound-range-boundary.d
@@ -0,0 +1,17 @@
+#name: Wraparound works for jump target at pc-relative range boundary
+#as: -m avr51
+#ld: --pmem-wrap-around=8k -m avr51
+#source: wraparound-range-boundary.s
+#objdump: -d
+#target: avr-*-*
+
+#...
+Disassembly of section .text:
+
+00000000 <__ctors_end>:
+       0:	00 c8       	rjmp	.\-4096   	; 0xfffff002 <__eeprom_end\+0xff7ef002>
+	...
+
+00001002 <target>:
+	...
+
diff --git a/ld/testsuite/ld-avr/wraparound-range-boundary.s b/ld/testsuite/ld-avr/wraparound-range-boundary.s
new file mode 100644
index 0000000..fbea0e1
--- /dev/null
+++ b/ld/testsuite/ld-avr/wraparound-range-boundary.s
@@ -0,0 +1,6 @@
+.global main
+main:
+	rjmp target
+	.ds.b 4096
+target:
+	nop


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]