* section.c (_bfd_strip_section_from_output): Add info parameter.
[deliverable/binutils-gdb.git] / bfd / elflink.h
index cfb49098827c4b8d4b6727feeb45804b68b87397..ce71d948c43f894a8357428221f3422d004899f4 100644 (file)
@@ -80,6 +80,138 @@ elf_bfd_link_add_symbols (abfd, info)
     }
 }
 \f
+/* Return true iff this is a non-common definition of a symbol.  */
+static boolean
+is_global_symbol_definition (abfd, sym)
+     bfd * abfd;
+     Elf_Internal_Sym * sym;
+{
+  /* Local symbols do not count, but target specific ones might.  */
+  if (ELF_ST_BIND (sym->st_info) != STB_GLOBAL
+      && ELF_ST_BIND (sym->st_info) < STB_LOOS)
+    return false;
+
+  /* If the section is undefined, then so is the symbol.  */
+  if (sym->st_shndx == SHN_UNDEF)
+    return false;
+  
+  /* If the symbol is defined in the common section, then
+     it is a common definition and so does not count.  */
+  if (sym->st_shndx == SHN_COMMON)
+    return false;
+
+  /* If the symbol is in a target specific section then we
+     must rely upon the backend to tell us what it is.  */
+  if (sym->st_shndx >= SHN_LORESERVE && sym->st_shndx < SHN_ABS)
+    /* FIXME - this function is not coded yet:
+       
+       return _bfd_is_global_symbol_definition (abfd, sym);
+       
+       Instead for now assume that the definition is not global,
+       Even if this is wrong, at least the linker will behave
+       in the same way that it used to do.  */
+    return false;
+      
+  return true;
+}
+
+
+/* Search the symbol table of the archive element of the archive ABFD
+   whoes archove map contains a mention of SYMDEF, and determine if
+   the symbol is defined in this element.  */
+static boolean
+elf_link_is_defined_archive_symbol (abfd, symdef)
+     bfd * abfd;
+     carsym * symdef;
+{
+  Elf_Internal_Shdr * hdr;
+  Elf_External_Sym *  esym;
+  Elf_External_Sym *  esymend;
+  Elf_External_Sym *  buf = NULL;
+  size_t symcount;
+  size_t extsymcount;
+  size_t extsymoff;
+  boolean result = false;
+  
+  abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+  if (abfd == (bfd *) NULL)
+    return false;
+
+  if (! bfd_check_format (abfd, bfd_object))
+    return false;
+
+  /* If we have already included the element containing this symbol in the
+     link then we do not need to include it again.  Just claim that any symbol
+     it contains is not a definition, so that our caller will not decide to
+     (re)include this element.  */
+  if (abfd->archive_pass)
+    return false;
+  
+  /* Select the appropriate symbol table.  */
+  if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
+    hdr = &elf_tdata (abfd)->symtab_hdr;
+  else
+    hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+
+  symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+
+  /* The sh_info field of the symtab header tells us where the
+     external symbols start.  We don't care about the local symbols.  */
+  if (elf_bad_symtab (abfd))
+    {
+      extsymcount = symcount;
+      extsymoff = 0;
+    }
+  else
+    {
+      extsymcount = symcount - hdr->sh_info;
+      extsymoff = hdr->sh_info;
+    }
+
+  buf = ((Elf_External_Sym *)
+        bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
+  if (buf == NULL && extsymcount != 0)
+    return false;
+
+  /* Read in the symbol table.
+     FIXME:  This ought to be cached somewhere.  */
+  if (bfd_seek (abfd,
+               hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
+               SEEK_SET) != 0
+      || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
+         != extsymcount * sizeof (Elf_External_Sym)))
+    {
+      free (buf);
+      return false;
+    }
+
+  /* Scan the symbol table looking for SYMDEF.  */
+  esymend = buf + extsymcount;
+  for (esym = buf;
+       esym < esymend;
+       esym++)
+    {
+      Elf_Internal_Sym sym;
+      const char * name;
+
+      elf_swap_symbol_in (abfd, esym, & sym);
+
+      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+      if (name == (const char *) NULL)
+       break;
+
+      if (strcmp (name, symdef->name) == 0)
+       {
+         result = is_global_symbol_definition (abfd, & sym);
+         break;
+       }
+    }
+
+  free (buf);
+  
+  return result;
+}
+\f
 
 /* Add symbols from an ELF archive file to the linker hash table.  We
    don't use _bfd_generic_link_add_archive_symbols because of a
@@ -200,7 +332,24 @@ elf_link_add_archive_symbols (abfd, info)
          if (h == NULL)
            continue;
 
-         if (h->root.type != bfd_link_hash_undefined)
+         if (h->root.type == bfd_link_hash_common)
+           {
+             /* We currently have a common symbol.  The archive map contains
+                a reference to this symbol, so we may want to include it.  We
+                only want to include it however, if this archive element
+                contains a definition of the symbol, not just another common
+                declaration of it.
+
+                Unfortunately some archivers (including GNU ar) will put
+                declarations of common symbols into their archive maps, as
+                well as real definitions, so we cannot just go by the archive
+                map alone.  Instead we must read in the element's symbol
+                table and check that to see what kind of symbol definition
+                this is.  */
+             if (! elf_link_is_defined_archive_symbol (abfd, symdef))
+               continue;
+           }
+         else if (h->root.type != bfd_link_hash_undefined)
            {
              if (h->root.type != bfd_link_hash_undefweak)
                defined[i] = true;
@@ -384,10 +533,35 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
   else
     newdyn = false;
 
-  if (oldbfd == NULL || (oldbfd->flags & DYNAMIC) == 0)
-    olddyn = false;
+  if (oldbfd != NULL)
+    olddyn = (oldbfd->flags & DYNAMIC) != 0;
   else
-    olddyn = true;
+    {
+      asection *hsec;
+
+      /* This code handles the special SHN_MIPS_{TEXT,DATA} section
+         indices used by MIPS ELF.  */
+      switch (h->root.type)
+       {
+       default:
+         hsec = NULL;
+         break;
+
+       case bfd_link_hash_defined:
+       case bfd_link_hash_defweak:
+         hsec = h->root.u.def.section;
+         break;
+
+       case bfd_link_hash_common:
+         hsec = h->root.u.c.p->section;
+         break;
+       }
+
+      if (hsec == NULL)
+       olddyn = false;
+      else
+       olddyn = (hsec->symbol->flags & BSF_DYNAMIC) != 0;
+    }
 
   /* NEWDEF and OLDDEF indicate whether the new or old symbol,
      respectively, appear to be a definition rather than reference.  */
@@ -658,8 +832,12 @@ elf_merge_symbol (abfd, info, name, sym, psec, pvalue, sym_hash,
       /* To make this work we have to frob the flags so that the rest
          of the code does not think we are using the regular
          definition.  */
-      h->elf_link_hash_flags &= ~ ELF_LINK_HASH_DEF_REGULAR;
-      h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+      if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+       h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+      else if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0)
+       h->elf_link_hash_flags |= ELF_LINK_HASH_REF_DYNAMIC;
+      h->elf_link_hash_flags &= ~ (ELF_LINK_HASH_DEF_REGULAR
+                                  | ELF_LINK_HASH_DEF_DYNAMIC);
 
       /* If H is the target of an indirection, we want the caller to
          use H rather than the indirect symbol.  Otherwise if we are
@@ -929,6 +1107,23 @@ elf_link_add_object_symbols (abfd, info)
            goto error_return;
          link = elf_elfsections (abfd)[elfsec]->sh_link;
 
+         {
+           /* The shared libraries distributed with hpux11 have a bogus
+              sh_link field for the ".dynamic" section.  This code detects
+              when LINK refers to a section that is not a string table and
+              tries to find the string table for the ".dynsym" section
+              instead.  */
+           Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[link];
+           if (hdr->sh_type != SHT_STRTAB)
+             {
+               asection *s = bfd_get_section_by_name (abfd, ".dynsym");
+               int elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+               if (elfsec == -1)
+                 goto error_return;
+               link = elf_elfsections (abfd)[elfsec]->sh_link;
+             }
+         }
+
          extdyn = dynbuf;
          extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
          for (; extdyn < extdynend; extdyn++)
