OSDN Git Service

mips64*-*-toppers* support.
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-m32r.c
index aecf0fe..bd2fd99 100644 (file)
@@ -1,12 +1,12 @@
 /* M32R-specific support for 32-bit ELF.
    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009  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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 "elf-bfd.h"
 #include "elf/m32r.h"
@@ -1254,6 +1255,22 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                                const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (m32r_elf_howto_table) / sizeof (m32r_elf_howto_table[0]);
+       i++)
+    if (m32r_elf_howto_table[i].name != NULL
+       && strcasecmp (m32r_elf_howto_table[i].name, r_name) == 0)
+      return &m32r_elf_howto_table[i];
+
+  return NULL;
+}
+
 /* Set the howto pointer for an M32R ELF reloc.  */
 
 static void
@@ -1509,8 +1526,8 @@ struct elf_m32r_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
-  /* Small local sym to section mapping cache.  */
-  struct sym_sec_cache sym_sec;
+  /* Small local sym cache.  */
+  struct sym_cache sym_cache;
 };
 
 /* Traverse an m32r ELF linker hash table.  */
@@ -1572,8 +1589,9 @@ m32r_elf_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                       m32r_elf_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                     m32r_elf_link_hash_newfunc,
+                                     sizeof (struct elf_m32r_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -1586,7 +1604,7 @@ m32r_elf_link_hash_table_create (bfd *abfd)
   ret->srelplt = NULL;
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
-  ret->sym_sec.abfd = NULL;
+  ret->sym_cache.abfd = NULL;
 
   return &ret->root.root;
 }
@@ -1605,20 +1623,10 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
   htab = m32r_elf_hash_table (info);
   htab->sgot = bfd_get_section_by_name (dynobj, ".got");
   htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
-  if (! htab->sgot || ! htab->sgotplt)
+  htab->srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+  if (! htab->sgot || ! htab->sgotplt || ! htab->srelgot)
     abort ();
 
-  htab->srelgot = bfd_make_section_with_flags (dynobj, ".rela.got",
-                                              (SEC_ALLOC
-                                               | SEC_LOAD
-                                               | SEC_HAS_CONTENTS
-                                               | SEC_IN_MEMORY
-                                               | SEC_LINKER_CREATED
-                                               | SEC_READONLY));
-  if (htab->srelgot == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
-    return FALSE;
-
   return TRUE;
 }
 
@@ -1816,7 +1824,6 @@ m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   struct elf_m32r_dyn_relocs *p;
   bfd *dynobj;
   asection *s;
-  unsigned int power_of_two;
 
 #ifdef DEBUG_PIC
   printf ("m32r_elf_adjust_dynamic_symbol()\n");
@@ -1944,28 +1951,7 @@ m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       h->needs_copy = 1;
     }
 
-  /* We need to figure out the alignment required for this symbol.  I
-     have no idea how ELF linkers handle this.  */
-  power_of_two = bfd_log2 (h->size);
-  if (power_of_two > 3)
-    power_of_two = 3;
-
-  /* Apply the required alignment.  */
-  s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
-  if (power_of_two > bfd_get_section_alignment (dynobj, s))
-    {
-      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
-        return FALSE;
-    }
-
-  /* Define the symbol as being at this point in the section.  */
-  h->root.u.def.section = s;
-  h->root.u.def.value = s->size;
-
-  /* Increment the section size to make room for the symbol.  */
-  s->size += h->size;
-
-  return TRUE;
+  return _bfd_elf_adjust_dynamic_copy (h, s);
 }
 
 /* Allocate space in .plt, .got and associated reloc sections for
@@ -2308,7 +2294,7 @@ m32r_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
           /* Strip this section if we don't need it; see the
              comment below.  */
         }
