public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PR12365 and common symbols
@ 2011-04-20  0:25 Alan Modra
  2011-04-22 22:33 ` H.J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Modra @ 2011-04-20  0:25 UTC (permalink / raw)
  To: binutils

This patch makes ld keep IR-only common symbols in their own specially
marked common section, so that ld can report an error if such a symbol
is referenced.

bfd/
	PR ld/12365
	* elfcode.h (elf_slurp_symbol_table): Put common plugin IR symbols
	in their own common section.
	* elflink.c (elf_link_add_object_symbols): Likewise.
	* linker.c (generic_link_check_archive_element): Don't lose flags
	if common section is pre-existing.
	(_bfd_generic_link_add_one_symbol): Likewise.
ld/
	PR ld/12365
	* ldfile.c (ldfile_try_open_bfd): Move code creating and switching
	to plugin IR BFD..
	* ldmain.c (add_archive_element): ..and similar code here..
	* plugin.c (plugin_maybe_claim): ..to here.  New function.
	(plugin_call_claim_file): Make static.
	(asymbol_from_plugin_symbol): Set ELF st_shndx for common syms.
	(plugin_multiple_common): New function.
	(plugin_call_all_symbols_read): Hook in plugin_multiple_common.
	* plugin.h (plugin_call_claim_file): Don't declare.
	(plugin_maybe_claim): Declare.

Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.105
diff -u -p -r1.105 elfcode.h
--- bfd/elfcode.h	14 Mar 2011 15:54:58 -0000	1.105
+++ bfd/elfcode.h	20 Apr 2011 00:12:16 -0000
@@ -1282,6 +1282,20 @@ elf_slurp_symbol_table (bfd *abfd, asymb
 	  else if (isym->st_shndx == SHN_COMMON)
 	    {
 	      sym->symbol.section = bfd_com_section_ptr;
+	      if ((abfd->flags & BFD_PLUGIN) != 0)
+		{
+		  asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+		  if (xc == NULL)
+		    {
+		      flagword flags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+					| SEC_EXCLUDE);
+		      xc = bfd_make_section_with_flags (abfd, "COMMON", flags);
+		      if (xc == NULL)
+			goto error_return;
+		    }
+		  sym->symbol.section = xc;
+		}
 	      /* Elf puts the alignment into the `value' field, and
 		 the size into the `size' field.  BFD wants to see the
 		 size in the value field, and doesn't care (at the
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.398
diff -u -p -r1.398 elflink.c
--- bfd/elflink.c	20 Apr 2011 00:11:31 -0000	1.398
+++ bfd/elflink.c	20 Apr 2011 00:12:21 -0000
@@ -3937,18 +3937,31 @@ error_free_dyn:
 	goto error_free_vers;
 
       if (isym->st_shndx == SHN_COMMON
-	  && ELF_ST_TYPE (isym->st_info) == STT_TLS
-	  && !info->relocatable)
+	  && (abfd->flags & BFD_PLUGIN) != 0)
+	{
+	  asection *xc = bfd_get_section_by_name (abfd, "COMMON");
+
+	  if (xc == NULL)
+	    {
+	      flagword sflags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP
+				 | SEC_EXCLUDE);
+	      xc = bfd_make_section_with_flags (abfd, "COMMON", sflags);
+	      if (xc == NULL)
+		goto error_free_vers;
+	    }
+	  sec = xc;
+	}
+      else if (isym->st_shndx == SHN_COMMON
+	       && ELF_ST_TYPE (isym->st_info) == STT_TLS
+	       && !info->relocatable)
 	{
 	  asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
 
 	  if (tcomm == NULL)
 	    {
-	      tcomm = bfd_make_section_with_flags (abfd, ".tcommon",
-						   (SEC_ALLOC
-						    | SEC_IS_COMMON
-						    | SEC_LINKER_CREATED
-						    | SEC_THREAD_LOCAL));
+	      flagword sflags = (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_IS_COMMON
+				 | SEC_LINKER_CREATED);
+	      tcomm = bfd_make_section_with_flags (abfd, ".tcommon", sflags);
 	      if (tcomm == NULL)
 		goto error_free_vers;
 	    }
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.79
diff -u -p -r1.79 linker.c
--- bfd/linker.c	20 Apr 2011 00:11:32 -0000	1.79
+++ bfd/linker.c	20 Apr 2011 00:12:23 -0000
@@ -1296,7 +1296,7 @@ generic_link_check_archive_element (bfd 
 	  else
 	    h->u.c.p->section = bfd_make_section_old_way (symbfd,
 							  p->section->name);
-	  h->u.c.p->section->flags = SEC_ALLOC;
+	  h->u.c.p->section->flags |= SEC_ALLOC;
 	}
       else
 	{
@@ -1756,13 +1756,13 @@ _bfd_generic_link_add_one_symbol (struct
 	  if (section == bfd_com_section_ptr)
 	    {
 	      h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
-	      h->u.c.p->section->flags = SEC_ALLOC;
+	      h->u.c.p->section->flags |= SEC_ALLOC;
 	    }
 	  else if (section->owner != abfd)
 	    {
 	      h->u.c.p->section = bfd_make_section_old_way (abfd,
 							    section->name);
-	      h->u.c.p->section->flags = SEC_ALLOC;
+	      h->u.c.p->section->flags |= SEC_ALLOC;
 	    }
 	  else
 	    h->u.c.p->section = section;
@@ -1803,13 +1803,13 @@ _bfd_generic_link_add_one_symbol (struct
 		{
 		  h->u.c.p->section
 		    = bfd_make_section_old_way (abfd, "COMMON");
-		  h->u.c.p->section->flags = SEC_ALLOC;
+		  h->u.c.p->section->flags |= SEC_ALLOC;
 		}
 	      else if (section->owner != abfd)
 		{
 		  h->u.c.p->section
 		    = bfd_make_section_old_way (abfd, section->name);
-		  h->u.c.p->section->flags = SEC_ALLOC;
+		  h->u.c.p->section->flags |= SEC_ALLOC;
 		}
 	      else
 		h->u.c.p->section = section;
Index: ld/ldfile.c
===================================================================
RCS file: /cvs/src/src/ld/ldfile.c,v
retrieving revision 1.62
diff -u -p -r1.62 ldfile.c
--- ld/ldfile.c	17 Apr 2011 23:15:13 -0000	1.62
+++ ld/ldfile.c	20 Apr 2011 00:12:44 -0000
@@ -320,35 +320,12 @@ success:
       if (fd >= 0)
 	{
 	  struct ld_plugin_input_file file;
-	  int claimed = 0;
 
 	  file.name = attempt;
 	  file.offset = 0;
 	  file.filesize = lseek (fd, 0, SEEK_END);
 	  file.fd = fd;
-	  /* We create a dummy BFD, initially empty, to house
-	     whatever symbols the plugin may want to add.  */
-	  file.handle = plugin_get_ir_dummy_bfd (attempt, entry->the_bfd);
-	  if (plugin_call_claim_file (&file, &claimed))
-	    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
-		   plugin_error_plugin ());
-	  /* fd belongs to us, not the plugin; but we don't need it.  */
-	  close (fd);
-	  if (claimed)
-	    {
-	      /* Discard the real file's BFD and substitute the dummy one.  */
-	      bfd_close (entry->the_bfd);
-	      entry->the_bfd = file.handle;
-	      entry->claimed = TRUE;
-	      bfd_make_readable (entry->the_bfd);
-	    }
-	  else
-	    {
-	      /* If plugin didn't claim the file, we don't need the dummy
-		 bfd.  Can't avoid speculatively creating it, alas.  */
-	      bfd_close_all_done (file.handle);
-	      entry->claimed = FALSE;
-	    }
+	  plugin_maybe_claim (&file, entry);
 	}
     }
 #endif /* ENABLE_PLUGINS */
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.152
diff -u -p -r1.152 ldmain.c
--- ld/ldmain.c	20 Apr 2011 00:11:33 -0000	1.152
+++ ld/ldmain.c	20 Apr 2011 00:12:45 -0000
@@ -813,7 +813,7 @@ add_archive_element (struct bfd_link_inf
       if (fd >= 0)
 	{
 	  struct ld_plugin_input_file file;
-	  int claimed = 0;
+
 	  /* Offset and filesize must refer to the individual archive
 	     member, not the whole file, and must exclude the header.
 	     Fortunately for us, that is how the data is stored in the
@@ -822,29 +822,12 @@ add_archive_element (struct bfd_link_inf
 	  file.offset = abfd->origin;
 	  file.filesize = arelt_size (abfd);
 	  file.fd = fd;
-	  /* We create a dummy BFD, initially empty, to house
-	     whatever symbols the plugin may want to add.  */
-	  file.handle = plugin_get_ir_dummy_bfd (abfd->filename, abfd);
-	  if (plugin_call_claim_file (&file, &claimed))
-	    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
-		   plugin_error_plugin ());
-	  /* fd belongs to us, not the plugin; but we don't need it.  */
-	  close (fd);
-	  if (claimed)
+	  plugin_maybe_claim (&file, input);
+	  if (input->claimed)
 	    {
-	      /* Substitute the dummy BFD.  */
-	      input->the_bfd = file.handle;
-	      input->claimed = TRUE;
 	      input->claim_archive = TRUE;
-	      bfd_make_readable (input->the_bfd);
 	      *subsbfd = input->the_bfd;
 	    }
-	  else
-	    {
-	      /* Abandon the dummy BFD.  */
-	      bfd_close_all_done (file.handle);
-	      input->claimed = FALSE;
-	    }
 	}
     }
 #endif /* ENABLE_PLUGINS */
Index: ld/plugin.c
===================================================================
RCS file: /cvs/src/src/ld/plugin.c,v
retrieving revision 1.31
diff -u -p -r1.31 plugin.c
--- ld/plugin.c	20 Apr 2011 00:11:33 -0000	1.31
+++ ld/plugin.c	20 Apr 2011 00:12:45 -0000
@@ -140,6 +140,11 @@ static bfd_boolean plugin_multiple_defin
 					       bfd *nbfd,
 					       asection *nsec,
 					       bfd_vma nval);
+static bfd_boolean plugin_multiple_common (struct bfd_link_info *info,
+					   struct bfd_link_hash_entry *h,
+					   bfd *nbfd,
+					   enum bfd_link_hash_type ntype,
+					   bfd_vma nsize);
 
 #if !defined (HAVE_DLFCN_H) && defined (HAVE_WINDOWS_H)
 
@@ -312,7 +317,10 @@ asymbol_from_plugin_symbol (bfd *abfd, a
       asym->value = ldsym->size;
       /* For ELF targets, set alignment of common symbol to 1.  */
       if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
-	((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+	{
+	  ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON;
+	  ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1;
+	}
       break;
 
     default:
@@ -812,7 +820,7 @@ plugin_load_plugins (void)
 }
 
 /* Call 'claim file' hook for all plugins.  */
-int
+static int
 plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
 {
   plugin_t *curplug = plugins_list;
@@ -835,6 +843,42 @@ plugin_call_claim_file (const struct ld_
   return plugin_error_p () ? -1 : 0;
 }
 
+void
+plugin_maybe_claim (struct ld_plugin_input_file *file,
+		    lang_input_statement_type *entry)
+{
+  int claimed = 0;
+
+  /* We create a dummy BFD, initially empty, to house whatever symbols
+     the plugin may want to add.  */
+  file->handle = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
+					  entry->the_bfd);
+  if (plugin_call_claim_file (file, &claimed))
+    einfo (_("%P%F: %s: plugin reported error claiming file\n"),
+	   plugin_error_plugin ());
+  /* fd belongs to us, not the plugin; but we don't need it.  */
+  close (file->fd);
+  if (claimed)
+    {
+      /* Discard the real file's BFD and substitute the dummy one.  */
+
+      /* BFD archive handling caches elements so we can't call
+	 bfd_close for archives.  */
+      if (entry->the_bfd->my_archive == NULL)
+	bfd_close (entry->the_bfd);
+      entry->the_bfd = file->handle;
+      entry->claimed = TRUE;
+      bfd_make_readable (entry->the_bfd);
+    }
+  else
+    {
+      /* If plugin didn't claim the file, we don't need the dummy bfd.
+	 Can't avoid speculatively creating it, alas.  */
+      bfd_close_all_done (file->handle);
+      entry->claimed = FALSE;
+    }
+}
+
 /* Call 'all symbols read' hook for all plugins.  */
 int
 plugin_call_all_symbols_read (void)
@@ -845,6 +889,7 @@ plugin_call_all_symbols_read (void)
   no_more_claiming = TRUE;
 
   plugin_callbacks.multiple_definition = &plugin_multiple_definition;
+  plugin_callbacks.multiple_common = &plugin_multiple_common;
 
   while (curplug)
     {
@@ -955,3 +1000,22 @@ plugin_multiple_definition (struct bfd_l
 
   return (*orig_callbacks->multiple_definition) (info, h, nbfd, nsec, nval);
 }
+
+static bfd_boolean
+plugin_multiple_common (struct bfd_link_info *info,
+			struct bfd_link_hash_entry *h,
+			bfd *nbfd, enum bfd_link_hash_type ntype, bfd_vma nsize)
+{
+  if (h->type == bfd_link_hash_common
+      && is_ir_dummy_bfd (h->u.c.p->section->owner)
+      && ntype == bfd_link_hash_common
+      && !is_ir_dummy_bfd (nbfd))
+    {
+      /* Arrange to have it replaced.  */
+      ASSERT (nsize != 0);
+      h->u.c.size = 0;
+      return TRUE;
+    }
+
+  return (*orig_callbacks->multiple_common) (info, h, nbfd, ntype, nsize);
+}
Index: ld/plugin.h
===================================================================
RCS file: /cvs/src/src/ld/plugin.h,v
retrieving revision 1.8
diff -u -p -r1.8 plugin.h
--- ld/plugin.h	17 Apr 2011 23:15:13 -0000	1.8
+++ ld/plugin.h	20 Apr 2011 00:12:45 -0000
@@ -50,8 +50,8 @@ extern int plugin_load_plugins (void);
 extern const char *plugin_error_plugin (void);
 
 /* Call 'claim file' hook for all plugins.  */
-extern int plugin_call_claim_file (const struct ld_plugin_input_file *file,
-				   int *claimed);
+extern void plugin_maybe_claim (struct ld_plugin_input_file *,
+				lang_input_statement_type *);
 
 /* Call 'all symbols read' hook for all plugins.  */
 extern int plugin_call_all_symbols_read (void);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread
* Change bfd_link_hash_entry.type to a bitfield?
@ 2011-04-21  1:58 Alan Modra
  2011-04-21  2:55 ` H.J. Lu
  0 siblings, 1 reply; 11+ messages in thread
