diff options
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/elf32-m32r.c | 80 |
2 files changed, 79 insertions, 11 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 13018d6..a364c5c 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +Wed Mar 30 15:28:00 2000 Donald Lindsay <dlindsay@cygnus.com> + + * elf32-m32r.c (m32r_elf_generic_reloc): new function. All + HOWTO references to bfd_elf_generic_reloc, that have + partial_inplace == true, now use the new function. The function + is based on the recent rewrite of m32r_elf_lo16_reloc(), and + extends its fixes to the R_M32R_{16,24,32} relocs. + The new logic in m32r_elf_lo16_reloc() has been removed, and + it instead calls the new routine to obtain that functionality. + 2000-03-27 Alan Modra <alan@linuxcare.com> * elf32-avr.c (elf32_avr_gc_mark_hook, elf32_avr_gc_sweep_hook, diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index 84666b6..efb6555 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -1,5 +1,5 @@ /* M32R-specific support for 32-bit ELF. - Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -35,6 +35,8 @@ static void m32r_elf_relocate_hi16 bfd_byte *, bfd_vma)); bfd_reloc_status_type m32r_elf_lo16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); +bfd_reloc_status_type m32r_elf_generic_reloc + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type m32r_elf_sda16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup @@ -105,7 +107,7 @@ static reloc_howto_type m32r_elf_howto_table[] = false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + m32r_elf_generic_reloc,/* special_function */ "R_M32R_16", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ @@ -120,7 +122,7 @@ static reloc_howto_type m32r_elf_howto_table[] = false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + m32r_elf_generic_reloc,/* special_function */ "R_M32R_32", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ @@ -135,7 +137,7 @@ static reloc_howto_type m32r_elf_howto_table[] = false, /* pc_relative */ 0, /* bitpos */ complain_overflow_unsigned, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + m32r_elf_generic_reloc,/* special_function */ "R_M32R_24", /* name */ true, /* partial_inplace */ 0xffffff, /* src_mask */ @@ -508,10 +510,6 @@ m32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data, bfd *output_bfd; char **error_message; { - bfd_reloc_status_type ret; - bfd_vma relocation; - unsigned long insn; - /* This part is from bfd_elf_generic_reloc. If we're relocating, and this an external symbol, we don't want to change anything. */ @@ -564,6 +562,44 @@ m32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data, but we have partial_inplace == TRUE. bfd_elf_generic_reloc will pass the handling back to bfd_install_relocation which will install a section relative addend which is wrong. */ + return m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} + +/* Do generic partial_inplace relocation. + This is a local replacement for bfd_elf_generic_reloc. */ + +bfd_reloc_status_type +m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message) + bfd *input_bfd; + arelent *reloc_entry; + asymbol *symbol; + PTR data; + asection *input_section; + bfd *output_bfd; + char **error_message; +{ + bfd_reloc_status_type ret; + bfd_vma relocation; + bfd_byte *inplace_address; + + /* This part is from bfd_elf_generic_reloc. + If we're relocating, and this an external symbol, we don't want + to change anything. */ + if (output_bfd != (bfd *) NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + /* Now do the the reloc in the usual way. + ??? It would be nice to call bfd_elf_generic_reloc here, + but we have partial_inplace == TRUE. bfd_elf_generic_reloc will + pass the handling back to bfd_install_relocation which will install + a section relative addend which is wrong. */ /* Sanity check the address (offset in section). */ if (reloc_entry->address > input_section->_cooked_size) @@ -588,10 +624,32 @@ m32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data, } relocation += reloc_entry->addend; + inplace_address = data + reloc_entry->address; + +#define DOIT(x) \ + x = ( (x & ~reloc_entry->howto->dst_mask) | \ + (((x & reloc_entry->howto->src_mask) + relocation) & \ + reloc_entry->howto->dst_mask)) - insn = bfd_get_32 (input_bfd, data + reloc_entry->address); - insn = (insn & 0xffff0000) | (relocation & 0xffff); - bfd_put_32 (input_bfd, insn, data + reloc_entry->address); + switch (reloc_entry->howto->size) + { + case 1: + { + short x = bfd_get_16 (input_bfd, inplace_address); + DOIT (x); + bfd_put_16 (input_bfd, x, inplace_address); + } + break; + case 2: + { + unsigned long x = bfd_get_32 (input_bfd, inplace_address); + DOIT (x); + bfd_put_32 (input_bfd, x, inplace_address); + } + break; + default: + BFD_ASSERT (0); + } if (output_bfd != (bfd *) NULL) reloc_entry->address += input_section->output_offset; |