diff options
author | DJ Delorie <dj@redhat.com> | 2008-02-12 19:11:55 +0000 |
---|---|---|
committer | DJ Delorie <dj@redhat.com> | 2008-02-12 19:11:55 +0000 |
commit | f15557e4abfa55bdab0a034aaf78e7de8c3c7614 (patch) | |
tree | 091d353cf3f7868d4726640f3503d5ae9e458b62 /bfd/elf32-iq2000.c | |
parent | e8efc4d9fd94e07a7922ef7258e66f7a11dee1a1 (diff) | |
download | gdb-f15557e4abfa55bdab0a034aaf78e7de8c3c7614.zip gdb-f15557e4abfa55bdab0a034aaf78e7de8c3c7614.tar.gz gdb-f15557e4abfa55bdab0a034aaf78e7de8c3c7614.tar.bz2 |
* 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.
Diffstat (limited to 'bfd/elf32-iq2000.c')
-rw-r--r-- | bfd/elf32-iq2000.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/bfd/elf32-iq2000.c b/bfd/elf32-iq2000.c index 2a5ad78..73ab8e9 100644 --- a/bfd/elf32-iq2000.c +++ b/bfd/elf32-iq2000.c @@ -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. */ |