From: Alan Modra @ 2011-04-21  1:58 UTC (permalink / raw)
  To: binutils

How do people feel about poking some flags into bfd_link_hash_entry?
This can be done without increasing the size of the struct, since
"type" is an unsigned int but only needs 3 bits.  The negative side is
that hosts without efficient byte read access will see a linker
slowdown.  "type" is the most used field of bfd_link_hash_entry.
On the positive side, this would allow the linker lto plugin code to
lose a potentially very large symbol hash table.  Also, other fields
from elf_link_hash_entry and coff_link_hash_entry could move into
bfd_link_hash_entry, reducing the size of the linker hash table.

include/
	* bfdlink.h (ENUM_BITFIELD): Define.
	(struct bfd_link_hash_entry): Make "type" a bitfield.  Add "non_ir_ref".
	(struct bfd_link_callbacks <notice>): Pass bfd_link_hash_entry pointer
	rather than "name".
bfd/
	* coff-aux.c (coff_m68k_aux_link_add_one_symbol): Update "notice" call.
	* linker.c (_bfd_link_hash_newfunc): Clear bitfields.
	(_bfd_generic_link_add_one_symbol): Update "notice" call.
ld/
	* ldmain.c (notice): Delete "name" param, add "h".
	* plugin.c (plugin_notice): Likewise.  Set non_ir_ref.
	(non_ironly_hash, init_non_ironly_hash): Delete.
	(is_visible_from_outside): Traverse entry_symbol chain.
	(get_symbols): Use non_ir_ref flag rather than hash lookup.

