ELF/BFD: Hold the number of internal static relocs in `->reloc_count'
[deliverable/binutils-gdb.git] / bfd / elflink.c
index b93d4f37c175b0264f838d732d153ce63104943f..07d3ea5d9c51d481ba57ca4d8ba0db9872f8c419 100644 (file)
@@ -580,7 +580,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 +623,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 +647,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
@@ -2444,8 +2450,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
@@ -2803,6 +2808,24 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   if (! _bfd_elf_fix_symbol_flags (h, eif))
     return FALSE;
 
+  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);
+      else if (eif->info->dynamic_undefined_weak > 0
+              && h->ref_regular
+              && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+              && !bfd_hide_sym_by_version (eif->info->version_info,
+                                           h->root.root.string))
+       {
+         if (!bfd_elf_link_record_dynamic_symbol (eif->info, h))
+           {
+             eif->failed = TRUE;
+             return FALSE;
+           }
+       }
+    }
+
   /* If this symbol does not require a PLT entry, and it is not
      defined by a dynamic object, or is not referenced by a regular
      object, ignore it.  We do have to handle a weak defined symbol,
@@ -3045,10 +3068,10 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
    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.  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.
+   for the place where dynindx == -1 is tested.  If that test is 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
@@ -3071,6 +3094,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
       || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
     return TRUE;
 
+  /* Forced local symbols resolve locally.  */
+  if (h->forced_local)
+    return TRUE;
+
   /* Common symbols that become definitions don't get the DEF_REGULAR
      flag set, so test it first, and don't bail out.  */
   if (ELF_COMMON_DEF_P (h))
@@ -3080,11 +3107,7 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
   else if (!h->def_regular)
     return FALSE;
 
-  /* Forced local symbols resolve locally.  */
-  if (h->forced_local)
-    return TRUE;
-
-  /* As do non-dynamic symbols.  */
+  /* Non-dynamic symbols resolve locally.  */
   if (h->dynindx == -1)
     return TRUE;
 
@@ -3833,6 +3856,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       if (!just_syms
          && (bfd_link_pic (info)
              || (!bfd_link_relocatable (info)
+                 && info->nointerp
                  && (info->export_dynamic || info->dynamic)))
          && is_elf_hash_table (htab)
          && info->output_bfd->xvec == abfd->xvec
@@ -4914,6 +4938,7 @@ error_free_dyn:
          struct elf_link_hash_entry *h;
          bfd_size_type size;
          unsigned int alignment_power;
+         unsigned int non_ir_ref_dynamic;
 
          for (p = htab->root.table.table[i]; p != NULL; p = p->next)
            {
@@ -4935,6 +4960,10 @@ error_free_dyn:
                  size = 0;
                  alignment_power = 0;
                }
+             /* Preserve non_ir_ref_dynamic so that this symbol
+                will be exported when the dynamic lib becomes needed
+                in the second pass.  */
+             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;
@@ -4951,6 +4980,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.non_ir_ref_dynamic = non_ir_ref_dynamic;
            }
        }
 
@@ -6435,7 +6465,12 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       elf_link_hash_traverse (elf_hash_table (info), elf_gc_sweep_symbol,
                              &sweep_info);
 
-      _bfd_elf_link_renumber_dynsyms (output_bfd, info, &section_sym_count);
+      /* 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);
     }
 
   /* Any syms created from now on start with -1 in
@@ -6802,6 +6837,8 @@ bfd_boolean
 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;
 
   if (!is_elf_hash_table (info->hash))
     return TRUE;
@@ -6809,24 +6846,30 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info)
   bed = get_elf_backend_data (output_bfd);
   (*bed->elf_backend_init_index_section) (output_bfd, info);
 
+  /* Assign dynsym indices.  In a shared library we generate a section
+     symbol for each output section, which come first.  Next come all
+     of the back-end allocated local dynamic syms, followed by the rest
+     of the global symbols.
+
+     This is usually not needed for static binaries, however backends
+     can request to always do it, e.g. the MIPS backend uses dynamic
+     symbol counts to lay out GOT, which will be produced in the
+     presence of GOT relocations even in static binaries (holding fixed
+     data in that case, to satisfy those relocations).  */
+
+  if (elf_hash_table (info)->dynamic_sections_created
+      || bed->always_renumber_dynsyms)
+    dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
+                                                 &section_sym_count);
+
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       bfd *dynobj;
       asection *s;
-      bfd_size_type dynsymcount;
-      unsigned long section_sym_count;
       unsigned int dtagcount;
 
       dynobj = elf_hash_table (info)->dynobj;
 
-      /* Assign dynsym indicies.  In a shared library we generate a
-        section symbol for each output section, which come first.
-        Next come all of the back-end allocated local dynamic syms,
-        followed by the rest of the global symbols.  */
-
-      dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info,
-                                                   &section_sym_count);
-
       /* Work out the size of the symbol version section.  */
       s = bfd_get_linker_section (dynobj, ".gnu.version");
       BFD_ASSERT (s != NULL);
@@ -7257,9 +7300,10 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
       h->forced_local = 1;
       if (h->dynindx != -1)
        {
-         h->dynindx = -1;
          _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
                                  h->dynstr_index);
+         h->dynindx = -1;
+         h->dynstr_index = 0;
        }
     }
 }
@@ -8780,7 +8824,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"),
@@ -8798,7 +8842,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"),
@@ -8837,7 +8881,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"),
@@ -8855,7 +8899,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"),
@@ -10357,7 +10401,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 */
@@ -10381,7 +10426,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;
@@ -10427,7 +10472,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
@@ -10569,7 +10615,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.  */
@@ -11232,10 +11278,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.  */
@@ -11742,8 +11789,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;
@@ -12542,8 +12588,7 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
       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;
@@ -12622,6 +12667,24 @@ _bfd_elf_gc_mark_hook (asection *sec,
   return NULL;
 }
 
+/* Return the global debug definition section.  */
+
+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)
+{
+  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;
+
+  return NULL;
+}
+
 /* For undefined __start_<name> and __stop_<name> symbols, return the
    first input section matching <name>.  Return NULL otherwise.  */
 
@@ -12883,6 +12946,7 @@ _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;
@@ -12890,22 +12954,24 @@ _bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info,
       /* 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;
 
@@ -12920,45 +12986,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;
 }
@@ -13128,7 +13201,7 @@ 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)
@@ -13768,6 +13841,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   if (o != NULL)
     {
       asection *i;
+      int eh_changed = 0;
 
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
@@ -13785,10 +13859,17 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
          if (_bfd_elf_discard_section_eh_frame (abfd, info, i,
                                                 bfd_elf_reloc_symbol_deleted_p,
                                                 &cookie))
-           changed = 1;
+           {
+             eh_changed = 1;
+             if (i->size != i->rawsize)
+               changed = 1;
+           }
 
          fini_reloc_cookie_for_section (&cookie, i);
        }
+      if (eh_changed)
+       elf_link_hash_traverse (elf_hash_table (info),
+                               _bfd_elf_adjust_eh_frame_global_symbol, NULL);
     }
 
   for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
This page took 0.032623 seconds and 4 git commands to generate.