* elf64-sparc.c (sparc64_elf_relocate_section): Adjust addend of
[deliverable/binutils-gdb.git] / bfd / elflink.h
index b1732e43c2f0c6345d30a165bd9cdd91ee71d067..c116ed5d44aa9de8beac05223cdf4760ff83bb3c 100644 (file)
@@ -899,19 +899,19 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
 
 /* This function is called to create an indirect symbol from the
    default for the symbol with the default version if needed. The
-   symbol is described by H, NAME, SYM, SEC, VALUE, and OVERRIDE.  We
+   symbol is described by H, NAME, SYM, PSEC, VALUE, and OVERRIDE.  We
    set DYNSYM if the new indirect symbol is dynamic. DT_NEEDED
    indicates if it comes from a DT_NEEDED entry of a shared object.  */
 
 static boolean
-elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
+elf_add_default_symbol (abfd, info, h, name, sym, psec, value,
                        dynsym, override, dt_needed)
      bfd *abfd;
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
      const char *name;
      Elf_Internal_Sym *sym;
-     asection **sec;
+     asection **psec;
      bfd_vma *value;
      boolean *dynsym;
      boolean override;
@@ -921,11 +921,13 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   boolean size_change_ok;
   char *shortname;
   struct elf_link_hash_entry *hi;
+  struct bfd_link_hash_entry *bh;
   struct elf_backend_data *bed;
   boolean collect;
   boolean dynamic;
   char *p;
   size_t len, shortlen;
+  asection *sec;
 
   /* If this symbol has a version, and it is the default version, we
      create an indirect symbol from the default name to the fully
@@ -970,18 +972,20 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
      actually going to define an indirect symbol.  */
   type_change_ok = false;
   size_change_ok = false;
-  if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+  sec = *psec;
+  if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
                          &hi, &override, &type_change_ok,
                          &size_change_ok, dt_needed))
     return false;
 
   if (! override)
     {
+      bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT, bfd_ind_section_ptr,
-             (bfd_vma) 0, name, false, collect,
-             (struct bfd_link_hash_entry **) &hi)))
+             (bfd_vma) 0, name, false, collect, &bh)))
        return false;
+      hi = (struct elf_link_hash_entry *) bh;
     }
   else
     {
@@ -1042,7 +1046,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
                      | ELF_LINK_HASH_DEF_REGULAR)) == 0);
 
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
-      (*bed->elf_backend_copy_indirect_symbol) (ht, hi);
+      (*bed->elf_backend_copy_indirect_symbol) (bed, ht, hi);
 
       /* See if the new flags lead us to realize that the symbol must
         be dynamic.  */
@@ -1077,7 +1081,8 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   /* Once again, merge with any existing symbol.  */
   type_change_ok = false;
   size_change_ok = false;
-  if (! elf_merge_symbol (abfd, info, shortname, sym, sec, value,
+  sec = *psec;
+  if (! elf_merge_symbol (abfd, info, shortname, sym, &sec, value,
                          &hi, &override, &type_change_ok,
                          &size_change_ok, dt_needed))
     return false;
@@ -1085,18 +1090,22 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
   if (override)
     {
       /* Here SHORTNAME is a versioned name, so we don't expect to see
-        the type of override we do in the case above.  */
-      (*_bfd_error_handler)
-       (_("%s: warning: unexpected redefinition of `%s'"),
-        bfd_archive_filename (abfd), shortname);
+        the type of override we do in the case above unless it is
+        overridden by a versioned definiton.  */
+      if (hi->root.type != bfd_link_hash_defined
+         && hi->root.type != bfd_link_hash_defweak)
+       (*_bfd_error_handler)
+         (_("%s: warning: unexpected redefinition of indirect versioned symbol `%s'"),
+          bfd_archive_filename (abfd), shortname);
     }
   else
     {
+      bh = &hi->root;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, shortname, BSF_INDIRECT,
-             bfd_ind_section_ptr, (bfd_vma) 0, name, false,
-             collect, (struct bfd_link_hash_entry **) &hi)))
+             bfd_ind_section_ptr, (bfd_vma) 0, name, false, collect, &bh)))
        return false;
