]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elflink.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / bfd / elflink.c
index 6cc636142c77e2aaae01362205080e54a080b370..1dfed2fdd1508bcf33cb82c7e25ed7f289f292bd 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2020 Free Software Foundation, Inc.
+   Copyright (C) 1995-2021 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -1006,7 +1006,7 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
 
 static void
 elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
-                   const Elf_Internal_Sym *isym, asection *sec,
+                   unsigned int st_other, asection *sec,
                    bfd_boolean definition, bfd_boolean dynamic)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -1014,12 +1014,12 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
   /* If st_other has a processor-specific meaning, specific
      code might be needed here.  */
   if (bed->elf_backend_merge_symbol_attribute)
-    (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
+    (*bed->elf_backend_merge_symbol_attribute) (h, st_other, definition,
                                                dynamic);
 
   if (!dynamic)
     {
-      unsigned symvis = ELF_ST_VISIBILITY (isym->st_other);
+      unsigned symvis = ELF_ST_VISIBILITY (st_other);
       unsigned hvis = ELF_ST_VISIBILITY (h->other);
 
       /* Keep the most constraining visibility.  Leave the remainder
@@ -1028,7 +1028,7 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
        h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1));
     }
   else if (definition
-          && ELF_ST_VISIBILITY (isym->st_other) != STV_DEFAULT
+          && ELF_ST_VISIBILITY (st_other) != STV_DEFAULT
           && (sec->flags & SEC_READONLY) == 0)
     h->protected_def = 1;
 }
@@ -1701,7 +1701,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* Merge st_other.  If the symbol already has a dynamic index,
         but visibility says it should not be visible, turn it into a
         local symbol.  */
-      elf_merge_st_other (abfd, h, sym, sec, newdef, newdyn);
+      elf_merge_st_other (abfd, h, sym->st_other, sec, newdef, newdyn);
       if (h->dynindx != -1)
        switch (ELF_ST_VISIBILITY (h->other))
          {
@@ -2028,6 +2028,10 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
       (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi);
 
+      /* If we first saw a reference to SHORTNAME with non-default
+        visibility, merge that visibility to the @@VER symbol.  */
+      elf_merge_st_other (abfd, ht, hi->other, sec, TRUE, dynamic);
+
       /* A reference to the SHORTNAME symbol from a dynamic library
         will be satisfied by the versioned symbol at runtime.  In
         effect, we have a reference to the versioned symbol.  */
@@ -2074,9 +2078,26 @@ _bfd_elf_add_default_symbol (bfd *abfd,
     return FALSE;
 
   if (skip)
-    return TRUE;
-
-  if (override)
+    {
+      if (!dynamic
+         && h->root.type == bfd_link_hash_defweak
+         && hi->root.type == bfd_link_hash_defined)
+       {
+         /* We are handling a weak sym@@ver and attempting to define
+            a weak sym@ver, but _bfd_elf_merge_symbol said to skip the
+            new weak sym@ver because there is already a strong sym@ver.
+            However, sym@ver and sym@@ver are really the same symbol.
+            The existing strong sym@ver ought to override sym@@ver.  */
+         h->root.type = bfd_link_hash_defined;
+         h->root.u.def.section = hi->root.u.def.section;
+         h->root.u.def.value = hi->root.u.def.value;
+         hi->root.type = bfd_link_hash_indirect;
+         hi->root.u.i.link = &h->root;
+       }
+      else
+       return TRUE;
+    }
+  else if (override)
     {
       /* Here SHORTNAME is a versioned name, so we don't expect to see
         the type of override we do in the case above unless it is
@@ -2087,6 +2108,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
          /* xgettext:c-format */
          (_("%pB: unexpected redefinition of indirect versioned symbol `%s'"),
           abfd, shortname);
+      return TRUE;
     }
   else
     {
@@ -2096,32 +2118,36 @@ _bfd_elf_add_default_symbol (bfd *abfd,
              bfd_ind_section_ptr, 0, name, FALSE, collect, &bh)))
        return FALSE;
       hi = (struct elf_link_hash_entry *) bh;
+    }
+
+  /* If there is a duplicate definition somewhere, then HI may not
+     point to an indirect symbol.  We will have reported an error
+     to the user in that case.  */
+  if (hi->root.type == bfd_link_hash_indirect)
+    {
+      (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
+      h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
+      hi->dynamic_def |= h->dynamic_def;
 
-      /* If there is a duplicate definition somewhere, then HI may not
-        point to an indirect symbol.  We will have reported an error
-        to the user in that case.  */
+      /* If we first saw a reference to @VER symbol with
+        non-default visibility, merge that visibility to the
+        @@VER symbol.  */
+      elf_merge_st_other (abfd, h, hi->other, sec, TRUE, dynamic);
 
-      if (hi->root.type == bfd_link_hash_indirect)
+      /* See if the new flags lead us to realize that the symbol
+        must be dynamic.  */
+      if (! *dynsym)
        {
-         (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
-         h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
-         hi->dynamic_def |= h->dynamic_def;
-
-         /* See if the new flags lead us to realize that the symbol
-            must be dynamic.  */
-         if (! *dynsym)
+         if (! dynamic)
            {
-             if (! dynamic)
-               {
-                 if (! bfd_link_executable (info)
-                     || hi->ref_dynamic)
-                   *dynsym = TRUE;
-               }
-             else
-               {
-                 if (hi->ref_regular)
-                   *dynsym = TRUE;
-               }
+             if (! bfd_link_executable (info)
+                 || hi->ref_dynamic)
+               *dynsym = TRUE;
+           }
+         else
+           {
+             if (hi->ref_regular)
+               *dynsym = TRUE;
            }
        }
     }
@@ -3779,6 +3805,11 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   _bfd_elf_strtab_finalize (dynstr);
   size = _bfd_elf_strtab_size (dynstr);
 
+  /* Allow the linker to examine the dynsymtab now it's fully populated.  */
+
+  if (info->callbacks->examine_strtab)
+    info->callbacks->examine_strtab (dynstr);
+
   bed = get_elf_backend_data (dynobj);
   sdyn = bfd_get_linker_section (dynobj, ".dynamic");
   BFD_ASSERT (sdyn != NULL);
@@ -5046,8 +5077,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          /* Check to see if we need to add an indirect symbol for
             the default name.  */
-         if (definition
-             || (!override && h->root.type == bfd_link_hash_common))
+         if ((definition
+              || (!override && h->root.type == bfd_link_hash_common))
+             && !(hi != h
+                  && hi->versioned == versioned_hidden))
            if (!_bfd_elf_add_default_symbol (abfd, info, h, name, isym,
                                              sec, value, &old_bfd, &dynsym))
              goto error_free_vers;
@@ -5168,7 +5201,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            }
 
          /* Merge st_other field.  */
-         elf_merge_st_other (abfd, h, isym, sec, definition, dynamic);
+         elf_merge_st_other (abfd, h, isym->st_other, sec,
+                             definition, dynamic);
 
          /* We don't want to make debug symbol dynamic.  */
          if (definition
@@ -7144,7 +7178,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              || !_bfd_elf_add_dynamic_entry (info, DT_SYMTAB, 0)
              || !_bfd_elf_add_dynamic_entry (info, DT_STRSZ, strsize)
              || !_bfd_elf_add_dynamic_entry (info, DT_SYMENT,
-                                             bed->s->sizeof_sym))
+                                             bed->s->sizeof_sym)
+             || (info->gnu_flags_1
+                 && !_bfd_elf_add_dynamic_entry (info, DT_GNU_FLAGS_1,
+                                                 info->gnu_flags_1)))
            return FALSE;
        }
     }
