aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elf32-m32r.c80
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;