-Og warning fixes
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 4af4b1cd3d33c0b566349d545038accee4ffd51a..58fb83b4b2783d0918fba65a9f5e393040225702 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;
@@ -580,7 +584,7 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
               && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT
                   || ELF_ST_TYPE (sym->st_info) == STT_COMMON))))
       || (d != NULL
-         && h->root.type == bfd_link_hash_new
+         && h->non_elf
          && (*d->match) (&d->head, NULL, h->root.root.string)))
     h->dynamic = 1;
 }
@@ -623,6 +627,14 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        }
     }
 
+  /* Symbols defined in a linker script but not referenced anywhere
+     else will have non_elf set.  */
+  if (h->non_elf)
+    {
+      bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
+      h->non_elf = 0;
+    }
+
   switch (h->root.type)
     {
     case bfd_link_hash_defined:
@@ -639,8 +651,6 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
        bfd_link_repair_undef_list (&htab->root);
       break;
     case bfd_link_hash_new:
-      bfd_elf_link_mark_dynamic_symbol (info, h, NULL);
-      h->non_elf = 0;
       break;
     case bfd_link_hash_indirect:
       /* We had a versioned symbol in a dynamic library.  We make the
@@ -2384,9 +2394,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;
@@ -2396,10 +2406,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;
@@ -2444,8 +2454,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
     {
       bfd_size_type size;
 
-      size = o->reloc_count;
-      size *= bed->s->int_rels_per_ext_rel * sizeof (Elf_Internal_Rela);
+      size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
       if (keep_memory)
        internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
       else
@@ -2926,7 +2935,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
@@ -4245,6 +4254,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);
@@ -4743,9 +4758,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;
            }
@@ -4933,7 +4947,7 @@ error_free_dyn:
          struct elf_link_hash_entry *h;
          bfd_size_type size;
          unsigned int alignment_power;
-         unsigned int dynamic_ref_after_ir_def;
+         unsigned int non_ir_ref_dynamic;
 
          for (p = htab->root.table.table[i]; p != NULL; p = p->next)
            {
@@ -4955,10 +4969,10 @@ error_free_dyn:
                  size = 0;
                  alignment_power = 0;
                }
-             /* Preserve dynamic_ref_after_ir_def so that this symbol
+             /* Preserve non_ir_ref_dynamic so that this symbol
                 will be exported when the dynamic lib becomes needed
                 in the second pass.  */
-             dynamic_ref_after_ir_def = h->root.dynamic_ref_after_ir_def;
+             non_ir_ref_dynamic = h->root.non_ir_ref_dynamic;
              memcpy (p, old_ent, htab->root.table.entsize);
              old_ent = (char *) old_ent + htab->root.table.entsize;
              h = (struct elf_link_hash_entry *) p;
@@ -4975,7 +4989,7 @@ error_free_dyn:
                  if (alignment_power > h->root.u.c.p->alignment_power)
                    h->root.u.c.p->alignment_power = alignment_power;
                }
-             h->root.dynamic_ref_after_ir_def = dynamic_ref_after_ir_def;
+             h->root.non_ir_ref_dynamic = non_ir_ref_dynamic;
            }
        }
 
