Commit 9849f005 authored by Max Filippov's avatar Max Filippov Committed by Thomas Petazzoni
Browse files

binutils: fix 'call8: call target out of range' xtensa ld bug



This fixes the following linux kernel build errors:

  LD      init/built-in.o
  net/built-in.o: In function `raw_proc_exit':
  (.init.text+0xe29): dangerous relocation:
		      call8: call target out of range: udp_proc_register
  net/built-in.o: In function `udp_table_init':
  (.init.text+0xf09): dangerous relocation:
		      call8: call target out of range: udp_proc_register
  net/built-in.o: In function `inet_init':
  af_inet.c:(.init.text+0x142e): dangerous relocation:
				 call8: call target out of range: udp4_proc_exit
  net/built-in.o: In function `ip_auto_config':
  ipconfig.c:(.init.text+0x28aa): dangerous relocation:
				  call8: call target out of range: arp_send

Backported from: 331ed1307b93d3ff77d248bdf2f7b79a20851457
Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
Signed-off-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
parent 0b337a08
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
From 7fc39194f8fb48914c995f8ec3826d50086f1ec0 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <augustine.sterling@gmail.com>
Date: Tue, 25 Jan 2011 13:59:13 -0800
Subject: [PATCH] Fix 'call8: call target out of range' xtensa ld relaxation
 bug

During link-time relaxation distance between cross-section call site and
its target may grow, producing 'call target out of range' error for
relaxed calls. Be more conservative when calculating whether or not a
callx can be converted to a straight call.

2014-09-23  Sterling Augustine  <augustine.sterling@gmail.com>

bfd/
    * elf32-xtensa.c (is_resolvable_asm_expansion): for cross-section
    call relaxation use furthermost addresses where call source and
    destination can be to check whether it's in the range of a direct
    call.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 bfd/elf32-xtensa.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 09862e3..e32496a 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -7124,10 +7124,43 @@ is_resolvable_asm_expansion (bfd *abfd,
 	  || is_reloc_sym_weak (abfd, irel)))
     return FALSE;
 
-  self_address = (sec->output_section->vma
-		  + sec->output_offset + irel->r_offset + 3);
-  dest_address = (target_sec->output_section->vma
-		  + target_sec->output_offset + target_offset);
+  if (target_sec->output_section != sec->output_section)
+    {
+      /* If the two sections are sufficiently far away that relaxation
+	 might take the call out of range, we can't simplify.  For
+	 example, a positive displacement call into another memory
+	 could get moved to a lower address due to literal removal,
+	 but the destination won't move, and so the displacment might
+	 get larger.
+
+	 If the displacement is negative, assume the destination could
+	 move as far back as the start of the output section.  The
+	 self_address will be at least as far into the output section
+	 as it is prior to relaxation.
+
+	 If the displacement is postive, assume the destination will be in
+	 it's pre-relaxed location (because relaxation only makes sections
+	 smaller).  The self_address could go all the way to the beginning
+	 of the output section.  */
+
+      dest_address = target_sec->output_section->vma;
+      self_address = sec->output_section->vma;
+
+      if (sec->output_section->vma > target_sec->output_section->vma)
+	self_address += sec->output_offset + irel->r_offset + 3;
+      else
+	dest_address += bfd_get_section_limit (abfd, target_sec->output_section);
+      /* Call targets should be four-byte aligned.  */
+      dest_address = (dest_address + 3) & ~3;
+    }
+  else
+    {
+
+      self_address = (sec->output_section->vma
+		      + sec->output_offset + irel->r_offset + 3);
+      dest_address = (target_sec->output_section->vma
+		      + target_sec->output_offset + target_offset);
+    }
       
   *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
 				      self_address, dest_address);
-- 
1.8.1.4
+79 −0
Original line number Diff line number Diff line
From 7fc39194f8fb48914c995f8ec3826d50086f1ec0 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <augustine.sterling@gmail.com>
Date: Tue, 25 Jan 2011 13:59:13 -0800
Subject: [PATCH] Fix 'call8: call target out of range' xtensa ld relaxation
 bug

During link-time relaxation distance between cross-section call site and
its target may grow, producing 'call target out of range' error for
relaxed calls. Be more conservative when calculating whether or not a
callx can be converted to a straight call.

2014-09-23  Sterling Augustine  <augustine.sterling@gmail.com>

bfd/
    * elf32-xtensa.c (is_resolvable_asm_expansion): for cross-section
    call relaxation use furthermost addresses where call source and
    destination can be to check whether it's in the range of a direct
    call.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 bfd/elf32-xtensa.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 09862e3..e32496a 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -7124,10 +7124,43 @@ is_resolvable_asm_expansion (bfd *abfd,
 	  || is_reloc_sym_weak (abfd, irel)))
     return FALSE;
 