@@ -1371,9 +1566,24 @@ elf_link_add_object_symbols (abfd, info)
              h->type = ELF_ST_TYPE (sym.st_info);
            }
 
-         if (sym.st_other != 0
-             && (definition || h->other == 0))
-           h->other = sym.st_other;
+         /* If st_other has a processor-specific meaning, specific code
+            might be needed here.  */
+         if (sym.st_other != 0)
+           {
+             /* Combine visibilities, using the most constraining one.  */
+             unsigned char hvis   = ELF_ST_VISIBILITY (h->other);
+             unsigned char symvis = ELF_ST_VISIBILITY (sym.st_other);
+             
+             if (symvis && (hvis > symvis || hvis == 0))
+               h->other = sym.st_other;
+             
+             /* If neither has visibility, use the st_other of the
+                definition.  This is an arbitrary choice, since the
+                other bits have no general meaning.  */
+             if (!symvis && !hvis
+                 && (definition || h->other == 0))
+               h->other = sym.st_other;
+           }
 
          /* Set a flag in the hash table entry indicating the type of
             reference or definition we just found.  Keep a count of
@@ -1532,7 +1742,8 @@ elf_link_add_object_symbols (abfd, info)
                        (hi->elf_link_hash_flags
                         & (ELF_LINK_HASH_REF_DYNAMIC
                            | ELF_LINK_HASH_REF_REGULAR
-                           | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+                           | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+                           | ELF_LINK_NON_GOT_REF));
 
                      /* Copy over the global and procedure linkage table
                         offset entries.  These may have been already set
@@ -1641,7 +1852,8 @@ elf_link_add_object_symbols (abfd, info)
                            (hi->elf_link_hash_flags
                             & (ELF_LINK_HASH_REF_DYNAMIC
                                | ELF_LINK_HASH_REF_REGULAR
-                               | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+                               | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+                               | ELF_LINK_NON_GOT_REF));
 
                          /* Copy over the global and procedure linkage
                              table offset entries.  These may have been
@@ -2346,7 +2558,10 @@ NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide)
     h->verinfo.verdef = NULL;
 
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
-  h->type = STT_OBJECT;
+
+  /* When possible, keep the original type of the symbol */
+  if (h->type == STT_NOTYPE)
+    h->type = STT_OBJECT;
 
   if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
                                  | ELF_LINK_HASH_REF_DYNAMIC)) != 0