Index: include/bfdlink.h
===================================================================
RCS file: /cvs/src/src/include/bfdlink.h,v
retrieving revision 1.83
diff -u -p -r1.83 bfdlink.h
--- include/bfdlink.h	20 Apr 2011 00:11:29 -0000	1.83
+++ include/bfdlink.h	20 Apr 2011 07:58:23 -0000
@@ -24,6 +24,12 @@
 #ifndef BFDLINK_H
 #define BFDLINK_H
 
+#if (__GNUC__ * 1000 + __GNUC_MINOR__ > 2000)
+#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
+#else
+#define ENUM_BITFIELD(TYPE) unsigned int
+#endif
+
 /* Which symbols to strip during a link.  */
 enum bfd_link_strip
 {
@@ -91,7 +97,9 @@ struct bfd_link_hash_entry
   struct bfd_hash_entry root;
 
   /* Type of this entry.  */
-  enum bfd_link_hash_type type;
+  ENUM_BITFIELD (bfd_link_hash_type) type : 8;
+
+  unsigned int non_ir_ref : 1;
 
   /* A union of information depending upon the type.  */
   union
@@ -570,11 +578,11 @@ struct bfd_link_callbacks
     (struct bfd_link_info *, const char *name,
      bfd *abfd, asection *section, bfd_vma address);
   /* A function which is called when a symbol in notice_hash is
-     defined or referenced.  NAME is the symbol.  ABFD, SECTION and
-     ADDRESS are the value of the symbol.  If SECTION is
+     defined or referenced.  H is the symbol.  ABFD, SECTION and
+     ADDRESS are the (new) value of the symbol.  If SECTION is
      bfd_und_section, this is a reference.  */
   bfd_boolean (*notice)
-    (struct bfd_link_info *, const char *name,
+    (struct bfd_link_info *, struct bfd_link_hash_entry *h,
      bfd *abfd, asection *section, bfd_vma address);
   /* Error or warning link info message.  */
   void (*einfo)
Index: bfd/coff-aux.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-aux.c,v
retrieving revision 1.10
diff -u -p -r1.10 coff-aux.c
--- bfd/coff-aux.c	2 Sep 2009 07:18:36 -0000	1.10
+++ bfd/coff-aux.c	20 Apr 2011 07:57:20 -0000
@@ -105,7 +105,7 @@ coff_m68k_aux_link_add_one_symbol (info,
 	  && (bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE)
 	      != (struct bfd_hash_entry *) NULL))
 	{
-	  if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+	  if (! (*info->callbacks->notice) (info, h, abfd, section, value))
 	    return FALSE;
 	}
 
Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.80
diff -u -p -r1.80 linker.c
--- bfd/linker.c	20 Apr 2011 00:22:08 -0000	1.80
+++ bfd/linker.c	20 Apr 2011 07:57:50 -0000
@@ -465,10 +465,8 @@ _bfd_link_hash_newfunc (struct bfd_hash_
       struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry;
 
       /* Initialize the local fields.  */
-      h->type = bfd_link_hash_new;
-      memset (&h->u.undef.next, 0,
-	      (sizeof (struct bfd_link_hash_entry)
-	       - offsetof (struct bfd_link_hash_entry, u.undef.next)));
+      memset ((char *) &h->root + sizeof (h->root), 0,
+	      sizeof (*h) - sizeof (h->root));
     }
 
   return entry;
@@ -1609,8 +1608,7 @@ _bfd_generic_link_add_one_symbol (struct
       || (info->notice_hash != NULL
 	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
     {
-      if (! (*info->callbacks->notice) (info, h->root.string, abfd, section,
-					value))
+      if (! (*info->callbacks->notice) (info, h, abfd, section, value))
 	return FALSE;
     }
 
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.153
diff -u -p -r1.153 ldmain.c
--- ld/ldmain.c	20 Apr 2011 00:22:08 -0000	1.153
+++ ld/ldmain.c	20 Apr 2011 07:58:25 -0000
@@ -150,7 +150,8 @@ static bfd_boolean reloc_dangerous
 static bfd_boolean unattached_reloc
   (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
 static bfd_boolean notice
-  (struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma);
+  (struct bfd_link_info *, struct bfd_link_hash_entry *,
+   bfd *, asection *, bfd_vma);
 
 static struct bfd_link_callbacks link_callbacks =
 {
@@ -1479,18 +1480,21 @@ unattached_reloc (struct bfd_link_info *
 
 static bfd_boolean
 notice (struct bfd_link_info *info,
-	const char *name,
+	struct bfd_link_hash_entry *h,
 	bfd *abfd,
 	asection *section,
 	bfd_vma value)
 {
-  if (name == NULL)
+  const char *name;
+
+  if (h == NULL)
     {
       if (command_line.cref || nocrossref_list != NULL)
 	return handle_asneeded_cref (abfd, (enum notice_asneeded_action) value);
       return TRUE;
     }
 
+  name = h->root.string;
   if (info->notice_hash != NULL
       && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)
     {
Index: ld/plugin.c
===================================================================
RCS file: /cvs/src/src/ld/plugin.c,v
retrieving revision 1.32
diff -u -p -r1.32 plugin.c
--- ld/plugin.c	20 Apr 2011 00:22:08 -0000	1.32
+++ ld/plugin.c	20 Apr 2011 07:58:26 -0000
@@ -90,13 +90,6 @@ static plugin_t *called_plugin = NULL;
 /* Last plugin to cause an error, if any.  */
 static const char *error_plugin = NULL;
 
-/* A hash table that records symbols referenced by non-IR files.  Used
-   at get_symbols time to determine whether any prevailing defs from
-   IR files are referenced only from other IR files, so tthat we can
-   we can distinguish the LDPR_PREVAILING_DEF and LDPR_PREVAILING_DEF_IRONLY
-   cases when establishing symbol resolutions.  */
-static struct bfd_hash_table *non_ironly_hash = NULL;
-
 /* State of linker "notice" interface before we poked at it.  */
 static bfd_boolean orig_notice_all;
 
@@ -133,7 +126,7 @@ static const size_t tv_header_size = ARR
 
 /* Forward references.  */
 static bfd_boolean plugin_notice (struct bfd_link_info *info,
-				  const char *name, bfd *abfd,
+				  struct bfd_link_hash_entry *h, bfd *abfd,
 				  asection *section, bfd_vma value);
 static bfd_boolean plugin_multiple_definition (struct bfd_link_info *info,
 					       struct bfd_link_hash_entry *h,
@@ -438,6 +431,8 @@ static inline bfd_boolean
 is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section,
 			 struct bfd_link_hash_entry *blhe)
 {
+  struct bfd_sym_chain *sym;
+
   /* Section's owner may be NULL if it is the absolute
      section, fortunately is_ir_dummy_bfd handles that.  */
   if (!is_ir_dummy_bfd (section->owner))
@@ -466,6 +461,12 @@ is_visible_from_outside (struct ld_plugi
       return (lsym->visibility == LDPV_DEFAULT
 	      || lsym->visibility == LDPV_PROTECTED);
     }
+
+  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
+    if (sym->name
+	&& strcmp (sym->name, blhe->root.string) == 0)
+      return TRUE;
+
   return FALSE;
 }
 
@@ -520,9 +521,8 @@ get_symbols (const void *handle, int nsy
 	 even potentially-referenced, perhaps in a future final link if
 	 this is a partial one, perhaps dynamically at load-time if the
 	 symbol is externally visible.  */
-      ironly = (!is_visible_from_outside (&syms[n], owner_sec, blhe)
-		&& !bfd_hash_lookup (non_ironly_hash, syms[n].name,
-				     FALSE, FALSE));
+      ironly = !(blhe->non_ir_ref
+		 || is_visible_from_outside (&syms[n], owner_sec, blhe));
 
       /* If it was originally undefined or common, then it has been
 	 resolved; determine how.  */
@@ -740,27 +740,6 @@ plugin_active_plugins_p (void)
   return plugins_list != NULL;
 }
 
-/* Init the non_ironly hash table.  */
-static void
-init_non_ironly_hash (void)
-{
-  struct bfd_sym_chain *sym;
-
-  non_ironly_hash
-    = (struct bfd_hash_table *) xmalloc (sizeof (struct bfd_hash_table));
-  if (!bfd_hash_table_init_n (non_ironly_hash,
-			      bfd_hash_newfunc,
-			      sizeof (struct bfd_hash_entry),
-			      61))
-    einfo (_("%P%F: bfd_hash_table_init failed: %E\n"));
-
-  for (sym = &entry_symbol; sym != NULL; sym = sym->next)
-    if (sym->name
-	&& !bfd_hash_lookup (non_ironly_hash, sym->name, TRUE, TRUE))
-      einfo (_("%P%X: hash table failure adding symbol %s\n"),
-	     sym->name);
-}
-
 /* Load up and initialise all plugins after argument parsing.  */
 int
 plugin_load_plugins (void)
@@ -814,7 +793,6 @@ plugin_load_plugins (void)
   plugin_callbacks.notice = &plugin_notice;
   link_info.notice_all = TRUE;
   link_info.callbacks = &plugin_callbacks;
-  init_non_ironly_hash ();
 
   return 0;
 }
@@ -934,20 +912,18 @@ plugin_call_cleanup (void)
 
 /* To determine which symbols should be resolved LDPR_PREVAILING_DEF
    and which LDPR_PREVAILING_DEF_IRONLY, we notice all the symbols as
-   the linker adds them to the linker hash table.  If we see a symbol
-   being referenced from a non-IR file, we add it to the non_ironly hash
-   table.  If we can't find it there at get_symbols time, we know that
-   it was referenced only by IR files.  We have to notice_all symbols,
-   because we won't necessarily know until later which ones will be
-   contributed by IR files.  */
+   the linker adds them to the linker hash table.  Mark those
+   referenced from a non-IR file with non_ir_ref.  We have to
+   notice_all symbols, because we won't necessarily know until later
+   which ones will be contributed by IR files.  */
 static bfd_boolean
 plugin_notice (struct bfd_link_info *info,
-	       const char *name,
+	       struct bfd_link_hash_entry *h,
 	       bfd *abfd,
 	       asection *section,
 	       bfd_vma value)
 {
-  if (name != NULL)
+  if (h != NULL)
     {
       /* No further processing if this def/ref is from an IR dummy BFD.  */
       if (is_ir_dummy_bfd (abfd))
@@ -957,21 +933,16 @@ plugin_notice (struct bfd_link_info *inf
 	 pointing to the undefined section (according to the bfd
 	 linker notice callback interface definition).  */
       if (bfd_is_und_section (section))
-	{
-	  /* This is a ref from a non-IR file, so note the ref'd
-	     symbol in the non-IR-only hash.  */
-	  if (!bfd_hash_lookup (non_ironly_hash, name, TRUE, TRUE))
-	    einfo (_("%P%X: %s: hash table failure adding symbol %s\n"),
-		   abfd->filename, name);
-	}
+	h->non_ir_ref = TRUE;
     }
 
   /* Continue with cref/nocrossref/trace-sym processing.  */
-  if (name == NULL
+  if (h == NULL
       || orig_notice_all
       || (info->notice_hash != NULL
-	  && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL))
-    return (*orig_callbacks->notice) (info, name, abfd, section, value);
+	  && bfd_hash_lookup (info->notice_hash, h->root.string,
+			      FALSE, FALSE) != NULL))
+    return (*orig_callbacks->notice) (info, h, abfd, section, value);
   return TRUE;
 }
 

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-04-25 18:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-20  0:25 PR12365 and common symbols Alan Modra
2011-04-22 22:33 ` H.J. Lu
2011-04-24 10:14   ` Change bfd_link_hash_entry.type to a bitfield? Alan Modra
2011-04-24 14:49     ` [patch] ENUM_BITFIELD broke GDB [Re: Change bfd_link_hash_entry.type to a bitfield?] Jan Kratochvil
2011-04-24 15:28       ` Andreas Schwab
2011-04-24 15:31         ` [patch] ENUM_BITFIELD broke GDB Jan Kratochvil
2011-04-25  4:04           ` Alan Modra
2011-04-25 18:33             ` [commit include/+gdb/] " Jan Kratochvil
2011-04-21  1:58 Change bfd_link_hash_entry.type to a bitfield? Alan Modra
2011-04-21  2:55 ` H.J. Lu
2011-04-21 11:55   ` Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).