bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index 05b0665a7f37ce7f30e5a0d155413d2d7e9d9622..25077cc82ffc9f0b28d773bd9b9d97e1ce5f59b1 100644 (file)
@@ -1,6 +1,6 @@
 /* Renesas / SuperH SH 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.
    Contributed by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -17,7 +17,7 @@
 
    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.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -3649,15 +3649,13 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
   if (! htab->sgot || ! htab->sgotplt)
     abort ();
 
-  htab->srelgot = bfd_make_section (dynobj, ".rela.got");
+  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_flags (dynobj, htab->srelgot,
-                                 (SEC_ALLOC
-                                  | SEC_LOAD
-                                  | SEC_HAS_CONTENTS
-                                  | SEC_IN_MEMORY
-                                  | SEC_LINKER_CREATED
-                                  | SEC_READONLY))
       || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
     return FALSE;
   return TRUE;
@@ -3706,10 +3704,9 @@ sh_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (bed->plt_readonly)
     pltflags |= SEC_READONLY;
 
-  s = bfd_make_section (abfd, ".plt");
+  s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
   htab->splt = s;
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, pltflags)
       || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return FALSE;
 
@@ -3729,17 +3726,18 @@ sh_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))
        return FALSE;
     }
 
-  s = bfd_make_section (abfd,
-                       bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
+  s = bfd_make_section_with_flags (abfd,
+                                  bed->default_use_rela_p ? ".rela.plt" : ".rel.plt",
+                                  flags | SEC_READONLY);
   htab->srelplt = s;
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
       || ! bfd_set_section_alignment (abfd, s, ptralign))
     return FALSE;
 
@@ -3765,9 +3763,9 @@ sh_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        strcat (relname, secname);
        if (bfd_get_section_by_name (abfd, secname))
          continue;
-       s = bfd_make_section (abfd, relname);
+       s = bfd_make_section_with_flags (abfd, relname,
+                                        flags | SEC_READONLY);
        if (s == NULL
-           || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
            || ! bfd_set_section_alignment (abfd, s, ptralign))
          return FALSE;
       }
@@ -3781,10 +3779,10 @@ sh_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         image and use a R_*_COPY reloc to tell the dynamic linker to
         initialize them at run time.  The linker script puts the .dynbss
         section into the .bss section of the final image.  */
-      s = bfd_make_section (abfd, ".dynbss");
+      s = bfd_make_section_with_flags (abfd, ".dynbss",
+                                      SEC_ALLOC | SEC_LINKER_CREATED);
       htab->sdynbss = s;
-      if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+      if (s == NULL)
        return FALSE;
 
       /* The .rel[a].bss section holds copy relocs.  This section is not
@@ -3800,12 +3798,12 @@ sh_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
         copy relocs.  */
       if (! info->shared)
        {
-         s = bfd_make_section (abfd,
-                               (bed->default_use_rela_p
-                                ? ".rela.bss" : ".rel.bss"));
+         s = bfd_make_section_with_flags (abfd,
+                                          (bed->default_use_rela_p
+                                           ? ".rela.bss" : ".rel.bss"),
+                                          flags | SEC_READONLY);
          htab->srelbss = s;
          if (s == NULL
-             || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
              || ! bfd_set_section_alignment (abfd, s, ptralign))
            return FALSE;
        }
@@ -3918,6 +3916,13 @@ sh_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
@@ -4156,9 +4161,21 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+      if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
-       eh->dyn_relocs = NULL;
+       {
+         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
     {
@@ -4357,7 +4374,8 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s == htab->splt
          || s == htab->sgot
-         || s == htab->sgotplt)
+         || s == htab->sgotplt
+         || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
@@ -4389,10 +4407,13 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
             function which decides whether anything needs to go
             into these sections.  */
 
-         _bfd_strip_section_from_output (info, s);
+         s->flags |= SEC_EXCLUDE;
          continue;
        }
 