@@ -2603,20 +2818,6 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   if (dynobj == NULL)
     return true;
 
-  /* If we are supposed to export all symbols into the dynamic symbol
-     table (this is not the normal case), then do so.  */
-  if (export_dynamic)
-    {
-      struct elf_info_failed eif;
-
-      eif.failed = false;
-      eif.info = info;
-      elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
-                             (PTR) &eif);
-      if (eif.failed)
-       return false;
-    }
-
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       struct elf_info_failed eif;
@@ -2679,6 +2880,20 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
            }
        }
 
+      /* If we are supposed to export all symbols into the dynamic symbol
+         table (this is not the normal case), then do so.  */
+      if (export_dynamic)
+       {
+         struct elf_info_failed eif;
+
+         eif.failed = false;
+         eif.info = info;
+         elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
+                                 (PTR) &eif);
+         if (eif.failed)
+           return false;
+       }
+
       /* Attach all the symbols to their version information.  */
       asvinfo.output_bfd = output_bfd;
       asvinfo.info = info;
@@ -2766,7 +2981,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       verdefs = asvinfo.verdefs;
 
       if (verdefs == NULL)
-       _bfd_strip_section_from_output (s);
+       _bfd_strip_section_from_output (info, s);
       else
        {
          unsigned int cdefs;
@@ -2942,7 +3157,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
                                (PTR) &sinfo);
 
        if (elf_tdata (output_bfd)->verref == NULL)
