Fix handling of I32 and I20 relocs.
authorNick Clifton <nickc@redhat.com>
Wed, 25 Nov 1998 00:54:31 +0000 (00:54 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 25 Nov 1998 00:54:31 +0000 (00:54 +0000)
bfd/ChangeLog
bfd/elf32-fr30.c

index d2d21a979040e3d99c8ca7602c5fa28ec3f15184..dfd18359e6f0d02225ff1c2cabf7c022f41a4fcd 100644 (file)
@@ -1,3 +1,24 @@
+Tue Nov 24 10:25:27 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * elf32-fr30.c (fr30_elf_relocate_section): Call
+       fr30_final_link_relocate.
+       (fr30_final_link_relocate): New function: Handle I20 and I32
+       relocs.
+       (fr30_elf_i32_reloc): New function: Handle I32 relocs.
+
+       * elf32-v850.c (v850_elf_relocate_section): Reset hi16s reloc
+       chain to empty.
+       
+       The following changes are based on a patch submitted by Gianluca
+       Moro <glctr@abc.it>:
+       
+       (v850_elf_perform_relocation): Only update a hi16s reloc if it has
+       not already been updated.
+       (find_remembered_hi16s_reloc): New parameter 'already_found'
+       returns state of remembered hi16s reloc.
+       (remember_hi16s_reloc): Set 'found' field to false.
+       (hi16s_location): Add 'found' field.
+
 1998-11-23  DJ Delorie  <dj@cygnus.com>
 
        * coff-i386.c (bfd_pe_dll_not_recognized_hack): the linker wants
index 387789c77a22fe278896fabfc71e30f2f2434ab6..b50edfeb14db2db4e10b56d55b516a4665f848d1 100644 (file)
@@ -26,12 +26,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 /* Forward declarations.  */
 static bfd_reloc_status_type fr30_elf_i20_reloc
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type fr30_elf_i32_reloc
+  PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
 static reloc_howto_type * fr30_reloc_type_lookup
   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
 static void fr30_info_to_howto_rela 
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
 static boolean fr30_elf_relocate_section 
   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static bfd_reloc_status_type fr30_final_link_relocate
+  PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));
 
 static reloc_howto_type fr30_elf_howto_table [] =
 {
@@ -88,7 +92,7 @@ static reloc_howto_type fr30_elf_howto_table [] =
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        fr30_elf_i32_reloc,    /* special_function */
         "R_FR30_32",           /* name */
         true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
@@ -214,7 +218,7 @@ fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
 
   if (output_bfd != NULL)
     /* FIXME: See bfd_perform_relocation.  Is this right?  */
-    return bfd_reloc_continue;
+    return bfd_reloc_ok;
 
   relocation =
     symbol->value
@@ -232,6 +236,47 @@ fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
   return bfd_reloc_ok;
 }
 
+\f
+/* Utility to actually perform a R_FR30_32 reloc.  */
+
+static bfd_reloc_status_type
+fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
+                   input_section, output_bfd, error_message)
+     bfd *      abfd;
+     arelent *  reloc_entry;
+     asymbol *  symbol;
+     PTR        data;
+     asection * input_section;
+     bfd *      output_bfd;
+     char **    error_message;
+{
+  bfd_vma       relocation;
+
+  /* This part is from bfd_elf_generic_reloc.  */
+  if (output_bfd != (bfd *) NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (! reloc_entry->howto->partial_inplace
+         || reloc_entry->addend == 0))
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (output_bfd != NULL)
+    /* FIXME: See bfd_perform_relocation.  Is this right?  */
+    return bfd_reloc_ok;
+
+  relocation =
+    symbol->value
+    + symbol->section->output_section->vma
+    + symbol->section->output_offset
+    + reloc_entry->addend;
+
+  bfd_put_32 (abfd, relocation, data + reloc_entry->address + 2);
+
+  return bfd_reloc_ok;
+}
+
 \f
 /* Map BFD reloc types to FR30 ELF reloc types.  */
 
@@ -284,6 +329,47 @@ fr30_info_to_howto_rela (abfd, cache_ptr, dst)
   BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
   cache_ptr->howto = & fr30_elf_howto_table [r_type];
 }
