bfd and gas patch for sh3 REL32 (Re: Self build error)
Izumi Tsutsui <[email protected]>
| Newsgroups | gmane.os.netbsd.ports.sh3,gmane.os.netbsd.ports.dreamcast |
|---|---|
| Message-ID | <[email protected]> |
In article <[email protected]> on port-dreamcast I wrote: > In article <[email protected]> > I wrote: > > > In article <[email protected]> > > [email protected] 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 [email protected] 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