* elf32-m32r.c (m32r_elf_generic_reloc): new function. All
authorDoug Evans <dje@google.com>
Thu, 30 Mar 2000 22:16:39 +0000 (22:16 +0000)
committerDoug Evans <dje@google.com>
Thu, 30 Mar 2000 22:16:39 +0000 (22:16 +0000)
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.

bfd/ChangeLog
bfd/elf32-m32r.c

index 13018d65b273e18b16b3995145dd7496a254fe91..a364c5c6109b81ce8c2ac16e7dd0e2f28c325858 100644 (file)
@@ -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,
index 84666b6914992cd6018a78ffd6d56e66f281ac28..efb6555267165fbf4ba17fa17ee551249f31a0ff 100644 (file)
@@ -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;