Automatic date update in version.in
[platform/upstream/binutils.git] / bfd / elf32-xstormy16.c
index c09e9de..f918a1e 100644 (file)
@@ -1,61 +1,72 @@
-/* XSTORMY16-specific support for 32-bit ELF.
-   Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Xstormy16-specific support for 32-bit ELF.
+   Copyright (C) 2000-2014 Free Software Foundation, Inc.
 
-This file is part of BFD, the Binary File Descriptor library.
+   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
-(at your option) any later version.
+   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 3 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-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.  */
+   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., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf/xstormy16.h"
 #include "libiberty.h"
 
-/* Forward declarations.  */
-static reloc_howto_type * xstormy16_reloc_type_lookup
-  PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
-static void xstormy16_info_to_howto_rela
-  PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
-static bfd_reloc_status_type xstormy16_elf_24_reloc
-  PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol,
-          PTR data, asection *input_section, bfd *output_bfd,
-          char **error_message));
-static bfd_boolean xstormy16_elf_check_relocs
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-static bfd_boolean xstormy16_relax_plt_check
-  PARAMS ((struct elf_link_hash_entry *, PTR));
-static bfd_boolean xstormy16_relax_plt_realloc
-  PARAMS ((struct elf_link_hash_entry *, PTR));
-static bfd_boolean xstormy16_elf_relax_section
-  PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
-          bfd_boolean *again));
-static bfd_boolean xstormy16_elf_always_size_sections
-  PARAMS ((bfd *, struct bfd_link_info *));
-static bfd_boolean xstormy16_elf_relocate_section
-  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
-          Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
-static bfd_boolean xstormy16_elf_finish_dynamic_sections
-  PARAMS((bfd *, struct bfd_link_info *));
-static bfd_boolean xstormy16_elf_gc_sweep_hook
-  PARAMS ((bfd *, struct bfd_link_info *, asection *,
-          const Elf_Internal_Rela *));
-static asection * xstormy16_elf_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
+/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement.  */
+
+static bfd_reloc_status_type
+xstormy16_elf_24_reloc (bfd *abfd,
+                       arelent *reloc_entry,
+                       asymbol *symbol,
+                       void * data,
+                       asection *input_section,
+                       bfd *output_bfd,
+                       char **error_message ATTRIBUTE_UNUSED)
+{
+  bfd_vma relocation, x;
+
+  if (output_bfd != NULL)
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  relocation += symbol->section->output_section->vma;
+  relocation += symbol->section->output_offset;
+  relocation += reloc_entry->addend;
+
+  x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+  x &= 0x0000ff00;
+  x |= relocation & 0xff;
+  x |= (relocation << 8) & 0xffff0000;
+  bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
+
+  if (relocation & ~ (bfd_vma) 0xffffff)
+    return bfd_reloc_overflow;
+
+  return bfd_reloc_ok;
+}
 
 static reloc_howto_type xstormy16_elf_howto_table [] =
 {
@@ -101,22 +112,22 @@ static reloc_howto_type xstormy16_elf_howto_table [] =
         "R_XSTORMY16_16",      /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0xffffffff,            /* dst_mask */
+        0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* An 8 bit absolute relocation.  */
-  HOWTO (R_XSTORMY16_8,        /* type */
+  HOWTO (R_XSTORMY16_8,                /* type */
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
         8,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
+        complain_overflow_unsigned, /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         "R_XSTORMY16_8",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0xffffffff,            /* dst_mask */
+        0xff,                  /* dst_mask */
         FALSE),                /* pcrel_offset */
 
   /* A 32 bit pc-relative relocation.  */
@@ -176,7 +187,7 @@ static reloc_howto_type xstormy16_elf_howto_table [] =
         "R_XSTORMY16_REL_12",  /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
-        0x0fff,                /* dst_mask */
+        0x0ffe,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   /* A 24-bit absolute relocation suitable for the jump instructions.  */
@@ -238,7 +249,7 @@ static reloc_howto_type xstormy16_elf_howto_table [] =
         0,                     /* src_mask */
         0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
+
   /* A 12 bit absolute relocation.  */
   HOWTO (R_XSTORMY16_12,       /* type */
         0,                     /* rightshift */
@@ -318,9 +329,8 @@ static const reloc_map xstormy16_reloc_map [] =
 };
 
 static reloc_howto_type *
-xstormy16_reloc_type_lookup (abfd, code)
-     bfd * abfd ATTRIBUTE_UNUSED;
-     bfd_reloc_code_real_type code;
+xstormy16_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
+                            bfd_reloc_code_real_type code)
 {
   unsigned int i;
 
@@ -338,13 +348,37 @@ xstormy16_reloc_type_lookup (abfd, code)
   return NULL;
 }
 
+static reloc_howto_type *
+xstormy16_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                            const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < (sizeof (xstormy16_elf_howto_table)
+           / sizeof (xstormy16_elf_howto_table[0]));
+       i++)
+    if (xstormy16_elf_howto_table[i].name != NULL
+       && strcasecmp (xstormy16_elf_howto_table[i].name, r_name) == 0)
+      return &xstormy16_elf_howto_table[i];
+
+  for (i = 0;
+       i < (sizeof (xstormy16_elf_howto_table2)
+           / sizeof (xstormy16_elf_howto_table2[0]));
+       i++)
+    if (xstormy16_elf_howto_table2[i].name != NULL
+       && strcasecmp (xstormy16_elf_howto_table2[i].name, r_name) == 0)
+      return &xstormy16_elf_howto_table2[i];
+
+  return NULL;
+}
+
 /* Set the howto pointer for an XSTORMY16 ELF reloc.  */
 
 static void
-xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
-     bfd * abfd ATTRIBUTE_UNUSED;
-     arelent * cache_ptr;
-     Elf_Internal_Rela * dst;
+xstormy16_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
+                             arelent * cache_ptr,
+                             Elf_Internal_Rela * dst)
 {
   unsigned int r_type = ELF32_R_TYPE (dst->r_info);
 
@@ -357,51 +391,6 @@ xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
   else
     abort ();
 }
-
-/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement.  */
-
-static bfd_reloc_status_type
-xstormy16_elf_24_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 ATTRIBUTE_UNUSED;
-{
-  bfd_vma relocation, x;
-
-  if (output_bfd != NULL)
-    {
-      reloc_entry->address += input_section->output_offset;
-      return bfd_reloc_ok;
-    }
-
-  if (reloc_entry->address > input_section->_cooked_size)
-    return bfd_reloc_outofrange;
-
-  if (bfd_is_com_section (symbol->section))
-    relocation = 0;
-  else
-    relocation = symbol->value;
-
-  relocation += symbol->section->output_section->vma;
-  relocation += symbol->section->output_offset;
-  relocation += reloc_entry->addend;
-
-  x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  x &= 0x0000ff00;
-  x |= relocation & 0xff;
-  x |= (relocation << 8) & 0xffff0000;
-  bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
-
-  if (relocation & ~ (bfd_vma) 0xffffff)
-    return bfd_reloc_overflow;
-
-  return bfd_reloc_ok;
-}
 \f
 /* We support 16-bit pointers to code above 64k by generating a thunk
    below 64k containing a JMPF instruction to the final address.  We
@@ -410,11 +399,10 @@ xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section,
    sections will fall in the address space.  */
 
 static bfd_boolean
-xstormy16_elf_check_relocs (abfd, info, sec, relocs)
-     bfd *abfd;
-     struct bfd_link_info *info;
-     asection *sec;
-     const Elf_Internal_Rela *relocs;
+xstormy16_elf_check_relocs (bfd *abfd,
+                           struct bfd_link_info *info,
+                           asection *sec,
+                           const Elf_Internal_Rela *relocs)
 {
   const Elf_Internal_Rela *rel, *relend;
   struct elf_link_hash_entry **sym_hashes;
@@ -423,7 +411,7 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs)
   asection *splt;
   bfd *dynobj;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