+      if ((s->flags & SEC_HAS_CONTENTS) == 0)
+       continue;
+
       /* Allocate memory for the section contents.  We use bfd_zalloc
         here in case unused entries are not reclaimed before the
         section's contents are written out.  This should not happen,
@@ -4685,7 +4706,8 @@ sh_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                          || !h->def_regular)
                      && ((r_type == R_SH_DIR32
                           && !h->forced_local)
-                         || r_type == R_SH_REL32)
+                         || (r_type == R_SH_REL32
+                             && !SYMBOL_CALLS_LOCAL (info, h)))
                      && ((input_section->flags & SEC_ALLOC) != 0
                          /* DWARF will emit R_SH_DIR32 relocations in its
                             sections against symbols defined externally
@@ -4706,8 +4728,12 @@ sh_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              else if (sec->output_section == NULL)
                {
                  (*_bfd_error_handler)
-                   (_("%B(%A): unresolvable relocation against symbol `%s'"),
-                    input_bfd, input_section, h->root.root.string);
+                   (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
+                    input_bfd,
+                    input_section,
+                    (long) rel->r_offset,
+                    howto->name,
+                    h->root.root.string);
                  return FALSE;
                }
              else
@@ -6051,14 +6077,11 @@ sh_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
 /* Copy the extra info we tack onto an elf_link_hash_entry.  */
 
 static void
-sh_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
+sh_elf_copy_indirect_symbol (struct bfd_link_info *info,
                             struct elf_link_hash_entry *dir,
                             struct elf_link_hash_entry *ind)
 {
   struct elf_sh_link_hash_entry *edir, *eind;
-#ifdef INCLUDE_SHMEDIA
-  bfd_signed_vma tmp;
-#endif
 
   edir = (struct elf_sh_link_hash_entry *) dir;
   eind = (struct elf_sh_link_hash_entry *) ind;
@@ -6070,9 +6093,7 @@ sh_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
          struct elf_sh_dyn_relocs **pp;
          struct elf_sh_dyn_relocs *p;
 
-         BFD_ASSERT (ind->root.type != bfd_link_hash_indirect);
-
-         /* 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; )
            {
@@ -6098,14 +6119,8 @@ sh_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
   edir->gotplt_refcount = eind->gotplt_refcount;
   eind->gotplt_refcount = 0;
 #ifdef INCLUDE_SHMEDIA
-  tmp = edir->datalabel_got.refcount;
-  if (tmp < 1)
-    {
-      edir->datalabel_got.refcount = eind->datalabel_got.refcount;
-      eind->datalabel_got.refcount = tmp;
-    }
-  else
-    BFD_ASSERT (eind->datalabel_got.refcount < 1);
+  edir->datalabel_got.refcount += eind->datalabel_got.refcount;
+  eind->datalabel_got.refcount = 0;
 #endif
 
   if (ind->root.type == bfd_link_hash_indirect
@@ -6127,7 +6142,7 @@ sh_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
       dir->needs_plt |= ind->needs_plt;
     }
   else
-    _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+    _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
 static int
@@ -6204,14 +6219,14 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
       else
        {
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-#ifdef INCLUDE_SHMEDIA
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
            {
+#ifdef INCLUDE_SHMEDIA
              seen_stt_datalabel |= h->type == STT_DATALABEL;
+#endif
              h = (struct elf_link_hash_entry *) h->root.u.i.link;
            }
-#endif
        }
 
       r_type = sh_elf_optimized_tls_reloc (info, r_type, h == NULL);
@@ -6531,14 +6546,14 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                    {
                      flagword flags;
 
-                     sreloc = bfd_make_section (htab->root.dynobj, name);
                      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 (htab->root.dynobj,
+                                                           name,
+                                                           flags);
                      if (sreloc == NULL
-                         || ! bfd_set_section_flags (htab->root.dynobj,
-                                                     sreloc, flags)
                          || ! bfd_set_section_alignment (htab->root.dynobj,
                                                          sreloc, 2))
                        return FALSE;
@@ -6553,6 +6568,7 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
              else
                {
                  asection *s;
+                 void *vpp;
 
                  /* Track dynamic relocs needed for local syms too.  */
                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
@@ -6560,8 +6576,8 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                  if (s == NULL)
                    return FALSE;
 
-                 head = ((struct elf_sh_dyn_relocs **)
-                         &elf_section_data (s)->local_dynrel);
+                 vpp = &elf_section_data (s)->local_dynrel;
+                 head = (struct elf_sh_dyn_relocs **) vpp;
                }
 
              p = *head;
@@ -6643,7 +6659,7 @@ sh_elf_set_mach_from_flags (bfd *abfd)
 int
 sh_elf_get_flags_from_mach (unsigned long mach)
 {
-  int i = ARRAY_SIZE (sh_ef_bfd_table);
+  int i = ARRAY_SIZE (sh_ef_bfd_table) - 1;
   
   for (; i>0; i--)
     if (sh_ef_bfd_table[i] == mach)
This page took 0.02854 seconds and 4 git commands to generate.