PATCH: Fix mixed ELF32 and ELF64 in archive

H. J. Lu hjl@lucon.org
Sun Feb 29 05:40:00 GMT 2004


On Sun, Feb 29, 2004 at 12:44:17PM +1030, Alan Modra wrote:
> On Fri, Feb 27, 2004 at 02:46:28PM -0800, H. J. Lu wrote:
> > When there are mixed ELF32 and ELF64 objects in archive and linker
> > supporting both, linker gets really confused since the wrong
> > value/function are used. When we deal with archive, we can't assume
> > the size and we have to get the right thing from the backend. This
> > patch fixes it. Ok to install?
> 
> This is OK.  Can I ask you to do a little more, and move
> elf_link_add_archive_symbols and elf_link_is_defined_archive_symbol
> to elflink.c?  That's where they belong if there are no size dependent
> structures, macros etc. left.  Moving them to elflink.c will prove
> that your patch is complete too.
> 
> > 2004-02-27  H.J. Lu  <hongjiu.lu@intel.com>
> > 
> > 	* elflink.h (elf_link_is_defined_archive_symbol): Get the size
> > 	of ELF symbol table entry from backend.
> > 	(elf_link_add_archive_symbols): Call bfd_link_add_symbols
> > 	instead of elf_link_add_object_symbols.
> 
 
Done. There is no regression on Linux/x86 and Linux/x86_64.


H.J.
-------------- next part --------------
2004-02-28  H.J. Lu  <hongjiu.lu@intel.com>

	* elf-bfd.h (_bfd_elf_link_add_archive_symbols): New prototype.

	* elflink.h (is_global_data_symbol_definition): Moved to
	elflink.c.
	(elf_link_is_defined_archive_symbol): Likewise.
	(elf_link_add_archive_symbols): Likewise. Renamed to
	_bfd_elf_link_add_archive_symbols.

	* elflink.c (elf_link_is_defined_archive_symbol): Get the size
	of ELF symbol table entry from backend.
	(_bfd_elf_link_add_archive_symbols): Call bfd_link_add_symbols
	instead of elf_link_add_object_symbols.

--- bfd/elf-bfd.h.mixed	2004-02-09 09:22:27.000000000 -0800
+++ bfd/elf-bfd.h	2004-02-28 21:14:38.000000000 -0800
@@ -1523,6 +1523,9 @@ extern bfd_boolean _bfd_elf_dynamic_symb
 extern bfd_boolean _bfd_elf_symbol_refs_local_p
   (struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean);
 
+extern bfd_boolean _bfd_elf_link_add_archive_symbols
+  (bfd *, struct bfd_link_info *);
+
 extern const bfd_target *bfd_elf32_object_p
   (bfd *);
 extern const bfd_target *bfd_elf32_core_file_p
--- bfd/elflink.c.mixed	2004-02-28 21:35:19.000000000 -0800
+++ bfd/elflink.c	2004-02-28 21:19:49.000000000 -0800
@@ -2564,3 +2564,348 @@ _bfd_elf_tls_setup (bfd *obfd, struct bf
 
   return tls;
 }