@@ -448,6 +436,10 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs)
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+         /* PR15323, ref flags aren't set for references in the same
+            object.  */
+         h->root.non_ir_ref = 1;
        }
 
       switch (ELF32_R_TYPE (rel->r_info))
@@ -467,19 +459,16 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs)
            elf_hash_table (info)->dynobj = dynobj = abfd;
          if (splt == NULL)
            {
-             splt = bfd_get_section_by_name (dynobj, ".plt");
+             splt = bfd_get_linker_section (dynobj, ".plt");
              if (splt == NULL)
                {
-                 splt = bfd_make_section (dynobj, ".plt");
+                 flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                                   | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                                   | SEC_READONLY | SEC_CODE);
+
+                 splt = bfd_make_section_anyway_with_flags (dynobj, ".plt",
+                                                            flags);
                  if (splt == NULL
-                     || ! bfd_set_section_flags (dynobj, splt,
-                                                 (SEC_ALLOC
-                                                  | SEC_LOAD
-                                                  | SEC_HAS_CONTENTS
-                                                  | SEC_IN_MEMORY
-                                                  | SEC_LINKER_CREATED
-                                                  | SEC_READONLY
-                                                  | SEC_CODE))
                      || ! bfd_set_section_alignment (dynobj, splt, 1))
                    return FALSE;
                }
@@ -495,7 +484,7 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs)
                  unsigned int i;
 
                  size = symtab_hdr->sh_info * sizeof (bfd_vma);
-                 local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+                 local_plt_offsets = bfd_alloc (abfd, size);
                  if (local_plt_offsets == NULL)
                    return FALSE;
                  elf_local_got_offsets (abfd) = local_plt_offsets;
@@ -508,22 +497,24 @@ xstormy16_elf_check_relocs (abfd, info, sec, relocs)
 
          if (*offset == (bfd_vma) -1)
            {
-             *offset = splt->_raw_size;
-             splt->_raw_size += 4;
+             *offset = splt->size;
+             splt->size += 4;
            }
          break;
 
          /* This relocation describes the C++ object vtable hierarchy.
             Reconstruct it for later use during GC.  */
         case R_XSTORMY16_GNU_VTINHERIT:
-          if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+          if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
             return FALSE;
           break;
 
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
         case R_XSTORMY16_GNU_VTENTRY:
-          if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
+          BFD_ASSERT (h != NULL);
+          if (h != NULL
+              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
             return FALSE;
           break;
        }
@@ -542,15 +533,10 @@ struct relax_plt_data
 };
 
 static bfd_boolean