-      else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
+      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
         {
           if (s->size != 0 && s != htab->srelplt)
             relocs = TRUE;
@@ -2476,6 +2462,7 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
          `r_addend'.  */
       bfd_vma addend = rel->r_addend;
       bfd_vma offset = rel->r_offset;
+      bfd_vma relocation;
       Elf_Internal_Sym *sym;
       asection *sec;
       const char *sym_name;
@@ -2508,27 +2495,152 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
       howto = m32r_elf_howto_table + r_type;
       r_symndx = ELF32_R_SYM (rel->r_info);
 
-      if (info->relocatable && use_rel)
+      sym = NULL;
+      sec = NULL;
+      h = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+       {
+         /* Local symbol.  */
+         sym = local_syms + r_symndx;
+         sec = local_sections[r_symndx];
+         sym_name = "<local symbol>";
+
+         if (!use_rel)
+           {
+             relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+             addend = rel->r_addend;
+           }
+         else
+           {
+             relocation = (sec->output_section->vma
+                           + sec->output_offset
+                           + sym->st_value);
+           }
+       }
+      else
+       {
+         /* External symbol.  */
+         relocation = 0;
+
+         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+         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;
+         sym_name = h->root.root.string;
+
+         if (h->root.type == bfd_link_hash_defined
+             || h->root.type == bfd_link_hash_defweak)
+           {
+             bfd_boolean dyn;
+             sec = h->root.u.def.section;
+
+             dyn = htab->root.dynamic_sections_created;
+             sec = h->root.u.def.section;
+             if (r_type == R_M32R_GOTPC24
+                 || (r_type == R_M32R_GOTPC_HI_ULO
+                     || r_type == R_M32R_GOTPC_HI_SLO
+                     || r_type == R_M32R_GOTPC_LO)
+                 || (r_type == R_M32R_26_PLTREL
+                     && h->plt.offset != (bfd_vma) -1)
+                 || ((r_type == R_M32R_GOT24
+                      || r_type == R_M32R_GOT16_HI_ULO
+                      || r_type == R_M32R_GOT16_HI_SLO
+                      || r_type == R_M32R_GOT16_LO)
+                     && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+                                                         info->shared, h)
+                     && (! info->shared
+                         || (! info->symbolic && h->dynindx != -1)
+                         || !h->def_regular))
+                 || (info->shared
+                     && ((! info->symbolic && h->dynindx != -1)
+                         || !h->def_regular)
+                     && (((r_type == R_M32R_16_RELA
+                           || r_type == R_M32R_32_RELA
+                           || r_type == R_M32R_24_RELA
+                           || r_type == R_M32R_HI16_ULO_RELA
+                           || r_type == R_M32R_HI16_SLO_RELA
+                           || r_type == R_M32R_LO16_RELA)
+                          && !h->forced_local)
+                         || r_type == R_M32R_REL32
+                         || r_type == R_M32R_10_PCREL_RELA
+                         || r_type == R_M32R_18_PCREL_RELA
+                         || r_type == R_M32R_26_PCREL_RELA)
+                     && ((input_section->flags & SEC_ALLOC) != 0
+                         /* DWARF will emit R_M32R_16(24,32) relocations
+                            in its sections against symbols defined
+                            externally in shared libraries.  We can't do
+                            anything with them here.  */
+                         || ((input_section->flags & SEC_DEBUGGING) != 0
+                             && h->def_dynamic))))
+               {
+                 /* In these cases, we don't need the relocation
+                    value.  We check specially because in some
+                    obscure cases sec->output_section will be NULL.  */
+               }
+             else if (sec->output_section != NULL)
+               relocation = (h->root.u.def.value
+                             + sec->output_section->vma
+                             + sec->output_offset);
+             else if (!info->relocatable)
+               {
+                 (*_bfd_error_handler)
+                   (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+                    input_bfd,
+                    input_section,
+                    (long) rel->r_offset,
+                    howto->name,
+                    h->root.root.string);
+               }
+           }
+         else if (h->root.type == bfd_link_hash_undefweak)
+           ;
+         else if (info->unresolved_syms_in_objects == RM_IGNORE
+                  && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+           ;
+         else if (!info->relocatable)
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd,
+                     input_section, offset,
+                     (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
+                      || ELF_ST_VISIBILITY (h->other)))))
+               return FALSE;
+           }
+       }
+
+      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 (info->relocatable && !use_rel)
        {
          /* 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.  */
-         sec = NULL;
-         if (r_symndx >= symtab_hdr->sh_info)
-           /* External symbol.  */
-           continue;
+         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+           rel->r_addend += sec->output_offset;
+         continue;
+       }
 
-         /* Local symbol.  */
-         sym = local_syms + r_symndx;
-         sym_name = "<local symbol>";
-         /* STT_SECTION: symbol is associated with a section.  */
-         if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
-           /* Symbol isn't associated with a section.  Nothing to do.  */
+      if (info->relocatable && use_rel)
+       {
+         /* 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)
            continue;
 
-         sec = local_sections[r_symndx];
-         addend += sec->output_offset + sym->st_value;
+         addend += sec->output_offset;
 
          /* If partial_inplace, we need to store any additional addend
             back in the section.  */
@@ -2566,140 +2678,6 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
       else
        {
-         bfd_vma relocation;
-
-         /* This is a final link.  */
-         sym = NULL;
-         sec = NULL;
-          h = NULL;
-
-         if (r_symndx < symtab_hdr->sh_info)
-           {
-             /* Local symbol.  */
-             sym = local_syms + r_symndx;
-             sec = local_sections[r_symndx];
-             sym_name = "<local symbol>";
-
-              if (!use_rel)
-                {
-                 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-                 addend = rel->r_addend;
-
-                  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 (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-                        rel->r_addend += sec->output_offset + sym->st_value;
-
-                      continue;
-                    }
-                }
-              else
-                {
-                 relocation = (sec->output_section->vma
-                               + sec->output_offset
-                               + sym->st_value);
-                }
-           }
-         else
-           {
-             /* External symbol.  */
-              if (info->relocatable && !use_rel)
-                continue;
-
-             h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-             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;
-             sym_name = h->root.root.string;
-
-             if (h->root.type == bfd_link_hash_defined
-                 || h->root.type == bfd_link_hash_defweak)
-               {
-                 bfd_boolean dyn;
-                 sec = h->root.u.def.section;
-
-                 dyn = htab->root.dynamic_sections_created;
-                  sec = h->root.u.def.section;
-                  if (r_type == R_M32R_GOTPC24
-                      || (r_type == R_M32R_GOTPC_HI_ULO
-                          || r_type == R_M32R_GOTPC_HI_SLO
-                          || r_type == R_M32R_GOTPC_LO)
-                      || (r_type == R_M32R_26_PLTREL
-                          && h->plt.offset != (bfd_vma) -1)
-                      || ((r_type == R_M32R_GOT24
-                           || r_type == R_M32R_GOT16_HI_ULO
-                           || r_type == R_M32R_GOT16_HI_SLO
-                           || r_type == R_M32R_GOT16_LO)
-                          && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
-                                                             info->shared, h)
-                          && (! info->shared
-                              || (! info->symbolic && h->dynindx != -1)
-                              || !h->def_regular))
-                      || (info->shared
-                          && ((! info->symbolic && h->dynindx != -1)
-                              || !h->def_regular)
-                          && (((r_type == R_M32R_16_RELA
-                              || r_type == R_M32R_32_RELA
-                              || r_type == R_M32R_24_RELA
-                              || r_type == R_M32R_HI16_ULO_RELA
-                              || r_type == R_M32R_HI16_SLO_RELA
-                              || r_type == R_M32R_LO16_RELA)
-                                 && !h->forced_local)
-                              || r_type == R_M32R_REL32
-                              || r_type == R_M32R_10_PCREL_RELA
-                              || r_type == R_M32R_18_PCREL_RELA
-                              || r_type == R_M32R_26_PCREL_RELA)
-                          && ((input_section->flags & SEC_ALLOC) != 0
-                              /* DWARF will emit R_M32R_16(24,32) relocations
-                                 in its sections against symbols defined
-                                 externally in shared libraries.  We can't do
-                                 anything with them here.  */
-                              || ((input_section->flags & SEC_DEBUGGING) != 0
-                                  && h->def_dynamic))))
-                    {
-                      /* In these cases, we don't need the relocation
-                         value.  We check specially because in some
-                         obscure cases sec->output_section will be NULL.  */
-                      relocation = 0;
-                    }
-                 else if (sec->output_section == NULL)
-                    {
-                      (*_bfd_error_handler)
-                        (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
-                        input_bfd,
-                        input_section,
-                        (long) rel->r_offset,
-                        howto->name,
-                        h->root.root.string);
-
-                      relocation = 0;
-                    }
-                 else
-                   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->unresolved_syms_in_objects == RM_IGNORE
-                       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
-                relocation = 0;
-             else
-               {
-                 if (! ((*info->callbacks->undefined_symbol)
-                        (info, h->root.root.string, input_bfd,
-                         input_section, offset,
-                          (info->unresolved_syms_in_objects == RM_GENERATE_ERROR
-                           || ELF_ST_VISIBILITY (h->other)))))
-                   return FALSE;
-                 relocation = 0;
-               }
-           }
-
          /* Sanity check the address.  */
          if (offset > high_address)
            {
@@ -2923,22 +2901,10 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
                      time.  */
                   if (sreloc == NULL)
                     {
-                      const char *name;
-
-                      name = (bfd_elf_string_from_elf_section
-                              (input_bfd,
-                               elf_elfheader (input_bfd)->e_shstrndx,
-                               elf_section_data (input_section)->rel_hdr.sh_name));
-                      if (name == NULL)
-                        return FALSE;
-
-                      BFD_ASSERT (strncmp (name, ".rela", 5) == 0
-                                  && strcmp (bfd_get_section_name (input_bfd,
-                                                                   input_section),
-                                             name + 5) == 0);
-
-                      sreloc = bfd_get_section_by_name (dynobj, name);
-                      BFD_ASSERT (sreloc != NULL);
+                     sreloc = _bfd_elf_get_dynamic_reloc_section
+                       (input_bfd, input_section, /*rela?*/ TRUE);
+                     if (sreloc == NULL)
+                       return FALSE;
                     }
 
                   skip = FALSE;
@@ -3636,40 +3602,22 @@ m32r_elf_print_private_bfd_data (bfd *abfd, void * ptr)
 
 static asection *
 m32r_elf_gc_mark_hook (asection *sec,
-                      struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                      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))
+    switch (ELF32_R_TYPE (rel->r_info))
       {
       case R_M32R_GNU_VTINHERIT:
       case R_M32R_GNU_VTENTRY:
       case R_M32R_RELA_GNU_VTINHERIT:
       case R_M32R_RELA_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;
+      }
 
-  return NULL;
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 static bfd_boolean
@@ -3684,6 +3632,9 @@ m32r_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
+  if (info->relocatable)
+    return TRUE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -3796,7 +3747,7 @@ m32r_elf_check_relocs (bfd *abfd,
                       const Elf_Internal_Rela *relocs)
 {
   Elf_Internal_Shdr *symtab_hdr;
-  struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
+  struct elf_link_hash_entry **sym_hashes;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   struct elf_m32r_link_hash_table *htab;
@@ -3811,9 +3762,6 @@ m32r_elf_check_relocs (bfd *abfd,
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
 
   htab = m32r_elf_hash_table (info);
   dynobj = htab->root.dynobj;
@@ -3980,36 +3928,11 @@ m32r_elf_check_relocs (bfd *abfd,
                  section in dynobj and make room for the reloc.  */
               if (sreloc == NULL)
                 {
-                  const char *name;
+                 sreloc = _bfd_elf_make_dynamic_reloc_section
+                   (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
 
-                  name = (bfd_elf_string_from_elf_section
-                          (abfd,
-                           elf_elfheader (abfd)->e_shstrndx,
-                           elf_section_data (sec)->rel_hdr.sh_name));
-                  if (name == NULL)
-                    return FALSE;
-
-                  BFD_ASSERT (strncmp (name, ".rela", 5) == 0
-                              && strcmp (bfd_get_section_name (abfd, sec),
-                                         name + 5) == 0);
-
-                  sreloc = bfd_get_section_by_name (dynobj, name);
-                  if (sreloc == NULL)
-                    {
-                      flagword flags;
-
-                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
-                               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-                      if ((sec->flags & SEC_ALLOC) != 0)
-                        flags |= SEC_ALLOC | SEC_LOAD;
-                      sreloc = bfd_make_section_with_flags (dynobj,
-                                                           name,
-                                                           flags);
-                      if (sreloc == NULL
-                          || ! bfd_set_section_alignment (dynobj, sreloc, 2))
-                        return FALSE;
-                    }
-                  elf_section_data (sec)->sreloc = sreloc;
+                 if (sreloc == NULL)
+                   return FALSE;
                 }
 
               /* If this is a global symbol, we count the number of
@@ -4018,14 +3941,19 @@ m32r_elf_check_relocs (bfd *abfd,
                 head = &((struct elf_m32r_link_hash_entry *) h)->dyn_relocs;
               else
                 {
+                  /* Track dynamic relocs needed for local syms too.  */
                   asection *s;
                   void *vpp;
+                 Elf_Internal_Sym *isym;
 
-                  /* Track dynamic relocs needed for local syms too.  */
-                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
-                                                 sec, r_symndx);
-                  if (s == NULL)
-                    return FALSE;
+                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                               abfd, r_symndx);
+                 if (isym == NULL)
+                   return FALSE;
+
+                 s = bfd_section_from_elf_index (abfd, isym->st_shndx);
+                 if (s == NULL)
+                   s = sec;
 
                  vpp = &elf_section_data (s)->local_dynrel;
                   head = (struct elf_m32r_dyn_relocs **) vpp;
@@ -4066,11 +3994,15 @@ m32r_elf_check_relocs (bfd *abfd,
         /* This relocation describes which C++ vtable entries are actually
            used.  Record for later use during GC.  */
         case R_M32R_GNU_VTENTRY:
-          if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+          BFD_ASSERT (h != NULL);
+          if (h != NULL
+              && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
             return FALSE;
           break;
         case R_M32R_RELA_GNU_VTENTRY:
-          if (!bfd_elf_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;
         }
@@ -4081,9 +4013,9 @@ m32r_elf_check_relocs (bfd *abfd,
 
 static const struct bfd_elf_special_section m32r_elf_special_sections[] =
 {
-  { ".sbss",    5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
-  { ".sdata",   6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
-  { NULL,       0,  0, 0,            0 }
+  { STRING_COMMA_LEN (".sbss"),  -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".sdata"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  { NULL,                     0,  0, 0,            0 }
 };
 
 static bfd_boolean
@@ -4158,6 +4090,8 @@ m32r_elf_reloc_type_class (const Elf_Internal_Rela *rela)
 #define elf_backend_create_dynamic_sections     m32r_elf_create_dynamic_sections
 #define bfd_elf32_bfd_link_hash_table_create    m32r_elf_link_hash_table_create
 #define elf_backend_size_dynamic_sections       m32r_elf_size_dynamic_sections
+#define elf_backend_omit_section_dynsym \
+  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
 #define elf_backend_finish_dynamic_sections     m32r_elf_finish_dynamic_sections
 #define elf_backend_adjust_dynamic_symbol       m32r_elf_adjust_dynamic_symbol
 #define elf_backend_finish_dynamic_symbol       m32r_elf_finish_dynamic_symbol