Fix excessive memory allocation attempts and possible integer overfloaws when attempt...
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 1a83b88be08018835508930a3a66c523ed398db4..122549c594b1034553383200abe225f1146cf95d 100644 (file)
@@ -218,9 +218,13 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info)
       if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0)
        {
          bfd *ibfd;
+         asection *s;
          for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next)
            if ((ibfd->flags
-                & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0)
+                & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0
+               && bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+               && !((s = ibfd->sections) != NULL
+                    && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS))
              {
                abfd = ibfd;
                break;
@@ -1032,6 +1036,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   bfd_boolean newweak, oldweak, newfunc, oldfunc;
   const struct elf_backend_data *bed;
   char *new_version;
+  bfd_boolean default_sym = *matched;
 
   *skip = FALSE;
   *override = FALSE;
@@ -1157,11 +1162,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (pold_weak)
     *pold_weak = oldweak;
 
-  /* This code is for coping with dynamic objects, and is only useful
-     if we are doing an ELF link.  */
-  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    return TRUE;
-
   /* We have to check it for every instance since the first few may be
      references and not all compilers emit symbol type for undefined
      symbols.  */
@@ -1230,6 +1230,16 @@ _bfd_elf_merge_symbol (bfd *abfd,
       olddyn = (oldsec->symbol->flags & BSF_DYNAMIC) != 0;
     }
 
+  /* Handle a case where plugin_notice won't be called and thus won't
+     set the non_ir_ref flags on the first pass over symbols.  */
+  if (oldbfd != NULL
+      && (oldbfd->flags & BFD_PLUGIN) != (abfd->flags & BFD_PLUGIN)
+      && newdyn != olddyn)
+    {
+      h->root.non_ir_ref_dynamic = TRUE;
+      hi->root.non_ir_ref_dynamic = TRUE;
+    }
+
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
      respectively, appear to be a definition rather than reference.  */
 
@@ -1543,6 +1553,18 @@ _bfd_elf_merge_symbol (bfd *abfd,
       sec = *psec;
     }
 
+  /* There are multiple definitions of a normal symbol.
+     Skip the default symbol as well.  */
+  if (olddef && !olddyn && !oldweak && newdef && !newdyn && !newweak
+      && !default_sym && h->def_regular)
+    {
+      /* Handle a multiple definition.  */
+      (*info->callbacks->multiple_definition) (info, &h->root,
+                                              abfd, sec, *pvalue);
+      *skip = TRUE;
+      return TRUE;
+    }
+
   /* If both the old and the new symbols look like common symbols in a
      dynamic object, set the size of the symbol to the larger of the
      two.  */
@@ -2390,9 +2412,9 @@ elf_link_read_relocs_from_section (bfd *abfd,
            {
              _bfd_error_handler
                /* xgettext:c-format */
-               (_("%B: bad reloc symbol index (0x%lx >= 0x%lx)"
-                  " for offset 0x%lx in section `%A'"),
-                abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+               (_("%B: bad reloc symbol index (%#Lx >= %#lx)"
+                  " for offset %#Lx in section `%A'"),
+                abfd, r_symndx, (unsigned long) nsyms,
                 irela->r_offset, sec);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
@@ -2402,10 +2424,10 @@ elf_link_read_relocs_from_section (bfd *abfd,
        {
          _bfd_error_handler
            /* xgettext:c-format */
-           (_("%B: non-zero symbol index (0x%lx)"
-              " for offset 0x%lx in section `%A'"
+           (_("%B: non-zero symbol index (%#Lx)"
+              " for offset %#Lx in section `%A'"
               " when the object file has no symbol table"),
-            abfd, (unsigned long) r_symndx, (unsigned long) nsyms,
+            abfd, r_symndx,
             irela->r_offset, sec);
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
@@ -2794,7 +2816,7 @@ static bfd_boolean
 _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
 {
   struct elf_info_failed *eif = (struct elf_info_failed *) data;
-  bfd *dynobj;
+  struct elf_link_hash_table *htab;
   const struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (eif->info->hash))
@@ -2808,10 +2830,13 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (! _bfd_elf_fix_symbol_flags (h, eif))
     return FALSE;
 
+  htab = elf_hash_table (eif->info);
+  bed = get_elf_backend_data (htab->dynobj);
+
   if (h->root.type == bfd_link_hash_undefweak)
     {
       if (eif->info->dynamic_undefined_weak == 0)
-       _bfd_elf_link_hash_hide_symbol (eif->info, h, TRUE);
+       (*bed->elf_backend_hide_symbol) (eif->info, h, TRUE);
       else if (eif->info->dynamic_undefined_weak > 0
               && h->ref_regular
               && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -2907,9 +2932,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
       (_("warning: type and size of dynamic symbol `%s' are not defined"),
        h->root.root.string);
 
-  dynobj = elf_hash_table (eif->info)->dynobj;
-  bed = get_elf_backend_data (dynobj);
-
   if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
     {
       eif->failed = TRUE;
@@ -2931,7 +2953,7 @@ _bfd_elf_adjust_dynamic_copy (struct bfd_link_info *info,
   bfd_vma mask;
   asection *sec = h->root.u.def.section;
 
-  /* The section aligment of definition is the maximum alignment
+  /* The section alignment of the definition is the maximum alignment
      requirement of symbols defined in the section.  Since we don't
      know the symbol alignment requirement, we start with the
      maximum alignment and check low bits of the symbol address
@@ -4250,6 +4272,12 @@ error_free_dyn:
       sec = NULL;
       value = isym->st_value;
       common = bed->common_definition (isym);
+      if (common && info->inhibit_common_definition)
+       {
+         /* Treat common symbol as undefined for --no-define-common.  */
+         isym->st_shndx = SHN_UNDEF;
+         common = FALSE;
+       }
       discarded = FALSE;
 
       bind = ELF_ST_BIND (isym->st_info);
@@ -4748,9 +4776,8 @@ error_free_dyn:
                _bfd_error_handler
                  /* xgettext:c-format */
                  (_("Warning: size of symbol `%s' changed"
-                    " from %lu in %B to %lu in %B"),
-                  name, (unsigned long) h->size, old_bfd,
-                  (unsigned long) isym->st_size, abfd);
+                    " from %Lu in %B to %Lu in %B"),
+                  name, h->size, old_bfd, isym->st_size, abfd);
 
              h->size = isym->st_size;
            }
@@ -5215,10 +5242,6 @@ error_free_dyn:
       && !(*bed->check_directives) (abfd, info))
     return FALSE;
 
-  if (!info->check_relocs_after_open_input
-      && !_bfd_elf_link_check_relocs (abfd, info))
-    return FALSE;
-
   /* If this is a non-traditional link, try to optimize the handling
      of the .stab/.stabstr sections.  */
   if (! dynamic
@@ -5861,9 +5884,12 @@ bfd_boolean
 _bfd_elf_size_group_sections (struct bfd_link_info *info)
 {
   bfd *ibfd;
+  asection *s;
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+       && (s = ibfd->sections) != NULL
+       && s->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
        && !_bfd_elf_fixup_group_sections (ibfd, bfd_abs_section_ptr))
       return FALSE;
   return TRUE;
@@ -5994,19 +6020,18 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       struct elf_info_failed asvinfo;
       struct bfd_elf_version_tree *t;
       struct bfd_elf_version_expr *d;
-      struct elf_info_failed eif;
-      bfd_boolean all_defined;
       asection *s;
       size_t soname_indx;
 
-      eif.info = info;
-      eif.failed = FALSE;
-
       /* If we are supposed to export all symbols into the dynamic symbol
         table (this is not the normal case), then do so.  */
       if (info->export_dynamic
          || (bfd_link_executable (info) && info->dynamic))
        {
+         struct elf_info_failed eif;
+
+         eif.info = info;
+         eif.failed = FALSE;
          elf_link_hash_traverse (elf_hash_table (info),
                                  _bfd_elf_export_symbol,
                                  &eif);
@@ -6090,7 +6115,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if (!info->allow_undefined_version)
        {
          /* Check if all global versions have a definition.  */
-         all_defined = TRUE;
+         bfd_boolean all_defined = TRUE;
          for (t = info->version_info; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
              if (d->literal && !d->symver && !d->script)
@@ -6343,134 +6368,128 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
          elf_tdata (output_bfd)->cverdefs = cdefs;
        }
+    }
+
+  bed = get_elf_backend_data (output_bfd);
+
+  if (info->gc_sections && bed->can_gc_sections)
+    {
+      struct elf_gc_sweep_symbol_info sweep_info;
+
+      /* Remove the symbols that were in the swept sections from the
+        dynamic symbol table.  */
+      sweep_info.info = info;
+      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
+      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
+                             &sweep_info);
+    }
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+    {
+      asection *s;
+      struct elf_find_verdep_info sinfo;
 
       /* Work out the size of the version reference section.  */
 
       s = bfd_get_linker_section (dynobj, ".gnu.version_r");
       BFD_ASSERT (s != NULL);
-      {
-       struct elf_find_verdep_info sinfo;
 
-       sinfo.info = info;
-       sinfo.vers = elf_tdata (output_bfd)->cverdefs;
-       if (sinfo.vers == 0)
-         sinfo.vers = 1;
-       sinfo.failed = FALSE;
+      sinfo.info = info;
+      sinfo.vers = elf_tdata (output_bfd)->cverdefs;
+      if (sinfo.vers == 0)
+       sinfo.vers = 1;
+      sinfo.failed = FALSE;
 
-       elf_link_hash_traverse (elf_hash_table (info),
-                               _bfd_elf_link_find_version_dependencies,
-                               &sinfo);
-       if (sinfo.failed)
-         return FALSE;
-
-       if (elf_tdata (output_bfd)->verref == NULL)
-         s->flags |= SEC_EXCLUDE;
-       else
-         {
-           Elf_Internal_Verneed *vn;
-           unsigned int size;
-           unsigned int crefs;
-           bfd_byte *p;
-
-           /* Build the version dependency section.  */
-           size = 0;
-           crefs = 0;
-           for (vn = elf_tdata (output_bfd)->verref;
-                vn != NULL;
-                vn = vn->vn_nextref)
-             {
-               Elf_Internal_Vernaux *a;
+      elf_link_hash_traverse (elf_hash_table (info),
+                             _bfd_elf_link_find_version_dependencies,
+                             &sinfo);
+      if (sinfo.failed)
+       return FALSE;
 
-               size += sizeof (Elf_External_Verneed);
-               ++crefs;
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 size += sizeof (Elf_External_Vernaux);
-             }
+      if (elf_tdata (output_bfd)->verref == NULL)
+       s->flags |= SEC_EXCLUDE;
+      else
+       {
+         Elf_Internal_Verneed *vn;
+         unsigned int size;
+         unsigned int crefs;
+         bfd_byte *p;
 
-           s->size = size;
-           s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
-           if (s->contents == NULL)
-             return FALSE;
+         /* Build the version dependency section.  */
+         size = 0;
+         crefs = 0;
+         for (vn = elf_tdata (output_bfd)->verref;
+              vn != NULL;
+              vn = vn->vn_nextref)
+           {
+             Elf_Internal_Vernaux *a;
 
-           p = s->contents;
-           for (vn = elf_tdata (output_bfd)->verref;
-                vn != NULL;
-                vn = vn->vn_nextref)
-             {
-               unsigned int caux;
-               Elf_Internal_Vernaux *a;
-               size_t indx;
-
-               caux = 0;
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 ++caux;
-
-               vn->vn_version = VER_NEED_CURRENT;
-               vn->vn_cnt = caux;
-               indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                           elf_dt_name (vn->vn_bfd) != NULL
-                                           ? elf_dt_name (vn->vn_bfd)
-                                           : lbasename (vn->vn_bfd->filename),
-                                           FALSE);
-               if (indx == (size_t) -1)
-                 return FALSE;
-               vn->vn_file = indx;
-               vn->vn_aux = sizeof (Elf_External_Verneed);
-               if (vn->vn_nextref == NULL)
-                 vn->vn_next = 0;
-               else
-                 vn->vn_next = (sizeof (Elf_External_Verneed)
-                               + caux * sizeof (Elf_External_Vernaux));
+             size += sizeof (Elf_External_Verneed);
+             ++crefs;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               size += sizeof (Elf_External_Vernaux);
+           }
 
-               _bfd_elf_swap_verneed_out (output_bfd, vn,
-                                          (Elf_External_Verneed *) p);
-               p += sizeof (Elf_External_Verneed);
+         s->size = size;
+         s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size);
+         if (s->contents == NULL)
+           return FALSE;
 
-               for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
-                 {
-                   a->vna_hash = bfd_elf_hash (a->vna_nodename);
-                   indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
-                                               a->vna_nodename, FALSE);
-                   if (indx == (size_t) -1)
-                     return FALSE;
-                   a->vna_name = indx;
-                   if (a->vna_nextptr == NULL)
-                     a->vna_next = 0;
-                   else
-                     a->vna_next = sizeof (Elf_External_Vernaux);
+         p = s->contents;
+         for (vn = elf_tdata (output_bfd)->verref;
+              vn != NULL;
+              vn = vn->vn_nextref)
+           {
+             unsigned int caux;
+             Elf_Internal_Vernaux *a;
+             size_t indx;
 
-                   _bfd_elf_swap_vernaux_out (output_bfd, a,
-                                              (Elf_External_Vernaux *) p);
-                   p += sizeof (Elf_External_Vernaux);
-                 }
-             }
+             caux = 0;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               ++caux;
 
-           elf_tdata (output_bfd)->cverrefs = crefs;
-         }
-      }
-    }
+             vn->vn_version = VER_NEED_CURRENT;
+             vn->vn_cnt = caux;
+             indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                         elf_dt_name (vn->vn_bfd) != NULL
+                                         ? elf_dt_name (vn->vn_bfd)
+                                         : lbasename (vn->vn_bfd->filename),
+                                         FALSE);
+             if (indx == (size_t) -1)
+               return FALSE;
+             vn->vn_file = indx;
+             vn->vn_aux = sizeof (Elf_External_Verneed);
+             if (vn->vn_nextref == NULL)
+               vn->vn_next = 0;
+             else
+               vn->vn_next = (sizeof (Elf_External_Verneed)
+                              + caux * sizeof (Elf_External_Vernaux));
 
-  bed = get_elf_backend_data (output_bfd);
+             _bfd_elf_swap_verneed_out (output_bfd, vn,
+                                        (Elf_External_Verneed *) p);
+             p += sizeof (Elf_External_Verneed);
 
-  if (info->gc_sections && bed->can_gc_sections)
-    {
-      struct elf_gc_sweep_symbol_info sweep_info;
-      unsigned long section_sym_count;
+             for (a = vn->vn_auxptr; a != NULL; a = a->vna_nextptr)
+               {
+                 a->vna_hash = bfd_elf_hash (a->vna_nodename);
+                 indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
+                                             a->vna_nodename, FALSE);
+                 if (indx == (size_t) -1)
+                   return FALSE;
+                 a->vna_name = indx;
+                 if (a->vna_nextptr == NULL)
+                   a->vna_next = 0;
+                 else
+                   a->vna_next = sizeof (Elf_External_Vernaux);
 
-      /* Remove the symbols that were in the swept sections from the
-        dynamic symbol table.  GCFIXME: Anyone know how to get them
-        out of the static symbol table as well?  */
-      sweep_info.info = info;
-      sweep_info.hide_symbol = bed->elf_backend_hide_symbol;
-      elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
-                             &sweep_info);
+                 _bfd_elf_swap_vernaux_out (output_bfd, a,
+                                            (Elf_External_Vernaux *) p);
+                 p += sizeof (Elf_External_Vernaux);
+               }
+           }
 
-      /* We need to reassign dynsym indices now that symbols may have
-        been removed.  See the call in `bfd_elf_size_dynsym_hash_dynstr'
-        for the details of the conditions used here.  */
-      if (elf_hash_table (info)->dynamic_sections_created
-         || bed->always_renumber_dynsyms)
-       _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+         elf_tdata (output_bfd)->cverrefs = crefs;
+       }
     }
 
   /* Any syms created from now on start with -1 in
@@ -6511,6 +6530,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
          if (inputobj->flags
              & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED))
            continue;
+         s = inputobj->sections;
+         if (s == NULL || s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+           continue;
+
          s = bfd_get_section_by_name (inputobj, ".note.GNU-stack");
          if (s)
            {
@@ -6660,9 +6683,10 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              bfd *sub;
              asection *o;
 
-             for (sub = info->input_bfds; sub != NULL;
-                  sub = sub->link.next)
-               if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
+             for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
+               if (bfd_get_flavour (sub) == bfd_target_elf_flavour
+                   && (o = sub->sections) != NULL
+                   && o->sec_info_type != SEC_INFO_TYPE_JUST_SYMS)
                  for (o = sub->sections; o != NULL; o = o->next)
                    if (elf_section_data (o)->this_hdr.sh_type
                        == SHT_PREINIT_ARRAY)
@@ -6775,7 +6799,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       if ((elf_tdata (output_bfd)->cverrefs == 0
           && elf_tdata (output_bfd)->cverdefs == 0)
          || _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-                                            &section_sym_count) == 0)
+                                            &section_sym_count) <= 1)
        {
          asection *s;
 
@@ -6838,7 +6862,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
 {
   const struct elf_backend_data *bed;
   unsigned long section_sym_count;
-  bfd_size_type dynsymcount;
+  bfd_size_type dynsymcount = 0;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -6940,7 +6964,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
            = compute_bucket_count (info, hashcodes, nsyms, 0);
          free (hashcodes);
 
-         if (bucketcount == 0)
+         if (bucketcount == 0 && nsyms > 0)
            return FALSE;
 
          elf_hash_table (info)->bucketcount = bucketcount;
@@ -8605,8 +8629,7 @@ elf_link_adjust_relocs (bfd *abfd,
                              abfd, sec,
                              (*rel_hash)->root.root.string);
          _bfd_error_handler (_("%B:%A: error: try relinking with --gc-keep-exported enabled."),
-                             abfd, sec,
-                             (*rel_hash)->root.root.string);
+                             abfd, sec);
          bfd_set_error (bfd_error_invalid_operation);
          return FALSE;
        }
@@ -9895,8 +9918,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
      relocatable output or when needed for --emit-relocs.  */
   else if (input_sec == bfd_und_section_ptr
           && h->indx != -2
+          /* PR 22319 Do not strip global undefined symbols marked as being needed.  */
+          && (h->mark != 1 || ELF_ST_BIND (sym.st_info) != STB_GLOBAL)
           && !bfd_link_relocatable (flinfo->info))
     return TRUE;
+
   /* Also strip others that we couldn't earlier due to dynamic symbol
      processing.  */
   if (strip)
@@ -10425,7 +10451,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                    (_("error: %B: size of section %A is not "
                       "multiple of address size"),
                     input_bfd, o);
-                 bfd_set_error (bfd_error_on_input);
+                 bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
              o->flags |= SEC_ELF_REVERSE_COPY;
@@ -10465,14 +10491,11 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                     we do not seg fault.  */
                  if (h == NULL)
                    {
-                     char buffer [32];
-
-                     sprintf_vma (buffer, rel->r_info);
                      _bfd_error_handler
                        /* xgettext:c-format */
-                       (_("error: %B contains a reloc (0x%s) for section %A "
+                       (_("error: %B contains a reloc (%#Lx) for section %A "
                           "that references a non-existent global symbol"),
-                        input_bfd, buffer, o);
+                        input_bfd, rel->r_info, o);
                      bfd_set_error (bfd_error_bad_value);
                      return FALSE;
                    }
@@ -12330,7 +12353,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            get_vma:
              o = bfd_get_linker_section (dynobj, name);
            do_vma:
-             if (o == NULL)
+             if (o == NULL || bfd_is_abs_section (o->output_section))
                {
                  _bfd_error_handler
                    (_("could not find section %s"), name);
@@ -12911,6 +12934,9 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
+      isec = ibfd->sections;
+      if (isec == NULL || isec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
 
       /* Ensure all linker created sections are kept,
         see if any other section is already marked,
@@ -12997,25 +13023,23 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
   return TRUE;
 }
 
-/* The sweep phase of garbage collection.  Remove all garbage sections.  */
-
-typedef bfd_boolean (*gc_sweep_hook_fn)
-  (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
-
 static bfd_boolean
 elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
 {
   bfd *sub;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  gc_sweep_hook_fn gc_sweep_hook = bed->gc_sweep_hook;
 
   for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
     {
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+         || elf_object_id (sub) != elf_hash_table_id (elf_hash_table (info))
          || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
        continue;
+      o = sub->sections;
+      if (o == NULL || o->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
 
       for (o = sub->sections; o != NULL; o = o->next)
        {
@@ -13044,33 +13068,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
            /* xgettext:c-format */
            _bfd_error_handler (_("Removing unused section '%A' in file '%B'"),
                                o, sub);
-
-         /* But we also have to update some of the relocation
-            info we collected before.  */
-         if (gc_sweep_hook
-             && (o->flags & SEC_RELOC) != 0
-             && o->reloc_count != 0
-             && !((info->strip == strip_all || info->strip == strip_debugger)
-                  && (o->flags & SEC_DEBUGGING) != 0)
-             && !bfd_is_abs_section (o->output_section))
-           {
-             Elf_Internal_Rela *internal_relocs;
-             bfd_boolean r;
-
-             internal_relocs
-               = _bfd_elf_link_read_relocs (o->owner, o, NULL, NULL,
-                                            info->keep_memory);
-             if (internal_relocs == NULL)
-               return FALSE;
-
-             r = (*gc_sweep_hook) (o->owner, info, o, internal_relocs);
-
-             if (elf_section_data (o)->relocs != internal_relocs)
-               free (internal_relocs);
-
-             if (!r)
-               return FALSE;
-           }
        }
     }
 
@@ -13253,6 +13250,9 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
 
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
+      sec = ibfd->sections;
+      if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
 
       if (!init_reloc_cookie (&cookie, info, ibfd))
        return FALSE;
@@ -13300,6 +13300,9 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       asection *sec;
       struct elf_reloc_cookie cookie;
 
+      sec = sub->sections;
+      if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
       sec = bfd_get_section_by_name (sub, ".eh_frame");
       while (sec && init_reloc_cookie_for_section (&cookie, info, sec))
        {
@@ -13333,9 +13336,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       asection *o;
 
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour
+         || elf_object_id (sub) != elf_hash_table_id (htab)
          || !(*bed->relocs_compatible) (sub->xvec, abfd->xvec))
        continue;
 
+      o = sub->sections;
+      if (o == NULL || o->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
+
       /* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep).
         Also treat note sections as a root, if the section is not part
         of a group.  */
@@ -13394,8 +13402,8 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
     }
 
   /* xgettext:c-format */
-  _bfd_error_handler (_("%B: %A+%lu: No symbol found for INHERIT"),
-                     abfd, sec, (unsigned long) offset);
+  _bfd_error_handler (_("%B: %A+%#Lx: No symbol found for INHERIT"),
+                     abfd, sec, offset);
   bfd_set_error (bfd_error_invalid_operation);
   return FALSE;
 
@@ -13807,6 +13815,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *i;
       int eh_changed = 0;
+      unsigned int eh_alignment;
 
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
@@ -13832,6 +13841,36 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
 
          fini_reloc_cookie_for_section (&cookie, i);
        }
+
+      eh_alignment = 1 << o->alignment_power;
+      /* Skip over zero terminator, and prevent empty sections from
+        adding alignment padding at the end.  */
+      for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
+       if (i->size == 0)
+         i->flags |= SEC_EXCLUDE;
+       else if (i->size > 4)
+         break;
+      /* The last non-empty eh_frame section doesn't need padding.  */
+      if (i != NULL)
+       i = i->map_tail.s;
+      /* Any prior sections must pad the last FDE out to the output
+        section alignment.  Otherwise we might have zero padding
+        between sections, which would be seen as a terminator.  */
+      for (; i != NULL; i = i->map_tail.s)
+       if (i->size == 4)
+         /* All but the last zero terminator should have been removed.  */
+         BFD_FAIL ();
+       else
+         {
+           bfd_size_type size
+             = (i->size + eh_alignment - 1) & -eh_alignment;
+           if (i->size != size)
+             {
+               i->size = size;
+               changed = 1;
+               eh_changed = 1;
+             }
+         }
       if (eh_changed)
        elf_link_hash_traverse (elf_hash_table (info),
                                _bfd_elf_adjust_eh_frame_global_symbol, NULL);
@@ -13840,9 +13879,13 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
     {
       const struct elf_backend_data *bed;
+      asection *s;
 
       if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
        continue;
+      s = abfd->sections;
+      if (s == NULL || s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+       continue;
 
       bed = get_elf_backend_data (abfd);
 
@@ -14198,18 +14241,32 @@ struct bfd_link_hash_entry *
 bfd_elf_define_start_stop (struct bfd_link_info *info,
                           const char *symbol, asection *sec)
 {
-  struct bfd_link_hash_entry *h;
+  struct elf_link_hash_entry *h;
 
-  h = bfd_generic_define_start_stop (info, symbol, sec);
-  if (h != NULL)
+  h = elf_link_hash_lookup (elf_hash_table (info), symbol,
+                           FALSE, FALSE, TRUE);
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_undefined
+         || h->root.type == bfd_link_hash_undefweak
+         || (h->ref_regular && !h->def_regular)))
     {
-      struct elf_link_hash_entry *eh = (struct elf_link_hash_entry *) h;
-      eh->start_stop = 1;
-      eh->u2.start_stop_section = sec;
-      _bfd_elf_link_hash_hide_symbol (info, eh, TRUE);
-      if (ELF_ST_VISIBILITY (eh->other) != STV_INTERNAL)
-       eh->other = ((eh->other & ~ELF_ST_VISIBILITY (-1))
-                    | STV_HIDDEN);
+      h->root.type = bfd_link_hash_defined;
+      h->root.u.def.section = sec;
+      h->root.u.def.value = 0;
+      h->def_regular = 1;
+      h->def_dynamic = 0;
+      h->start_stop = 1;
+      h->u2.start_stop_section = sec;
+      if (symbol[0] == '.')
+       {
+         /* .startof. and .sizeof. symbols are local.  */
+         const struct elf_backend_data *bed;
+         bed = get_elf_backend_data (info->output_bfd);
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+       }
+      else if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+       h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_PROTECTED;
+      return &h->root;
     }
-  return h;
+  return NULL;
 }
This page took 0.035978 seconds and 4 git commands to generate.