@@ -9853,6 +9890,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
        }
     }
 
+  /* Now swap out the symbols.  */
   for (i = 0; i < hash_table->strtabcount; i++)
     {
       struct elf_sym_strtab *elfsym = &hash_table->strtab[i];
@@ -9862,6 +9900,13 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
        elfsym->sym.st_name
          = (unsigned long) _bfd_elf_strtab_offset (flinfo->symstrtab,
                                                    elfsym->sym.st_name);
+
+      /* Inform the linker of the addition of this symbol.  */
+
+      if (flinfo->info->callbacks->ctf_new_symbol)
+       flinfo->info->callbacks->ctf_new_symbol (elfsym->dest_index,
+                                                &elfsym->sym);
+
       bed->s->swap_symbol_out (flinfo->output_bfd, &elfsym->sym,
                               ((bfd_byte *) symbuf
                                + (elfsym->dest_index
@@ -9870,14 +9915,6 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
                                + elfsym->destshndx_index));
     }
 
-  /* Allow the linker to examine the strtab and symtab now they are
-     populated.  */
-
-  if (flinfo->info->callbacks->examine_strtab)
-    flinfo->info->callbacks->examine_strtab (hash_table->strtab,
-                                            hash_table->strtabcount,
-                                            flinfo->symstrtab);
-
   hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr;
   pos = hdr->sh_offset + hdr->sh_size;
   amt = hash_table->strtabcount * bed->s->sizeof_sym;
@@ -10485,6 +10522,12 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          eoinfo->failed = TRUE;
          return FALSE;
        }