-         _bfd_strip_section_from_output (s);
+         _bfd_strip_section_from_output (info, s);
        else
          {
            Elf_Internal_Verneed *t;
@@ -3046,7 +3261,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
       if (dynsymcount == 0
          || (verdefs == NULL && elf_tdata (output_bfd)->verref == NULL))
        {
-         _bfd_strip_section_from_output (s);
+         _bfd_strip_section_from_output (info, s);
          /* The DYNSYMCOUNT might have changed if we were going to
             output a dynamic symbol table entry for S.  */
          dynsymcount = _bfd_elf_link_renumber_dynsyms (output_bfd, info);
@@ -3203,6 +3418,33 @@ elf_fix_symbol_flags (h, eif)
       h->plt.offset = (bfd_vma) -1;
     }
 
+  /* If this is a weak defined symbol in a dynamic object, and we know
+     the real definition in the dynamic object, copy interesting flags
+     over to the real definition.  */
+  if (h->weakdef != NULL)
+    {
+      struct elf_link_hash_entry *weakdef;
+
+      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);
+
+      /* If the real definition is defined by a regular object file,
+        don't do anything special.  See the longer description in
+        elf_adjust_dynamic_symbol, below.  */
+      if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+       h->weakdef = NULL;
+      else
+       weakdef->elf_link_hash_flags |=
+         (h->elf_link_hash_flags
+          & (ELF_LINK_HASH_REF_REGULAR
+             | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+             | ELF_LINK_NON_GOT_REF));
+    }
+
   return true;
 }
 
@@ -3285,32 +3527,14 @@ elf_adjust_dynamic_symbol (h, data)
 
   if (h->weakdef != NULL)
     {
-      struct elf_link_hash_entry *weakdef;
+      /* If we get to this point, we know there is an implicit
+        reference by a regular object file via the weak symbol H.
+        FIXME: Is this really true?  What if the traversal finds
+        H->WEAKDEF before it finds H?  */
+      h->weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
 
-      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);
-      if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
-       {
-         /* This symbol is defined by a regular object file, so we
-            will not do anything special.  Clear weakdef for the
-            convenience of the processor backend.  */
-         h->weakdef = NULL;
-       }
-      else
-       {
-         /* There is an implicit reference by a regular object file
-            via the weak symbol.  */
-         weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
-         if (h->weakdef->elf_link_hash_flags
-             & ELF_LINK_HASH_REF_REGULAR_NONWEAK)
-           weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR_NONWEAK;
-         if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif))
-           return false;
-       }
+      if (! elf_adjust_dynamic_symbol (h->weakdef, (PTR) eif))
+       return false;
     }
 
   /* If a symbol has no type and no size and does not require a PLT
@@ -3761,34 +3985,38 @@ elf_link_size_reloc_section (abfd, rel_hdr, o)
      asection *o;
 {
   register struct elf_link_hash_entry **p, **pend;
+  unsigned reloc_count;
 
-  /* We are overestimating the size required for the relocation
-     sections, in the case that we are using both REL and RELA
-     relocations for a single section.  In that case, RELOC_COUNT will
-     be the total number of relocations required, and we allocate
-     space for that many REL relocations as well as that many RELA
-     relocations.  This approximation is wasteful of disk space.
-     However, until we keep track of how many of each kind of
-     relocation is required, it's difficult to calculate the right
-     value.  */
-  rel_hdr->sh_size = rel_hdr->sh_entsize * o->reloc_count;
+  /* Figure out how many relocations there will be.  */
+  if (rel_hdr == &elf_section_data (o)->rel_hdr)
+    reloc_count = elf_section_data (o)->rel_count;
+  else
+    reloc_count = elf_section_data (o)->rel_count2;
+
+  /* That allows us to calculate the size of the section.  */
+  rel_hdr->sh_size = rel_hdr->sh_entsize * reloc_count;
 
   /* The contents field must last into write_object_contents, so we
      allocate it with bfd_alloc rather than malloc.  */
   rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
   if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
     return false;