+
+/* Return TRUE iff this is a non-common, definition of a non-function symbol.  */
+static bfd_boolean
+is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
+				  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;
+
+  /* Function symbols do not count.  */
+  if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+    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
+   whose archive map contains a mention of SYMDEF, and determine if
+   the symbol is defined in this element.  */
+static bfd_boolean
+elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
+{
+  Elf_Internal_Shdr * hdr;
+  bfd_size_type symcount;
+  bfd_size_type extsymcount;
+  bfd_size_type extsymoff;
+  Elf_Internal_Sym *isymbuf;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
+  bfd_boolean result;
+
+  abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+  if (abfd == 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 / get_elf_backend_data (abfd)->s->sizeof_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;
+    }
+
+  if (extsymcount == 0)
+    return FALSE;
+
+  /* Read in the symbol table.  */
+  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
+				  NULL, NULL, NULL);
+  if (isymbuf == NULL)
+    return FALSE;
+
+  /* Scan the symbol table looking for SYMDEF.  */
+  result = FALSE;
+  for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++)
+    {
+      const char *name;
+
+      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+					      isym->st_name);
+      if (name == NULL)
+	break;
+
+      if (strcmp (name, symdef->name) == 0)
+	{
+	  result = is_global_data_symbol_definition (abfd, isym);
+	  break;
+	}
+    }
+
+  free (isymbuf);
+
+  return result;
+}
+
+/* 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
+   problem which arises on UnixWare.  The UnixWare libc.so is an
+   archive which includes an entry libc.so.1 which defines a bunch of
+   symbols.  The libc.so archive also includes a number of other
+   object files, which also define symbols, some of which are the same
+   as those defined in libc.so.1.  Correct linking requires that we
+   consider each object file in turn, and include it if it defines any
+   symbols we need.  _bfd_generic_link_add_archive_symbols does not do
+   this; it looks through the list of undefined symbols, and includes
+   any object file which defines them.  When this algorithm is used on
+   UnixWare, it winds up pulling in libc.so.1 early and defining a
+   bunch of symbols.  This means that some of the other objects in the
+   archive are not included in the link, which is incorrect since they
+   precede libc.so.1 in the archive.
+
+   Fortunately, ELF archive handling is simpler than that done by
+   _bfd_generic_link_add_archive_symbols, which has to allow for a.out
+   oddities.  In ELF, if we find a symbol in the archive map, and the
+   symbol is currently undefined, we know that we must pull in that
+   object file.
+
+   Unfortunately, we do have to make multiple passes over the symbol
+   table until nothing further is resolved.  */
+
+bfd_boolean
+_bfd_elf_link_add_archive_symbols (bfd *abfd,
+				   struct bfd_link_info *info)
+{
+  symindex c;
+  bfd_boolean *defined = NULL;
+  bfd_boolean *included = NULL;
+  carsym *symdefs;
+  bfd_boolean loop;
+  bfd_size_type amt;
+
+  if (! bfd_has_map (abfd))
+    {
+      /* An empty archive is a special case.  */
+      if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
+	return TRUE;
+      bfd_set_error (bfd_error_no_armap);
+      return FALSE;
+    }
+
+  /* Keep track of all symbols we know to be already defined, and all
+     files we know to be already included.  This is to speed up the
+     second and subsequent passes.  */
+  c = bfd_ardata (abfd)->symdef_count;
+  if (c == 0)
+    return TRUE;
+  amt = c;
+  amt *= sizeof (bfd_boolean);
+  defined = bfd_zmalloc (amt);
+  included = bfd_zmalloc (amt);
+  if (defined == NULL || included == NULL)
+    goto error_return;
+
+  symdefs = bfd_ardata (abfd)->symdefs;
+
+  do
+    {
+      file_ptr last;
+      symindex i;
+      carsym *symdef;
+      carsym *symdefend;
+
+      loop = FALSE;
+      last = -1;
+
+      symdef = symdefs;
+      symdefend = symdef + c;
+      for (i = 0; symdef < symdefend; symdef++, i++)
+	{
+	  struct elf_link_hash_entry *h;
+	  bfd *element;
+	  struct bfd_link_hash_entry *undefs_tail;
+	  symindex mark;
+
+	  if (defined[i] || included[i])
+	    continue;
+	  if (symdef->file_offset == last)
+	    {
+	      included[i] = TRUE;
+	      continue;
+	    }
+
+	  h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,
+				    FALSE, FALSE, FALSE);
+
+	  if (h == NULL)
+	    {
+	      char *p, *copy;
+	      size_t len, first;
+
+	      /* If this is a default version (the name contains @@),
+		 look up the symbol again with only one `@' as well
+		 as without the version.  The effect is that references
+		 to the symbol with and without the version will be
+		 matched by the default symbol in the archive.  */
+
+	      p = strchr (symdef->name, ELF_VER_CHR);
+	      if (p == NULL || p[1] != ELF_VER_CHR)
+		continue;
+
+	      /* First check with only one `@'.  */
+	      len = strlen (symdef->name);
+	      copy = bfd_alloc (abfd, len);
+	      if (copy == NULL)
+		goto error_return;
+	      first = p - symdef->name + 1;
+	      memcpy (copy, symdef->name, first);
+	      memcpy (copy + first, symdef->name + first + 1, len - first);
+
+	      h = elf_link_hash_lookup (elf_hash_table (info), copy,
+					FALSE, FALSE, FALSE);
+
+	      if (h == NULL)
+		{
+		  /* We also need to check references to the symbol
+		     without the version.  */
+
+		  copy[first - 1] = '\0';
+		  h = elf_link_hash_lookup (elf_hash_table (info),
+					    copy, FALSE, FALSE, FALSE);
+		}
+
+	      bfd_release (abfd, copy);
+	    }
+
+	  if (h == NULL)
+	    continue;
+
+	  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;
+	      continue;
+	    }
+
+	  /* We need to include this archive member.  */
+	  element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+	  if (element == NULL)
+	    goto error_return;
+
+	  if (! bfd_check_format (element, bfd_object))
+	    goto error_return;
+
+	  /* Doublecheck that we have not included this object
+	     already--it should be impossible, but there may be
+	     something wrong with the archive.  */
+	  if (element->archive_pass != 0)
+	    {
+	      bfd_set_error (bfd_error_bad_value);
+	      goto error_return;
+	    }
+	  element->archive_pass = 1;
+
+	  undefs_tail = info->hash->undefs_tail;
+
+	  if (! (*info->callbacks->add_archive_element) (info, element,
+							 symdef->name))
+	    goto error_return;
+	  if (! bfd_link_add_symbols (element, info))
+	    goto error_return;
+
+	  /* If there are any new undefined symbols, we need to make
+	     another pass through the archive in order to see whether
+	     they can be defined.  FIXME: This isn't perfect, because
+	     common symbols wind up on undefs_tail and because an
+	     undefined symbol which is defined later on in this pass
+	     does not require another pass.  This isn't a bug, but it
+	     does make the code less efficient than it could be.  */
+	  if (undefs_tail != info->hash->undefs_tail)
+	    loop = TRUE;
+
+	  /* Look backward to mark all symbols from this object file
+	     which we have already seen in this pass.  */
+	  mark = i;
+	  do
+	    {
+	      included[mark] = TRUE;
+	      if (mark == 0)
+		break;
+	      --mark;
+	    }
+	  while (symdefs[mark].file_offset == symdef->file_offset);
+
+	  /* We mark subsequent symbols from this object file as we go
+	     on through the loop.  */
+	  last = symdef->file_offset;
+	}
+    }
+  while (loop);
+
+  free (defined);
+  free (included);
+
+  return TRUE;
+
+ error_return:
+  if (defined != NULL)
+    free (defined);
+  if (included != NULL)
+    free (included);
+  return FALSE;
+}
--- bfd/elflink.h.mixed	2004-02-27 09:41:43.000000000 -0800
+++ bfd/elflink.h	2004-02-28 21:19:16.000000000 -0800
@@ -23,8 +23,6 @@
 #include "safe-ctype.h"
 
 static bfd_boolean elf_link_add_object_symbols (bfd *, struct bfd_link_info *);
