daily update
[deliverable/binutils-gdb.git] / bfd / elf-m10300.c
index 3935c85edda14dcce089db31e7fa62f568c50d1e..7a729259f1dc23577e8fed3dc529d59ee94ad7e5 100644 (file)
@@ -1,22 +1,22 @@
 /* Matsushita 10300 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 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 2 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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"
@@ -85,6 +85,9 @@ struct elf32_mn10300_link_hash_entry {
    prologue deleted.  */
 #define MN10300_DELETED_PROLOGUE_BYTES 0x2
   unsigned char flags;
+
+  /* Calculated value.  */
+  bfd_vma value;
 };
 
 /* We derive a hash table from the main elf linker hash table so
@@ -131,9 +134,6 @@ static void mn10300_info_to_howto
 static bfd_boolean mn10300_elf_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
-static asection *mn10300_elf_gc_mark_hook
-  PARAMS ((asection *, struct bfd_link_info *info, Elf_Internal_Rela *,
-          struct elf_link_hash_entry *, Elf_Internal_Sym *));
 static bfd_boolean mn10300_elf_relax_delete_bytes
   PARAMS ((bfd *, asection *, bfd_vma, int));
 static bfd_boolean mn10300_elf_symbol_address_p
@@ -582,10 +582,14 @@ _bfd_mn10300_elf_create_got_section (abfd, info)
 
   /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
      .plt section.  */
-  if (bed->want_plt_sym
-      && !_bfd_elf_define_linkage_sym (abfd, info, s,
-                                      "_PROCEDURE_LINKAGE_TABLE_"))
-    return FALSE;
+  if (bed->want_plt_sym)
+    {
+      h = _bfd_elf_define_linkage_sym (abfd, info, s,
+                                      "_PROCEDURE_LINKAGE_TABLE_");
+      elf_hash_table (info)->hplt = h;
+      if (h == NULL)
+       return FALSE;
+    }
 
   s = bfd_make_section_with_flags (abfd, ".got", flags);
   if (s == NULL
@@ -879,7 +883,7 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
                  if (name == NULL)
                    return FALSE;
 
-                 BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+                 BFD_ASSERT (CONST_STRNEQ (name, ".rela")
                              && strcmp (bfd_get_section_name (abfd, sec),
                                         name + 5) == 0);
 
@@ -915,40 +919,21 @@ mn10300_elf_check_relocs (abfd, info, sec, relocs)
    relocation.  */
 
 static asection *
-mn10300_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;
+mn10300_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_MN10300_GNU_VTINHERIT:
-       case R_MN10300_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);
+    switch (ELF32_R_TYPE (rel->r_info))
+      {
+      case R_MN10300_GNU_VTINHERIT:
+      case R_MN10300_GNU_VTENTRY:
+       return NULL;
+      }
 
-  return NULL;
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Perform a relocation as part of a final link.  */
@@ -1029,7 +1014,7 @@ mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
              if (name == NULL)
                return FALSE;
 
-             BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+             BFD_ASSERT (CONST_STRNEQ (name, ".rela")
                          && strcmp (bfd_get_section_name (input_bfd,
                                                           input_section),
                                     name + 5) == 0);
@@ -1457,9 +1442,12 @@ mn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
          else if (unresolved_reloc)
            (*_bfd_error_handler)
-             (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
-              bfd_get_filename (input_bfd), h->root.root.root.string,
-              bfd_get_section_name (input_bfd, input_section));
+             (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+              input_bfd,
+              input_section,
+              (long) rel->r_offset,
+              howto->name,
+              h->root.root.root.string);
        }
 
       r = mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
@@ -1595,6 +1583,42 @@ elf32_mn10300_finish_hash_table_entry (gen_entry, in_args)
   return TRUE;
 }
 
+/* Used to count hash table entries.  */
+static bfd_boolean
+elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
+                                       PTR in_args)
+{
+  int *count = (int *)in_args;
+
+  (*count) ++;
+  return TRUE;
+}
+
+/* Used to enumerate hash table entries into a linear array.  */
+static bfd_boolean
+elf32_mn10300_list_hash_table_entries (struct bfd_hash_entry *gen_entry,
+                                      PTR in_args)
+{
+  struct bfd_hash_entry ***ptr = (struct bfd_hash_entry ***) in_args;
+
+  **ptr = gen_entry;
+  (*ptr) ++;
+  return TRUE;
+}
+
+/* Used to sort the array created by the above.  */
+static int
+sort_by_value (const void *va, const void *vb)
+{
+  struct elf32_mn10300_link_hash_entry *a
+    = *(struct elf32_mn10300_link_hash_entry **)va;
+  struct elf32_mn10300_link_hash_entry *b
+    = *(struct elf32_mn10300_link_hash_entry **)vb;
+
+  return a->value - b->value;
+}
+
+
 /* This function handles relaxing for the mn10300.
 
    There are quite a few relaxing opportunities available on the mn10300:
@@ -1690,9 +1714,10 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
              char *new_name;
 
              /* If there's nothing to do in this section, skip it.  */
-             if (! (((section->flags & SEC_RELOC) != 0
-                     && section->reloc_count != 0)
-                    || (section->flags & SEC_CODE) != 0))
+             if (! ((section->flags & SEC_RELOC) != 0
+                    && section->reloc_count != 0))
+               continue;
+             if ((section->flags & SEC_ALLOC) == 0)
                continue;
 
              /* Get cached copy of section contents if it exists.  */
