| Line 1... | Line 1... | 
      
        | /* Renesas / SuperH SH specific support for 32-bit ELF
 | /* Renesas / SuperH SH specific support for 32-bit ELF
 | 
      
        |    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 |    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
 | 
      
        |    2006, 2007, 2008 Free Software Foundation, Inc.
 |    2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 | 
      
        |    Contributed by Ian Lance Taylor, Cygnus Support.
 |    Contributed by Ian Lance Taylor, Cygnus Support.
 | 
      
        |  
 |  
 | 
      
        |    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
 |    This program is free software; you can redistribute it and/or modify
 | 
      
        | Line 2185... | Line 2185... | 
      
        |   asection *srelbss;
 |   asection *srelbss;
 | 
      
        |  
 |  
 | 
      
        |   /* The (unloaded but important) VxWorks .rela.plt.unloaded section.  */
 |   /* The (unloaded but important) VxWorks .rela.plt.unloaded section.  */
 | 
      
        |   asection *srelplt2;
 |   asection *srelplt2;
 | 
      
        |  
 |  
 | 
      
        |   /* Small local sym to section mapping cache.  */
 |   /* Small local sym cache.  */
 | 
      
        |   struct sym_sec_cache sym_sec;
 |   struct sym_cache sym_cache;
 | 
      
        |  
 |  
 | 
      
        |   /* A counter or offset to track a TLS got entry.  */
 |   /* A counter or offset to track a TLS got entry.  */
 | 
      
        |   union
 |   union
 | 
      
        |     {
 |     {
 | 
      
        |       bfd_signed_vma refcount;
 |       bfd_signed_vma refcount;
 | 
      
        | Line 2279... | Line 2279... | 
      
        |   ret->splt = NULL;
 |   ret->splt = NULL;
 | 
      
        |   ret->srelplt = NULL;
 |   ret->srelplt = NULL;
 | 
      
        |   ret->sdynbss = NULL;
 |   ret->sdynbss = NULL;
 | 
      
        |   ret->srelbss = NULL;
 |   ret->srelbss = NULL;
 | 
      
        |   ret->srelplt2 = NULL;
 |   ret->srelplt2 = NULL;
 | 
      
        |   ret->sym_sec.abfd = NULL;
 |   ret->sym_cache.abfd = NULL;
 | 
      
        |   ret->tls_ldm_got.refcount = 0;
 |   ret->tls_ldm_got.refcount = 0;
 | 
      
        |   ret->plt_info = NULL;
 |   ret->plt_info = NULL;
 | 
      
        |   ret->vxworks_p = vxworks_object_p (abfd);
 |   ret->vxworks_p = vxworks_object_p (abfd);
 | 
      
        |  
 |  
 | 
      
        |   return &ret->root.root;
 |   return &ret->root.root;
 | 
      
        | Line 2301... | Line 2301... | 
      
        |     return FALSE;
 |     return FALSE;
 | 
      
        |  
 |  
 | 
      
        |   htab = sh_elf_hash_table (info);
 |   htab = sh_elf_hash_table (info);
 | 
      
        |   htab->sgot = bfd_get_section_by_name (dynobj, ".got");
 |   htab->sgot = bfd_get_section_by_name (dynobj, ".got");
 | 
      
        |   htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
 |   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 ();
 |     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;
 |   return TRUE;
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        | /* Create dynamic sections when linking against a dynamic object.  */
 | /* Create dynamic sections when linking against a dynamic object.  */
 | 
      
        |  
 |  
 | 
      
        | Line 2815... | Line 2806... | 
      
        |               else
 |               else
 | 
      
        |                 pp = &p->next;
 |                 pp = &p->next;
 | 
      
        |             }
 |             }
 | 
      
        |         }
 |         }
 | 
      
        |  
 |  
 | 
      
        |   |       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
 |       /* Also discard relocs on undefined weak syms with non-default
 | 
      
        |          visibility.  */
 |          visibility.  */
 | 
      
        |       if (eh->dyn_relocs != NULL
 |       if (eh->dyn_relocs != NULL
 | 
      
        |           && h->root.type == bfd_link_hash_undefweak)
 |           && h->root.type == bfd_link_hash_undefweak)
 | 
      
        |         {
 |         {
 | 
      
        | Line 2975... | Line 2979... | 
      
        |                   /* Input section has been discarded, either because
 |                   /* Input section has been discarded, either because
 | 
      
        |                      it is a copy of a linkonce section or due to
 |                      it is a copy of a linkonce section or due to
 | 
      
        |                      linker script /DISCARD/, so we'll be discarding
 |                      linker script /DISCARD/, so we'll be discarding
 | 
      
        |                      the relocs too.  */
 |                      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)
 |               else if (p->count != 0)
 | 
      
        |                 {
 |                 {
 | 
      
        |                   srel = elf_section_data (p->sec)->sreloc;
 |                   srel = elf_section_data (p->sec)->sreloc;
 | 
      
        |                   srel->size += p->count * sizeof (Elf32_External_Rela);
 |                   srel->size += p->count * sizeof (Elf32_External_Rela);
 | 
      
        |                   if ((p->sec->output_section->flags & SEC_READONLY) != 0)
 |                   if ((p->sec->output_section->flags & SEC_READONLY) != 0)
 | 
      
        | Line 3164... | Line 3175... | 
      
        |   asection *sgot;
 |   asection *sgot;
 | 
      
        |   asection *sgotplt;
 |   asection *sgotplt;
 | 
      
        |   asection *splt;
 |   asection *splt;
 | 
      
        |   asection *sreloc;
 |   asection *sreloc;
 | 
      
        |   asection *srelgot;
 |   asection *srelgot;
 | 
      
        |   |   bfd_boolean is_vxworks_tls;
 | 
      
        |  
 |  
 | 
      
        |   BFD_ASSERT (is_sh_elf (input_bfd));
 |   BFD_ASSERT (is_sh_elf (input_bfd));
 | 
      
        |  
 |  
 | 
      
        |   htab = sh_elf_hash_table (info);
 |   htab = sh_elf_hash_table (info);
 | 
      
        |   symtab_hdr = &elf_symtab_hdr (input_bfd);
 |   symtab_hdr = &elf_symtab_hdr (input_bfd);
 | 
      
        | Line 3178... | Line 3190... | 
      
        |   sgot = htab->sgot;
 |   sgot = htab->sgot;
 | 
      
        |   sgotplt = htab->sgotplt;
 |   sgotplt = htab->sgotplt;
 | 
      
        |   splt = htab->splt;
 |   splt = htab->splt;
 | 
      
        |   sreloc = NULL;
 |   sreloc = NULL;
 | 
      
        |   srelgot = 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;
 |   rel = relocs;
 | 
      
        |   relend = relocs + input_section->reloc_count;
 |   relend = relocs + input_section->reloc_count;
 | 
      
        |   for (; rel < relend; rel++)
 |   for (; rel < relend; rel++)
 | 
      
        |     {
 |     {
 | 
      
        | Line 3584... | Line 3601... | 
      
        |               && (h == NULL
 |               && (h == NULL
 | 
      
        |                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 |                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
 | 
      
        |                   || h->root.type != bfd_link_hash_undefweak)
 |                   || h->root.type != bfd_link_hash_undefweak)
 | 
      
        |               && r_symndx != 0
 |               && r_symndx != 0
 | 
      
        |               && (input_section->flags & SEC_ALLOC) != 0
 |               && (input_section->flags & SEC_ALLOC) != 0
 | 
      
        |   |               && !is_vxworks_tls
 | 
      
        |               && (r_type == R_SH_DIR32
 |               && (r_type == R_SH_DIR32
 | 
      
        |                   || !SYMBOL_CALLS_LOCAL (info, h)))
 |                   || !SYMBOL_CALLS_LOCAL (info, h)))
 | 
      
        |             {
 |             {
 | 
      
        |               Elf_Internal_Rela outrel;
 |               Elf_Internal_Rela outrel;
 | 
      
        |               bfd_byte *loc;
 |               bfd_byte *loc;
 | 
      
        | Line 3597... | Line 3615... | 
      
        |                  are copied into the output file to be resolved at run
 |                  are copied into the output file to be resolved at run
 | 
      
        |                  time.  */
 |                  time.  */
 | 
      
        |  
 |  
 | 
      
        |               if (sreloc == NULL)
 |               if (sreloc == NULL)
 | 
      
        |                 {
 |                 {
 | 
      
        |                   const char *name;
 |                   sreloc = _bfd_elf_get_dynamic_reloc_section
 | 
      
        |  
 |                     (input_bfd, input_section, /*rela?*/ TRUE);
 | 
      
        |                   name = (bfd_elf_string_from_elf_section
 |                   if (sreloc == NULL)
 | 
      
        |                           (input_bfd,
 |   | 
      
        |                            elf_elfheader (input_bfd)->e_shstrndx,
 |   | 
      
        |                            elf_section_data (input_section)->rel_hdr.sh_name));
 |   | 
      
        |                   if (name == NULL)
 |   | 
      
        |                     return FALSE;
 |                     return FALSE;
 | 
      
        |  
 |   | 
      
        |                   BFD_ASSERT (CONST_STRNEQ (name, ".rela")
 |   | 
      
        |                               && strcmp (bfd_get_section_name (input_bfd,
 |   | 
      
        |                                                                input_section),
 |   | 
      
        |                                          name + 5) == 0);
 |   | 
      
        |  
 |   | 
      
        |                   sreloc = bfd_get_section_by_name (dynobj, name);
 |   | 
      
        |                   BFD_ASSERT (sreloc != NULL);
 |   | 
      
        |                 }
 |                 }
 | 
      
        |  
 |  
 | 
      
        |               skip = FALSE;
 |               skip = FALSE;
 | 
      
        |               relocate = FALSE;
 |               relocate = FALSE;
 | 
      
        |  
 |  
 | 
      
        | Line 4323... | Line 4329... | 
      
        |                 goto final_link_relocate;
 |                 goto final_link_relocate;
 | 
      
        |               }
 |               }
 | 
      
        |  
 |  
 | 
      
        |             if (sreloc == NULL)
 |             if (sreloc == NULL)
 | 
      
        |               {
 |               {
 | 
      
        |                 const char *name;
 |                 sreloc = _bfd_elf_get_dynamic_reloc_section
 | 
      
        |  
 |                   (input_bfd, input_section, /*rela?*/ TRUE);
 | 
      
        |                 name = (bfd_elf_string_from_elf_section
 |                 if (sreloc == NULL)
 | 
      
        |                         (input_bfd,
 |   | 
      
        |                          elf_elfheader (input_bfd)->e_shstrndx,
 |   | 
      
        |                          elf_section_data (input_section)->rel_hdr.sh_name));
 |   | 
      
        |                 if (name == NULL)
 |   | 
      
        |                   return FALSE;
 |                   return FALSE;
 | 
      
        |  
 |   | 
      
        |                 BFD_ASSERT (CONST_STRNEQ (name, ".rela")
 |   | 
      
        |                             && strcmp (bfd_get_section_name (input_bfd,
 |   | 
      
        |                                                              input_section),
 |   | 
      
        |                                        name + 5) == 0);
 |   | 
      
        |  
 |   | 
      
        |                 sreloc = bfd_get_section_by_name (dynobj, name);
 |   | 
      
        |                 BFD_ASSERT (sreloc != NULL);
 |   | 
      
        |               }
 |               }
 | 
      
        |  
 |  
 | 
      
        |             if (h == NULL || h->dynindx == -1)
 |             if (h == NULL || h->dynindx == -1)
 | 
      
        |               indx = 0;
 |               indx = 0;
 | 
      
        |             else
 |             else
 | 
      
        | Line 5194... | Line 5188... | 
      
        |               /* When creating a shared object, we must copy these
 |               /* When creating a shared object, we must copy these
 | 
      
        |                  reloc types into the output file.  We create a reloc
 |                  reloc types into the output file.  We create a reloc
 | 
      
        |                  section in dynobj and make room for this reloc.  */
 |                  section in dynobj and make room for this reloc.  */
 | 
      
        |               if (sreloc == NULL)
 |               if (sreloc == NULL)
 | 
      
        |                 {
 |                 {
 | 
      
        |                   const char *name;
 |                   sreloc = _bfd_elf_make_dynamic_reloc_section
 | 
      
        |  
 |                     (sec, htab->root.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 (CONST_STRNEQ (name, ".rela")
 |   | 
      
        |                               && strcmp (bfd_get_section_name (abfd, sec),
 |   | 
      
        |                                          name + 5) == 0);
 |   | 
      
        |  
 |  
 | 
      
        |                   sreloc = bfd_get_section_by_name (htab->root.dynobj, name);
 |   | 
      
        |                   if (sreloc == NULL)
 |                   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 (htab->root.dynobj,
 |   | 
      
        |                                                             name,
 |   | 
      
        |                                                             flags);
 |   | 
      
        |                       if (sreloc == NULL
 |   | 
      
        |                           || ! bfd_set_section_alignment (htab->root.dynobj,
 |   | 
      
        |                                                           sreloc, 2))
 |   | 
      
        |                         return FALSE;
 |                         return FALSE;
 | 
      
        |                     }
 |                     }
 | 
      
        |                   elf_section_data (sec)->sreloc = sreloc;
 |   | 
      
        |                 }
 |   | 
      
        |  
 |  
 | 
      
        |               /* If this is a global symbol, we count the number of
 |               /* If this is a global symbol, we count the number of
 | 
      
        |                  relocations we need for this symbol.  */
 |                  relocations we need for this symbol.  */
 | 
      
        |               if (h != NULL)
 |               if (h != NULL)
 | 
      
        |                 head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs;
 |                 head = &((struct elf_sh_link_hash_entry *) h)->dyn_relocs;
 | 
      
        |               else
 |               else
 | 
      
        |                 {
 |                 {
 | 
      
        |   |                   /* Track dynamic relocs needed for local syms too.  */
 | 
      
        |                   asection *s;
 |                   asection *s;
 | 
      
        |                   void *vpp;
 |                   void *vpp;
 | 
      
        |   |                   Elf_Internal_Sym *isym;
 | 
      
        |  
 |  
 | 
      
        |                   /* Track dynamic relocs needed for local syms too.  */
 |                   isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 | 
      
        |                   s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
 |                                                 abfd, r_symndx);
 | 
      
        |                                                  sec, r_symndx);
 |                   if (isym == NULL)
 | 
      
        |                   if (s == NULL)
 |   | 
      
        |                     return FALSE;
 |                     return FALSE;
 | 
      
        |  
 |  
 | 
      
        |   |                   s = bfd_section_from_elf_index (abfd, isym->st_shndx);
 | 
      
        |   |                   if (s == NULL)
 | 
      
        |   |                     s = sec;
 | 
      
        |   |  
 | 
      
        |                   vpp = &elf_section_data (s)->local_dynrel;
 |                   vpp = &elf_section_data (s)->local_dynrel;
 | 
      
        |                   head = (struct elf_sh_dyn_relocs **) vpp;
 |                   head = (struct elf_sh_dyn_relocs **) vpp;
 | 
      
        |                 }
 |                 }
 | 
      
        |  
 |  
 | 
      
        |               p = *head;
 |               p = *head;
 |