bfd/
[deliverable/binutils-gdb.git] / bfd / elf32-sh.c
index 8041f5e4c02ba96899ab7479fded9b1bdedffbbd..5306a2534f64583142d24ee195ad762afda81d9b 100644 (file)
@@ -2034,7 +2034,7 @@ sh_elf_relax_section (abfd, sec, link_info, again)
 
   *again = FALSE;
 
-  if (link_info->relocateable
+  if (link_info->relocatable
       || (sec->flags & SEC_RELOC) == 0
       || sec->reloc_count == 0)
     return TRUE;
@@ -3754,6 +3754,8 @@ sh_elf_create_dynamic_sections (abfd, info)
     }
 
   htab = sh_elf_hash_table (info);
+  if (htab->root.dynamic_sections_created)
+    return TRUE;
 
   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
      .rel[a].bss sections.  */
@@ -3805,7 +3807,8 @@ sh_elf_create_dynamic_sections (abfd, info)
       || ! bfd_set_section_alignment (abfd, s, ptralign))
     return FALSE;
 
-  if (! create_got_section (abfd, info))
+  if (htab->sgot == NULL
+      && !create_got_section (abfd, info))
     return FALSE;
 
   {
@@ -3824,6 +3827,8 @@ sh_elf_create_dynamic_sections (abfd, info)
        relname = (char *) bfd_malloc ((bfd_size_type) strlen (secname) + 6);
        strcpy (relname, ".rela");
        strcat (relname, secname);
+       if (bfd_get_section_by_name (abfd, secname))
+         continue;
        s = bfd_make_section (abfd, relname);
        if (s == NULL
            || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
@@ -3887,14 +3892,13 @@ sh_elf_adjust_dynamic_symbol (info, h)
   struct elf_sh_link_hash_table *htab;
   struct elf_sh_link_hash_entry *eh;
   struct elf_sh_dyn_relocs *p;
-  bfd *dynobj;
   asection *s;
   unsigned int power_of_two;
 
-  dynobj = elf_hash_table (info)->dynobj;
+  htab = sh_elf_hash_table (info);
 
   /* Make sure we know what is going on here.  */
-  BFD_ASSERT (dynobj != NULL
+  BFD_ASSERT (htab->root.dynobj != NULL
              && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
                  || h->weakdef != NULL
                  || ((h->elf_link_hash_flags
@@ -3940,6 +3944,10 @@ sh_elf_adjust_dynamic_symbol (info, h)
                  || h->weakdef->root.type == bfd_link_hash_defweak);
       h->root.u.def.section = h->weakdef->root.u.def.section;
       h->root.u.def.value = h->weakdef->root.u.def.value;
+      if (info->nocopyreloc)
+       h->elf_link_hash_flags
+         = ((h->elf_link_hash_flags & ~ELF_LINK_NON_GOT_REF)
+            | (h->weakdef->elf_link_hash_flags & ELF_LINK_NON_GOT_REF));
       return TRUE;
     }
 
@@ -3992,7 +4000,6 @@ sh_elf_adjust_dynamic_symbol (info, h)
      both the dynamic object and the regular object will refer to the
      same memory location for the variable.  */
 
-  htab = sh_elf_hash_table (info);
   s = htab->sdynbss;
   BFD_ASSERT (s != NULL);
 
@@ -4018,9 +4025,9 @@ sh_elf_adjust_dynamic_symbol (info, h)
 
   /* Apply the required alignment.  */
   s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two));
-  if (power_of_two > bfd_get_section_alignment (dynobj, s))
+  if (power_of_two > bfd_get_section_alignment (htab->root.dynobj, s))
     {
-      if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+      if (! bfd_set_section_alignment (htab->root.dynobj, s, power_of_two))
        return FALSE;
     }
 
@@ -4083,7 +4090,9 @@ allocate_dynrelocs (h, inf)
     }
 
   if (htab->root.dynamic_sections_created
-      && h->plt.refcount > 0)
+      && h->plt.refcount > 0
+      && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+         || h->root.type != bfd_link_hash_undefweak))
     {
       /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
@@ -4169,8 +4178,10 @@ allocate_dynrelocs (h, inf)
        htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
       else if (tls_type == GOT_TLS_GD)
        htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rela);
