diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 5 | ||||
-rw-r--r-- | bfd/elf32-i860.c | 44 |
2 files changed, 47 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 32294da..2289215 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2003-08-31 Christian Groessler <chris@groessler.org> + + * elf32-i860.c (i860_howto_pc26_reloc): Finish relocation here + instead of returning bfd_reloc_continue. + 2003-08-31 Andreas Jaeger <aj@suse.de> * merge.c: Update to ISO C90. diff --git a/bfd/elf32-i860.c b/bfd/elf32-i860.c index b523fb3..78e5a34 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. */ |