diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7270c5ff54..f2b4ad4844 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2006-08-08 DJ Delorie + + * elf32-sh.c (sh_elf_relax_section): Allow for branches across + non-moving .align directives. Preserve any DIR32 offset when + converting bsr's to jsr's. + 2006-08-08 Alan Modra * elf64-ppc.c (ppc64_elf_build_stubs): Clear relbrlt reloc_count diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c index 849c9c7e3e..a410901601 100644 --- a/bfd/elf32-sh.c +++ b/bfd/elf32-sh.c @@ -614,7 +614,11 @@ sh_elf_relax_section (bfd *abfd, asection *sec, + sec->output_section->vma + sec->output_offset + 4)); - if (foff < -0x1000 || foff >= 0x1000) + /* A branch to an address beyond ours might be increased by an + .align that doesn't move when bytes behind us are deleted. + So, we add some slop in this calculation to allow for + that. */ + if (foff < -0x1000 || foff >= 0x1000 - 8) { /* After all that work, we can't shorten this function call. */ continue; @@ -652,6 +656,12 @@ sh_elf_relax_section (bfd *abfd, asection *sec, irel->r_addend = -4; + /* When we calculated the symbol "value" we had an offset in the + DIR32's word in memory (we read and add it above). However, + the jsr we create does NOT have this offset encoded, so we + have to add it to the addend to preserve it. */ + irel->r_addend += bfd_get_32 (abfd, contents + paddr); + /* See if there is another R_SH_USES reloc referring to the same register load. */ for (irelscan = internal_relocs; irelscan < irelend; irelscan++)