summaryrefslogtreecommitdiff
path: root/bfd/elf32-i860.c
diff options
context:
space:
mode:
authorChristian Groessler <chris@groessler.org>2003-08-31 18:22:06 +0000
committerChristian Groessler <chris@groessler.org>2003-08-31 18:22:06 +0000
commit1c0881ddd90f76eb7ececedfdcaa96f4c40e14d6 (patch)
tree297ab89dfb3772ee74ccc3e33f5726c365aef23d /bfd/elf32-i860.c
parent5bca7895b748abc3e01c88221778bda7e5ad3185 (diff)
* elf32-i860.c (i860_howto_pc26_reloc): Finish relocation here
instead of returning bfd_reloc_continue.
Diffstat (limited to 'bfd/elf32-i860.c')
-rw-r--r--bfd/elf32-i860.c44
1 files changed, 42 insertions, 2 deletions
diff --git a/bfd/elf32-i860.c b/bfd/elf32-i860.c
index b523fb3f28..78e5a3446b 100644
--- a/bfd/elf32-i860.c
+++ b/bfd/elf32-i860.c
@@ -37,6 +37,10 @@ i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
{
+ bfd_vma insn;
+ bfd_vma relocation;
+ bfd_byte *addr;
+
if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
@@ -46,8 +50,44 @@ i860_howto_pc26_reloc (bfd *abfd ATTRIBUTE_UNUSED,
return bfd_reloc_ok;
}
- reloc_entry->addend -= 4;
- return bfd_reloc_continue;
+ /* Used elf32-mips.c as an example. */
+ if (bfd_is_und_section (symbol->section)
+ && output_bfd == (bfd *) NULL)
+ return bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Adjust for PC-relative relocation. */
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + reloc_entry->address
+ + 4);
+
+ /* Check for target out of range. */
+ if ((bfd_signed_vma)relocation > (0x3ffffff << 2)
+ || (bfd_signed_vma)relocation < (-0x4000000 << 2))
+ return bfd_reloc_outofrange;
+
+ addr = (bfd_byte *) data + reloc_entry->address;
+ insn = bfd_get_32 (abfd, addr);
+
+ relocation >>= reloc_entry->howto->rightshift;
+ insn = (insn & ~reloc_entry->howto->dst_mask)
+ | (relocation & reloc_entry->howto->dst_mask);
+
+ bfd_put_32 (abfd, (bfd_vma) insn, addr);
+
+ return bfd_reloc_ok;
}
/* special_function for R_860_PC16 relocation. */