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:
parent
68f3446482
commit
331ed1307b
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue