* elf32-sh.c (sh_elf_relax_section): Allow for branches across
authorDJ Delorie <dj@redhat.com>
Tue, 8 Aug 2006 17:21:55 +0000 (17:21 +0000)
committerDJ Delorie <dj@redhat.com>
Tue, 8 Aug 2006 17:21:55 +0000 (17:21 +0000)
non-moving .align directives.  Preserve any DIR32 offset when
converting bsr's to jsr's.

bfd/ChangeLog
bfd/elf32-sh.c

index 7270c5ff5418ac760cb4aa5191c4e70185b310fc..f2b4ad48447579ec330b8768b55a7977a09eec10 100644 (file)
@@ -1,3 +1,9 @@
+2006-08-08  DJ Delorie  <dj@redhat.com>
+
+       * 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  <amodra@bigpond.net.au>
 
        * elf64-ppc.c (ppc64_elf_build_stubs): Clear relbrlt reloc_count
index 849c9c7e3ef3264c28ea72f3e1c0446e4cb98384..a4109016017dc6fef94495440e05a67b648d8355 100644 (file)
@@ -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++)