Add support to GDB for the Renesas rl78 architecture.
[external/binutils.git] / bfd / elf32-cr16c.c
index 8c579e5..ca2d7cb 100644 (file)
@@ -1,11 +1,12 @@
 /* BFD back-end for National Semiconductor's CR16C ELF
-   Copyright 2004 Free Software Foundation, Inc.
+   Copyright 2004, 2005, 2006, 2007, 2009, 2010
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "bfdlink.h"
 #include "elf/cr16c.h"
@@ -150,6 +152,20 @@ elf_cr16c_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return 0;
 }
 
+static reloc_howto_type *
+elf_cr16c_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                            const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0; i < sizeof (elf_howto_table) / sizeof (elf_howto_table[0]); i++)
+    if (elf_howto_table[i].name != NULL
+       && strcasecmp (elf_howto_table[i].name, r_name) == 0)
+      return &elf_howto_table[i];
+
+  return NULL;
+}
+
 static void
 elf_cr16c_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
                         arelent *cache_ptr ATTRIBUTE_UNUSED,
@@ -189,7 +205,6 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
   unsigned long format, addr_type, code_factor;
   unsigned short size;
   unsigned short r_type;
-  asymbol *symbol = NULL;
 
   unsigned long disp20_opcod;
   char neg = 0;
@@ -209,9 +224,6 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
   addr_type = r_type & R_ADDRTYPE;
   code_factor = ((addr_type == R_CODE_ADDR) ? 1 : 0);
 
-  if (sym_sec)
-    symbol = sym_sec->symbol;
-
   switch (format)
     {
     case R_NUMBER:
@@ -426,8 +438,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            return bfd_reloc_overflow;
          value &= 0xFF;
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_16:        /* Two bytes.  */
          if (value > (int) MAX_UWORD || value < MIN_WORD)
            return bfd_reloc_overflow;
@@ -435,13 +447,13 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          sword = value;
          bfd_put_16 (abfd, (bfd_vma) sword,
                      (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_32:        /* Four bytes.  */
          value &= 0xFFFFFFFF;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        default:
          return bfd_reloc_notsupported;
        }
@@ -459,8 +471,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          value <<= 4;
          value |= left_val;
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_08:    /* word1(0-3,8-11).  */
          if (value > 255 || value < -256 || value == 0x80)
            return bfd_reloc_overflow;
@@ -471,8 +483,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          sword |= left_val;
          bfd_put_16 (abfd, (bfd_vma) sword,
                      (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_16:    /* word2.  */
          if (value > 65535 || value < -65536)
            return bfd_reloc_overflow;
@@ -482,8 +494,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          sword = value;
          bfd_put_16 (abfd, (bfd_vma) sword,
                      (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_24_a:      /* word1(0-7),word2.  */
          if (value > 16777215 || value < -16777216)
            return bfd_reloc_overflow;
@@ -493,8 +505,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x00800000) >> 7) | ((value & 0x007F8000) >> 15);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_24:    /* word2(0-3,8-11),word3.  */
          if (value > 16777215 || value < -16777216)
            return bfd_reloc_overflow;
@@ -507,8 +519,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        default:
          return bfd_reloc_notsupported;
        }
@@ -523,8 +535,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          value &= 0xF;
          value |= left_val;
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_04_a:      /* word1(12-15) not scaled.  */
          if (value > 26 || value < 0)
            return bfd_reloc_overflow;
@@ -532,8 +544,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          value >>= 1;
          value |= left_val;
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_14:        /* word1(4-5),word2(0-3,8-15).  */
          if (value < 0 || value > 16383)
            return bfd_reloc_overflow;
@@ -543,8 +555,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x0000000F) << 16) | (value & 0x00000030);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_16:        /* word2.  */
          if (value > 65535 || value < 0)
            return bfd_reloc_overflow;
@@ -552,8 +564,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          sword = value;
          bfd_put_16 (abfd, (bfd_vma) sword,
                      (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_20:        /* word2(8-11),word3.  */
          /* if (value > 1048575 || value < 0) RELOC_ERROR(1); */
          value &= 0xFFFFF;
@@ -573,8 +585,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
              bfd_put_8 (abfd, (bfd_vma) value,
                         (unsigned char *) data + octets - 3);
            }
-         return bfd_reloc_ok;
          break;
+
        default:
          return bfd_reloc_notsupported;
        }
@@ -591,8 +603,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x000F0000) >> 16);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_24:        /* word2(0-3,8-11),word3.  */
          /* if (value > 16777215 || value < 0) RELOC_ERROR(1); */
          value &= 0xFFFFFF;
@@ -600,8 +612,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x000F0000) >> 8) | ((value & 0x00F00000) >> 20);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        default:
          return bfd_reloc_notsupported;
        }
