2010-09-17 Tejas Belagod <tejas.belagod@arm.com>
[deliverable/binutils-gdb.git] / bfd / elflink.c
index c42c6e135bde963d5b332533d13c5b2298a2fc43..4351e28cfef2c6b10770b74790a2c3639c4165d8 100644 (file)
@@ -1,6 +1,6 @@
 /* ELF linking support for BFD.
    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009
+   2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -185,7 +185,7 @@ bfd_boolean
 _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags;
-  register asection *s;
+  asection *s;
   const struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (info->hash))
@@ -570,8 +570,7 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
   if (provide && hidden)
     {
-      const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-
+      bed = get_elf_backend_data (output_bfd);
       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
       (*bed->elf_backend_hide_symbol) (info, h, TRUE);
     }
@@ -1014,6 +1013,11 @@ _bfd_elf_merge_symbol (bfd *abfd,
       break;
     }
 
+  /* Differentiate strong and weak symbols.  */
+  newweak = bind == STB_WEAK;
+  oldweak = (h->root.type == bfd_link_hash_defweak
+            || h->root.type == bfd_link_hash_undefweak);
+
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
      confusion that results if we try to override a symbol with
@@ -1021,6 +1025,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
      _GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a
      dynamic object, which we do want to handle here.  */
   if (abfd == oldbfd
+      && (newweak || oldweak)
       && ((abfd->flags & DYNAMIC) == 0
          || !h->def_regular))
     return TRUE;
@@ -1184,9 +1189,8 @@ _bfd_elf_merge_symbol (bfd *abfd,
             was referenced before.  */
          if (h->ref_regular)
            {
-             const struct elf_backend_data *bed
-               = get_elf_backend_data (abfd);
              struct elf_link_hash_entry *vh = *sym_hash;
+
              vh->root.type = h->root.type;
              h->root.type = bfd_link_hash_indirect;
              (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
@@ -1243,11 +1247,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       return TRUE;
     }
 
-  /* Differentiate strong and weak symbols.  */
-  newweak = bind == STB_WEAK;
-  oldweak = (h->root.type == bfd_link_hash_defweak
-            || h->root.type == bfd_link_hash_undefweak);
-
   if (bind == STB_GNU_UNIQUE)
     h->unique_global = 1;
 
@@ -1548,7 +1547,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       /* Handle the case where we had a versioned symbol in a dynamic
         library and now find a definition in a normal object.  In this
         case, we make the versioned symbol point to the normal one.  */
-      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
       flip->root.type = h->root.type;
       flip->root.u.undef.abfd = h->root.u.undef.abfd;
       h->root.type = bfd_link_hash_indirect;
@@ -1718,7 +1716,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
        {
          if (! dynamic)
            {
-             if (info->shared
+             if (! info->executable
                  || hi->ref_dynamic)
                *dynsym = TRUE;
            }
@@ -1787,7 +1785,7 @@ nondefault:
            {
              if (! dynamic)
                {
-                 if (info->shared
+                 if (! info->executable
                      || hi->ref_dynamic)
                    *dynsym = TRUE;
                }
@@ -2772,7 +2770,7 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data)
 bfd_boolean
 _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
                           struct bfd_link_info *info,
-                          bfd_boolean ignore_protected)
+                          bfd_boolean not_local_protected)
 {
   bfd_boolean binding_stays_local_p;
   const struct elf_backend_data *bed;
@@ -2811,7 +2809,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
       /* Proper resolution for function pointer equality may require
         that these symbols perhaps be resolved dynamically, even though
         we should be resolving them to the current module.  */
-      if (!ignore_protected || !bed->is_function_type (h->type))
+      if (!not_local_protected || !bed->is_function_type (h->type))
        binding_stays_local_p = TRUE;
       break;
 
@@ -2820,7 +2818,7 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
     }
 
   /* If it isn't defined locally, then clearly it's dynamic.  */
-  if (!h->def_regular)
+  if (!h->def_regular && !ELF_COMMON_DEF_P (h))
     return TRUE;
 
   /* Otherwise, the symbol is dynamic if binding rules don't tell
@@ -2831,7 +2829,15 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
 /* Return true if the symbol referred to by H should be considered
    to resolve local to the current module, and false otherwise.  Differs
    from (the inverse of) _bfd_elf_dynamic_symbol_p in the treatment of
-   undefined symbols and weak symbols.  */
+   undefined symbols.  The two functions are virtually identical except
+   for the place where forced_local and dynindx == -1 are tested.  If
+   either of those tests are true, _bfd_elf_dynamic_symbol_p will say
+   the symbol is local, while _bfd_elf_symbol_refs_local_p will say
+   the symbol is local only for defined symbols.
+   It might seem that _bfd_elf_dynamic_symbol_p could be rewritten as
+   !_bfd_elf_symbol_refs_local_p, except that targets differ in their
+   treatment of undefined weak symbols.  For those that do not make
+   undefined weak symbols dynamic, both functions may return false.  */
 
 bfd_boolean
 _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
@@ -3234,6 +3240,8 @@ elf_finalize_dynstr (bfd *output_bfd, struct bfd_link_info *info)
        case DT_RUNPATH:
        case DT_FILTER:
        case DT_AUXILIARY:
+       case DT_AUDIT:
+       case DT_DEPAUDIT:
          dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val);
          break;
        default:
@@ -3525,6 +3533,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     {
       asection *s;
       const char *soname = NULL;
+      char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
       int ret;
 
@@ -3653,6 +3662,11 @@ error_free_dyn:
                    ;
                  *pn = n;
                }
+             if (dyn.d_tag == DT_AUDIT)
+               {
+                 unsigned int tagv = dyn.d_un.d_val;
+                 audit = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
+               }
            }
 
          free (dynbuf);
@@ -3705,6 +3719,9 @@ error_free_dyn:
         particular dynamic object more than once.  */
       if (ret > 0)
        return TRUE;
+
+      /* Save the DT_AUDIT entry for the linker emulation code. */
+      elf_dt_audit (abfd) = audit; 
     }
 
   /* If this is a dynamic object, we always link against the .dynsym
@@ -3866,6 +3883,7 @@ error_free_dyn:
       bfd_boolean common;
       unsigned int old_alignment;
       bfd *old_bfd;
+      bfd * undef_bfd = NULL;
 
       override = FALSE;
 
@@ -3990,6 +4008,20 @@ error_free_dyn:
          unsigned int vernum = 0;
          bfd_boolean skip;
 
+         /* If this is a definition of a symbol which was previously
+            referenced in a non-weak manner then make a note of the bfd
+            that contained the reference.  This is used if we need to
+            refer to the source of the reference later on.  */
+         if (! bfd_is_und_section (sec))
+           {
+             h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+
+             if (h != NULL
+                 && h->root.type == bfd_link_hash_undefined
+                 && h->root.u.undef.abfd)
+               undef_bfd = h->root.u.undef.abfd;
+           }
+         
          if (ever == NULL)
            {
              if (info->default_imported_symver)
@@ -4097,6 +4129,19 @@ error_free_dyn:
              name = newname;
            }
 