-      else if (info->shared ||
-              WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+               || h->root.type != bfd_link_hash_undefweak)
+              && (info->shared
+                  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->srelgot->_raw_size += sizeof (Elf32_External_Rela);
     }
   else
@@ -4229,6 +4240,12 @@ allocate_dynrelocs (h, inf)
                pp = &p->next;
            }
        }
+
+      /* Also discard relocs on undefined weak syms with non-default
+        visibility.  */
+      if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+         && h->root.type == bfd_link_hash_undefweak)
+       eh->dyn_relocs = NULL;
     }
   else
     {
@@ -4324,7 +4341,7 @@ sh_elf_size_dynamic_sections (output_bfd, info)
   if (htab->root.dynamic_sections_created)
     {
       /* Set the contents of the .interp section to the interpreter.  */
-      if (! info->shared)
+      if (info->executable)
        {
          s = bfd_get_section_by_name (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
@@ -4486,7 +4503,7 @@ sh_elf_size_dynamic_sections (output_bfd, info)
 #define add_dynamic_entry(TAG, VAL) \
   bfd_elf32_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
 
-      if (! info->shared)
+      if (info->executable)
        {
          if (! add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
@@ -4636,9 +4653,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
             (info,
              _("Unexpected STO_SH5_ISA32 on local symbol is not handled"),
              input_bfd, input_section, rel->r_offset));
-         if (info->relocateable)
+         if (info->relocatable)
            {
-             /* This is a relocateable link.  We don't have to change
+             /* 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.  */
@@ -4707,8 +4724,8 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          /* Section symbol are never (?) placed in the hash table, so
             we can just ignore hash relocations when creating a
-            relocateable object file.  */
-         if (info->relocateable)
+            relocatable object file.  */
+         if (info->relocatable)
            continue;
 
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
@@ -4885,6 +4902,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_SH_DIR32:
        case R_SH_REL32:
          if (info->shared
+             && (h == NULL
+                 || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                 || h->root.type != bfd_link_hash_undefweak)
              && r_symndx != 0
              && (input_section->flags & SEC_ALLOC) != 0
              && (r_type != R_SH_REL32
@@ -5053,7 +5073,9 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
                  || (info->shared
                      && (info->symbolic || h->dynindx == -1
                          || (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
-                     && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+                     && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+                 || (ELF_ST_VISIBILITY (h->other)
+                     && h->root.type == bfd_link_hash_undefweak))
                {
                  /* This is actually a static link, or it is a
                     -Bsymbolic link and the symbol is defined
@@ -5699,12 +5721,12 @@ sh_elf_relocate_section (output_bfd, info, input_bfd, input_section,
 
 static bfd_byte *
 sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
-                                      data, relocateable, symbols)
+                                      data, relocatable, symbols)
      bfd *output_bfd;
      struct bfd_link_info *link_info;
      struct bfd_link_order *link_order;
      bfd_byte *data;
-     bfd_boolean relocateable;
+     bfd_boolean relocatable;
      asymbol **symbols;
 {
   Elf_Internal_Shdr *symtab_hdr;
@@ -5716,11 +5738,11 @@ sh_elf_get_relocated_section_contents (output_bfd, link_info, link_order,
 
   /* We only need to handle the case of relaxing, or of having a
      particular set of section contents, specially.  */
-  if (relocateable
+  if (relocatable
       || elf_section_data (input_section)->this_hdr.contents == NULL)
     return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
                                                       link_order, data,
-                                                      relocateable,
+                                                      relocatable,
                                                       symbols);
 
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
@@ -6128,7 +6150,17 @@ sh_elf_copy_indirect_symbol (bed, dir, ind)
       eind->tls_type = GOT_UNKNOWN;
     }
 
-  _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
+  if (ind->root.type != bfd_link_hash_indirect
+      && (dir->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+    /* If called to transfer flags for a weakdef during processing
+       of elf_adjust_dynamic_symbol, don't copy ELF_LINK_NON_GOT_REF.
+       We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
+    dir->elf_link_hash_flags |=
+      (ind->elf_link_hash_flags & (ELF_LINK_HASH_REF_DYNAMIC
+                                  | ELF_LINK_HASH_REF_REGULAR
+                                  | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+  else
+    _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
 
 static int
@@ -6170,7 +6202,6 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
   struct elf_sh_link_hash_table *htab;
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
-  bfd *dynobj;
   bfd_vma *local_got_offsets;
   asection *sgot;
   asection *srelgot;
@@ -6182,7 +6213,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
   srelgot = NULL;
   sreloc = NULL;
 
-  if (info->relocateable)
+  if (info->relocatable)
     return TRUE;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -6192,7 +6223,6 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
     sym_hashes_end -= symtab_hdr->sh_info;
 
   htab = sh_elf_hash_table (info);
-  dynobj = htab->root.dynobj;
   local_got_offsets = elf_local_got_offsets (abfd);
 
   rel_end = relocs + sec->reloc_count;
@@ -6266,10 +6296,13 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
            case R_SH_TLS_GD_32:
            case R_SH_TLS_LD_32:
            case R_SH_TLS_IE_32:
-             if (dynobj == NULL)
-               htab->root.dynobj = dynobj = abfd;
-             if (! create_got_section (dynobj, info))
-               return FALSE;
+             if (htab->sgot == NULL)
+               {
+                 if (htab->root.dynobj == NULL)
+                   htab->root.dynobj = abfd;
+                 if (!create_got_section (htab->root.dynobj, info))
+                   return FALSE;
+               }
              break;
 
            default:
@@ -6506,8 +6539,8 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
              struct elf_sh_dyn_relocs *p;
              struct elf_sh_dyn_relocs **head;
 
-             if (dynobj == NULL)
-               htab->root.dynobj = dynobj = abfd;
+             if (htab->root.dynobj == NULL)
+               htab->root.dynobj = abfd;
 
              /* When creating a shared object, we must copy these
                 reloc types into the output file.  We create a reloc
@@ -6527,19 +6560,21 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
                              && strcmp (bfd_get_section_name (abfd, sec),
                                         name + 5) == 0);
 
-                 sreloc = bfd_get_section_by_name (dynobj, name);
+                 sreloc = bfd_get_section_by_name (htab->root.dynobj, name);
                  if (sreloc == NULL)
                    {
                      flagword flags;
 
-                     sreloc = bfd_make_section (dynobj, name);
+                     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;
                      if (sreloc == NULL
-                         || ! bfd_set_section_flags (dynobj, sreloc, flags)
-                         || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+                         || ! bfd_set_section_flags (htab->root.dynobj,
+                                                     sreloc, flags)
+                         || ! bfd_set_section_alignment (htab->root.dynobj,
+                                                         sreloc, 2))
                        return FALSE;
                    }
                  if (sec->flags & SEC_READONLY)
@@ -6569,7 +6604,7 @@ sh_elf_check_relocs (abfd, info, sec, relocs)
              if (p == NULL || p->sec != sec)
                {
                  bfd_size_type amt = sizeof (*p);
-                 p = ((struct elf_sh_dyn_relocs *) bfd_alloc (dynobj, amt));
+                 p = bfd_alloc (htab->root.dynobj, amt);
                  if (p == NULL)
                    return FALSE;
                  p->next = *head;
@@ -6759,10 +6794,8 @@ sh_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
      Elf_Internal_Sym *sym;
 {
   struct elf_sh_link_hash_table *htab;
-  bfd *dynobj;
 
   htab = sh_elf_hash_table (info);
-  dynobj = htab->root.dynobj;
 
   if (h->plt.offset != (bfd_vma) -1)
     {
@@ -7047,15 +7080,12 @@ sh_elf_finish_dynamic_sections (output_bfd, info)
      struct bfd_link_info *info;
 {
   struct elf_sh_link_hash_table *htab;
-  bfd *dynobj;
   asection *sgot;
   asection *sdyn;
 
   htab = sh_elf_hash_table (info);
-  dynobj = htab->root.dynobj;
-
   sgot = htab->sgotplt;
-  sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+  sdyn = bfd_get_section_by_name (htab->root.dynobj, ".dynamic");
 
   if (htab->root.dynamic_sections_created)
     {
@@ -7074,7 +7104,7 @@ sh_elf_finish_dynamic_sections (output_bfd, info)
          const char *name;
 #endif
 
-         bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+         bfd_elf32_swap_dyn_in (htab->root.dynobj, dyncon, &dyn);
 
          switch (dyn.d_tag)
            {
This page took 0.028211 seconds and 4 git commands to generate.