@@ -1795,13 +1820,17 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                   elf_sym_hashes (input_bfd)[r_index];
                        }
 
-                     /* If this is not a "call" instruction, then we
-                        should convert "call" instructions to "calls"
-                        instructions.  */
-                     code = bfd_get_8 (input_bfd,
-                                       contents + irel->r_offset - 1);
-                     if (code != 0xdd && code != 0xcd)
-                       hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
+                     sym_name = hash->root.root.root.string;
+                     if ((section->flags & SEC_CODE) != 0)
+                       {
+                         /* If this is not a "call" instruction, then we
+                            should convert "call" instructions to "calls"
+                            instructions.  */
+                         code = bfd_get_8 (input_bfd,
+                                           contents + irel->r_offset - 1);
+                         if (code != 0xdd && code != 0xcd)
+                           hash->flags |= MN10300_CONVERT_CALL_TO_CALLS;
+                       }
 
                      /* If this is a jump/call, then bump the
                         direct_calls counter.  Else force "call" to
@@ -1894,6 +1923,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                          free (new_name);
                          compute_function_info (input_bfd, hash,
                                                 isym->st_value, contents);
+                         hash->value = isym->st_value;
                        }
                    }
 
@@ -1955,6 +1985,44 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
                                        elf32_mn10300_finish_hash_table_entry,
                                        link_info);
 
+      {
+       /* This section of code collects all our local symbols, sorts
+          them by value, and looks for multiple symbols referring to
+          the same address.  For those symbols, the flags are merged.
+          At this point, the only flag that can be set is
+          MN10300_CONVERT_CALL_TO_CALLS, so we simply OR the flags
+          together.  */
+       int static_count = 0, i;
+       struct elf32_mn10300_link_hash_entry **entries;
+       struct elf32_mn10300_link_hash_entry **ptr;
+
+       elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
+                                         elf32_mn10300_count_hash_table_entries,
+                                         &static_count);
+
+       entries = (struct elf32_mn10300_link_hash_entry **)
+         bfd_malloc (static_count * sizeof (struct elf32_mn10300_link_hash_entry *));
+
+       ptr = entries;
+       elf32_mn10300_link_hash_traverse (hash_table->static_hash_table,
+                                         elf32_mn10300_list_hash_table_entries,
+                                         &ptr);
+
+       qsort (entries, static_count, sizeof(entries[0]), sort_by_value);
+
+       for (i=0; i<static_count-1; i++)
+         if (entries[i]->value && entries[i]->value == entries[i+1]->value)
+           {
+             int v = entries[i]->flags;
+             int j;
+             for (j=i+1; j<static_count && entries[j]->value == entries[i]->value; j++)
+               v |= entries[j]->flags;
+             for (j=i; j<static_count && entries[j]->value == entries[i]->value; j++)
+               entries[j]->flags = v;
+             i = j-1;
+           }
+      }
+
       /* All entries in the hash table are fully initialized.  */
       hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED;
 
@@ -2788,8 +2856,7 @@ mn10300_elf_relax_section (abfd, sec, link_info, again)
         into a 16bit immediate, displacement or absolute address.  */
       if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_32
          || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOT32
-         || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTOFF32
-         || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTPC32)
+         || ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOTOFF32)
        {
          bfd_vma value = symval;
 
@@ -3670,6 +3737,7 @@ elf32_mn10300_link_hash_newfunc (entry, table, string)
       ret->movm_args = 0;
       ret->movm_stack_size = 0;
       ret->flags = 0;
+      ret->value = 0;
     }
 
   return (struct bfd_hash_entry *) ret;
@@ -3688,8 +3756,9 @@ elf32_mn10300_link_hash_table_create (abfd)
   if (ret == (struct elf32_mn10300_link_hash_table *) NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
-                                      elf32_mn10300_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                     elf32_mn10300_link_hash_newfunc,
+                                     sizeof (struct elf32_mn10300_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -3705,8 +3774,9 @@ elf32_mn10300_link_hash_table_create (abfd)
       return NULL;
     }
 
-  if (! _bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
-                                      elf32_mn10300_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->static_hash_table->root, abfd,
+                                     elf32_mn10300_link_hash_newfunc,
+                                     sizeof (struct elf32_mn10300_link_hash_entry)))
     {
       free (ret->static_hash_table);
       free (ret);
@@ -4218,7 +4288,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
          /* Remember whether there is a PLT.  */
          plt = s->size != 0;
        }
-      else if (strncmp (name, ".rela", 5) == 0)
+      else if (CONST_STRNEQ (name, ".rela"))
        {
          if (s->size != 0)
            {
@@ -4251,7 +4321,7 @@ _bfd_mn10300_elf_size_dynamic_sections (output_bfd, info)
              s->reloc_count = 0;
            }
        }
-      else if (strncmp (name, ".got", 4) != 0
+      else if (! CONST_STRNEQ (name, ".got")
               && strcmp (name, ".dynbss") != 0)
        /* It's not one of our sections, so don't allocate space.  */
        continue;
@@ -4495,7 +4565,7 @@ _bfd_mn10300_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || h == elf_hash_table (info)->hgot)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -4686,6 +4756,8 @@ _bfd_mn10300_elf_reloc_type_class (const Elf_Internal_Rela *rela)
   _bfd_mn10300_elf_adjust_dynamic_symbol
 #define elf_backend_size_dynamic_sections \
   _bfd_mn10300_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_symbol \
   _bfd_mn10300_elf_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
This page took 0.028206 seconds and 4 git commands to generate.