* elf32-ppc.c (struct ppc_dyn_relocs): New.
[binutils-gdb.git] / bfd / elf32-cr16.c
index 354cbd91f764a1509a45484532ade491ac0c530b..656caffb330ee8bd5b5521151d29c6b2b5a26781 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for National Semiconductor's CR16 ELF
-   Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
    Written by M R Swami Reddy.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -585,7 +585,7 @@ _bfd_cr16_elf_create_got_section (bfd * abfd, struct bfd_link_info * info)
   int ptralign;
 
   /* This function may be called more than once.  */
-  if (bfd_get_section_by_name (abfd, ".got") != NULL)
+  if (bfd_get_linker_section (abfd, ".got") != NULL)
     return TRUE;
 
   switch (bed->s->arch_size)
@@ -606,14 +606,14 @@ _bfd_cr16_elf_create_got_section (bfd * abfd, struct bfd_link_info * info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
            | SEC_LINKER_CREATED);
 
-  s = bfd_make_section_with_flags (abfd, ".got", flags);
+  s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, ptralign))
     return FALSE;
 
   if (bed->want_got_plt)
     {
-      s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
+      s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
           || ! bfd_set_section_alignment (abfd, s, ptralign))
         return FALSE;
@@ -752,24 +752,22 @@ cr16_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
 
           if (sgot == NULL)
             {
-              sgot = bfd_get_section_by_name (dynobj, ".got");
+              sgot = bfd_get_linker_section (dynobj, ".got");
               BFD_ASSERT (sgot != NULL);
             }
 
           if (srelgot == NULL
               && (h != NULL || info->executable))
             {
-              srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+              srelgot = bfd_get_linker_section (dynobj, ".rela.got");
               if (srelgot == NULL)
                 {
-                  srelgot = bfd_make_section_with_flags (dynobj,
-                                                         ".rela.got",
-                                                         (SEC_ALLOC
-                                                          | SEC_LOAD
-                                                          | SEC_HAS_CONTENTS
-                                                          | SEC_IN_MEMORY
-                                                          | SEC_LINKER_CREATED
-                                                          | SEC_READONLY));
+                 flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                                   | SEC_READONLY);
+                 srelgot = bfd_make_section_anyway_with_flags (dynobj,
+                                                               ".rela.got",
+                                                               flags);
                   if (srelgot == NULL
                       || ! bfd_set_section_alignment (dynobj, srelgot, 2))
                     goto fail;
@@ -862,10 +860,8 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
   bfd_byte *hit_data = contents + offset;
   bfd_vma reloc_bits, check, Rvalue1;
   bfd *      dynobj;
-  bfd_vma *  local_got_offsets;
 
   dynobj = elf_hash_table (info)->dynobj;
-  local_got_offsets = elf_local_got_offsets (input_bfd);
 
   switch (r_type)
     {
@@ -916,7 +912,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
        /* We only care about the addend, where the difference between
           expressions is kept.  */
        Rvalue = 0;
-       
+
      default:
        break;
     }
@@ -1047,9 +1043,9 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
                         | ((Rvalue >> 16) & 0xf)), hit_data);
             bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
           }