+
+      /* Inform the linker of the addition of this symbol.  */
+
+      if (flinfo->info->callbacks->ctf_new_dynsym)
+       flinfo->info->callbacks->ctf_new_dynsym (h->dynindx, &sym);
+
       bed->s->swap_symbol_out (flinfo->output_bfd, &sym, esym, 0);
 
       if (flinfo->hash_sec != NULL)
@@ -10687,10 +10730,21 @@ _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info)
     {
       if ((kept->flags & SEC_GROUP) != 0)
        kept = match_group_member (sec, kept, info);
-      if (kept != NULL
-         && ((sec->rawsize != 0 ? sec->rawsize : sec->size)
-             != (kept->rawsize != 0 ? kept->rawsize : kept->size)))
-       kept = NULL;
+      if (kept != NULL)
+       {
+         if ((sec->rawsize != 0 ? sec->rawsize : sec->size)
+             != (kept->rawsize != 0 ? kept->rawsize : kept->size))
+           kept = NULL;
+         else
+           {
+             /* Get the real kept section.  */
+             asection *next;
+             for (next = kept->kept_section;
+                  next != NULL;
+                  next = next->kept_section)
+               kept = next;
+           }
+       }
       sec->kept_section = kept;
     }
   return kept;
@@ -10752,7 +10806,9 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
       || bed->elf_osabi == ELFOSABI_GNU
       || bed->elf_osabi == ELFOSABI_FREEBSD)
     elf_tdata (output_bfd)->has_gnu_osabi
-      |= elf_tdata (input_bfd)->has_gnu_osabi;
+      |= (elf_tdata (input_bfd)->has_gnu_osabi
+         & (bfd_link_relocatable (flinfo->info)
+            ? -1 : ~elf_gnu_osabi_retain));
 
   /* Read the local symbols.  */
   isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
@@ -12761,6 +12817,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                }
              sym.st_value = s->vma;
              dest = dynsym + dynindx * bed->s->sizeof_sym;
+
+             /* Inform the linker of the addition of this symbol.  */
+
+             if (info->callbacks->ctf_new_dynsym)
+               info->callbacks->ctf_new_dynsym (dynindx, &sym);
+
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
        }
@@ -12799,6 +12861,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                                  + e->isym.st_value);
                }
 
+             /* Inform the linker of the addition of this symbol.  */
+
+             if (info->callbacks->ctf_new_dynsym)
+               info->callbacks->ctf_new_dynsym (e->dynindx, &sym);
+
              dest = dynsym + e->dynindx * bed->s->sizeof_sym;
              bed->s->swap_symbol_out (abfd, &sym, dest, 0);
            }
@@ -14293,7 +14360,7 @@ typedef struct
   flagword flag_value;
 } elf_flags_to_name_table;
 
-static elf_flags_to_name_table elf_flags_to_names [] =
+static const elf_flags_to_name_table elf_flags_to_names [] =
 {
   { "SHF_WRITE", SHF_WRITE },
   { "SHF_ALLOC", SHF_ALLOC },
@@ -14994,7 +15061,7 @@ _bfd_elf_copy_link_hash_symbol_type (bfd *abfd,
   ehdest->target_internal = ehsrc->target_internal;
 
   isym.st_other = ehsrc->other;
-  elf_merge_st_other (abfd, ehdest, &isym, NULL, TRUE, FALSE);
+  elf_merge_st_other (abfd, ehdest, isym.st_other, NULL, TRUE, FALSE);
 }
 
 /* Append a RELA relocation REL to section S in BFD.  */