+      hi = (struct elf_link_hash_entry *) bh;
 
       /* If there is a duplicate definition somewhere, then HI may not
         point to an indirect symbol.  We will have reported an error
@@ -1110,7 +1119,7 @@ elf_add_default_symbol (abfd, info, h, name, sym, sec, value,
                       & (ELF_LINK_HASH_DEF_DYNAMIC
                          | ELF_LINK_HASH_DEF_REGULAR)) == 0);
 
-         (*bed->elf_backend_copy_indirect_symbol) (h, hi);
+         (*bed->elf_backend_copy_indirect_symbol) (bed, h, hi);
 
          /* See if the new flags lead us to realize that the symbol
             must be dynamic.  */
@@ -1289,6 +1298,14 @@ elf_link_add_object_symbols (abfd, info)
       const char *name;
       bfd_size_type oldsize;
       bfd_size_type strindex;
+      struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
+
+      /* ld --just-symbols and dynamic objects don't mix very well.
+        Test for --just-symbols by looking at info set up by
+        _bfd_elf_link_just_syms.  */
+      if ((s = abfd->sections) != NULL
+         && elf_section_data (s)->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
+       goto error_return;
 
       /* Find the name to use in a DT_NEEDED entry that refers to this
         object.  If the object has a DT_SONAME entry, we use it.
@@ -1318,8 +1335,6 @@ elf_link_add_object_symbols (abfd, info)
          Elf_External_Dyn *extdynend;
          int elfsec;
          unsigned long shlink;
-         int rpath;
-         int runpath;
 
          dynbuf = (Elf_External_Dyn *) bfd_malloc (s->_raw_size);
          if (dynbuf == NULL)
@@ -1336,8 +1351,6 @@ elf_link_add_object_symbols (abfd, info)
 
          extdyn = dynbuf;
          extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
-         rpath = 0;
-         runpath = 0;
          for (; extdyn < extdynend; extdyn++)
            {
              Elf_Internal_Dyn dyn;
@@ -1381,13 +1394,6 @@ elf_link_add_object_symbols (abfd, info)
                  char *fnm, *anm;
                  unsigned int tagv = dyn.d_un.d_val;
 
-                 /* When we see DT_RPATH before DT_RUNPATH, we have
-                    to clear runpath.  Do _NOT_ bfd_release, as that
-                    frees all more recently bfd_alloc'd blocks as
-                    well.  */
-                 if (rpath && hash_table->runpath)
-                   hash_table->runpath = NULL;
-
                  amt = sizeof (struct bfd_link_needed_list);
                  n = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
                  fnm = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
@@ -1401,13 +1407,11 @@ elf_link_add_object_symbols (abfd, info)
                  n->name = anm;
                  n->by = abfd;
                  n->next = NULL;
-                 for (pn = & hash_table->runpath;
+                 for (pn = & runpath;
                       *pn != NULL;
                       pn = &(*pn)->next)
                    ;
                  *pn = n;
-                 runpath = 1;
-                 rpath = 0;
                }
              /* Ignore DT_RPATH if we have seen DT_RUNPATH.  */
              if (!runpath && dyn.d_tag == DT_RPATH)
@@ -1433,18 +1437,32 @@ elf_link_add_object_symbols (abfd, info)
                  n->name = anm;
                  n->by = abfd;
                  n->next = NULL;
-                 for (pn = & hash_table->runpath;
+                 for (pn = & rpath;
                       *pn != NULL;
                       pn = &(*pn)->next)
                    ;
                  *pn = n;
-                 rpath = 1;
                }
            }
 
          free (dynbuf);
        }
 