-  self_address = (sec->output_section->vma
-		  + sec->output_offset + irel->r_offset + 3);
-  dest_address = (target_sec->output_section->vma
-		  + target_sec->output_offset + target_offset);
+  if (target_sec->output_section != sec->output_section)
+    {
+      /* If the two sections are sufficiently far away that relaxation
+	 might take the call out of range, we can't simplify.  For
+	 example, a positive displacement call into another memory
+	 could get moved to a lower address due to literal removal,
+	 but the destination won't move, and so the displacment might
+	 get larger.
+
+	 If the displacement is negative, assume the destination could
+	 move as far back as the start of the output section.  The
+	 self_address will be at least as far into the output section
+	 as it is prior to relaxation.
+
+	 If the displacement is postive, assume the destination will be in
+	 it's pre-relaxed location (because relaxation only makes sections
+	 smaller).  The self_address could go all the way to the beginning
+	 of the output section.  */
+
+      dest_address = target_sec->output_section->vma;
+      self_address = sec->output_section->vma;
+
+      if (sec->output_section->vma > target_sec->output_section->vma)
+	self_address += sec->output_offset + irel->r_offset + 3;
+      else
+	dest_address += bfd_get_section_limit (abfd, target_sec->output_section);
+      /* Call targets should be four-byte aligned.  */
+      dest_address = (dest_address + 3) & ~3;
+    }
+  else
+    {
+
+      self_address = (sec->output_section->vma
+		      + sec->output_offset + irel->r_offset + 3);
+      dest_address = (target_sec->output_section->vma
+		      + target_sec->output_offset + target_offset);
+    }
       
   *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
 				      self_address, dest_address);
-- 
1.8.1.4
+79 −0
Original line number Diff line number Diff line
From 7fc39194f8fb48914c995f8ec3826d50086f1ec0 Mon Sep 17 00:00:00 2001
From: Sterling Augustine <augustine.sterling@gmail.com>
Date: Tue, 25 Jan 2011 13:59:13 -0800
Subject: [PATCH] Fix 'call8: call target out of range' xtensa ld relaxation
 bug

During link-time relaxation distance between cross-section call site and
its target may grow, producing 'call target out of range' error for
relaxed calls. Be more conservative when calculating whether or not a
callx can be converted to a straight call.

2014-09-23  Sterling Augustine  <augustine.sterling@gmail.com>

bfd/
    * elf32-xtensa.c (is_resolvable_asm_expansion): for cross-section
    call relaxation use furthermost addresses where call source and
    destination can be to check whether it's in the range of a direct
    call.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 bfd/elf32-xtensa.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 09862e3..e32496a 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -7124,10 +7124,43 @@ is_resolvable_asm_expansion (bfd *abfd,
 	  || is_reloc_sym_weak (abfd, irel)))
     return FALSE;
 
-  self_address = (sec->output_section->vma
-		  + sec->output_offset + irel->r_offset + 3);
-  dest_address = (target_sec->output_section->vma
-		  + target_sec->output_offset + target_offset);
+  if (target_sec->output_section != sec->output_section)
+    {
+      /* If the two sections are sufficiently far away that relaxation
+	 might take the call out of range, we can't simplify.  For
+	 example, a positive displacement call into another memory
+	 could get moved to a lower address due to literal removal,
+	 but the destination won't move, and so the displacment might
+	 get larger.
+
+	 If the displacement is negative, assume the destination could
+	 move as far back as the start of the output section.  The
+	 self_address will be at least as far into the output section
+	 as it is prior to relaxation.
+
+	 If the displacement is postive, assume the destination will be in
+	 it's pre-relaxed location (because relaxation only makes sections
+	 smaller).  The self_address could go all the way to the beginning
+	 of the output section.  */
+
+      dest_address = target_sec->output_section->vma;
+      self_address = sec->output_section->vma;
+
+      if (sec->output_section->vma > target_sec->output_section->vma)
+	self_address += sec->output_offset + irel->r_offset + 3;
+      else
+	dest_address += bfd_get_section_limit (abfd, target_sec->output_section);
+      /* Call targets should be four-byte aligned.  */
+      dest_address = (dest_address + 3) & ~3;
+    }
+  else
+    {
+
+      self_address = (sec->output_section->vma
+		      + sec->output_offset + irel->r_offset + 3);
+      dest_address = (target_sec->output_section->vma
+		      + target_sec->output_offset + target_offset);
+    }
 
   *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
 				      self_address, dest_address);
-- 
1.8.1.4