+\f
+/* Perform a single relocation.  By default we use the standard BFD
+   routines, but a few relocs, we have to do them ourselves.  */
+
+static bfd_reloc_status_type
+fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation)
+     reloc_howto_type *  howto;
+     bfd *               input_bfd;
+     asection *          input_section;
+     bfd_byte *          contents;
+     Elf_Internal_Rela * rel;
+     bfd_vma             relocation;
+{
+  bfd_reloc_status_type r = bfd_reloc_ok;
+  bfd_vma               x;
+  
+  switch (howto->type)
+    {
+    case R_FR30_20:
+      contents += rel->r_offset;
+      relocation += rel->r_addend;
+      x = bfd_get_32 (input_bfd, contents);
+      x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
+      bfd_put_32 (input_bfd, relocation, contents);
+      break;
+      
+    case R_FR30_32:
+      contents += rel->r_offset + 2;
+      relocation += rel->r_addend;
+      bfd_put_32 (input_bfd, relocation, contents);
+      break;
+      
+    default:
+      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                   contents, rel->r_offset,
+                                   relocation, rel->r_addend);
+    }
+
+  return r;
+}
+
 \f
 /* Relocate an FR30 ELF section.
    There is some attempt to make this function usable for many architectures,
@@ -338,7 +424,7 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   relend     = relocs + input_section->reloc_count;
-  
+
   for (rel = relocs; rel < relend; rel ++)
     {
       reloc_howto_type *           howto;
@@ -348,7 +434,7 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
       struct elf_link_hash_entry * h;
       bfd_vma                      relocation;
       bfd_reloc_status_type        r;
-      const char *                 name;
+      const char *                 name = NULL;
 
       r_symndx = ELF32_R_SYM (rel->r_info);
 
@@ -440,66 +526,50 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              relocation = 0;
            }
        }
-
-      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                   contents, rel->r_offset,
-                                   relocation, rel->r_addend);
+      
+      r = fr30_final_link_relocate (howto, input_bfd, input_section,
+                                    contents, rel, relocation);
 
       if (r != bfd_reloc_ok)
        {
-         const char * msg = (const char *)0;
+         const char * msg = (const char *) NULL;
 
          switch (r)
            {
            case bfd_reloc_overflow:
-             if (! ((*info->callbacks->reloc_overflow)
-                    (info, name, howto->name, (bfd_vma) 0,
-                     input_bfd, input_section, rel->r_offset)))
-               return false;
+             r = info->callbacks->reloc_overflow
+               (info, name, howto->name, (bfd_vma) 0,
+                input_bfd, input_section, rel->r_offset);
              break;
-
+             
            case bfd_reloc_undefined:
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, name, input_bfd, input_section,
-                     rel->r_offset)))
-               return false;
+             r = info->callbacks->undefined_symbol
+               (info, name, input_bfd, input_section, rel->r_offset);
              break;
-
+             
            case bfd_reloc_outofrange:
              msg = _("internal error: out of range error");
-             goto common_error;
+             break;
 
            case bfd_reloc_notsupported:
              msg = _("internal error: unsupported relocation error");
-             goto common_error;
+             break;
 
            case bfd_reloc_dangerous:
              msg = _("internal error: dangerous relocation");
-             goto common_error;
-
-           case bfd_reloc_other:
-             msg = _("could not locate special linker symbol __gp");
-             goto common_error;
-
-           case bfd_reloc_continue:
-             msg = _("could not locate special linker symbol __ep");
-             goto common_error;
+             break;
 
-           case (bfd_reloc_dangerous + 1):
-             msg = _("could not locate special linker symbol __ctbp");
-             goto common_error;
-             
            default:
              msg = _("internal error: unknown error");
-             /* fall through */
-
-           common_error:
-             if (!((*info->callbacks->warning)
-                   (info, msg, name, input_bfd, input_section,
-                    rel->r_offset)))
-               return false;
              break;
            }
+
+         if (msg)
+           r = info->callbacks->warning
+             (info, msg, name, input_bfd, input_section, rel->r_offset);
+
+         if (! r)
+           return false;
        }
     }