aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorSterling Augustine <augustine.sterling@gmail.com>2011-01-25 13:59:13 -0800
committerMax Filippov <jcmvbkbc@gmail.com>2014-09-23 03:41:35 +0400
commit331ed1307b93d3ff77d248bdf2f7b79a20851457 (patch)
tree826cae7557e96829755e148e166d3af207796208 /bfd
parent68f34464821105e0c74a0ce16c5d26d4c3e1d20c (diff)
downloadgdb-331ed1307b93d3ff77d248bdf2f7b79a20851457.zip
gdb-331ed1307b93d3ff77d248bdf2f7b79a20851457.tar.gz
gdb-331ed1307b93d3ff77d248bdf2f7b79a20851457.tar.bz2
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.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf32-xtensa.c41
2 files changed, 44 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 2fc0e1e..d8559ea 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2014-09-23 Sterling Augustine <augustine.sterling@gmail.com>
+
+ * 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.
+
2014-09-22 Alan Modra <amodra@gmail.com>
* elf-eh-frame.c (_bfd_elf_write_section_eh_frame_hdr): Don't return
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);