OSDN Git Service

mips64*-*-toppers* support.
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf32-m32r.c
index 23075d6..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
-   Free Software Foundation, Inc.
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+   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;
 }
 
@@ -1668,6 +1676,7 @@ m32r_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
       h = (struct elf_link_hash_entry *) bh;
       h->def_regular = 1;
       h->type = STT_OBJECT;
+      htab->root.hplt = h;
 
       if (info->shared
           && ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -1755,7 +1764,7 @@ m32r_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
-m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+m32r_elf_copy_indirect_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *dir,
                                struct elf_link_hash_entry *ind)
 {
@@ -1772,10 +1781,7 @@ m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
           struct elf_m32r_dyn_relocs **pp;
           struct elf_m32r_dyn_relocs *p;
 
-          if (ind->root.type == bfd_link_hash_indirect)
-            abort ();
-
-          /* Add reloc counts against the weak sym to the strong sym
+          /* Add reloc counts against the indirect sym to the direct sym
              list.  Merge any entries against the same section.  */
           for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
             {
@@ -1799,7 +1805,7 @@ m32r_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
       eind->dyn_relocs = NULL;
     }
 
-  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+  _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
 \f
@@ -1818,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");
@@ -1911,6 +1916,13 @@ m32r_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
       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
@@ -1939,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
@@ -2097,6 +2088,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
                 pp = &p->next;
             }
         }
+
+      /* Also discard relocs on undefined weak syms with non-default
+        visibility.  */
+      if (eh->dyn_relocs != NULL
+         && h->root.type == bfd_link_hash_undefweak)
+       {
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+           eh->dyn_relocs = NULL;
+
+         /* Make sure undefined weak symbols are output as a dynamic
+            symbol in PIEs.  */
+         else if (h->dynindx == -1
+                  && !h->forced_local)
+           {
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+           }
+       }
     }
   else
     {
@@ -2285,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;
@@ -2453,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;
@@ -2485,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.  */
@@ -2543,137 +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)
-                        (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
-                         bfd_get_filename (input_bfd), h->root.root.string,
-                         bfd_get_section_name (input_bfd, input_section));
-
-                      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)
            {
@@ -2871,6 +2875,7 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
             case R_M32R_24_RELA:
             case R_M32R_32_RELA:
             case R_M32R_REL32:
+           case R_M32R_10_PCREL_RELA:
             case R_M32R_18_PCREL_RELA:
             case R_M32R_26_PCREL_RELA:
             case R_M32R_HI16_ULO_RELA:
@@ -2878,7 +2883,8 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
               if (info->shared
                   && r_symndx != 0
                   && (input_section->flags & SEC_ALLOC) != 0
-                  && ((r_type != R_M32R_18_PCREL_RELA
+                  && ((   r_type != R_M32R_10_PCREL_RELA
+                       && r_type != R_M32R_18_PCREL_RELA
                        && r_type != R_M32R_26_PCREL_RELA
                        && r_type != R_M32R_REL32)
                       || (h != NULL
@@ -2895,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;
@@ -2929,7 +2923,8 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
 
                   if (skip)
                     memset (&outrel, 0, sizeof outrel);
-                  else if (r_type == R_M32R_18_PCREL_RELA
+                  else if (   r_type == R_M32R_10_PCREL_RELA
+                           || r_type == R_M32R_18_PCREL_RELA
                            || r_type == R_M32R_26_PCREL_RELA
                            || r_type == R_M32R_REL32)
                     {
@@ -2968,8 +2963,11 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
                      an addend for the dynamic reloc.  */
                   if (! relocate)
                     continue;
+                 break;
                 }
-              break;
+             else if (r_type != R_M32R_10_PCREL_RELA)
+               break;
+             /* Fall through.  */
 
            case (int) R_M32R_10_PCREL :
              r = m32r_elf_do_10_pcrel_reloc (input_bfd, howto, input_section,
@@ -3326,7 +3324,7 @@ m32r_elf_finish_dynamic_symbol (bfd *output_bfd,
 
   /* Mark some specially defined symbols as absolute.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || h == htab->root.hgot)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -3604,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
@@ -3652,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;
@@ -3707,6 +3690,7 @@ m32r_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
        case R_M32R_HI16_SLO_RELA:
        case R_M32R_LO16_RELA:
        case R_M32R_SDA16_RELA:
+       case R_M32R_10_PCREL_RELA:
        case R_M32R_18_PCREL_RELA:
        case R_M32R_26_PCREL_RELA:
          if (h != NULL)
@@ -3723,8 +3707,9 @@ m32r_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
              for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
                if (p->sec == sec)
                  {
-                   if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA
-                       || ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA
+                   if (   ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA
+                       || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA
+                       || ELF32_R_TYPE (rel->r_info) == R_M32R_10_PCREL_RELA
                        || ELF32_R_TYPE (rel->r_info) == R_M32R_REL32)
                      p->pc_count -= 1;
                    p->count -= 1;
@@ -3762,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;
@@ -3777,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;
@@ -3890,6 +3872,7 @@ m32r_elf_check_relocs (bfd *abfd,
         case R_M32R_HI16_SLO_RELA:
         case R_M32R_LO16_RELA:
         case R_M32R_SDA16_RELA:
+       case R_M32R_10_PCREL_RELA:
         case R_M32R_18_PCREL_RELA:
         case R_M32R_26_PCREL_RELA:
 
@@ -3920,8 +3903,9 @@ m32r_elf_check_relocs (bfd *abfd,
              symbol.  */
           if ((info->shared
                && (sec->flags & SEC_ALLOC) != 0
-              && ((r_type != R_M32R_26_PCREL_RELA
+              && ((   r_type != R_M32R_26_PCREL_RELA
                     && r_type != R_M32R_18_PCREL_RELA
+                    && r_type != R_M32R_10_PCREL_RELA
                     && r_type != R_M32R_REL32)
                   || (h != NULL
                       && (! info->symbolic
@@ -3944,36 +3928,11 @@ m32r_elf_check_relocs (bfd *abfd,
                  section in dynobj and make room for the reloc.  */
               if (sreloc == NULL)
                 {
-                  const char *name;
-
-                  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_elf_make_dynamic_reloc_section
+                   (sec, dynobj, 2, abfd, /*rela?*/ TRUE);
 
-                  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
@@ -3982,16 +3941,22 @@ 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;
 
-                  head = ((struct elf_m32r_dyn_relocs **)
-                          &elf_section_data (s)->local_dynrel);
+                 vpp = &elf_section_data (s)->local_dynrel;
+                  head = (struct elf_m32r_dyn_relocs **) vpp;
                 }
 
               p = *head;
@@ -4010,8 +3975,10 @@ m32r_elf_check_relocs (bfd *abfd,
                 }
 
               p->count += 1;
-              if (ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA
-                  || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA)
+              if (   ELF32_R_TYPE (rel->r_info) == R_M32R_26_PCREL_RELA
+                  || ELF32_R_TYPE (rel->r_info) == R_M32R_18_PCREL_RELA
+                 || ELF32_R_TYPE (rel->r_info) == R_M32R_10_PCREL_RELA
+                 || ELF32_R_TYPE (rel->r_info) == R_M32R_REL32)
                 p->pc_count += 1;
             }
           break;
@@ -4027,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;
         }
@@ -4042,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
@@ -4119,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