@@ -5856,9 +5870,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;
@@ -6506,6 +6523,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)
            {
@@ -6655,9 +6676,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)
@@ -6833,7 +6855,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;
@@ -6935,7 +6957,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;
@@ -8542,7 +8564,8 @@ static bfd_boolean
 elf_link_adjust_relocs (bfd *abfd,
                        asection *sec,
                        struct bfd_elf_section_reloc_data *reldata,
-                       bfd_boolean sort)
+                       bfd_boolean sort,
+                       struct bfd_link_info *info)
 {
   unsigned int i;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -8590,6 +8613,19 @@ elf_link_adjust_relocs (bfd *abfd,
       if (*rel_hash == NULL)
        continue;
 
+      if ((*rel_hash)->indx == -2
+         && info->gc_sections
+         && ! info->gc_keep_exported)
+       {
+         /* PR 21524: Let the user know if a symbol was removed by garbage collection.  */
+         _bfd_error_handler (_("%B:%A: error: relocation references symbol %s which was removed by garbage collection."),
+                             abfd, sec,
+                             (*rel_hash)->root.root.string);
+         _bfd_error_handler (_("%B:%A: error: try relinking with --gc-keep-exported enabled."),
+                             abfd, sec);
+         bfd_set_error (bfd_error_invalid_operation);
+         return FALSE;
+       }
       BFD_ASSERT ((*rel_hash)->indx >= 0);
 
       (*swap_in) (abfd, erela, irela);
@@ -8819,7 +8855,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                else
                  {
                    /* Section size is only divisible by rela.  */
-                   if (use_rela_initialised && (use_rela == FALSE))
+                   if (use_rela_initialised && !use_rela)
                      {
                        _bfd_error_handler (_("%B: Unable to sort relocs - "
                                              "they are in more than one size"),
@@ -8837,7 +8873,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
            else if ((o->size % bed->s->sizeof_rel) == 0)
              {
                /* Section size is only divisible by rel.  */
-               if (use_rela_initialised && (use_rela == TRUE))
+               if (use_rela_initialised && use_rela)
                  {
                    _bfd_error_handler (_("%B: Unable to sort relocs - "
                                          "they are in more than one size"),
@@ -8876,7 +8912,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
                else
                  {
                    /* Section size is only divisible by rela.  */
-                   if (use_rela_initialised && (use_rela == FALSE))
+                   if (use_rela_initialised && !use_rela)
                      {
                        _bfd_error_handler (_("%B: Unable to sort relocs - "
                                              "they are in more than one size"),
@@ -8894,7 +8930,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
            else if ((o->size % bed->s->sizeof_rel) == 0)
              {
                /* Section size is only divisible by rel.  */
-               if (use_rela_initialised && (use_rela == TRUE))
+               if (use_rela_initialised && use_rela)
                  {
                    _bfd_error_handler (_("%B: Unable to sort relocs - "
                                          "they are in more than one size"),
@@ -10272,7 +10308,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          continue;
        }
 
-      if (bfd_link_relocatable (flinfo->info)
+      if (!flinfo->info->resolve_section_groups
          && (o->flags & (SEC_LINKER_CREATED | SEC_GROUP)) == SEC_GROUP)
        {
          /* Deal with the group signature symbol.  */
@@ -10280,6 +10316,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          unsigned long symndx = sec_data->this_hdr.sh_info;
          asection *osec = o->output_section;
 
+         BFD_ASSERT (bfd_link_relocatable (flinfo->info));
          if (symndx >= locsymcount
              || (elf_bad_symtab (input_bfd)
                  && flinfo->sections[symndx] == NULL))
@@ -10396,7 +10433,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                                 ".fini_array") == 0))
              && (o->name[6] == 0 || o->name[6] == '.'))
            {
-             if (o->size != o->reloc_count * address_size)
+             if (o->size * bed->s->int_rels_per_ext_rel
+                 != o->reloc_count * address_size)
                {
                  _bfd_error_handler
                    /* xgettext:c-format */
@@ -10420,7 +10458,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
             relocs against removed link-once sections.  */
 
          rel = internal_relocs;
-         relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+         relend = rel + o->reloc_count;
          for ( ; rel < relend; rel++)
            {
              unsigned long r_symndx = rel->r_info >> r_sym_shift;
@@ -10443,14 +10481,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;
                    }
@@ -10466,7 +10501,8 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                     linker may attach linker created dynamic sections
                     to the plugin bfd.  Symbols defined in linker
                     created sections are not plugin symbols.  */
-                 if (h->root.non_ir_ref
+                 if ((h->root.non_ir_ref_regular
+                      || h->root.non_ir_ref_dynamic)
                      && (h->root.type == bfd_link_hash_defined
                          || h->root.type == bfd_link_hash_defweak)
                      && (h->root.u.def.section->flags
@@ -10608,7 +10644,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
              /* Adjust the reloc addresses and symbol indices.  */
 
              irela = internal_relocs;
-             irelaend = irela + o->reloc_count * bed->s->int_rels_per_ext_rel;
+             irelaend = irela + o->reloc_count;
              rel_hash = esdo->rel.hashes + esdo->rel.count;
              /* We start processing the REL relocs, if any.  When we reach
                 IRELAMID in the loop, we switch to the RELA relocs.  */
@@ -10693,7 +10729,6 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
                         used by a reloc.  */
                      BFD_ASSERT (rh->indx < 0);
                      rh->indx = -2;
-
                      *rel_hash = rh;
 
                      continue;
@@ -11271,10 +11306,11 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
   if (!bfd_set_format (implib_bfd, bfd_object))
     return FALSE;
 
+  /* Use flag from executable but make it a relocatable object.  */
   flags = bfd_get_file_flags (abfd);
   flags &= ~HAS_RELOC;
   if (!bfd_set_start_address (implib_bfd, 0)
-      || !bfd_set_file_flags (implib_bfd, flags))
+      || !bfd_set_file_flags (implib_bfd, flags & ~EXEC_P))
     return FALSE;
 
   /* Copy architecture of output file to import library file.  */
@@ -11781,8 +11817,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (max_internal_reloc_count != 0)
     {
-      amt = max_internal_reloc_count * bed->s->int_rels_per_ext_rel;
-      amt *= sizeof (Elf_Internal_Rela);
+      amt = max_internal_reloc_count * sizeof (Elf_Internal_Rela);
       flinfo.internal_relocs = (Elf_Internal_Rela *) bfd_malloc (amt);
       if (flinfo.internal_relocs == NULL)
        goto error_return;
@@ -12160,15 +12195,16 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
       bfd_boolean sort;
+
       if ((o->flags & SEC_RELOC) == 0)
        continue;
 
       sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
       if (esdo->rel.hdr != NULL
-         && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort))
+         && !elf_link_adjust_relocs (abfd, o, &esdo->rel, sort, info))
        return FALSE;
       if (esdo->rela.hdr != NULL
-         && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort))
+         && !elf_link_adjust_relocs (abfd, o, &esdo->rela, sort, info))
        return FALSE;
 
       /* Set the reloc_count field to 0 to prevent write_relocs from
@@ -12307,7 +12343,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);
@@ -12456,10 +12492,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (bfd_link_relocatable (info))
+  if (!info->resolve_section_groups)
     {
       bfd_boolean failed = FALSE;
 
+      BFD_ASSERT (bfd_link_relocatable (info));
       bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
       if (failed)
        goto error_return;
@@ -12565,8 +12602,6 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
                        struct bfd_link_info *info, bfd *abfd,
                        asection *sec)
 {
-  const struct elf_backend_data *bed;
-
   if (sec->reloc_count == 0)
     {
       cookie->rels = NULL;
@@ -12574,15 +12609,12 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
     }
   else
     {
-      bed = get_elf_backend_data (abfd);
-
       cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
                                                info->keep_memory);
       if (cookie->rels == NULL)
        return FALSE;
       cookie->rel = cookie->rels;
-      cookie->relend = (cookie->rels
-                       + sec->reloc_count * bed->s->int_rels_per_ext_rel);
+      cookie->relend = cookie->rels + sec->reloc_count;
     }
   cookie->rel = cookie->rels;
   return TRUE;
@@ -12661,53 +12693,22 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
-/* For undefined __start_<name> and __stop_<name> symbols, return the
-   first input section matching <name>.  Return NULL otherwise.  */
+/* Return the global debug definition section.  */
 
-asection *
-_bfd_elf_is_start_stop (const struct bfd_link_info *info,
-                       struct elf_link_hash_entry *h)
+static asection *
+elf_gc_mark_debug_section (asection *sec ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+                          struct elf_link_hash_entry *h,
+                          Elf_Internal_Sym *sym ATTRIBUTE_UNUSED)
 {
-  asection *s;
-  const char *sec_name;
-
-  if (h->root.type != bfd_link_hash_undefined
-      && h->root.type != bfd_link_hash_undefweak)
-    return NULL;
-
-  s = h->root.u.undef.section;
-  if (s != NULL)
-    {
-      if (s == (asection *) 0 - 1)
-       return NULL;
-      return s;
-    }
-
-  sec_name = NULL;
-  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;
-
-  if (sec_name != NULL && *sec_name != '\0')
-    {
-      bfd *i;
-
-      for (i = info->input_bfds; i != NULL; i = i->link.next)
-       {
-         s = bfd_get_section_by_name (i, sec_name);
-         if (s != NULL)
-           {
-             h->root.u.undef.section = s;
-             break;
-           }
-       }
-    }
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+      && (h->root.u.def.section->flags & SEC_DEBUGGING) != 0)
+    return h->root.u.def.section;
 
-  if (s == NULL)
-    h->root.u.undef.section = (asection *) 0 - 1;
-
-  return s;
+  return NULL;
 }
 
 /* COOKIE->rel describes a relocation against section SEC, which is
@@ -12750,15 +12751,12 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
 
       if (start_stop != NULL)
        {
-         /* To work around a glibc bug, mark 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.  */
-         asection *s = _bfd_elf_is_start_stop (info, h);
-
-         if (s != NULL)
+         /* To work around a glibc bug, mark XXX input sections
+            when there is a reference to __start_XXX or __stop_XXX
+            symbols.  */
+         if (h->start_stop)
            {
+             asection *s = h->u2.start_stop_section;
              *start_stop = !s->gc_mark;
              return s;
            }
@@ -12922,29 +12920,35 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       asection *isec;
       bfd_boolean some_kept;
       bfd_boolean debug_frag_seen;
+      bfd_boolean has_kept_debug_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,
         and note if we have any fragmented debug sections.  */
-      debug_frag_seen = some_kept = FALSE;
+      debug_frag_seen = some_kept = has_kept_debug_info = FALSE;
       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
        {
          if ((isec->flags & SEC_LINKER_CREATED) != 0)
            isec->gc_mark = 1;
-         else if (isec->gc_mark)
+         else if (isec->gc_mark
+                  && (isec->flags & SEC_ALLOC) != 0
+                  && elf_section_type (isec) != SHT_NOTE)
            some_kept = TRUE;
 
-         if (debug_frag_seen == FALSE
+         if (!debug_frag_seen
              && (isec->flags & SEC_DEBUGGING)
              && CONST_STRNEQ (isec->name, ".debug_line."))
            debug_frag_seen = TRUE;
        }
 
-      /* If no section in this file will be kept, then we can
-        toss out the debug and special sections.  */
+      /* If no non-note alloc section in this file will be kept, then
+        we can toss out the debug and special sections.  */
       if (!some_kept)
        continue;
 
@@ -12959,45 +12963,52 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
                    || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)
                   && elf_next_in_group (isec) == NULL)
            isec->gc_mark = 1;
+         if (isec->gc_mark && (isec->flags & SEC_DEBUGGING) != 0)
+           has_kept_debug_info = TRUE;
        }
 
-      if (! debug_frag_seen)
-       continue;
-
       /* Look for CODE sections which are going to be discarded,
         and find and discard any fragmented debug sections which
         are associated with that code section.  */
-      for (isec = ibfd->sections; isec != NULL; isec = isec->next)
-       if ((isec->flags & SEC_CODE) != 0
-           && isec->gc_mark == 0)
-         {
-           unsigned int ilen;
-           asection *dsec;
+      if (debug_frag_seen)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if ((isec->flags & SEC_CODE) != 0
+             && isec->gc_mark == 0)
+           {
+             unsigned int ilen;
+             asection *dsec;
 
-           ilen = strlen (isec->name);
+             ilen = strlen (isec->name);
 
-           /* Association is determined by the name of the debug section
-              containing the name of the code section as a suffix.  For
-              example .debug_line.text.foo is a debug section associated
-              with .text.foo.  */
-           for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
-             {
-               unsigned int dlen;
+             /* Association is determined by the name of the debug
+                section containing the name of the code section as
+                a suffix.  For example .debug_line.text.foo is a
+                debug section associated with .text.foo.  */
+             for (dsec = ibfd->sections; dsec != NULL; dsec = dsec->next)
+               {
+                 unsigned int dlen;
 
-               if (dsec->gc_mark == 0
-                   || (dsec->flags & SEC_DEBUGGING) == 0)
-                 continue;
+                 if (dsec->gc_mark == 0
+                     || (dsec->flags & SEC_DEBUGGING) == 0)
+                   continue;
 
-               dlen = strlen (dsec->name);
+                 dlen = strlen (dsec->name);
 
-               if (dlen > ilen
-                   && strncmp (dsec->name + (dlen - ilen),
-                               isec->name, ilen) == 0)
-                 {
+                 if (dlen > ilen
+                     && strncmp (dsec->name + (dlen - ilen),
+                                 isec->name, ilen) == 0)
                    dsec->gc_mark = 0;
-                 }
-             }
+               }
          }
+
+      /* Mark debug sections referenced by kept debug sections.  */
+      if (has_kept_debug_info)
+       for (isec = ibfd->sections; isec != NULL; isec = isec->next)
+         if (isec->gc_mark
+             && (isec->flags & SEC_DEBUGGING) != 0)
+           if (!_bfd_elf_gc_mark (info, isec,
+                                  elf_gc_mark_debug_section))
+             return FALSE;
     }
   return TRUE;
 }
@@ -13021,6 +13032,9 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
       if (bfd_get_flavour (sub) != bfd_target_elf_flavour
          || !(*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)
        {
@@ -13089,26 +13103,28 @@ static bfd_boolean
 elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 {
   /* Those that are not vtables.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   /* Those vtables that do not have parents, we cannot merge.  */
-  if (h->vtable->parent == (struct elf_link_hash_entry *) -1)
+  if (h->u2.vtable->parent == (struct elf_link_hash_entry *) -1)
     return TRUE;
 
   /* If we've already been done, exit.  */
-  if (h->vtable->used && h->vtable->used[-1])
+  if (h->u2.vtable->used && h->u2.vtable->used[-1])
     return TRUE;
 
   /* Make sure the parent's table is up to date.  */
-  elf_gc_propagate_vtable_entries_used (h->vtable->parent, okp);
+  elf_gc_propagate_vtable_entries_used (h->u2.vtable->parent, okp);
 
-  if (h->vtable->used == NULL)
+  if (h->u2.vtable->used == NULL)
     {
       /* None of this table's entries were referenced.  Re-use the
         parent's table.  */
-      h->vtable->used = h->vtable->parent->vtable->used;
-      h->vtable->size = h->vtable->parent->vtable->size;
+      h->u2.vtable->used = h->u2.vtable->parent->u2.vtable->used;
+      h->u2.vtable->size = h->u2.vtable->parent->u2.vtable->size;
     }
   else
     {
@@ -13116,9 +13132,9 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
       bfd_boolean *cu, *pu;
 
       /* Or the parent's entries into ours.  */
-      cu = h->vtable->used;
+      cu = h->u2.vtable->used;
       cu[-1] = TRUE;
-      pu = h->vtable->parent->vtable->used;
+      pu = h->u2.vtable->parent->u2.vtable->used;
       if (pu != NULL)
        {
          const struct elf_backend_data *bed;
@@ -13126,7 +13142,7 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
 
          bed = get_elf_backend_data (h->root.u.def.section->owner);
          log_file_align = bed->s->log_file_align;
-         n = h->vtable->parent->vtable->size >> log_file_align;
+         n = h->u2.vtable->parent->u2.vtable->size >> log_file_align;
          while (n--)
            {
              if (*pu)
@@ -13151,7 +13167,9 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
 
   /* Take care of both those symbols that do not describe vtables as
      well as those that are not loaded.  */
-  if (h->vtable == NULL || h->vtable->parent == NULL)
+  if (h->start_stop
+      || h->u2.vtable == NULL
+      || h->u2.vtable->parent == NULL)
     return TRUE;
 
   BFD_ASSERT (h->root.type == bfd_link_hash_defined
@@ -13167,17 +13185,17 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
   bed = get_elf_backend_data (sec->owner);
   log_file_align = bed->s->log_file_align;
 
-  relend = relstart + sec->reloc_count * bed->s->int_rels_per_ext_rel;
+  relend = relstart + sec->reloc_count;
 
   for (rel = relstart; rel < relend; ++rel)
     if (rel->r_offset >= hstart && rel->r_offset < hend)
       {
        /* If the entry is in use, do nothing.  */
-       if (h->vtable->used
-           && (rel->r_offset - hstart) < h->vtable->size)
+       if (h->u2.vtable->used
+           && (rel->r_offset - hstart) < h->u2.vtable->size)
          {
            bfd_vma entry = (rel->r_offset - hstart) >> log_file_align;
-           if (h->vtable->used[entry])
+           if (h->u2.vtable->used[entry])
              continue;
          }
        /* Otherwise, kill it.  */
@@ -13254,6 +13272,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;
@@ -13301,6 +13322,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))
        {
@@ -13337,6 +13361,10 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *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;
+
       /* 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.  */
@@ -13395,17 +13423,17 @@ 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;
 
  win:
-  if (!child->vtable)
+  if (!child->u2.vtable)
     {
-      child->vtable = ((struct elf_link_virtual_table_entry *)
-                      bfd_zalloc (abfd, sizeof (*child->vtable)));
-      if (!child->vtable)
+      child->u2.vtable = ((struct elf_link_virtual_table_entry *)
+                         bfd_zalloc (abfd, sizeof (*child->u2.vtable)));
+      if (!child->u2.vtable)
        return FALSE;
     }
   if (!h)
@@ -13415,10 +13443,10 @@ bfd_elf_gc_record_vtinherit (bfd *abfd,
         would be bad.  It isn't worth paging in the local symbols to be
         sure though; that case should simply be handled by the assembler.  */
 
-      child->vtable->parent = (struct elf_link_hash_entry *) -1;
+      child->u2.vtable->parent = (struct elf_link_hash_entry *) -1;
     }
   else
-    child->vtable->parent = h;
+    child->u2.vtable->parent = h;
 
   return TRUE;
 }
@@ -13434,18 +13462,18 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   unsigned int log_file_align = bed->s->log_file_align;
 
-  if (!h->vtable)
+  if (!h->u2.vtable)
     {
-      h->vtable = ((struct elf_link_virtual_table_entry *)
-                  bfd_zalloc (abfd, sizeof (*h->vtable)));
-      if (!h->vtable)
+      h->u2.vtable = ((struct elf_link_virtual_table_entry *)
+                     bfd_zalloc (abfd, sizeof (*h->u2.vtable)));
+      if (!h->u2.vtable)
        return FALSE;
     }
 
-  if (addend >= h->vtable->size)
+  if (addend >= h->u2.vtable->size)
     {
       size_t size, bytes, file_align;
-      bfd_boolean *ptr = h->vtable->used;
+      bfd_boolean *ptr = h->u2.vtable->used;
 
       /* While the symbol is undefined, we have to be prepared to handle
         a zero size.  */
@@ -13476,7 +13504,7 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
            {
              size_t oldbytes;
 
-             oldbytes = (((h->vtable->size >> log_file_align) + 1)
+             oldbytes = (((h->u2.vtable->size >> log_file_align) + 1)
                          * sizeof (bfd_boolean));
              memset (((char *) ptr) + oldbytes, 0, bytes - oldbytes);
            }
@@ -13488,11 +13516,11 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED,
        return FALSE;
 
       /* And arrange for that done flag to be at index -1.  */
-      h->vtable->used = ptr + 1;
-      h->vtable->size = size;
+      h->u2.vtable->used = ptr + 1;
+      h->u2.vtable->size = size;
     }
 
-  h->vtable->used[addend >> log_file_align] = TRUE;
+  h->u2.vtable->used[addend >> log_file_align] = TRUE;
 
   return TRUE;
 }
@@ -13808,6 +13836,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)
        {
@@ -13833,6 +13862,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);
@@ -13841,9 +13900,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);
 
@@ -14192,3 +14255,37 @@ elf_append_rel (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
   BFD_ASSERT (loc + bed->s->sizeof_rel <= s->contents + s->size);
   bed->s->swap_reloc_out (abfd, rel, loc);
 }
+
+/* Define __start, __stop, .startof. or .sizeof. symbol.  */
+
+struct bfd_link_hash_entry *
+bfd_elf_define_start_stop (struct bfd_link_info *info,
+                          const char *symbol, asection *sec)
+{
+  struct elf_link_hash_entry *h;
+
+  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)))
+    {
+      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.  */
+         _bfd_elf_link_hash_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 NULL;
+}
This page took 0.051815 seconds and 4 git commands to generate.