-xstormy16_relax_plt_check (h, xdata)
-     struct elf_link_hash_entry *h;
-     PTR xdata;
+xstormy16_relax_plt_check (struct elf_link_hash_entry *h, void * xdata)
 {
   struct relax_plt_data *data = (struct relax_plt_data *) xdata;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   if (h->plt.offset != (bfd_vma) -1)
     {
       bfd_vma address;
@@ -566,7 +552,7 @@ xstormy16_relax_plt_check (h, xdata)
       if (address <= 0xffff)
        {
          h->plt.offset = -1;
-         data->splt->_cooked_size -= 4;
+         data->splt->size -= 4;
          *data->again = TRUE;
        }
     }
@@ -578,15 +564,10 @@ xstormy16_relax_plt_check (h, xdata)
    previously had a plt entry, give it a new entry offset.  */
 
 static bfd_boolean
-xstormy16_relax_plt_realloc (h, xdata)
-     struct elf_link_hash_entry *h;
-     PTR xdata;
+xstormy16_relax_plt_realloc (struct elf_link_hash_entry *h, void * xdata)
 {
   bfd_vma *entry = (bfd_vma *) xdata;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   if (h->plt.offset != (bfd_vma) -1)
     {
       h->plt.offset = *entry;
@@ -597,11 +578,10 @@ xstormy16_relax_plt_realloc (h, xdata)
 }
 
 static bfd_boolean
-xstormy16_elf_relax_section (dynobj, splt, info, again)
-     bfd *dynobj;
-     asection *splt;
-     struct bfd_link_info *info;
-     bfd_boolean *again;
+xstormy16_elf_relax_section (bfd *dynobj,
+                            asection *splt,
+                            struct bfd_link_info *info,
+                            bfd_boolean *again)
 {
   struct relax_plt_data relax_plt_data;
   bfd *ibfd;
@@ -609,7 +589,7 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
   /* Assume nothing changes.  */
   *again = FALSE;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   /* We only relax the .plt section at the moment.  */
@@ -618,14 +598,9 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
     return TRUE;
 
   /* Quick check for an empty plt.  */
-  if (splt->_raw_size == 0)
+  if (splt->size == 0)
     return TRUE;
 
-  /* If this is the first time we have been called for this section,
-     initialize the cooked size.  */
-  if (splt->_cooked_size == 0)
-    splt->_cooked_size = splt->_raw_size;
-
   /* Map across all global symbols; see which ones happen to
      fall in the low 64k.  */
   relax_plt_data.splt = splt;
@@ -635,7 +610,7 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
 
   /* Likewise for local symbols, though that's somewhat less convenient
      as we have to walk the list of input bfds and swap in symbol data.  */
-  for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
     {
       bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
       Elf_Internal_Shdr *symtab_hdr;
@@ -682,7 +657,7 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
          if (address <= 0xffff)
            {
              local_plt_offsets[idx] = -1;
-             splt->_cooked_size -= 4;
+             splt->size -= 4;
              *again = TRUE;
            }
        }
@@ -702,14 +677,14 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
 
   /* If we changed anything, walk the symbols again to reallocate
      .plt entry addresses.  */
-  if (*again && splt->_cooked_size > 0)
+  if (*again && splt->size > 0)
     {
       bfd_vma entry = 0;
 
       elf_link_hash_traverse (elf_hash_table (info),
                              xstormy16_relax_plt_realloc, &entry);
 
-      for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
+      for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link.next)
        {
          bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
          unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
@@ -727,29 +702,27 @@ xstormy16_elf_relax_section (dynobj, splt, info, again)
        }
     }
 
-  splt->_raw_size = splt->_cooked_size;
   return TRUE;
 }
 
 static bfd_boolean
-xstormy16_elf_always_size_sections (output_bfd, info)
-     bfd *output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+                                   struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *splt;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   dynobj = elf_hash_table (info)->dynobj;
   if (dynobj == NULL)
     return TRUE;
 
-  splt = bfd_get_section_by_name (dynobj, ".plt");
+  splt = bfd_get_linker_section (dynobj, ".plt");
   BFD_ASSERT (splt != NULL);
 
-  splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size);
+  splt->contents = bfd_zalloc (dynobj, splt->size);
   if (splt->contents == NULL)
     return FALSE;
 
@@ -766,7 +739,7 @@ xstormy16_elf_always_size_sections (output_bfd, info)
    zero.
 
    This function is responsible for adjusting the section contents as
