bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index c71354e0b81f96d7977f00af138af6c3da1f08fd..26c69bce314c1b4df50104cc9c9ba9a1fe6e5633 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,
-   2006, 2007 Free Software Foundation, Inc.
+   2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -487,7 +487,7 @@ sh_elf_relax_section (bfd *abfd, asection *sec,
     }
 #endif
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (abfd);
 
   internal_relocs = (_bfd_elf_link_read_relocs
                     (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
@@ -852,7 +852,7 @@ sh_elf_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr,
   unsigned int symcount;
   asection *o;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (abfd);
   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
 
   sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
@@ -2154,20 +2154,19 @@ struct sh_elf_obj_tdata
 #define sh_elf_local_got_tls_type(abfd) \
   (sh_elf_tdata (abfd)->local_got_tls_type)
 
+#define is_sh_elf(bfd) \
+  (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
+   && elf_tdata (bfd) != NULL \
+   && elf_object_id (bfd) == SH_ELF_TDATA)
+
 /* Override the generic function because we need to store sh_elf_obj_tdata
    as the specific tdata.  */
 
 static bfd_boolean
 sh_elf_mkobject (bfd *abfd)
 {
-  if (abfd->tdata.any == NULL)
-    {
-      bfd_size_type amt = sizeof (struct sh_elf_obj_tdata);
-      abfd->tdata.any = bfd_zalloc (abfd, amt);
-      if (abfd->tdata.any == NULL)
-       return FALSE;
-    }
-  return bfd_elf_mkobject (abfd);
+  return bfd_elf_allocate_object (abfd, sizeof (struct sh_elf_obj_tdata),
+                                 SH_ELF_TDATA);
 }
 
 /* sh ELF linker hash table.  */
@@ -2818,6 +2817,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            }
        }
 
+      if (htab->vxworks_p)
+       {
+         struct elf_sh_dyn_relocs **pp;
+
+         for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+           {
+             if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
+               *pp = p->next;
+             else
+               pp = &p->next;
+           }
+       }
+
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
       if (eh->dyn_relocs != NULL
@@ -2958,7 +2970,7 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
 
-      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+      if (! is_sh_elf (ibfd))
        continue;
 
       for (s = ibfd->sections; s != NULL; s = s->next)
@@ -2978,6 +2990,13 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                     linker script /DISCARD/, so we'll be discarding
                     the relocs too.  */
                }
+             else if (htab->vxworks_p
+                      && strcmp (p->sec->output_section->name,
+                                 ".tls_vars") == 0)
+               {
+                 /* Relocations in vxworks .tls_vars sections are
+                    handled specially by the loader.  */
+               }
              else if (p->count != 0)
                {
                  srel = elf_section_data (p->sec)->sreloc;
@@ -2992,7 +3011,7 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (!local_got)
        continue;
 
-      symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+      symtab_hdr = &elf_symtab_hdr (ibfd);
       locsymcount = symtab_hdr->sh_info;
 #ifdef INCLUDE_SHMEDIA
       /* Count datalabel local GOT.  */
@@ -3138,6 +3157,9 @@ sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                return FALSE;
            }
        }
+      if (htab->vxworks_p
+         && !elf_vxworks_add_dynamic_entries (output_bfd, info))
+       return FALSE;
     }
 #undef add_dynamic_entry
 
@@ -3164,9 +3186,12 @@ sh_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   asection *splt;
   asection *sreloc;
   asection *srelgot;
+  bfd_boolean is_vxworks_tls;
+
+  BFD_ASSERT (is_sh_elf (input_bfd));
 
   htab = sh_elf_hash_table (info);
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
   sym_hashes = elf_sym_hashes (input_bfd);
   dynobj = htab->root.dynobj;
   local_got_offsets = elf_local_got_offsets (input_bfd);
@@ -3176,6 +3201,11 @@ sh_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   splt = htab->splt;
   sreloc = NULL;
   srelgot = NULL;
+  /* We have to handle relocations in vxworks .tls_vars sections
+     specially, because the dynamic loader is 'weird'.  */
+  is_vxworks_tls = (htab->vxworks_p && info->shared
+                   && !strcmp (input_section->output_section->name,
+                               ".tls_vars"));
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -3582,6 +3612,7 @@ sh_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  || h->root.type != bfd_link_hash_undefweak)
              && r_symndx != 0
              && (input_section->flags & SEC_ALLOC) != 0
+             && !is_vxworks_tls
              && (r_type == R_SH_DIR32
                  || !SYMBOL_CALLS_LOCAL (info, h)))
            {
@@ -4424,7 +4455,7 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd,
                                                       relocatable,
                                                       symbols);
 
-  symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+  symtab_hdr = &elf_symtab_hdr (input_bfd);
 
   memcpy (data, elf_section_data (input_section)->this_hdr.contents,
          (size_t) input_section->size);
@@ -4561,9 +4592,12 @@ sh_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
   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;
+  symtab_hdr = &elf_symtab_hdr (abfd);
   sym_hashes = elf_sym_hashes (abfd);
   local_got_refcounts = elf_local_got_refcounts (abfd);
 
@@ -4835,7 +4869,7 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                     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;
   struct elf_sh_link_hash_table *htab;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
@@ -4853,11 +4887,10 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
   if (info->relocatable)
     return TRUE;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  BFD_ASSERT (is_sh_elf (abfd));
+
+  symtab_hdr = &elf_symtab_hdr (abfd);
   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 = sh_elf_hash_table (info);
   local_got_offsets = elf_local_got_offsets (abfd);
@@ -4959,7 +4992,9 @@ sh_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_SH_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;
 
@@ -5353,13 +5388,12 @@ sh_elf_set_private_flags (bfd *abfd, flagword flags)
 static bfd_boolean
 sh_elf_copy_private_data (bfd * ibfd, bfd * obfd)
 {
-  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return TRUE;
-
   /* Copy object attributes.  */
   _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
+  if (! is_sh_elf (ibfd) || ! is_sh_elf (obfd))
+    return TRUE;
+
   return sh_elf_set_private_flags (obfd, elf_elfheader (ibfd)->e_flags);
 }
 #endif /* not sh_elf_copy_private_data */
@@ -5386,8 +5420,7 @@ sh_elf_merge_private_data (bfd *ibfd, bfd *obfd)
 {
   extern bfd_boolean sh_merge_bfd_arch (bfd *, bfd *);
 
-  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+  if (! is_sh_elf (ibfd) || ! is_sh_elf (obfd))
     return TRUE;
 
   if (! elf_flags_init (obfd))
@@ -5764,6 +5797,9 @@ sh_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
          switch (dyn.d_tag)
            {
            default:
+             if (htab->vxworks_p
+                 && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
+               bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
              break;
 
 #ifdef INCLUDE_SHMEDIA
This page took 0.038418 seconds and 4 git commands to generate.