+      /* DT_RUNPATH overrides DT_RPATH.  Do _NOT_ bfd_release, as that
+        frees all more recently bfd_alloc'd blocks as well.  */
+      if (runpath)
+       rpath = runpath;
+
+      if (rpath)
+       {
+         struct bfd_link_needed_list **pn;
+         for (pn = & hash_table->runpath;
+              *pn != NULL;
+              pn = &(*pn)->next)
+           ;
+         *pn = rpath;
+       }
+
       /* We do not want to include any of the sections in a dynamic
         object in the output file.  We hack by simply clobbering the
         list of sections in the BFD.  This could be handled more
@@ -2286,6 +2304,7 @@ elf_link_create_dynamic_sections (abfd, info)
   flagword flags;
   register asection *s;
   struct elf_link_hash_entry *h;
+  struct bfd_link_hash_entry *bh;
   struct elf_backend_data *bed;
 
   if (! is_elf_hash_table (info))
@@ -2378,12 +2397,12 @@ elf_link_create_dynamic_sections (abfd, info)
      creating a .dynamic section.  We don't want to define it if there
      is no .dynamic section, since on some ELF platforms the start up
      code examines it to decide how to initialize the process.  */
-  h = NULL;
+  bh = NULL;
   if (! (_bfd_generic_link_add_one_symbol
         (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
-         (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
-         (struct bfd_link_hash_entry **) &h)))
+         (const char *) 0, false, get_elf_backend_data (abfd)->collect, &bh)))
     return false;
+  h = (struct elf_link_hash_entry *) bh;
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
 
@@ -3062,8 +3081,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                }
              free (newname);
 
-             /* Mark this version if there is a definition.  */
+             /* Mark this version if there is a definition and it is
+                not defined in a shared object.  */
              if (newh != NULL
+                 && ((newh->elf_link_hash_flags
+                      & ELF_LINK_HASH_DEF_DYNAMIC) == 0)
                  && (newh->root.type == bfd_link_hash_defined
                      || newh->root.type == bfd_link_hash_defweak))
                d->symver = 1;
@@ -3317,19 +3339,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
              unsigned int cdeps;
              struct bfd_elf_version_deps *n;
              struct elf_link_hash_entry *h;
+             struct bfd_link_hash_entry *bh;
 
              cdeps = 0;
              for (n = t->deps; n != NULL; n = n->next)
                ++cdeps;
 
              /* Add a symbol representing this version.  */
-             h = NULL;
+             bh = NULL;
              if (! (_bfd_generic_link_add_one_symbol
                     (info, dynobj, t->name, BSF_GLOBAL, bfd_abs_section_ptr,
                      (bfd_vma) 0, (const char *) NULL, false,
-                     get_elf_backend_data (dynobj)->collect,
-                     (struct bfd_link_hash_entry **) &h)))
+                     get_elf_backend_data (dynobj)->collect, &bh)))
                return false;
+             h = (struct elf_link_hash_entry *) bh;
              h->elf_link_hash_flags &= ~ ELF_LINK_NON_ELF;
              h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
              h->type = STT_OBJECT;
@@ -3877,9 +3900,12 @@ elf_fix_symbol_flags (h, eif)
     {
       struct elf_link_hash_entry *weakdef;
 
+      weakdef = h->weakdef;
+      if (h->root.type == bfd_link_hash_indirect)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
       BFD_ASSERT (h->root.type == bfd_link_hash_defined
                  || h->root.type == bfd_link_hash_defweak);
-      weakdef = h->weakdef;
       BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
                  || weakdef->root.type == bfd_link_hash_defweak);
       BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
@@ -3894,7 +3920,7 @@ elf_fix_symbol_flags (h, eif)
          struct elf_backend_data *bed;
 
          bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj);
-         (*bed->elf_backend_copy_indirect_symbol) (weakdef, h);
+         (*bed->elf_backend_copy_indirect_symbol) (bed, weakdef, h);
        }
     }
 
@@ -4468,6 +4494,8 @@ struct elf_final_link_info
   size_t symbuf_count;
   /* Number of symbols which fit in symbuf.  */
   size_t symbuf_size;
+  /* And same for symshndxbuf.  */
+  size_t shndxbuf_size;
 };
 
 static boolean elf_link_output_sym
@@ -4643,8 +4671,9 @@ struct elf_link_sort_rela
   enum elf_reloc_type_class type;
   union
   {
-    Elf_Internal_Rel rel;
-    Elf_Internal_Rela rela;
+    /* We use these as arrays of size int_rels_per_ext_rel.  */
+    Elf_Internal_Rel rel[1];
+    Elf_Internal_Rela rela[1];
   } u;
 };
 
@@ -4664,13 +4693,13 @@ elf_link_sort_cmp1 (A, B)
     return 1;
   if (relativea > relativeb)
     return -1;