+         /* If necessary, make a second attempt to locate the bfd
+            containing an unresolved, non-weak reference to the
+            current symbol.  */
+         if (! bfd_is_und_section (sec) && undef_bfd == NULL)
+           {
+             h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE);
+
+             if (h != NULL
+                 && h->root.type == bfd_link_hash_undefined
+                 && h->root.u.undef.abfd)
+               undef_bfd = h->root.u.undef.abfd;
+           }
+
          if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec,
                                      &value, &old_alignment,
                                      sym_hash, &skip, &override,
@@ -4154,7 +4199,8 @@ error_free_dyn:
        h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
       *sym_hash = h;
-      h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
+      if (is_elf_hash_table (htab))
+       h->unique_global = (flags & BSF_GNU_UNIQUE) != 0;
 
       new_weakdef = FALSE;
       if (dynamic
@@ -4362,7 +4408,6 @@ error_free_dyn:
          if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable)
            {
              /* We don't want to make debug symbol dynamic.  */
-             (*bed->elf_backend_hide_symbol) (info, h, TRUE);
              dynsym = FALSE;
            }
 
@@ -4433,13 +4478,18 @@ error_free_dyn:
              /* A symbol from a library loaded via DT_NEEDED of some
                 other library is referenced by a regular object.
                 Add a DT_NEEDED entry for it.  Issue an error if
-                --no-add-needed is used.  */
-             if ((elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
+                --no-add-needed is used and the reference was not
+                a weak one.  */
+             if (undef_bfd != NULL
+                 && (elf_dyn_lib_class (abfd) & DYN_NO_NEEDED) != 0)
                {
                  (*_bfd_error_handler)
-                   (_("%s: invalid DSO for symbol `%s' definition"),
+                   (_("%B: undefined reference to symbol '%s'"),
+                    undef_bfd, name);
+                 (*_bfd_error_handler)
+                   (_("note: '%s' is defined in DSO %B so try adding it to the linker command line"),
                     abfd, name);
-                 bfd_set_error (bfd_error_bad_value);
+                 bfd_set_error (bfd_error_invalid_operation);
                  goto error_free_vers;
                }
 
@@ -4750,6 +4800,7 @@ error_free_dyn:
   if (! dynamic
       && is_elf_hash_table (htab)
       && bed->check_relocs != NULL
+      && elf_object_id (abfd) == elf_hash_table_id (htab)
       && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
     {
       asection *o;
@@ -5311,7 +5362,7 @@ static const size_t elf_buckets[] =
    Therefore the result is always a good payoff between few collisions
    (= short chain lengths) and table size.  */
 static size_t
-compute_bucket_count (struct bfd_link_info *info,
+compute_bucket_count (struct bfd_link_info *info ATTRIBUTE_UNUSED,
                      unsigned long int *hashcodes ATTRIBUTE_UNUSED,
                      unsigned long int nsyms,
                      int gnu_hash)
@@ -5333,6 +5384,7 @@ compute_bucket_count (struct bfd_link_info *info,
       const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
       unsigned long int *counts;
       bfd_size_type amt;
+      unsigned int no_improvement_count = 0;
 
       /* Possible optimization parameters: if we have NSYMS symbols we say
         that the hashing table must at least have NSYMS/4 and at most
@@ -5417,7 +5469,12 @@ compute_bucket_count (struct bfd_link_info *info,
            {
              best_chlen = max;
              best_size = i;
+              no_improvement_count = 0;
            }
+         /* PR 11843: Avoid futile long searches for the best bucket size
+            when there are a large number of symbols.  */
+         else if (++no_improvement_count == 100)
+           break;
        }
 
       free (counts);
@@ -5441,6 +5498,20 @@ compute_bucket_count (struct bfd_link_info *info,
   return best_size;
 }
 
+/* Size any SHT_GROUP section for ld -r.  */
+
+bfd_boolean
+_bfd_elf_size_group_sections (struct bfd_link_info *info)
+{
+  bfd *ibfd;
+
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+       && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
+      return FALSE;
+  return TRUE;
+}
+
 /* Set up the sizes and contents of the ELF dynamic sections.  This is
    called by the ELF linker emulation before_allocation routine.  We
    must set the sizes of the sections before the linker sets the
@@ -5451,6 +5522,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                               const char *soname,
                               const char *rpath,
                               const char *filter_shlib,
+                              const char *audit,
+                              const char *depaudit,
                               const char * const *auxiliary_filters,
                               struct bfd_link_info *info,
                               asection **sinterpptr,
@@ -5513,6 +5586,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   elf_hash_table (info)->init_plt_refcount
     = elf_hash_table (info)->init_plt_offset;
 
+  if (info->relocatable
+      && !_bfd_elf_size_group_sections (info))
+    return FALSE;
+
   /* The backend may have to create some sections regardless of whether
      we're dynamic or not.  */
   if (bed->elf_backend_always_size_sections
@@ -5603,6 +5680,28 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            }
        }
 
+      if (audit != NULL)
+       {
+         bfd_size_type indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, audit,
+                                     TRUE);
+         if (indx == (bfd_size_type) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_AUDIT, indx))
+           return FALSE;
+       }
+
+      if (depaudit != NULL)
+       {
+         bfd_size_type indx;
+
+         indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, depaudit,
+                                     TRUE);
+         if (indx == (bfd_size_type) -1
+             || !_bfd_elf_add_dynamic_entry (info, DT_DEPAUDIT, indx))
+           return FALSE;
+       }
+
       eif.info = info;
       eif.verdefs = verdefs;
       eif.failed = FALSE;
@@ -5864,6 +5963,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            {
              struct bfd_elf_version_deps *n;
 
+             /* Don't emit base version twice.  */
+             if (t->vernum == 0)
+               continue;
+
              size += sizeof (Elf_External_Verdef);
              size += sizeof (Elf_External_Verdaux);
              ++cdefs;
@@ -5963,6 +6066,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              unsigned int cdeps;
              struct bfd_elf_version_deps *n;
 
+             /* Don't emit the base version twice.  */
+             if (t->vernum == 0)
+               continue;
+
              cdeps = 0;
              for (n = t->deps; n != NULL; n = n->next)
                ++cdeps;
@@ -5994,7 +6101,13 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              def.vd_hash = bfd_elf_hash (t->name);
              def.vd_aux = sizeof (Elf_External_Verdef);
              def.vd_next = 0;
-             if (t->next != NULL)
+
+             /* If a basever node is next, it *must* be the last node in
+                the chain, otherwise Verdef construction breaks.  */
+             if (t->next != NULL && t->next->vernum == 0)
+               BFD_ASSERT (t->next->next == NULL);
+
+             if (t->next != NULL && t->next->vernum != 0)
                def.vd_next = (sizeof (Elf_External_Verdef)
                               + (cdeps + 1) * sizeof (Elf_External_Verdaux));
 
@@ -6095,7 +6208,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            unsigned int crefs;
            bfd_byte *p;
 
-           /* Build the version definition section.  */
+           /* Build the version dependency section.  */
            size = 0;
            crefs = 0;
            for (t = elf_tdata (output_bfd)->verref;
@@ -6718,7 +6831,8 @@ _bfd_elf_link_hash_table_init
    struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
                                      struct bfd_hash_table *,
                                      const char *),
-   unsigned int entsize)
+   unsigned int entsize,
+   enum elf_target_id target_id)
 {
   bfd_boolean ret;
   int can_refcount = get_elf_backend_data (abfd)->can_refcount;
@@ -6732,7 +6846,9 @@ _bfd_elf_link_hash_table_init
   table->dynsymcount = 1;
 
   ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
+
   table->root.type = bfd_link_elf_hash_table;
+  table->hash_table_id = target_id;
 
   return ret;
 }
@@ -6750,7 +6866,8 @@ _bfd_elf_link_hash_table_create (bfd *abfd)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
-                                      sizeof (struct elf_link_hash_entry)))
+                                      sizeof (struct elf_link_hash_entry),
+                                      GENERIC_ELF_DATA))
     {
       free (ret);
       return NULL;
@@ -8443,10 +8560,14 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
 
          _bfd_elf_swap_versym_in (input, ever, &iver);
 
-         if ((iver.vs_vers & VERSYM_HIDDEN) == 0)
+         if ((iver.vs_vers & VERSYM_HIDDEN) == 0
+             && !(h->def_regular
+                  && h->forced_local))
            {
              /* If we have a non-hidden versioned sym, then it should
-                have provided a definition for the undefined sym.  */
+                have provided a definition for the undefined sym unless
+                it is defined in a non-shared object and forced local.
+              */
              abort ();
            }
 
@@ -8511,7 +8632,9 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
     {
       /* If we have an undefined symbol reference here then it must have
         come from a shared library that is being linked in.  (Undefined
-        references in regular files have already been handled).  */
+        references in regular files have already been handled unless
+        they are in unreferenced sections which are removed by garbage
+        collection).  */
       bfd_boolean ignore_undef = FALSE;
 
       /* Some symbols may be special in that the fact that they're
@@ -8520,14 +8643,15 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
        ignore_undef = bed->elf_backend_ignore_undef_symbol (h);
 
       /* If we are reporting errors for this situation then do so now.  */
-      if (ignore_undef == FALSE
+      if (!ignore_undef
          && h->ref_dynamic
-         && ! h->ref_regular
+         && (!h->ref_regular || finfo->info->gc_sections)
          && ! elf_link_check_versioned_symbol (finfo->info, bed, h)
          && finfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
        {
          if (! (finfo->info->callbacks->undefined_symbol
-                (finfo->info, h->root.root.string, h->root.u.undef.abfd,
+                (finfo->info, h->root.root.string,
+                 h->ref_regular ? NULL : h->root.u.undef.abfd,
                  NULL, 0, finfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR)))
            {
              eoinfo->failed = TRUE;
@@ -8587,9 +8711,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
     strip = FALSE;
 
   /* If we're stripping it, and it's not a dynamic symbol, there's
-     nothing else to do unless it is a forced local symbol.  */
+     nothing else to do unless it is a forced local symbol or a
+     STT_GNU_IFUNC symbol.  */
   if (strip
       && h->dynindx == -1
+      && h->type != STT_GNU_IFUNC
       && !h->forced_local)
     return TRUE;
 
@@ -8597,7 +8723,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   sym.st_size = h->size;
   sym.st_other = h->other;
   if (h->forced_local)
-    sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+    {
+      sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
+      /* Turn off visibility on local symbol.  */
+      sym.st_other &= ~ELF_ST_VISIBILITY (-1);
+    }
   else if (h->unique_global)
     sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
   else if (h->root.type == bfd_link_hash_undefweak
@@ -9713,7 +9843,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          {
            /* FIXME: octets_per_byte.  */
            if (! (o->flags & SEC_EXCLUDE)
-               && ! (o->output_section->flags & SEC_NEVER_LOAD)
                && ! bfd_set_section_contents (output_bfd, o->output_section,
                                               contents,
                                               (file_ptr) o->output_offset,
@@ -10053,9 +10182,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   bfd_boolean emit_relocs;
   bfd *dynobj;
   struct elf_final_link_info finfo;
-  register asection *o;
-  register struct bfd_link_order *p;
-  register bfd *sub;
+  asection *o;
+  struct bfd_link_order *p;
+  bfd *sub;
   bfd_size_type max_contents_size;
   bfd_size_type max_external_reloc_size;
   bfd_size_type max_internal_reloc_count;
@@ -10230,7 +10359,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                    {
                      size_t ext_size;
 
-                     ext_size = elf_section_data (sec)->rel_hdr.sh_size;
+                     ext_size = esdi->rel_hdr.sh_size;
+                     if (esdi->rel_hdr2 != NULL)
+                       ext_size += esdi->rel_hdr2->sh_size;
+
                      if (ext_size > max_external_reloc_size)
                        max_external_reloc_size = ext_size;
                      if (sec->reloc_count > max_internal_reloc_count)
@@ -10504,9 +10636,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          if (size == 0
              && (sec->flags & SEC_HAS_CONTENTS) == 0)
            {
-             struct bfd_link_order *o = sec->map_tail.link_order;
-             if (o != NULL)
-               size = o->offset + o->size;
+             struct bfd_link_order *ord = sec->map_tail.link_order;
+
+             if (ord != NULL)
+               size = ord->offset + ord->size;
            }
          end = sec->vma + size;
        }
@@ -10669,13 +10802,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              asection *s;
              bfd_byte *dest;
 
-             sym.st_size = e->isym.st_size;
-             sym.st_other = e->isym.st_other;
-
-             /* Copy the internal symbol as is.
+             /* Copy the internal symbol and turn off visibility.
                 Note that we saved a word of storage and overwrote
                 the original st_name with the dynstr_index.  */
              sym = e->isym;
+             sym.st_other &= ~ELF_ST_VISIBILITY (-1);
 
              s = bfd_section_from_elf_index (e->input_bfd,
                                              e->isym.st_shndx);
@@ -11277,6 +11408,8 @@ _bfd_elf_gc_mark_hook (asection *sec,
                       struct elf_link_hash_entry *h,
                       Elf_Internal_Sym *sym)
 {
+  const char *sec_name;
+
   if (h != NULL)
     {
       switch (h->root.type)
@@ -11288,6 +11421,33 @@ _bfd_elf_gc_mark_hook (asection *sec,
        case bfd_link_hash_common:
          return h->root.u.c.p->section;
 
+       case bfd_link_hash_undefined:
+       case bfd_link_hash_undefweak:
+         /* To work around a glibc bug, keep all XXX input sections
+            when there is an as yet undefined reference to __start_XXX
+            or __stop_XXX symbols.  The linker will later define such
+            symbols for orphan input sections that have a name
+            representable as a C identifier.  */
+         if (strncmp (h->root.root.string, "__start_", 8) == 0)
+           sec_name = h->root.root.string + 8;
+         else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+           sec_name = h->root.root.string + 7;
+         else
+           sec_name = NULL;
+
+         if (sec_name && *sec_name != '\0')
+           {
+             bfd *i;
+             
+             for (i = info->input_bfds; i; i = i->link_next)
+               {
+                 sec = bfd_get_section_by_name (i, sec_name);
+                 if (sec)
+                   sec->flags |= SEC_KEEP;
+               }
+           }
+         break;
+
        default:
          break;
        }
@@ -11473,9 +11633,10 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
              o->gc_mark = first->gc_mark;
            }
          else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0
-                  || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
+                  || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0
+                  || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE)
            {
-             /* Keep debug and special sections.  */
+             /* Keep debug, special and SHT_NOTE sections.  */
              o->gc_mark = 1;
            }
 
@@ -12495,7 +12656,7 @@ _bfd_elf_get_dynamic_reloc_section (bfd *       abfd,
    section does not exist it is created and attached to the DYNOBJ
    bfd and stored in the SRELOC field of SEC's elf_section_data
    structure.
-   
+
    ALIGNMENT is the alignment for the newly created section and
    IS_RELA defines whether the name should be .rela.<SEC's name>
    or .rel.<SEC's name>.  The section name is looked up in the
@@ -12540,3 +12701,15 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
 
   return reloc_sec;
 }
+
+/* Copy the ELF symbol type associated with a linker hash entry.  */
+void
+_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
+    struct bfd_link_hash_entry * hdest,
+    struct bfd_link_hash_entry * hsrc)
+{
+  struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest;
+  struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc;
+
+  ehdest->type = ehsrc->type;
+}
This page took 0.036138 seconds and 4 git commands to generate.