-   necessary, and (if using Rela relocs and generating a relocateable
+   necessary, and (if using Rela relocs and generating a relocatable
    output file) adjusting the reloc addend as necessary.
 
    This function does not have to worry about setting the reloc
@@ -780,23 +753,21 @@ xstormy16_elf_always_size_sections (output_bfd, info)
    The global hash table entry for the global symbols can be found
    via elf_sym_hashes (input_bfd).
 
-   When generating relocateable output, this function must handle
+   When generating relocatable output, this function must handle
    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    going to be the section symbol corresponding to the output
    section, which means that the addend must be adjusted
    accordingly.  */
 
 static bfd_boolean
-xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
-                          contents, relocs, local_syms, local_sections)
-     bfd *                   output_bfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *  info;
-     bfd *                   input_bfd;
-     asection *              input_section;
-     bfd_byte *              contents;
-     Elf_Internal_Rela *     relocs;
-     Elf_Internal_Sym *      local_syms;
-     asection **             local_sections;
+xstormy16_elf_relocate_section (bfd *                   output_bfd ATTRIBUTE_UNUSED,
+                               struct bfd_link_info *  info,
+                               bfd *                   input_bfd,
+                               asection *              input_section,
+                               bfd_byte *              contents,
+                               Elf_Internal_Rela *     relocs,
+                               Elf_Internal_Sym *      local_syms,
+                               asection **             local_sections)
 {
   Elf_Internal_Shdr *           symtab_hdr;
   struct elf_link_hash_entry ** sym_hashes;
@@ -805,9 +776,6 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   bfd *dynobj;
   asection *splt;
 
-  if (info->relocateable)
-    return TRUE;
-
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   relend     = relocs + input_section->reloc_count;
@@ -815,7 +783,7 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
   dynobj = elf_hash_table (info)->dynobj;
   splt = NULL;
   if (dynobj != NULL)
-    splt = bfd_get_section_by_name (dynobj, ".plt");
+    splt = bfd_get_linker_section (dynobj, ".plt");
 
   for (rel = relocs; rel < relend; rel ++)
     {
@@ -845,44 +813,33 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          sym = local_syms + r_symndx;
          sec = local_sections [r_symndx];
-         relocation = (sec->output_section->vma
-                       + sec->output_offset
-                       + sym->st_value);
-
-         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;
+         relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
        }
       else
        {
-         h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+         bfd_boolean unresolved_reloc, warned, ignored;
 
-         while (h->root.type == bfd_link_hash_indirect
-                || h->root.type == bfd_link_hash_warning)
-           h = (struct elf_link_hash_entry *) h->root.u.i.link;
+         RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+                                  r_symndx, symtab_hdr, sym_hashes,
+                                  h, sec, relocation,
+                                  unresolved_reloc, warned, ignored);
+       }
 
-         name = h->root.root.string;
+      if (sec != NULL && discarded_section (sec))
+       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+                                        rel, 1, relend, howto, 0, contents);
 
-         if (h->root.type == bfd_link_hash_defined
-             || h->root.type == bfd_link_hash_defweak)
-           {
-             sec = h->root.u.def.section;
-             relocation = (h->root.u.def.value
-                           + sec->output_section->vma
-                           + sec->output_offset);
-           }
-         else if (h->root.type == bfd_link_hash_undefweak)
-           {
-             relocation = 0;
-           }
-         else
-           {
-             if (! ((*info->callbacks->undefined_symbol)
-                    (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset, TRUE)))
-               return FALSE;
-             relocation = 0;
-           }
+      if (info->relocatable)
+       continue;
+
+      if (h != NULL)
+       name = h->root.root.string;
+      else
+       {
+         name = (bfd_elf_string_from_elf_section
+                 (input_bfd, symtab_hdr->sh_link, sym->st_name));
+         if (name == NULL || *name == '\0')
+           name = bfd_section_name (input_bfd, sec);
        }
 
       switch (ELF32_R_TYPE (rel->r_info))