-  if (ELF_R_SYM (a->u.rel.r_info) < ELF_R_SYM (b->u.rel.r_info))
+  if (ELF_R_SYM (a->u.rel->r_info) < ELF_R_SYM (b->u.rel->r_info))
     return -1;
-  if (ELF_R_SYM (a->u.rel.r_info) > ELF_R_SYM (b->u.rel.r_info))
+  if (ELF_R_SYM (a->u.rel->r_info) > ELF_R_SYM (b->u.rel->r_info))
     return 1;
-  if (a->u.rel.r_offset < b->u.rel.r_offset)
+  if (a->u.rel->r_offset < b->u.rel->r_offset)
     return -1;
-  if (a->u.rel.r_offset > b->u.rel.r_offset)
+  if (a->u.rel->r_offset > b->u.rel->r_offset)
     return 1;
   return 0;
 }
@@ -4694,9 +4723,9 @@ elf_link_sort_cmp2 (A, B)
     return -1;
   if (copya > copyb)
     return 1;
-  if (a->u.rel.r_offset < b->u.rel.r_offset)
+  if (a->u.rel->r_offset < b->u.rel->r_offset)
     return -1;
-  if (a->u.rel.r_offset > b->u.rel.r_offset)
+  if (a->u.rel->r_offset > b->u.rel->r_offset)
     return 1;
   return 0;
 }
@@ -4714,6 +4743,7 @@ elf_link_sort_relocs (abfd, info, psec)
   size_t i, j, ret;
   struct elf_link_sort_rela *rela;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int i2e = bed->s->int_rels_per_ext_rel;
 
   reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
   if (reldyn == NULL || reldyn->_raw_size == 0)
@@ -4737,7 +4767,23 @@ elf_link_sort_relocs (abfd, info, psec)
   if (size != reldyn->_raw_size)
     return 0;
 
-  rela = (struct elf_link_sort_rela *) bfd_zmalloc (sizeof (*rela) * count);
+  /* We waste some memory here when N = i2e is greater than 1, since
+     we allocate space for N * sizeof (*rela) where sizeof (*rela) +
+     (N - 1) * sizeof (Elf_Internal_Rel/Rela) would do.  Also, we use
+     rela[k] only when k is a multiple of N, and then we index the
+     array within the union, such that rela[k].u.rel[i], i < N, is the
+     (i+1)th internal relocation corresponding to the (k/N)th external
+     relocation.  This is done such that the relocation swap-in and
+     swap-out functions can gen pointers to arrays of internal
+     relocations that form a single external relocation.
+
+     If C permitted arrays of structures with dynamic sizes, we could
+     do better, but trying to avoid wasting space at the end of the
+     chunk from rela[k] to rela[k+N-1] would require us to allocate a
+     separate array of pointers and since most ports have N == 1, this
+     would be more wasteful.  */
+  rela = (struct elf_link_sort_rela *) bfd_zmalloc
+    (sizeof (*rela) * count * i2e);
   if (rela == NULL)
     {
       (*info->callbacks->warning)
@@ -4758,15 +4804,16 @@ elf_link_sort_relocs (abfd, info, psec)
 
            erel = (Elf_External_Rel *) o->contents;
            erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
-           s = rela + o->output_offset / sizeof (Elf_External_Rel);
-           for (; erel < erelend; erel++, s++)
+           s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+           for (; erel < erelend; erel++, s += i2e)
              {
                if (bed->s->swap_reloc_in)
-                 (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel, &s->u.rel);
+                 (*bed->s->swap_reloc_in) (abfd, (bfd_byte *) erel,
+                                           s->u.rel);
                else
-                 elf_swap_reloc_in (abfd, erel, &s->u.rel);
+                 elf_swap_reloc_in (abfd, erel, s->u.rel);
 
-               s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+               s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
              }
          }
        else
@@ -4776,30 +4823,34 @@ elf_link_sort_relocs (abfd, info, psec)
 
            erela = (Elf_External_Rela *) o->contents;
            erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
