2016-01-03 11:05:27 +00:00
|
|
|
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>
|
|
|
|
---
|
2017-12-02 20:44:39 +00:00
|
|
|
bfd/elf32-xtensa.c | 41 +++++++++++++++++++++++++++++++++++++----
|
2016-01-03 11:05:27 +00:00
|
|
|
1 file changed, 37 insertions(+), 4 deletions(-)
|
|
|
|
|
|
|
|
--- a/bfd/elf32-xtensa.c
|
|
|
|
+++ b/bfd/elf32-xtensa.c
|
2017-12-02 20:44:39 +00:00
|
|
|
@@ -7123,10 +7123,43 @@
|
2016-01-03 11:05:27 +00:00
|
|
|
|| 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);
|