+2001-09-30 kaz Kojima <kkojima@rr.iij4u.or.jp>
+ Hans-Peter Nilsson <hp@bitrange.com>
+
+ * elf32-sh.c (sh_elf_howto_table, R_SH_REL32): Make
+ partial_inplace, matching assembler output. Set src_mask to
+ all ones.
+ (sh_elf_relocate_section): Delete misplaced comment.
+ For relocatable linking against section symbol, call
+ _bfd_relocate_contents for partial_inplace relocs and adjust
+ rel->r_addend for others.
+ <case R_SH_DIR32, R_SH_REL32>: Fetch partial_inplace addend with
+ bfd_get_32, not at rel->r_addend.
+
2001-09-30 Alan Modra <amodra@bigpond.net.au>
* elf.c (_bfd_elf_link_hash_copy_indirect): Set ind refcounts to
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 */
howto = sh_elf_howto_table + r_type;
- /* This is a final link. */
+ /* For relocs that aren't partial_inplace, we get the addend from
+ the relocation. */
+ if (! howto->partial_inplace)
+ addend = rel->r_addend;
+
h = NULL;
sym = NULL;
sec = NULL;
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;
}
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
{
{
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);
}
}
if (! relocate)
continue;
}
- else if (r_type == R_SH_DIR32)
- addend = rel->r_addend;
goto final_link_relocate;
case R_SH_GOT32:
}
}
+ relocation_done:
if (r != bfd_reloc_ok)
{
switch (r)