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.
This commit is contained in:
Sterling Augustine 2011-01-25 13:59:13 -08:00 committed by Max Filippov
parent 68f3446482
commit 331ed1307b
2 changed files with 44 additions and 4 deletions

View File

@ -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

View File

@ -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);