-           s = rela + o->output_offset / sizeof (Elf_External_Rela);
-           for (; erela < erelaend; erela++, s++)
+           s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+           for (; erela < erelaend; erela++, s += i2e)
              {
                if (bed->s->swap_reloca_in)
                  (*bed->s->swap_reloca_in) (dynobj, (bfd_byte *) erela,
-                                            &s->u.rela);
+                                            s->u.rela);
                else
-                 elf_swap_reloca_in (dynobj, erela, &s->u.rela);
+                 elf_swap_reloca_in (dynobj, erela, s->u.rela);
 
-               s->type = (*bed->elf_backend_reloc_type_class) (&s->u.rela);
+               s->type = (*bed->elf_backend_reloc_type_class) (s->u.rela);
              }
          }
       }
 
-  qsort (rela, (size_t) count, sizeof (*rela), elf_link_sort_cmp1);
-  for (ret = 0; ret < count && rela[ret].type == reloc_class_relative; ret++)
+  qsort (rela, (size_t) count, sizeof (*rela) * i2e, elf_link_sort_cmp1);
+  for (ret = 0; ret < count * i2e && rela[ret].type == reloc_class_relative;
+       ret += i2e)
     ;
-  for (i = ret, j = ret; i < count; i++)
+  for (i = ret, j = ret; i < count * i2e; i += i2e)
     {
-      if (ELF_R_SYM (rela[i].u.rel.r_info) != ELF_R_SYM (rela[j].u.rel.r_info))
+      if (ELF_R_SYM (rela[i].u.rel->r_info)
+         != ELF_R_SYM (rela[j].u.rel->r_info))
        j = i;
-      rela[i].offset = rela[j].u.rel.r_offset;
+      rela[i].offset = rela[j].u.rel->r_offset;
     }
-  qsort (rela + ret, (size_t) count - ret, sizeof (*rela), elf_link_sort_cmp2);
+  ret /= i2e;
+  qsort (rela + ret, (size_t) count - ret,
+        sizeof (*rela) * i2e, elf_link_sort_cmp2);
 
   for (o = dynobj->sections; o != NULL; o = o->next)
     if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
@@ -4813,14 +4864,14 @@ elf_link_sort_relocs (abfd, info, psec)
 
            erel = (Elf_External_Rel *) o->contents;
            erelend = (Elf_External_Rel *) (o->contents + o->_raw_size);
-           s = rela + o->output_offset / sizeof (Elf_External_Rel);
-           for (; erel < erelend; erel++, s++)
+           s = rela + (o->output_offset / sizeof (Elf_External_Rel) * i2e);
+           for (; erel < erelend; erel++, s += i2e)
              {
                if (bed->s->swap_reloc_out)
-                 (*bed->s->swap_reloc_out) (abfd, &s->u.rel,
+                 (*bed->s->swap_reloc_out) (abfd, s->u.rel,
                                             (bfd_byte *) erel);
                else
-                 elf_swap_reloc_out (abfd, &s->u.rel, erel);
+                 elf_swap_reloc_out (abfd, s->u.rel, erel);
              }
          }
        else
@@ -4830,14 +4881,14 @@ elf_link_sort_relocs (abfd, info, psec)
 
            erela = (Elf_External_Rela *) o->contents;
            erelaend = (Elf_External_Rela *) (o->contents + o->_raw_size);
-           s = rela + o->output_offset / sizeof (Elf_External_Rela);
-           for (; erela < erelaend; erela++, s++)
+           s = rela + (o->output_offset / sizeof (Elf_External_Rela) * i2e);
+           for (; erela < erelaend; erela++, s += i2e)
              {
                if (bed->s->swap_reloca_out)
-                 (*bed->s->swap_reloca_out) (dynobj, &s->u.rela,
+                 (*bed->s->swap_reloca_out) (dynobj, s->u.rela,
                                              (bfd_byte *) erela);
                else
-                 elf_swap_reloca_out (dynobj, &s->u.rela, erela);
+                 elf_swap_reloca_out (dynobj, s->u.rela, erela);
              }
          }
       }
@@ -4870,6 +4921,7 @@ elf_bfd_final_link (abfd, info)
   Elf_Internal_Sym elfsym;
   unsigned int i;
   Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *symtab_shndx_hdr;
   Elf_Internal_Shdr *symstrtab_hdr;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_outext_info eoinfo;