@@ -958,14 +915,14 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
       if (r != bfd_reloc_ok)
        {
-         const char * msg = (const char *) NULL;
+         const char * msg = NULL;
 
          switch (r)
            {
            case bfd_reloc_overflow:
              r = info->callbacks->reloc_overflow
-               (info, name, howto->name, (bfd_vma) 0,
-                input_bfd, input_section, rel->r_offset);
+               (info, (h ? &h->root : NULL), name, howto->name,
+                (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
              break;
 
            case bfd_reloc_undefined:
@@ -1006,9 +963,8 @@ xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 /* This must exist if dynobj is ever set.  */
 
 static bfd_boolean
-xstormy16_elf_finish_dynamic_sections (abfd, info)
-     bfd *abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *info;
+xstormy16_elf_finish_dynamic_sections (bfd *abfd ATTRIBUTE_UNUSED,
+                                      struct bfd_link_info *info)
 {
   bfd *dynobj;
   asection *splt;
@@ -1017,13 +973,15 @@ xstormy16_elf_finish_dynamic_sections (abfd, info)
      been filled in.  */
 
   if ((dynobj = elf_hash_table (info)->dynobj) != NULL
-      && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
+      && (splt = bfd_get_linker_section (dynobj, ".plt")) != NULL)
     {
       bfd_byte *contents = splt->contents;
-      unsigned int i, size = splt->_raw_size;
+      unsigned int i, size = splt->size;
+
       for (i = 0; i < size; i += 4)
        {
          unsigned int x = bfd_get_32 (dynobj, contents + i);
+
          BFD_ASSERT (x != 0);
        }
     }
@@ -1035,69 +993,39 @@ xstormy16_elf_finish_dynamic_sections (abfd, info)
    relocation.  */
 
 static asection *
-xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
-     asection *                   sec;
-     struct bfd_link_info *       info ATTRIBUTE_UNUSED;
-     Elf_Internal_Rela *          rel;
-     struct elf_link_hash_entry * h;
-     Elf_Internal_Sym *           sym;
+xstormy16_elf_gc_mark_hook (asection *sec,
+                           struct bfd_link_info *info,
+                           Elf_Internal_Rela *rel,
+                           struct elf_link_hash_entry *h,
+                           Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF32_R_TYPE (rel->r_info))
-       {
-       case R_XSTORMY16_GNU_VTINHERIT:
-       case R_XSTORMY16_GNU_VTENTRY:
-         break;
-
-       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
-xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
-     bfd *                     abfd ATTRIBUTE_UNUSED;
-     struct bfd_link_info *    info ATTRIBUTE_UNUSED;
-     asection *                sec ATTRIBUTE_UNUSED;
-     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
-{
-  return TRUE;
+    switch (ELF32_R_TYPE (rel->r_info))
+      {
+      case R_XSTORMY16_GNU_VTINHERIT:
+      case R_XSTORMY16_GNU_VTENTRY:
+       return NULL;
+      }
+
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 \f
 #define ELF_ARCH               bfd_arch_xstormy16
 #define ELF_MACHINE_CODE       EM_XSTORMY16
 #define ELF_MAXPAGESIZE                0x100
 
-#define TARGET_LITTLE_SYM       bfd_elf32_xstormy16_vec
+#define TARGET_LITTLE_SYM       xstormy16_elf32_vec
 #define TARGET_LITTLE_NAME     "elf32-xstormy16"
 
 #define elf_info_to_howto_rel                  NULL
 #define elf_info_to_howto                      xstormy16_info_to_howto_rela
 #define elf_backend_relocate_section           xstormy16_elf_relocate_section
 #define elf_backend_gc_mark_hook               xstormy16_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook              xstormy16_elf_gc_sweep_hook
 #define elf_backend_check_relocs                xstormy16_elf_check_relocs
 #define elf_backend_always_size_sections \
   xstormy16_elf_always_size_sections
+#define elf_backend_omit_section_dynsym \
+  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_finish_dynamic_sections \
   xstormy16_elf_finish_dynamic_sections
 
@@ -1105,6 +1033,8 @@ xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
 #define elf_backend_rela_normal                        1
 
 #define bfd_elf32_bfd_reloc_type_lookup                xstormy16_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup \
+  xstormy16_reloc_name_lookup
 #define bfd_elf32_bfd_relax_section            xstormy16_elf_relax_section
 
 #include "elf32-target.h"