* elf32-iq2000.c (iq2000_elf_relocate_section): Adjust addend of

relocation pointing to local symbol in merged section.
* elf32-iq2000.c (iq2000_elf_relocate_offset16): New.
(iq2000_elf_relocate_section): Call it.
This commit is contained in:
DJ Delorie 2008-02-12 19:11:55 +00:00
parent e8efc4d9fd
commit f15557e4ab
2 changed files with 55 additions and 2 deletions

View File

@ -1,3 +1,11 @@
2008-02-12 DJ Delorie <dj@redhat.com>
* elf32-iq2000.c (iq2000_elf_relocate_section): Adjust addend of
relocation pointing to local symbol in merged section.
* elf32-iq2000.c (iq2000_elf_relocate_offset16): New.
(iq2000_elf_relocate_section): Call it.
2008-02-12 Nick Clifton <nickc@redhat.com>
PR ld/5692

View File

@ -306,6 +306,34 @@ iq2000_elf_relocate_hi16 (bfd *input_bfd,
return bfd_reloc_ok;
}
static bfd_reloc_status_type
iq2000_elf_relocate_offset16 (bfd *input_bfd,
Elf_Internal_Rela *rel,
bfd_byte *contents,
bfd_vma value,
bfd_vma location)
{
bfd_vma insn;
bfd_vma jtarget;
insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
value += rel->r_addend;
if (value & 3)
return bfd_reloc_dangerous;
jtarget = (value & 0x3fffc) | (location & 0xf0000000L);
if (jtarget != value)
return bfd_reloc_overflow;
insn = (insn & ~0xFFFF) | ((value >> 2) & 0xFFFF);
bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
return bfd_reloc_ok;
}
/* Map BFD reloc types to IQ2000 ELF reloc types. */
static reloc_howto_type *
@ -572,15 +600,25 @@ iq2000_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED,
if (r_symndx < symtab_hdr->sh_info)
{
asection *osec;
sym = local_syms + r_symndx;
sec = local_sections [r_symndx];
osec = sec = local_sections [r_symndx];
if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION)
/* This relocation is relative to a section symbol that is
going to be merged. Change it so that it is relative
to the merged section symbol. */
rel->r_addend = _bfd_elf_rel_local_sym (output_bfd, sym, &sec,
rel->r_addend);
relocation = (sec->output_section->vma
+ sec->output_offset
+ sym->st_value);
name = bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name);
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
name = (name == NULL) ? bfd_section_name (input_bfd, osec) : name;
}
else
{
@ -615,6 +653,13 @@ iq2000_elf_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED,
r = iq2000_elf_relocate_hi16 (input_bfd, rel, contents, relocation);
break;
case R_IQ2000_OFFSET_16:
r = iq2000_elf_relocate_offset16 (input_bfd, rel, contents, relocation,
input_section->output_section->vma
+ input_section->output_offset
+ rel->r_offset);
break;
case R_IQ2000_PC16:
rel->r_addend -= 4;
/* Fall through. */