+  
+  /* We only allocate one set of hash entries, so we only do it the
+     first time we are called.  */
+  if (elf_section_data (o)->rel_hashes == NULL)
+    {
+      p = ((struct elf_link_hash_entry **)
+          bfd_malloc (o->reloc_count
+                      * sizeof (struct elf_link_hash_entry *)));
+      if (p == NULL && o->reloc_count != 0)
+       return false;
 
-  p = ((struct elf_link_hash_entry **)
-       bfd_malloc (o->reloc_count
-                  * sizeof (struct elf_link_hash_entry *)));
-  if (p == NULL && o->reloc_count != 0)
-    return false;
-
-  elf_section_data (o)->rel_hashes = p;
-  pend = p + o->reloc_count;
-  for (; p < pend; p++)
-    *p = NULL;
+      elf_section_data (o)->rel_hashes = p;
+      pend = p + o->reloc_count;
+      for (; p < pend; p++)
+       *p = NULL;
+    }
 
   return true;
 }
@@ -3997,6 +4225,54 @@ elf_bfd_final_link (abfd, info)
   if (! _bfd_elf_compute_section_file_positions (abfd, info))
     goto error_return;
 
+  /* Figure out how many relocations we will have in each section.
+     Just using RELOC_COUNT isn't good enough since that doesn't
+     maintain a separate value for REL vs. RELA relocations.  */
+  if (info->relocateable)
+    for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+      for (o = sub->sections; o != NULL; o = o->next)
+       {
+         asection *output_section;
+
+         if (! o->linker_mark)
+           {
+             /* This section was omitted from the link.  */
+             continue;
+           }
+
+         output_section = o->output_section;
+
+         if (output_section != NULL
+             && (o->flags & SEC_RELOC) != 0)
+           {
+             struct bfd_elf_section_data *esdi 
+               = elf_section_data (o);
+             struct bfd_elf_section_data *esdo 
+               = elf_section_data (output_section);
+             unsigned int *rel_count;
+             unsigned int *rel_count2;
+
+             /* We must be careful to add the relocation froms the
+                input section to the right output count.  */
+             if (esdi->rel_hdr.sh_entsize == esdo->rel_hdr.sh_entsize)
+               {
+                 rel_count = &esdo->rel_count;
+                 rel_count2 = &esdo->rel_count2;
+               }
+             else
+               {
+                 rel_count = &esdo->rel_count2;
+                 rel_count2 = &esdo->rel_count;
+               }
+             
+             *rel_count += (esdi->rel_hdr.sh_size 
+                            / esdi->rel_hdr.sh_entsize);
+             if (esdi->rel_hdr2)
+               *rel_count2 += (esdi->rel_hdr2->sh_size 
+                               / esdi->rel_hdr2->sh_entsize);
+           }
+       }
+
   /* That created the reloc sections.  Set their sizes, and assign
      them file positions, and allocate some buffers.  */
   for (o = abfd->sections; o != NULL; o = o->next)
@@ -4014,6 +4290,11 @@ elf_bfd_final_link (abfd, info)
                                               o))
            goto error_return;
        }
+
+      /* Now, reset REL_COUNT and REL_COUNT2 so that we can use them
+        to count upwards while actually outputting the relocations. */
+      elf_section_data (o)->rel_count = 0;
+      elf_section_data (o)->rel_count2 = 0;
     }
 
   _bfd_elf_assign_file_positions_for_relocs (abfd);
@@ -4215,7 +4496,7 @@ elf_bfd_final_link (abfd, info)
       Elf_Internal_Sym sym;
       Elf_External_Sym *dynsym =
        (Elf_External_Sym *)finfo.dynsym_sec->contents;
-      unsigned long last_local = 0;
+      long last_local = 0;
 
       /* Write out the section symbols for the output sections.  */
       if (info->shared)