@@ -4923,6 +4975,7 @@ elf_bfd_final_link (abfd, info)
   finfo.symbuf = NULL;
   finfo.symshndxbuf = NULL;
   finfo.symbuf_count = 0;
+  finfo.shndxbuf_size = 0;
   finfo.first_tls_sec = NULL;
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     if ((o->flags & SEC_THREAD_LOCAL) != 0
@@ -5143,9 +5196,7 @@ elf_bfd_final_link (abfd, info)
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   /* sh_name is set in prep_headers.  */
   symtab_hdr->sh_type = SHT_SYMTAB;
-  symtab_hdr->sh_flags = 0;
-  symtab_hdr->sh_addr = 0;
-  symtab_hdr->sh_size = 0;
+  /* sh_flags, sh_addr and sh_size all start off zero.  */
   symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
   /* sh_link is set in assign_section_numbers.  */
   /* sh_info is set below.  */
@@ -5172,9 +5223,11 @@ elf_bfd_final_link (abfd, info)
     goto error_return;
   if (elf_numsections (abfd) > SHN_LORESERVE)
     {
-      amt = finfo.symbuf_size;
+      /* Wild guess at number of output symbols.  realloc'd as needed.  */
+      amt = 2 * max_sym_count + elf_numsections (abfd) + 1000;
+      finfo.shndxbuf_size = amt;
       amt *= sizeof (Elf_External_Sym_Shndx);
-      finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+      finfo.symshndxbuf = (Elf_External_Sym_Shndx *) bfd_zmalloc (amt);
       if (finfo.symshndxbuf == NULL)
        goto error_return;
     }
@@ -5234,7 +5287,7 @@ elf_bfd_final_link (abfd, info)
          if (! elf_link_output_sym (&finfo, (const char *) NULL,
                                     &elfsym, o))
            goto error_return;
-         if (i == SHN_LORESERVE)
+         if (i == SHN_LORESERVE - 1)
            i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
        }
     }
@@ -5509,6 +5562,24 @@ elf_bfd_final_link (abfd, info)
   /* Now we know the size of the symtab section.  */
   off += symtab_hdr->sh_size;
 
+  symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  if (symtab_shndx_hdr->sh_name != 0)
+    {
+      symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+      symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+      symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+      amt = bfd_get_symcount (abfd) * sizeof (Elf_External_Sym_Shndx);
+      symtab_shndx_hdr->sh_size = amt;
+
+      off = _bfd_elf_assign_file_position_for_section (symtab_shndx_hdr,
+                                                      off, true);
+
+      if (bfd_seek (abfd, symtab_shndx_hdr->sh_offset, SEEK_SET) != 0
+         || (bfd_bwrite ((PTR) finfo.symshndxbuf, amt, abfd) != amt))
+       return false;
+    }
+
+
   /* Finish up and write out the symbol string table (.strtab)
      section.  */
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
@@ -5817,7 +5888,7 @@ elf_bfd_final_link (abfd, info)
   if (finfo.symbuf != NULL)
     free (finfo.symbuf);
   if (finfo.symshndxbuf != NULL)
