This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] sh relaxing
- From: DJ Delorie <dj at redhat dot com>
- To: binutils at sourceware dot org
- Date: Tue, 25 Jul 2006 17:25:46 -0400
- Subject: [patch] sh relaxing
A couple of patches to fix ld's sh-relax failures. The BFD bug caused
relaxed jumps to jump to the wrong place. The GAS one caused offset
tables to be deleted while they were still in use. Ok?
bfd/ChangeLog
2006-07-25 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.
gas/ChangeLog
2006-07-25 DJ Delorie <dj@redhat.com>
* config/tc-sh.c (sh_frob_section): Canonicalize pointers to local
vs full symbols so that we never have more than one pointer value
for any given symbol in our symbol table.
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.138
diff -p -U3 -r1.138 bfd/elf32-sh.c
--- bfd/elf32-sh.c 23 Jun 2006 02:58:00 -0000 1.138
+++ bfd/elf32-sh.c 25 Jul 2006 21:22:30 -0000
@@ -2284,7 +2284,11 @@ sh_elf_relax_section (bfd *abfd, asectio
+ 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;
@@ -2322,6 +2326,12 @@ sh_elf_relax_section (bfd *abfd, asectio
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++)
Index: gas/config/tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.119
diff -p -U3 -r1.119 gas/config/tc-sh.c
--- gas/config/tc-sh.c 21 Jul 2006 09:46:15 -0000 1.119
+++ gas/config/tc-sh.c 25 Jul 2006 21:22:32 -0000
@@ -3318,6 +3318,21 @@ sh_frob_section (bfd *abfd ATTRIBUTE_UNU
for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
{
symbolS *sym;
+
+ sym = fix->fx_addsy;
+ /* Check for a local_symbol. */
+ if (sym && sym->bsym == NULL)
+ {
+ struct local_symbol *ls = (struct local_symbol *)sym;
+ /* See if it's been converted. If so, canonicalize. */
+ if (local_symbol_converted_p (ls))
+ fix->fx_addsy = local_symbol_get_real_symbol (ls);
+ }
+ }
+
+ for (fix = seginfo->fix_root; fix != NULL; fix = fix->fx_next)
+ {
+ symbolS *sym;
bfd_vma val;
fixS *fscan;
struct sh_count_relocs info;