@@ -617,8 +629,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          value <<= 4;
          value |= left_val;
          bfd_put_8 (abfd, (bfd_vma) value, (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_16:        /* word2.  */
          if (value > 32767 || value < -32768)
            return bfd_reloc_overflow;
@@ -626,8 +638,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
          sword = value;
          bfd_put_16 (abfd, (bfd_vma) sword,
                      (unsigned char *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_20:        /* word1(0-3),word2.  */
          if (value > 1048575 || value < 0)
            return bfd_reloc_overflow;
@@ -636,15 +648,15 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
            ((value & 0x000F0000) >> 16);
          value |= left_val;
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        case R_S_16C_32:        /* word2, word3.  */
          value &= 0xFFFFFFFF;
          value = ((value & 0x0000FFFF) << 16) |
            ((value & 0xFFFF0000) >> 16);
          bfd_put_32 (abfd, (bfd_vma) value, (bfd_byte *) data + octets);
-         return bfd_reloc_ok;
          break;
+
        default:
          return bfd_reloc_notsupported;
        }
@@ -652,6 +664,8 @@ cr16c_elf_final_link_relocate (reloc_howto_type *howto,
     default:
       return bfd_reloc_notsupported;
     }
+
+  return bfd_reloc_ok;
 }
 
 /* Relocate a CR16C ELF section.  */
@@ -690,26 +704,6 @@ elf32_cr16c_relocate_section (bfd *output_bfd,
       r_type = ELF32_R_TYPE (rel->r_info);
       howto = elf_howto_table + r_type;
 
-      if (info->relocatable)
-       {
-         /* This is a relocatable link.  We don't have to change
-            anything, unless the reloc is against a section symbol,
-            in which case we have to adjust according to where the
-            section symbol winds up in the output section.  */
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             sym = local_syms + r_symndx;
-             if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-               {
-                 sec = local_sections[r_symndx];
-                 rel->r_addend += sec->output_offset + sym->st_value;
-               }
-           }
-
-         continue;
-       }
-
-      /* This is a final link.  */
       h = NULL;
       sym = NULL;
       sec = NULL;
@@ -729,6 +723,21 @@ elf32_cr16c_relocate_section (bfd *output_bfd,
                                   unresolved_reloc, warned);
        }
 
+      if (sec != NULL && elf_discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, relend, howto, contents);
+
+      if (info->relocatable)
+       {
+         /* This is a relocatable link.  We don't have to change
+            anything, unless the reloc is against a section symbol,
+            in which case we have to adjust according to where the
+            section symbol winds up in the output section.  */
+         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           rel->r_addend += sec->output_offset;
+         continue;
+       }
+
       r = cr16c_elf_final_link_relocate (howto, input_bfd, output_bfd,
                                         input_section,
                                         contents, rel->r_offset,
@@ -796,53 +805,6 @@ elf32_cr16c_relocate_section (bfd *output_bfd,
   return TRUE;
 }
 
-static asection *
-elf32_cr16c_gc_mark_hook (asection *sec,
-                         struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                         Elf_Internal_Rela *rel,
-                         struct elf_link_hash_entry *h,
-                         Elf_Internal_Sym *sym)
-{
-  if (h != NULL)
-    {
-      switch (ELF32_R_TYPE (rel->r_info))
-       {
-
-       default:
-         switch (h->root.type)
-           {
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-
-           default:
-             break;
-           }
-       }
-    }
-  else
-    {
-      return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-    }
-
-  return NULL;
-}
-
-/* Update the got entry reference counts for the section being removed.  */
-
-static bfd_boolean
-elf32_cr16c_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
-                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
-                          asection *sec ATTRIBUTE_UNUSED,
-                          const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
-{
-  /* We don't support garbage collection of GOT and PLT relocs yet.  */
-  return TRUE;
-}
-
 /* CR16C ELF uses three common sections:
    One is for default common symbols (placed in usual common section).
    Second is for near common symbols (placed in "ncommon" section).
@@ -955,7 +917,7 @@ elf32_cr16c_add_symbol_hook (bfd *abfd,
   return TRUE;
 }
 
-static bfd_boolean
+static int
 elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED,
                                     const char *name ATTRIBUTE_UNUSED,
                                     Elf_Internal_Sym *sym,
@@ -974,7 +936,7 @@ elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED
        sym->st_shndx = SHN_CR16C_NCOMMON;
     }
 
-  return TRUE;
+  return 1;
 }
 
 /* Definitions for setting CR16C target vector.  */
@@ -986,11 +948,10 @@ elf32_cr16c_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED
 #define elf_symbol_leading_char                '_'
 
 #define bfd_elf32_bfd_reloc_type_lookup                elf_cr16c_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup        elf_cr16c_reloc_name_lookup
 #define elf_info_to_howto                      elf_cr16c_info_to_howto
 #define elf_info_to_howto_rel                  elf_cr16c_info_to_howto_rel
 #define elf_backend_relocate_section           elf32_cr16c_relocate_section
-#define elf_backend_gc_mark_hook               elf32_cr16c_gc_mark_hook
-#define elf_backend_gc_sweep_hook              elf32_cr16c_gc_sweep_hook
 #define elf_backend_symbol_processing          elf32_cr16c_symbol_processing
 #define elf_backend_section_from_bfd_section   elf32_cr16c_section_from_bfd_section
 #define elf_backend_add_symbol_hook            elf32_cr16c_add_symbol_hook