-        else if (r_type == R_CR16_GOT_REGREL20) 
+        else if (r_type == R_CR16_GOT_REGREL20)
           {
-            asection * sgot = bfd_get_section_by_name (dynobj, ".got");
+            asection * sgot = bfd_get_linker_section (dynobj, ".got");
 
             if (h != NULL)
               {
@@ -1064,7 +1060,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
                        -Bsymbolic link and the symbol is defined
                        locally, or the symbol was forced to be local
                        because of a version file.  We must initialize
-                       this entry in the global offset table. 
+                       this entry in the global offset table.
                        When doing a dynamic link, we create a .rela.got
                        relocation entry to initialize the value.  This
                        is done in the finish_dynamic_symbol routine.  */
@@ -1084,7 +1080,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
 
              Rvalue += addend;
 
-             /* REVISIT: if ((long) Rvalue > 0xffffff || 
+             /* REVISIT: if ((long) Rvalue > 0xffffff ||
                                     (long) Rvalue < -0x800000).  */
              if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
                return bfd_reloc_overflow;
@@ -1098,7 +1094,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
         else if (r_type == R_CR16_GOTC_REGREL20)
           {
              asection * sgot;
-             sgot = bfd_get_section_by_name (dynobj, ".got");
+             sgot = bfd_get_linker_section (dynobj, ".got");
 
              if (h != NULL)
                {
@@ -1115,7 +1111,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
                     -Bsymbolic link and the symbol is defined
                      locally, or the symbol was forced to be local
                      because of a version file.  We must initialize
-                     this entry in the global offset table. 
+                     this entry in the global offset table.
                      When doing a dynamic link, we create a .rela.got
                      relocation entry to initialize the value.  This
                      is done in the finish_dynamic_symbol routine.  */
@@ -1146,7 +1142,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
                Rvalue += Rvalue1;
 
               /* Check for range.  */
-             /* REVISIT: if ((long) Rvalue > 0xffffff 
+             /* REVISIT: if ((long) Rvalue > 0xffffff
                              || (long) Rvalue < -0x800000).  */
              if ((long) Rvalue > 0xffffff || (long) Rvalue < 0)
                return bfd_reloc_overflow;
@@ -1228,7 +1224,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
               }
             else if (r_type == R_CR16_NUM32)
               {
-                 Rvalue1 = (bfd_get_32 (input_bfd, hit_data)); 
+                 Rvalue1 = (bfd_get_32 (input_bfd, hit_data));
 
                  /* Add or subtract the offset value */
                  if (Rvalue1 & 0x80000000)
@@ -1262,7 +1258,6 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
   unsigned int sec_shndx;
   bfd_byte *contents;
   Elf_Internal_Rela *irel, *irelend;
-  Elf_Internal_Rela *irelalign;
   bfd_vma toaddr;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
@@ -1275,9 +1270,6 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
 
   contents = elf_section_data (sec)->this_hdr.contents;
 
-  /* The deletion must stop at the next ALIGN reloc for an aligment
-     power larger than the number of bytes we are deleting.  */
-  irelalign = NULL;
   toaddr = sec->size;
 
   irel = elf_section_data (sec)->relocs;
@@ -1317,7 +1309,7 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
                   && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
                   && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
                  continue;
-        
+
               r_symndx = ELF32_R_SYM (irel->r_info);
               rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
 
@@ -1437,16 +1429,9 @@ elf32_cr16_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                                    unresolved_reloc, warned);
         }
 
-      if (sec != NULL && elf_discarded_section (sec))
-       {
-         /* For relocs against symbols from removed linkonce sections,
-            or sections discarded by a linker script, we just want the
-            section contents zeroed.  Avoid any special processing.  */
-         _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
-         rel->r_info = 0;
-         rel->r_addend = 0;
-         continue;
-       }
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
         continue;
@@ -1675,7 +1660,7 @@ elf32_cr16_link_hash_table_create (bfd *abfd)
   struct elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
-  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
+  ret = (struct elf_link_hash_table *) bfd_zmalloc (amt);
   if (ret == (struct elf_link_hash_table *) NULL)
     return NULL;
 
@@ -1691,18 +1676,6 @@ elf32_cr16_link_hash_table_create (bfd *abfd)
   return &ret->root;
 }
 
-/* Free an cr16 ELF linker hash table.  */
-
-static void
-elf32_cr16_link_hash_table_free (struct bfd_link_hash_table *hash)
-{
-  struct elf_link_hash_table *ret
-    = (struct elf_link_hash_table *) hash;
-
-  _bfd_generic_link_hash_table_free
-    ((struct bfd_link_hash_table *) ret);
-}
-
 static unsigned long
 elf_cr16_mach (flagword flags)
 {
@@ -1996,7 +1969,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
           bfd_vma value = symval;
           unsigned short is_add_mov = 0;
           bfd_vma value1 = 0;
-          
+
           /* Get the existing value from the mcode */
           value1 = ((bfd_get_32 (abfd, contents + irel->r_offset + 2) >> 16)
                    |(((bfd_get_32 (abfd, contents + irel->r_offset + 2) & 0xffff) << 16)));
@@ -2011,7 +1984,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
 
               /* Verify it's a 'arithmetic ADDD or MOVD instruction'.
                  For ADDD and MOVD only, convert to IMM32 -> IMM20.  */
-     
+
               if (((code & 0xfff0) == 0x0070) || ((code & 0xfff0) == 0x0020))
                  is_add_mov = 1;
 
@@ -2031,7 +2004,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
 
                   bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
 
-                  /* If existing value is nagavive adjust approriately 
+                  /* If existing value is nagavive adjust approriately
                      place the 16-20bits (ie 4 bit) in new opcode,
                      as the 0xffffxxxx, the higher 2 byte values removed. */
                   if (value1 & 0x80000000)
@@ -2055,7 +2028,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
             }
 
           /* See if the value will fit in 16 bits.  */
-          if ((!is_add_mov) 
+          if ((!is_add_mov)
               && ((long)(value + value1) < 0x7fff && (long)(value + value1) > 0))
             {
               unsigned short code;
@@ -2080,7 +2053,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
 
               bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
 
-              /* If existing value is nagavive adjust approriately 
+              /* If existing value is nagavive adjust approriately
                  place the 12-16bits (ie 4 bit) in new opcode,
                  as the 0xfffffxxx, the higher 2 byte values removed. */
               if (value1 & 0x80000000)
@@ -2107,7 +2080,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
 #if 0
       /* Try to turn a 16bit immediate address into a 4bit
          immediate address.  */
-      if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20) 
+      if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
           || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
         {
           bfd_vma value = symval;
@@ -2215,7 +2188,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
       else
        /* Cache the section contents for elf_link_input_bfd.  */
        elf_section_data (sec)->this_hdr.contents = contents;
-       
+
     }
 
   if (internal_relocs != NULL
@@ -2291,10 +2264,10 @@ _bfd_cr16_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
            | SEC_LINKER_CREATED);
 
-  s = bfd_make_section_with_flags (abfd,
-                                   (bed->default_use_rela_p
-                                    ? ".rela.plt" : ".rel.plt"),
-                                   flags | SEC_READONLY);
+  s = bfd_make_section_anyway_with_flags (abfd,
+                                         (bed->default_use_rela_p
+                                          ? ".rela.plt" : ".rel.plt"),
+                                         flags | SEC_READONLY);
   if (s == NULL
       || ! bfd_set_section_alignment (abfd, s, ptralign))
     return FALSE;
@@ -2302,32 +2275,6 @@ _bfd_cr16_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (! _bfd_cr16_elf_create_got_section (abfd, info))
     return FALSE;
 
-  {
-    const char * secname;
-    char *       relname;
-    flagword     secflags;
-    asection *   sec;
-
-    for (sec = abfd->sections; sec; sec = sec->next)
-      {
-        secflags = bfd_get_section_flags (abfd, sec);
-        if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
-            || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
-          continue;
-
-        secname = bfd_get_section_name (abfd, sec);
-        relname = (char *) bfd_malloc (strlen (secname) + 6);
-        strcpy (relname, ".rela");
-        strcat (relname, secname);
-
-        s = bfd_make_section_with_flags (abfd, relname,
-                                         flags | SEC_READONLY);
-        if (s == NULL
-            || ! bfd_set_section_alignment (abfd, s, ptralign))
-          return FALSE;
-      }
-  }
-
   if (bed->want_dynbss)
     {
       /* The .dynbss section is a place to put symbols which are defined
@@ -2336,8 +2283,8 @@ _bfd_cr16_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
          image and use a R_*_COPY reloc to tell the dynamic linker to
          initialize them at run time.  The linker script puts the .dynbss
          section into the .bss section of the final image.  */
-      s = bfd_make_section_with_flags (abfd, ".dynbss",
-                                       SEC_ALLOC | SEC_LINKER_CREATED);
+      s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+                                             SEC_ALLOC | SEC_LINKER_CREATED);
       if (s == NULL)
         return FALSE;
 
@@ -2354,10 +2301,10 @@ _bfd_cr16_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
          copy relocs.  */
       if (! info->executable)
         {
-          s = bfd_make_section_with_flags (abfd,
-                                           (bed->default_use_rela_p
-                                            ? ".rela.bss" : ".rel.bss"),
-                                           flags | SEC_READONLY);
+          s = bfd_make_section_anyway_with_flags (abfd,
+                                                 (bed->default_use_rela_p
+                                                  ? ".rela.bss" : ".rel.bss"),
+                                                 flags | SEC_READONLY);
           if (s == NULL
               || ! bfd_set_section_alignment (abfd, s, ptralign))
             return FALSE;
@@ -2419,13 +2366,13 @@ _bfd_cr16_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
       /* We also need to make an entry in the .got.plt section, which
          will be placed in the .got section by the linker script.  */
 
-      s = bfd_get_section_by_name (dynobj, ".got.plt");
+      s = bfd_get_linker_section (dynobj, ".got.plt");
       BFD_ASSERT (s != NULL);
       s->size += 4;
 
       /* We also need to make an entry in the .rela.plt section.  */
 
-      s = bfd_get_section_by_name (dynobj, ".rela.plt");
+      s = bfd_get_linker_section (dynobj, ".rela.plt");
       BFD_ASSERT (s != NULL);
       s->size += sizeof (Elf32_External_Rela);
 
@@ -2459,13 +2406,6 @@ _bfd_cr16_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
   if (!h->non_got_ref)
     return TRUE;
 
-  if (h->size == 0)
-    {
-      (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
-                             h->root.root.string);
-      return TRUE;
-    }
-
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -2476,18 +2416,18 @@ _bfd_cr16_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
 
-  s = bfd_get_section_by_name (dynobj, ".dynbss");
+  s = bfd_get_linker_section (dynobj, ".dynbss");
   BFD_ASSERT (s != NULL);
 
   /* We must generate a R_CR16_COPY reloc to tell the dynamic linker to
      copy the initial value out of the dynamic object and into the
      runtime process image.  We need to remember the offset into the
      .rela.bss section we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
     {
       asection * srel;
 
-      srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+      srel = bfd_get_linker_section (dynobj, ".rela.bss");
       BFD_ASSERT (srel != NULL);
       srel->size += sizeof (Elf32_External_Rela);
       h->needs_copy = 1;
@@ -2517,7 +2457,7 @@ _bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
       if (info->executable)
         {
 #if 0
-          s = bfd_get_section_by_name (dynobj, ".interp");
+          s = bfd_get_linker_section (dynobj, ".interp");
           BFD_ASSERT (s != NULL);
           s->size = sizeof ELF_DYNAMIC_INTERPRETER;
           s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -2531,7 +2471,7 @@ _bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
          not actually use these entries.  Reset the size of .rela.got,
          which will cause it to get stripped from the output file
          below.  */
-      s = bfd_get_section_by_name (dynobj, ".rela.got");
+      s = bfd_get_linker_section (dynobj, ".rela.got");
       if (s != NULL)
         s->size = 0;
     }
@@ -2686,8 +2626,8 @@ _bfd_cr16_elf_finish_dynamic_symbol (bfd * output_bfd,
 
       /* This symbol has an entry in the global offset table.  Set it up.  */
 
-      sgot = bfd_get_section_by_name (dynobj, ".got");
-      srel = bfd_get_section_by_name (dynobj, ".rela.got");
+      sgot = bfd_get_linker_section (dynobj, ".got");
+      srel = bfd_get_linker_section (dynobj, ".rela.got");
       BFD_ASSERT (sgot != NULL && srel != NULL);
 
       rel.r_offset = (sgot->output_section->vma
@@ -2731,8 +2671,7 @@ _bfd_cr16_elf_finish_dynamic_symbol (bfd * output_bfd,
                   && (h->root.type == bfd_link_hash_defined
                       || h->root.type == bfd_link_hash_defweak));
 
-      s = bfd_get_section_by_name (h->root.u.def.section->owner,
-                                   ".rela.bss");
+      s = bfd_get_linker_section (dynobj, ".rela.bss");
       BFD_ASSERT (s != NULL);
 
       rel.r_offset = (h->root.u.def.value
@@ -2747,7 +2686,7 @@ _bfd_cr16_elf_finish_dynamic_symbol (bfd * output_bfd,
     }
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+  if (h == elf_hash_table (info)->hdynamic
       || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
 
@@ -2766,9 +2705,9 @@ _bfd_cr16_elf_finish_dynamic_sections (bfd * output_bfd,
 
   dynobj = elf_hash_table (info)->dynobj;
 
-  sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+  sgot = bfd_get_linker_section (dynobj, ".got.plt");
   BFD_ASSERT (sgot != NULL);
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_linker_section (dynobj, ".dynamic");
 
   if (elf_hash_table (info)->dynamic_sections_created)
     {
@@ -2977,7 +2916,9 @@ error_return:
    properly.  */
 
 static enum elf_reloc_type_class
-_bfd_cr16_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+_bfd_cr16_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                               const asection *rel_sec ATTRIBUTE_UNUSED,
+                               const Elf_Internal_Rela *rela)
 {
   switch ((int) ELF32_R_TYPE (rela->r_info))
     {
@@ -3022,8 +2963,6 @@ _bfd_cr16_elf_reloc_type_class (const Elf_Internal_Rela *rela)
 
 #define bfd_elf32_bfd_link_hash_table_create \
                                   elf32_cr16_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free \
-                                  elf32_cr16_link_hash_table_free
 
 #define elf_backend_create_dynamic_sections \
                                   _bfd_cr16_elf_create_dynamic_sections