Subject: bfd and gas patch for sh3 REL32 (Re: Self build error)
To: None <thorpej@wasabisystems.com>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-dreamcast
Date: 02/04/2003 23:41:55
In article <200301261823.h0QINEM28634@mirage.ceres.dti.ne.jp> on port-dreamcast
I wrote:
> In article <200301242232.h0OMWg800801@mirage.ceres.dti.ne.jp>
> I wrote:
>
> > In article <20030124215106.GB8538@yeah-baby.shagadelic.org>
> > thorpej@wasabisystems.com wrote:
> >
> > > On Sat, Jan 25, 2003 at 05:45:27AM +0900, Izumi Tsutsui wrote:
> > > > The following patch seems to fix the problem.
> > > > (though I don't know gas statements..)
> > >
> > > I'm a little confused as to why the globl is needed ... it's supposed
> > > to be calling a non-global (static) function...
> >
> > I know all functions used in the macro declared as static, but
> > without .globl, MD_CALL_STATIC_FUNCTION(.init, __do_global_[cd]tors_aux)
> > jumps __ctors() (first function?), not __do_global_[cd]tors_aux().
>
> It seems SH bfd relocation bug. I applied the following diff:
> http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/bfd/elf32-sh.c.diff?r1=1.35&r2=1.36&cvsroot=src
> to toolchain/bfd/elf32-sh.c, and it changes the behavoir a bit,
> but it still sets wrong address.
Applying the above patch to bfd and also taking a patch
against gas/config/tc-sh.c from kaz Kojima's gnu-on-sh page
http://dodo.nurs.or.jp/~kkojima/gnu-on-sh/
seems to fix the problem..
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvsroot/src/gnu/dist/toolchain/bfd/elf32-sh.c,v
retrieving revision 1.4
diff -u -r1.4 elf32-sh.c
--- bfd/elf32-sh.c 2001/08/14 04:43:07 1.4
+++ bfd/elf32-sh.c 2003/02/04 14:36:19
@@ -121,8 +121,8 @@
complain_overflow_signed, /* complain_on_overflow */
sh_elf_ignore_reloc, /* special_function */
"R_SH_REL32", /* name */
- false, /* partial_inplace */
- 0, /* src_mask */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
true), /* pcrel_offset */
@@ -2917,8 +2917,12 @@
}
howto = sh_elf_howto_table + r_type;
+
+ /* For relocs that aren't partial_inplace, we get the addend from
+ the relocation. */
+ if (! howto->partial_inplace)
+ addend = rel->r_addend;
- /* This is a final link. */
h = NULL;
sym = NULL;
sec = NULL;
@@ -2938,7 +2942,32 @@
section symbol winds up in the output section. */
sym = local_syms + r_symndx;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- goto final_link_relocate;
+ {
+ if (! howto->partial_inplace)
+ {
+ /* For relocations with the addend in the
+ relocation, we need just to update the addend.
+ All real relocs are of type partial_inplace; this
+ code is mostly for completeness. */
+ rel->r_addend += sec->output_offset + sym->st_value;
+
+ continue;
+ }
+
+ /* Relocs of type partial_inplace need to pick up the
+ contents in the contents and add the offset resulting
+ from the changed location of the section symbol.
+ Using _bfd_final_link_relocate (e.g. goto
+ final_link_relocate) here would be wrong, because
+ relocations marked pc_relative would get the current
+ location subtracted, and we must only do that at the
+ final link. */
+ r = _bfd_relocate_contents (howto, input_bfd,
+ sec->output_offset
+ + sym->st_value,
+ contents + rel->r_offset);
+ goto relocation_done;
+ }
continue;
}
@@ -3111,7 +3140,8 @@
BFD_ASSERT (h != NULL && h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
- outrel.r_addend = rel->r_addend;
+ outrel.r_addend
+ = bfd_get_32 (input_bfd, contents + rel->r_offset);
}
else
{
@@ -3124,14 +3154,18 @@
{
relocate = true;
outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_addend
+ = relocation + bfd_get_32 (input_bfd,
+ contents + rel->r_offset);
}
else
{
BFD_ASSERT (h->dynindx != -1);
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_addend
+ = relocation + bfd_get_32 (input_bfd,
+ contents + rel->r_offset);
}
}
@@ -3148,8 +3182,6 @@
if (! relocate)
continue;
}
- else if (r_type == R_SH_DIR32)
- addend = rel->r_addend;
goto final_link_relocate;
case R_SH_GOT32:
@@ -3329,6 +3361,7 @@
}
}
+ relocation_done:
if (r != bfd_reloc_ok)
{
switch (r)
Index: gas/config/tc-sh.c
===================================================================
RCS file: /cvsroot/src/gnu/dist/toolchain/gas/config/tc-sh.c,v
retrieving revision 1.3
diff -u -r1.3 tc-sh.c
--- gas/config/tc-sh.c 2002/04/10 11:33:06 1.3
+++ gas/config/tc-sh.c 2003/02/04 14:36:23
@@ -2852,6 +2852,11 @@
&& fixP->fx_addsy != NULL
&& S_IS_WEAK (fixP->fx_addsy))
val -= S_GET_VALUE (fixP->fx_addsy);
+
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && fixP->fx_r_type == BFD_RELOC_32_PCREL
+ && fixP->fx_addsy != NULL)
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
#endif
#ifndef BFD_ASSEMBLER