-static bfd_boolean elf_link_add_archive_symbols (bfd *,
-						 struct bfd_link_info *);
 static bfd_boolean elf_finalize_dynstr (bfd *, struct bfd_link_info *);
 static bfd_boolean elf_collect_hash_codes (struct elf_link_hash_entry *,
 					   void *);
@@ -41,357 +39,13 @@ elf_bfd_link_add_symbols (bfd *abfd, str
     case bfd_object:
       return elf_link_add_object_symbols (abfd, info);
     case bfd_archive:
-      return elf_link_add_archive_symbols (abfd, info);
+      return _bfd_elf_link_add_archive_symbols (abfd, info);
     default:
       bfd_set_error (bfd_error_wrong_format);
       return FALSE;
     }
 }
 
-/* Return TRUE iff this is a non-common, definition of a non-function symbol.  */
-static bfd_boolean
-is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
-				  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;
-
-  /* Function symbols do not count.  */
-  if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
-    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
-   whose archive map contains a mention of SYMDEF, and determine if
-   the symbol is defined in this element.  */
-static bfd_boolean
-elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
-{
-  Elf_Internal_Shdr * hdr;
-  bfd_size_type symcount;
-  bfd_size_type extsymcount;
-  bfd_size_type extsymoff;
-  Elf_Internal_Sym *isymbuf;
-  Elf_Internal_Sym *isym;
-  Elf_Internal_Sym *isymend;
-  bfd_boolean result;
-
-  abfd = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
-  if (abfd == 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;
-    }
-
-  if (extsymcount == 0)
-    return FALSE;
-
-  /* Read in the symbol table.  */
-  isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
-				  NULL, NULL, NULL);
-  if (isymbuf == NULL)
-    return FALSE;
-
-  /* Scan the symbol table looking for SYMDEF.  */
-  result = FALSE;
-  for (isym = isymbuf, isymend = isymbuf + extsymcount; isym < isymend; isym++)
-    {
-      const char *name;
-
-      name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
-					      isym->st_name);
-      if (name == NULL)
-	break;
-
-      if (strcmp (name, symdef->name) == 0)
-	{
-	  result = is_global_data_symbol_definition (abfd, isym);
-	  break;
-	}
-    }
-
-  free (isymbuf);
-
-  return result;
-}
-
-/* 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
-   problem which arises on UnixWare.  The UnixWare libc.so is an
-   archive which includes an entry libc.so.1 which defines a bunch of
-   symbols.  The libc.so archive also includes a number of other
-   object files, which also define symbols, some of which are the same
-   as those defined in libc.so.1.  Correct linking requires that we
-   consider each object file in turn, and include it if it defines any
-   symbols we need.  _bfd_generic_link_add_archive_symbols does not do
-   this; it looks through the list of undefined symbols, and includes
-   any object file which defines them.  When this algorithm is used on
-   UnixWare, it winds up pulling in libc.so.1 early and defining a
-   bunch of symbols.  This means that some of the other objects in the
-   archive are not included in the link, which is incorrect since they
-   precede libc.so.1 in the archive.
-
-   Fortunately, ELF archive handling is simpler than that done by
-   _bfd_generic_link_add_archive_symbols, which has to allow for a.out
-   oddities.  In ELF, if we find a symbol in the archive map, and the
-   symbol is currently undefined, we know that we must pull in that
-   object file.
-
-   Unfortunately, we do have to make multiple passes over the symbol
-   table until nothing further is resolved.  */
-
-static bfd_boolean
-elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
-{
-  symindex c;
-  bfd_boolean *defined = NULL;
-  bfd_boolean *included = NULL;
-  carsym *symdefs;
-  bfd_boolean loop;
-  bfd_size_type amt;
-
-  if (! bfd_has_map (abfd))
-    {
-      /* An empty archive is a special case.  */
-      if (bfd_openr_next_archived_file (abfd, NULL) == NULL)
-	return TRUE;
-      bfd_set_error (bfd_error_no_armap);
-      return FALSE;
-    }
-
-  /* Keep track of all symbols we know to be already defined, and all
-     files we know to be already included.  This is to speed up the
-     second and subsequent passes.  */
-  c = bfd_ardata (abfd)->symdef_count;
-  if (c == 0)
-    return TRUE;
-  amt = c;
-  amt *= sizeof (bfd_boolean);
-  defined = bfd_zmalloc (amt);
-  included = bfd_zmalloc (amt);
-  if (defined == NULL || included == NULL)
-    goto error_return;
-
-  symdefs = bfd_ardata (abfd)->symdefs;
-
-  do
-    {
-      file_ptr last;
-      symindex i;
-      carsym *symdef;
-      carsym *symdefend;
-
-      loop = FALSE;
-      last = -1;
-
-      symdef = symdefs;
-      symdefend = symdef + c;
-      for (i = 0; symdef < symdefend; symdef++, i++)
-	{
-	  struct elf_link_hash_entry *h;
-	  bfd *element;
-	  struct bfd_link_hash_entry *undefs_tail;
-	  symindex mark;
-
-	  if (defined[i] || included[i])
-	    continue;
-	  if (symdef->file_offset == last)
-	    {
-	      included[i] = TRUE;
-	      continue;
-	    }
-
-	  h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,
-				    FALSE, FALSE, FALSE);
-
-	  if (h == NULL)
-	    {
-	      char *p, *copy;
-	      size_t len, first;
-
-	      /* If this is a default version (the name contains @@),
-		 look up the symbol again with only one `@' as well
-		 as without the version.  The effect is that references
-		 to the symbol with and without the version will be
-		 matched by the default symbol in the archive.  */
-
-	      p = strchr (symdef->name, ELF_VER_CHR);
-	      if (p == NULL || p[1] != ELF_VER_CHR)
-		continue;
-
-	      /* First check with only one `@'.  */
-	      len = strlen (symdef->name);
-	      copy = bfd_alloc (abfd, len);
-	      if (copy == NULL)
-		goto error_return;
-	      first = p - symdef->name + 1;
-	      memcpy (copy, symdef->name, first);
-	      memcpy (copy + first, symdef->name + first + 1, len - first);
-
-	      h = elf_link_hash_lookup (elf_hash_table (info), copy,
-					FALSE, FALSE, FALSE);
-
-	      if (h == NULL)
-		{
-		  /* We also need to check references to the symbol
-		     without the version.  */
-
-		  copy[first - 1] = '\0';
-		  h = elf_link_hash_lookup (elf_hash_table (info),
-					    copy, FALSE, FALSE, FALSE);
-		}
-
-	      bfd_release (abfd, copy);
-	    }
-
-	  if (h == NULL)
-	    continue;
-
-	  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;
-	      continue;
-	    }
-
-	  /* We need to include this archive member.  */
-	  element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
-	  if (element == NULL)
-	    goto error_return;
-
-	  if (! bfd_check_format (element, bfd_object))
-	    goto error_return;
-
-	  /* Doublecheck that we have not included this object
-	     already--it should be impossible, but there may be
-	     something wrong with the archive.  */
-	  if (element->archive_pass != 0)
-	    {
-	      bfd_set_error (bfd_error_bad_value);
-	      goto error_return;
-	    }
-	  element->archive_pass = 1;
-
-	  undefs_tail = info->hash->undefs_tail;
-
-	  if (! (*info->callbacks->add_archive_element) (info, element,
-							 symdef->name))
-	    goto error_return;
-	  if (! elf_link_add_object_symbols (element, info))
-	    goto error_return;
-
-	  /* If there are any new undefined symbols, we need to make
-	     another pass through the archive in order to see whether
-	     they can be defined.  FIXME: This isn't perfect, because
-	     common symbols wind up on undefs_tail and because an
-	     undefined symbol which is defined later on in this pass
-	     does not require another pass.  This isn't a bug, but it
-	     does make the code less efficient than it could be.  */
-	  if (undefs_tail != info->hash->undefs_tail)
-	    loop = TRUE;
-
-	  /* Look backward to mark all symbols from this object file
-	     which we have already seen in this pass.  */
-	  mark = i;
-	  do
-	    {
-	      included[mark] = TRUE;
-	      if (mark == 0)
-		break;
-	      --mark;
-	    }
-	  while (symdefs[mark].file_offset == symdef->file_offset);
-
-	  /* We mark subsequent symbols from this object file as we go
-	     on through the loop.  */
-	  last = symdef->file_offset;
-	}
-    }
-  while (loop);
-
-  free (defined);
-  free (included);
-
-  return TRUE;
-
- error_return:
-  if (defined != NULL)
-    free (defined);
-  if (included != NULL)
-    free (included);
-  return FALSE;
-}
-
 /* Sort symbol by value and section.  */
 static int
 sort_symbol (const void *arg1, const void *arg2)


More information about the Binutils mailing list