@@ -4253,16 +4534,12 @@ elf_bfd_final_link (abfd, info)
              sym.st_size = e->isym.st_size;
              sym.st_other = e->isym.st_other;
 
-             /* Note that we saved a word of storage and overwrote
+             /* Copy the internal symbol as is.
+                Note that we saved a word of storage and overwrote
                  the original st_name with the dynstr_index.  */
-             sym.st_name = e->isym.st_name;
+              sym = e->isym;
 
-             if (e->isym.st_shndx == 0 || e->isym.st_shndx >= SHN_LORESERVE)
-               {
-                 sym.st_shndx = e->isym.st_shndx;
-                 sym.st_value = e->isym.st_value;
-               }
-             else
+             if (e->isym.st_shndx > 0 && e->isym.st_shndx < SHN_LORESERVE)
                {
                  s = bfd_section_from_elf_index (e->input_bfd,
                                                  e->isym.st_shndx);
@@ -4281,8 +4558,8 @@ elf_bfd_final_link (abfd, info)
            }
        }
 
-      elf_section_data (finfo.dynsym_sec->output_section)
-       ->this_hdr.sh_info = last_local + 1;
+      elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info =
+       last_local + 1;
     }
 
   /* We get the global symbols from the hash table.  */
@@ -4847,14 +5124,23 @@ elf_link_output_extsym (h, data)
 
   /* If we are marking the symbol as undefined, and there are no
      non-weak references to this symbol from a regular object, then
-     mark the symbol as weak undefined.  We can't do this earlier,
+     mark the symbol as weak undefined; if there are non-weak
+     references, mark the symbol as strong.  We can't do this earlier,
      because it might not be marked as undefined until the
      finish_dynamic_symbol routine gets through with it.  */
   if (sym.st_shndx == SHN_UNDEF
-      && sym.st_info == ELF_ST_INFO (STB_GLOBAL, h->type)
       && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0
-      && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) == 0)
-    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+      && (ELF_ST_BIND(sym.st_info) == STB_GLOBAL
+         || ELF_ST_BIND(sym.st_info) == STB_WEAK))
+    {
+      int bindtype;
+
+      if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) != 0)
+       bindtype = STB_GLOBAL;
+      else
+       bindtype = STB_WEAK;
+      sym.st_info = ELF_ST_INFO (bindtype, ELF_ST_TYPE (sym.st_info));
+    }
 
   /* If this symbol should be put in the .dynsym section, then put it
      there now.  We have already know the symbol index.  We also fill
@@ -6311,30 +6597,31 @@ elf_gc_record_vtentry (abfd, sec, h, addend)
 
       /* Allocate one extra entry for use as a "done" flag for the
         consolidation pass.  */
-      bytes = (size / FILE_ALIGN + 1) * sizeof(boolean);
+      bytes = (size / FILE_ALIGN + 1) * sizeof (boolean);
 
       if (ptr)
        {
-         size_t oldbytes;
-
-         ptr = realloc (ptr-1, bytes);
-         if (ptr == NULL)
-           return false;
+         ptr = bfd_realloc (ptr - 1, bytes);
+         
+         if (ptr != NULL)
+           {
+             size_t oldbytes;
 
-         oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof(boolean);
-         memset (ptr + oldbytes, 0, bytes - oldbytes);
+             oldbytes = (h->vtable_entries_size/FILE_ALIGN + 1) * sizeof (boolean);
+             memset (((char *)ptr) + oldbytes, 0, bytes - oldbytes);
+           }
        }
       else
-       {
-         ptr = calloc (1, bytes);
-         if (ptr == NULL)
-           return false;
-       }
+       ptr = bfd_zmalloc (bytes);
 
+      if (ptr == NULL)
+       return false;
+      
       /* And arrange for that done flag to be at index -1.  */
-      h->vtable_entries_used = ptr+1;
+      h->vtable_entries_used = ptr + 1;
       h->vtable_entries_size = size;
     }
+  
   h->vtable_entries_used[addend / FILE_ALIGN] = true;
 
   return true;
This page took 0.046765 seconds and 4 git commands to generate.