Fix typo in orevious delta
[deliverable/binutils-gdb.git] / bfd / elf32-fr30.c
index 387789c77a22fe278896fabfc71e30f2f2434ab6..820e6eaf4396b1b23fb6ccf2f6f8265aef7ae73b 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 [] =
 {
@@ -95,6 +99,21 @@ static reloc_howto_type fr30_elf_howto_table [] =
         0xffffffff,            /* dst_mask */
         false),                /* pcrel_offset */
 
+  /* A 32 bit into 48 bits absolute relocation.  */
+  HOWTO (R_FR30_48,            /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        fr30_elf_i32_reloc,    /* special_function */
+        "R_FR30_32",           /* name */
+        true,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
+        0xffffffff,            /* dst_mask */
+        false),                /* pcrel_offset */
+
   /* A 6 bit absolute relocation.  */
   HOWTO (R_FR30_6_IN_4,                /* type */
         2,                     /* rightshift */
@@ -163,12 +182,12 @@ static reloc_howto_type fr30_elf_howto_table [] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "R_FR30_9_PCREL",      /* name */
         false,                 /* partial_inplace */
         0x00ff,                /* src_mask */
         0x00ff,                /* dst_mask */
-        true),                 /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* A PC relative 12 bit relocation, right shifted by 1.  */
   HOWTO (R_FR30_12_PCREL,      /* type */
@@ -178,12 +197,12 @@ static reloc_howto_type fr30_elf_howto_table [] =
         true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bfd_elf_generic_reloc, /* special_function */
         "R_FR30_12_PCREL",     /* name */
         false,                 /* partial_inplace */
         0x07ff,                /* src_mask */
         0x07ff,                /* dst_mask */
-        true),                 /* pcrel_offset */
+        false),                /* pcrel_offset */
 };
 \f
 /* Utility to actually perform an R_FR30_20 reloc.  */
@@ -214,7 +233,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 +251,46 @@ fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
   return bfd_reloc_ok;
 }
 
+\f
+/* Utility to actually perform a R_FR30_48 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.  */
 
@@ -247,6 +306,7 @@ static const struct fr30_reloc_map fr30_reloc_map [] =
   { BFD_RELOC_8,              R_FR30_8 },
   { BFD_RELOC_FR30_20,        R_FR30_20 },
   { BFD_RELOC_32,             R_FR30_32 },
+  { BFD_RELOC_FR30_48,        R_FR30_48 },
   { BFD_RELOC_FR30_6_IN_4,    R_FR30_6_IN_4 },
   { BFD_RELOC_FR30_8_IN_8,    R_FR30_8_IN_8 },
   { BFD_RELOC_FR30_9_IN_8,    R_FR30_9_IN_8 },
@@ -284,6 +344,84 @@ 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;
+
+      if (relocation > ((1 << 20) - 1))
+       return bfd_reloc_overflow;
+      
+      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_48:
+      contents   += rel->r_offset + 2;
+      relocation += rel->r_addend;
+      bfd_put_32 (input_bfd, relocation, contents);
+      break;
+
+    case R_FR30_9_PCREL:
+      contents   += rel->r_offset + 1;
+      relocation += rel->r_addend;
+      relocation -= (input_section->output_section->vma +
+                    input_section->output_offset);
+      
+      if (relocation & 1)
+       return bfd_reloc_outofrange;
+      if (relocation > ((1 << 8) - 1) || (relocation < - (1 << 8)))
+       return bfd_reloc_overflow;
+      
+      bfd_put_8 (input_bfd, relocation >> 1, contents);
+      break;
+
+    case R_FR30_12_PCREL:
+      contents   += rel->r_offset;
+      relocation += rel->r_addend;
+      relocation -= (input_section->output_section->vma +
+                    input_section->output_offset);
+      
+      if (relocation & 1)
+       return bfd_reloc_outofrange;
+      if (relocation > ((1 << 11) - 1) || (relocation < - (1 << 11)))
+       return bfd_reloc_overflow;
+      
+      x = bfd_get_16 (input_bfd, contents);
+      x = (x & 0xf800) | ((relocation >> 1) & 0x7ff);
+      bfd_put_16 (input_bfd, x, contents);
+      break;
+
+    default:
+fprintf (stderr, " type: %d offset: %x, before: %x\n",
+        howto->type, rel->r_offset, bfd_get_32 (input_bfd, contents + rel->r_offset));
+      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,6 +476,8 @@ 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;
+
+fprintf (stderr, "Relocate section: %s\n", bfd_section_name (input_bfd, input_section));
   
   for (rel = relocs; rel < relend; rel ++)
     {
@@ -348,7 +488,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);
 
@@ -389,7 +529,7 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
          name = bfd_elf_string_from_elf_section
            (input_bfd, symtab_hdr->sh_link, sym->st_name);
          name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
-#if 0
+#if 1
          fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
                   sec->name, name, sym->st_name,
                   sec->output_section->vma, sec->output_offset,
@@ -413,7 +553,7 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
              relocation = (h->root.u.def.value
                            + sec->output_section->vma
                            + sec->output_offset);
-#if 0
+#if 1
              fprintf (stderr,
                       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
                       sec->name, name, h->root.u.def.value,
@@ -422,7 +562,7 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            {
-#if 0
+#if 1
              fprintf (stderr, "undefined: sec: %s, name: %s\n",
                       sec->name, name);
 #endif
@@ -434,72 +574,56 @@ fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                     (info, h->root.root.string, input_bfd,
                      input_section, rel->r_offset)))
                return false;
-#if 0
+#if 1
              fprintf (stderr, "unknown: name: %s\n", name);
 #endif
              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;
        }
     }
 
This page took 0.027466 seconds and 4 git commands to generate.