-    free (finfo.symbuf);
+    free (finfo.symshndxbuf);
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       if ((o->flags & SEC_RELOC) != 0
@@ -5851,7 +5922,7 @@ elf_bfd_final_link (abfd, info)
   if (finfo.symbuf != NULL)
     free (finfo.symbuf);
   if (finfo.symshndxbuf != NULL)
-    free (finfo.symbuf);
+    free (finfo.symshndxbuf);
   for (o = abfd->sections; o != NULL; o = o->next)
     {
       if ((o->flags & SEC_RELOC) != 0
@@ -5910,11 +5981,24 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
   dest = finfo->symbuf + finfo->symbuf_count;
   destshndx = finfo->symshndxbuf;
   if (destshndx != NULL)
-    destshndx += finfo->symbuf_count;
-  elf_swap_symbol_out (finfo->output_bfd, elfsym, (PTR) dest, (PTR) destshndx);
-  ++finfo->symbuf_count;
+    {
+      if (bfd_get_symcount (finfo->output_bfd) >= finfo->shndxbuf_size)
+       {
+         bfd_size_type amt;
+
+         amt = finfo->shndxbuf_size * sizeof (Elf_External_Sym_Shndx);
+         finfo->symshndxbuf = destshndx = bfd_realloc (destshndx, amt * 2);
+         if (destshndx == NULL)
+           return false;
+         memset ((char *) destshndx + amt, 0, amt);
+         finfo->shndxbuf_size *= 2;
+       }
+      destshndx += bfd_get_symcount (finfo->output_bfd);
+    }
 
-  ++ bfd_get_symcount (finfo->output_bfd);
+  elf_swap_symbol_out (finfo->output_bfd, elfsym, (PTR) dest, (PTR) destshndx);
+  finfo->symbuf_count += 1;
+  bfd_get_symcount (finfo->output_bfd) += 1;
 
   return true;
 }
@@ -5939,20 +6023,6 @@ elf_link_flush_output_syms (finfo)
        return false;
 
       hdr->sh_size += amt;
-
-      if (finfo->symshndxbuf != NULL)
-       {
-         hdr = &elf_tdata (finfo->output_bfd)->symtab_shndx_hdr;
-         pos = hdr->sh_offset + hdr->sh_size;
-         amt = finfo->symbuf_count * sizeof (Elf_External_Sym_Shndx);
-         if (bfd_seek (finfo->output_bfd, pos, SEEK_SET) != 0
-             || (bfd_bwrite ((PTR) finfo->symshndxbuf, amt, finfo->output_bfd)
-                 != amt))
-           return false;
-
-         hdr->sh_size += amt;
-       }
-
       finfo->symbuf_count = 0;
     }
 
@@ -6803,20 +6873,12 @@ elf_link_input_bfd (finfo, input_bfd)
                           || h->root.type == bfd_link_hash_defweak)
                          && elf_discarded_section (h->root.u.def.section))
                        {
-#if BFD_VERSION_DATE < 20031005
                          if ((o->flags & SEC_DEBUGGING) != 0)
                            {
-#if BFD_VERSION_DATE > 20021005
-                             (*finfo->info->callbacks->warning)
-                               (finfo->info,
-                                _("warning: relocation against removed section; zeroing"),
-                                NULL, input_bfd, o, rel->r_offset);
-#endif
                              BFD_ASSERT (r_symndx != 0);
                              memset (rel, 0, sizeof (*rel));
                            }
                          else
-#endif
                            {
                              if (! ((*finfo->info->callbacks->undefined_symbol)
                                     (finfo->info, h->root.root.string,
@@ -6832,23 +6894,15 @@ elf_link_input_bfd (finfo, input_bfd)
 
                      if (sec != NULL && elf_discarded_section (sec))
                        {
-#if BFD_VERSION_DATE < 20031005
                          if ((o->flags & SEC_DEBUGGING) != 0
                              || (sec->flags & SEC_LINK_ONCE) != 0)
                            {
-#if BFD_VERSION_DATE > 20021005
-                             (*finfo->info->callbacks->warning)
-                               (finfo->info,
-                                _("warning: relocation against removed section"),
-                                NULL, input_bfd, o, rel->r_offset);
-#endif
                              BFD_ASSERT (r_symndx != 0);
                              rel->r_info
                                = ELF_R_INFO (0, ELF_R_TYPE (rel->r_info));
                              rel->r_addend = 0;
                            }
                          else
-#endif
                            {
                              boolean ok;
                              const char *msg
@@ -8470,7 +8524,12 @@ elf_bfd_discard_info (output_bfd, info)
          if (_bfd_elf_discard_section_eh_frame (abfd, info, eh, ehdr,
                                                 elf_reloc_symbol_deleted_p,
                                                 &cookie))
-           ret = true;
+           {
+             /* Relocs have been edited.  Ensure edited version is
+                used later in relocate_section.  */
+             elf_section_data (eh)->relocs = cookie.rels;
+             ret = true;
+           }
          if (cookie.rels && elf_section_data (eh)->relocs != cookie.rels)
            free (cookie.rels);
        }
This page took 0.031881 seconds and 4 git commands to generate.