public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
@ 2015-02-05 13:54 H.J. Lu
  2015-02-07  9:42 ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2015-02-05 13:54 UTC (permalink / raw)
  To: binutils

This patch adds bfd_maybe_object_p which is similar to

bfd_check_format (abfd, bfd_object)

The difference is bfd_maybe_object_p takes an argument to indicate if a
compiler plug-in library is applied.  When a compiler plug-in library is
active, it also returns TRUE if the file is not an archive or a coredump
file.  This patch checks bfd_maybe_object_p instead of bfd_check_format
when calling plugin_maybe_claim or dealing with archive member.  It adds
tests for non-object IR file, including inside archive.

Any feedbacks, comments, objections?


H.J.
---
bfd/

	PR ld/17878
	* archive.c (bfd_generic_archive_p): Replace bfd_check_format
	with bfd_maybe_object_p.
	(_bfd_write_archive_contents): Likewise.
	(_bfd_compute_and_write_armap): Likewise.
	* elflink.c (elf_link_is_defined_archive_symbol): Add a pointer
	argument to struct bfd_link_info.  Replace bfd_check_format with
	bfd_maybe_object_p.
	(elf_link_add_archive_symbols): Update call to
	elf_link_is_defined_archive_symbol.  Replace bfd_check_format
	with bfd_maybe_object_p.
	* format.c (bfd_maybe_object_p): New.
	* targets.c (plugin_active_p): Likewise.
	* bfd-in2.h: Regenerated.

ld/

	PR ld/17878
	* Makefile.am (noinst_LTLIBRARIES): Add libldtestplug2.la and
	libldtestplug3.la.
	(libldtestplug2_la_SOURCES): New.
	(libldtestplug2_la_CFLAGS): Likewise.
	(libldtestplug2_la_LDFLAGS): Likewise.
	(libldtestplug3_la_SOURCES): New.
	(libldtestplug3_la_CFLAGS): Likewise.
	(libldtestplug3_la_LDFLAGS): Likewise.
	* Makefile.in: Regenerated.
	* ldfile.c (ldfile_try_open_bfd): Replace bfd_check_format with
	bfd_maybe_object_p.
	* plugin.c (plugin_get_ir_dummy_bfd): Update BFD info only if
	input template is a bfd_object file.
	* testplug2.c: New file.
	* testplug3.c: Likewise.

ld/testsuite/

	PR ld/17878
	* ld-plugin/func.c: Add some comments.
	* ld-plugin/plugin-14.d: New file.
	* ld-plugin/plugin-15.d: Likewise.
	* ld-plugin/plugin-16.d: Likewise.
	* ld-plugin/plugin-17.d: Likewise.
	* ld-plugin/plugin-18.d: Likewise.
	* ld-plugin/plugin-19.d: Likewise.
	* ld-plugin/plugin-20.d: Likewise.
	* ld-plugin/plugin-21.d: Likewise.
	* ld-plugin/plugin-22.d: Likewise.
	* ld-plugin/plugin-23.d: Likewise.
	* ld-plugin/plugin.exp (plugin2_name): New.
	(plugin3_name): Likewise.
	(plugin2_path): Likewise.
	(plugin3_path): Likewise.
	(testsrcfiles): Likewise.
	(testsrcfiles_notext): Likewise.
	(plugin_tests): Add tests for non-object IR file.
	(plugin_lib_tests): Likewise.
	(plugin_extra_elf_tests): Likewise.
	(plugin_src_tests): New tests for non-object IR file.
	Run nm --plugin test.
	Run plugin_src_tests.
---
 bfd/archive.c                      |   6 +-
 bfd/bfd-in2.h                      |  11 +
 bfd/elflink.c                      |  10 +-
 bfd/format.c                       |  25 ++
 bfd/targets.c                      |   8 +
 ld/Makefile.am                     |   8 +-
 ld/Makefile.in                     |  49 ++-
 ld/ldfile.c                        |   6 +-
 ld/plugin.c                        |  14 +-
 ld/testplug2.c                     | 691 +++++++++++++++++++++++++++++++++++++
 ld/testplug3.c                     | 674 ++++++++++++++++++++++++++++++++++++
 ld/testsuite/ld-plugin/func.c      |   3 +
 ld/testsuite/ld-plugin/plugin-13.d |  22 ++
 ld/testsuite/ld-plugin/plugin-14.d |  33 ++
 ld/testsuite/ld-plugin/plugin-15.d |  33 ++
 ld/testsuite/ld-plugin/plugin-16.d |  37 ++
 ld/testsuite/ld-plugin/plugin-17.d |  37 ++
 ld/testsuite/ld-plugin/plugin-18.d |  38 ++
 ld/testsuite/ld-plugin/plugin-19.d |  42 +++
 ld/testsuite/ld-plugin/plugin-20.d |   6 +
 ld/testsuite/ld-plugin/plugin-21.d |   6 +
 ld/testsuite/ld-plugin/plugin-22.d |   6 +
 ld/testsuite/ld-plugin/plugin-23.d |   6 +
 ld/testsuite/ld-plugin/plugin.exp  | 128 +++++++
 24 files changed, 1882 insertions(+), 17 deletions(-)
 create mode 100644 ld/testplug2.c
 create mode 100644 ld/testplug3.c
 create mode 100644 ld/testsuite/ld-plugin/plugin-13.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-14.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-15.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-16.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-17.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-18.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-19.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-20.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-21.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-22.d
 create mode 100644 ld/testsuite/ld-plugin/plugin-23.d

diff --git a/bfd/archive.c b/bfd/archive.c
index cc4c52f..15d1e89 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -856,7 +856,7 @@ bfd_generic_archive_p (bfd *abfd)
       if (first != NULL)
 	{
 	  first->target_defaulted = FALSE;
-	  if (bfd_check_format (first, bfd_object)
+	  if (bfd_maybe_object_p (first, plugin_active_p (first))
 	      && first->xvec != abfd->xvec)
 	    bfd_set_error (bfd_error_wrong_object_format);
 	  /* And we ought to close `first' here too.  */
@@ -2163,7 +2163,7 @@ _bfd_write_archive_contents (bfd *arch)
 
       if (makemap && ! hasobjects)
 	{			/* Don't bother if we won't make a map!  */
-	  if ((bfd_check_format (current, bfd_object)))
+	  if (bfd_maybe_object_p (current, plugin_active_p (current)))
 	    hasobjects = TRUE;
 	}
     }
@@ -2318,7 +2318,7 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
        current != NULL;
        current = current->archive_next, elt_no++)
     {
-      if (bfd_check_format (current, bfd_object)
+      if (bfd_maybe_object_p (current, plugin_active_p (current))
 	  && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
 	{
 	  long storage;
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 91dbf80..df34f03 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7199,6 +7199,14 @@ typedef struct bfd_target
 
 } bfd_target;
 
+/* TRUE if plugin is applied on ABFD.  */
+#if BFD_SUPPORTS_PLUGINS
+extern const bfd_target plugin_vec;
+# define plugin_active_p(abfd) ((abfd)->xvec == &plugin_vec)
+#else
+# define plugin_active_p(abfd) FALSE
+#endif
+
 bfd_boolean bfd_set_default_target (const char *name);
 
 const bfd_target *bfd_find_target (const char *target_name, bfd *abfd);
@@ -7217,6 +7225,9 @@ const bfd_target *bfd_search_for_target
 /* Extracted from format.c.  */
 bfd_boolean bfd_check_format (bfd *abfd, bfd_format format);
 
+bfd_boolean bfd_maybe_object_p
+   (bfd *abfd, bfd_boolean plugin_active_p);
+
 bfd_boolean bfd_check_format_matches
    (bfd *abfd, bfd_format format, char ***matching);
 
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 604cfb6..0a022ad 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -2935,7 +2935,8 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
    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_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef,
+				    struct bfd_link_info *info)
 {
   Elf_Internal_Shdr * hdr;
   bfd_size_type symcount;
@@ -2950,7 +2951,7 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   if (abfd == NULL)
     return FALSE;
 
-  if (! bfd_check_format (abfd, bfd_object))
+  if (! bfd_maybe_object_p (abfd, info->lto_plugin_active))
     return FALSE;
 
   /* Select the appropriate symbol table.  */
@@ -5046,7 +5047,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 		 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))
+	      if (! elf_link_is_defined_archive_symbol (abfd, symdef,
+							info))
 		continue;
 	    }
 	  else if (h->root.type != bfd_link_hash_undefined)
@@ -5062,7 +5064,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 	  if (element == NULL)
 	    goto error_return;
 
-	  if (! bfd_check_format (element, bfd_object))
+	  if (! bfd_maybe_object_p (element, info->lto_plugin_active))
 	    goto error_return;
 
 	  undefs_tail = info->hash->undefs_tail;
diff --git a/bfd/format.c b/bfd/format.c
index dd6dc8a..0cf2764 100644
--- a/bfd/format.c
+++ b/bfd/format.c
@@ -94,6 +94,31 @@ bfd_check_format (bfd *abfd, bfd_format format)
   return bfd_check_format_matches (abfd, format, NULL);
 }
 
+/*
+FUNCTION
+	bfd_maybe_object_p
+
+SYNOPSIS
+	bfd_boolean bfd_maybe_object_p
+	  (bfd *abfd, bfd_boolean plugin_active_p);
+
+DESCRIPTION
+	The function returns <<TRUE>> if the file attached to the BFD
+	@var{abfd} may be an object file.  Compiler plug-in library is
+	applied to @var{abfd} if @var{plugin_active_p} is <<TRUE>>.
+*/
+
+bfd_boolean
+bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
+{
+  /* LTO IR object file may look like a bfd_object file or a file which
+     is not bfd_core nor bfd_archive.  */
+  return (bfd_check_format (abfd, bfd_object)
+	  || (plugin_active_p
+	      && !bfd_check_format (abfd, bfd_core)
+	      && !bfd_check_format (abfd, bfd_archive)));
+}
+
 struct bfd_preserve
 {
   void *marker;
diff --git a/bfd/targets.c b/bfd/targets.c
index 0c7fed5..2c76a4c 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -558,6 +558,14 @@ to find an alternative output format that is suitable.
 .
 .} bfd_target;
 .
+.{* TRUE if plugin is applied on ABFD.  *}
+.#if BFD_SUPPORTS_PLUGINS
+.extern const bfd_target plugin_vec;
+.# define plugin_active_p(abfd) ((abfd)->xvec == &plugin_vec)
+.#else
+.# define plugin_active_p(abfd) FALSE
+.#endif
+.
 */
 
 /* All known xvecs (even those that don't compile on all systems).
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 18bcf8b..75a481b 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -2053,10 +2053,16 @@ bootstrap: ld3$(EXEEXT)
 # Build a dummy plugin using libtool.
 #
 if ENABLE_PLUGINS
-noinst_LTLIBRARIES = libldtestplug.la
+noinst_LTLIBRARIES = libldtestplug.la libldtestplug2.la libldtestplug3.la
 libldtestplug_la_SOURCES = testplug.c
 libldtestplug_la_CFLAGS= -g -O2
 libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere
+libldtestplug2_la_SOURCES = testplug2.c
+libldtestplug2_la_CFLAGS= -g -O2
+libldtestplug2_la_LDFLAGS = -no-undefined -rpath /nowhere
+libldtestplug3_la_SOURCES = testplug3.c
+libldtestplug3_la_CFLAGS= -g -O2
+libldtestplug3_la_LDFLAGS = -no-undefined -rpath /nowhere
 endif
 
 # DOCUMENTATION TARGETS
diff --git a/ld/Makefile.in b/ld/Makefile.in
index a3011c9..6c54fda 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -101,6 +101,24 @@ libldtestplug_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(libldtestplug_la_CFLAGS) \
 	$(CFLAGS) $(libldtestplug_la_LDFLAGS) $(LDFLAGS) -o $@
 @ENABLE_PLUGINS_TRUE@am_libldtestplug_la_rpath =
+libldtestplug2_la_LIBADD =
+@ENABLE_PLUGINS_TRUE@am_libldtestplug2_la_OBJECTS =  \
+@ENABLE_PLUGINS_TRUE@	libldtestplug2_la-testplug2.lo
+libldtestplug2_la_OBJECTS = $(am_libldtestplug2_la_OBJECTS)
+libldtestplug2_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(libldtestplug2_la_CFLAGS) $(CFLAGS) \
+	$(libldtestplug2_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_PLUGINS_TRUE@am_libldtestplug2_la_rpath =
+libldtestplug3_la_LIBADD =
+@ENABLE_PLUGINS_TRUE@am_libldtestplug3_la_OBJECTS =  \
+@ENABLE_PLUGINS_TRUE@	libldtestplug3_la-testplug3.lo
+libldtestplug3_la_OBJECTS = $(am_libldtestplug3_la_OBJECTS)
+libldtestplug3_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+	$(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(libldtestplug3_la_CFLAGS) $(CFLAGS) \
+	$(libldtestplug3_la_LDFLAGS) $(LDFLAGS) -o $@
+@ENABLE_PLUGINS_TRUE@am_libldtestplug3_la_rpath =
 am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(infodir)" \
 	"$(DESTDIR)$(man1dir)"
 PROGRAMS = $(bin_PROGRAMS)
@@ -135,7 +153,8 @@ YLWRAP = $(top_srcdir)/../ylwrap
 YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS)
 LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
 	--mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS)
-SOURCES = $(libldtestplug_la_SOURCES) $(ld_new_SOURCES) \
+SOURCES = $(libldtestplug_la_SOURCES) $(libldtestplug2_la_SOURCES) \
+	$(libldtestplug3_la_SOURCES) $(ld_new_SOURCES) \
 	$(EXTRA_ld_new_SOURCES)
 INFO_DEPS = ld.info
 am__TEXINFO_TEX_DIR = $(srcdir)/../texinfo
@@ -889,10 +908,16 @@ ld_new_LDADD = $(EMULATION_OFILES) $(EMUL_EXTRA_OFILES) $(BFDLIB) $(LIBIBERTY) $
 #
 # Build a dummy plugin using libtool.
 #
-@ENABLE_PLUGINS_TRUE@noinst_LTLIBRARIES = libldtestplug.la
+@ENABLE_PLUGINS_TRUE@noinst_LTLIBRARIES = libldtestplug.la libldtestplug2.la libldtestplug3.la
 @ENABLE_PLUGINS_TRUE@libldtestplug_la_SOURCES = testplug.c
 @ENABLE_PLUGINS_TRUE@libldtestplug_la_CFLAGS = -g -O2
 @ENABLE_PLUGINS_TRUE@libldtestplug_la_LDFLAGS = -no-undefined -rpath /nowhere
+@ENABLE_PLUGINS_TRUE@libldtestplug2_la_SOURCES = testplug2.c
+@ENABLE_PLUGINS_TRUE@libldtestplug2_la_CFLAGS = -g -O2
+@ENABLE_PLUGINS_TRUE@libldtestplug2_la_LDFLAGS = -no-undefined -rpath /nowhere
+@ENABLE_PLUGINS_TRUE@libldtestplug3_la_SOURCES = testplug3.c
+@ENABLE_PLUGINS_TRUE@libldtestplug3_la_CFLAGS = -g -O2
+@ENABLE_PLUGINS_TRUE@libldtestplug3_la_LDFLAGS = -no-undefined -rpath /nowhere
 MAINTAINERCLEANFILES = configdoc.texi ld.1 ld.info
 
 # We want to reconfigure if configure.host or configure.tgt changes.
@@ -980,6 +1005,10 @@ clean-noinstLTLIBRARIES:
 	done
 libldtestplug.la: $(libldtestplug_la_OBJECTS) $(libldtestplug_la_DEPENDENCIES) 
 	$(libldtestplug_la_LINK) $(am_libldtestplug_la_rpath) $(libldtestplug_la_OBJECTS) $(libldtestplug_la_LIBADD) $(LIBS)
+libldtestplug2.la: $(libldtestplug2_la_OBJECTS) $(libldtestplug2_la_DEPENDENCIES) 
+	$(libldtestplug2_la_LINK) $(am_libldtestplug2_la_rpath) $(libldtestplug2_la_OBJECTS) $(libldtestplug2_la_LIBADD) $(LIBS)
+libldtestplug3.la: $(libldtestplug3_la_OBJECTS) $(libldtestplug3_la_DEPENDENCIES) 
+	$(libldtestplug3_la_LINK) $(am_libldtestplug3_la_rpath) $(libldtestplug3_la_OBJECTS) $(libldtestplug3_la_LIBADD) $(LIBS)
 install-binPROGRAMS: $(bin_PROGRAMS)
 	@$(NORMAL_INSTALL)
 	test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
@@ -1397,6 +1426,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldver.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ldwrite.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexsup.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug2_la-testplug2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug3_la-testplug3.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libldtestplug_la-testplug.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mri.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-dll.Po@am__quote@
@@ -1431,6 +1462,20 @@ libldtestplug_la-testplug.lo: testplug.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug_la_CFLAGS) $(CFLAGS) -c -o libldtestplug_la-testplug.lo `test -f 'testplug.c' || echo '$(srcdir)/'`testplug.c
 
+libldtestplug2_la-testplug2.lo: testplug2.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug2_la_CFLAGS) $(CFLAGS) -MT libldtestplug2_la-testplug2.lo -MD -MP -MF $(DEPDIR)/libldtestplug2_la-testplug2.Tpo -c -o libldtestplug2_la-testplug2.lo `test -f 'testplug2.c' || echo '$(srcdir)/'`testplug2.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libldtestplug2_la-testplug2.Tpo $(DEPDIR)/libldtestplug2_la-testplug2.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='testplug2.c' object='libldtestplug2_la-testplug2.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug2_la_CFLAGS) $(CFLAGS) -c -o libldtestplug2_la-testplug2.lo `test -f 'testplug2.c' || echo '$(srcdir)/'`testplug2.c
+
+libldtestplug3_la-testplug3.lo: testplug3.c
+@am__fastdepCC_TRUE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug3_la_CFLAGS) $(CFLAGS) -MT libldtestplug3_la-testplug3.lo -MD -MP -MF $(DEPDIR)/libldtestplug3_la-testplug3.Tpo -c -o libldtestplug3_la-testplug3.lo `test -f 'testplug3.c' || echo '$(srcdir)/'`testplug3.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/libldtestplug3_la-testplug3.Tpo $(DEPDIR)/libldtestplug3_la-testplug3.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='testplug3.c' object='libldtestplug3_la-testplug3.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(LIBTOOL)  --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libldtestplug3_la_CFLAGS) $(CFLAGS) -c -o libldtestplug3_la-testplug3.lo `test -f 'testplug3.c' || echo '$(srcdir)/'`testplug3.c
+
 .l.c:
 	$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
 
diff --git a/ld/ldfile.c b/ld/ldfile.c
index c9c9541..94e07fd 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -301,9 +301,9 @@ success:
      bfd_object that it sets the bfd's arch and mach, which
      will be needed when and if we want to bfd_create a new
      one using this one as a template.  */
-  if (bfd_check_format (entry->the_bfd, bfd_object)
-      && link_info.lto_plugin_active
-      && !no_more_claiming)
+  if (link_info.lto_plugin_active
+      && !no_more_claiming
+      && bfd_maybe_object_p (entry->the_bfd, link_info.lto_plugin_active))
     {
       int fd = open (attempt, O_RDONLY | O_BINARY);
       if (fd >= 0)
diff --git a/ld/plugin.c b/ld/plugin.c
index 28236f2..c5f1443 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -272,10 +272,15 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
   if (abfd != NULL)
     {
       abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN;
-      bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
-      bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
-      if (bfd_make_writable (abfd)
-	  && bfd_copy_private_bfd_data (srctemplate, abfd))
+      if (!bfd_make_writable (abfd))
+	goto report_error;
+      if (bfd_check_format (srctemplate, bfd_object))
+	{
+	  bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate));
+	  bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate));
+	  if (!bfd_copy_private_bfd_data (srctemplate, abfd))
+	    goto report_error;
+	}
 	{
 	  flagword flags;
 
@@ -286,6 +291,7 @@ plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate)
 	    return abfd;
 	}
     }
+report_error:
   einfo (_("could not create dummy IR bfd: %F%E\n"));
   return NULL;
 }
diff --git a/ld/testplug2.c b/ld/testplug2.c
new file mode 100644
index 0000000..34d686c
--- /dev/null
+++ b/ld/testplug2.c
@@ -0,0 +1,691 @@
+/* Test plugin for the GNU linker.  Check non-object IR file as well as
+   get_input_file, get_view and release_input_file interfaces.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+   This file is part of the GNU Binutils.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "plugin-api.h"
+#include "filenames.h"
+/* For ARRAY_SIZE macro only - we don't link the library itself.  */
+#include "libiberty.h"
+
+extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
+static enum ld_plugin_status onclaim_file (const struct ld_plugin_input_file *file,
+				int *claimed);
+static enum ld_plugin_status onall_symbols_read (void);
+static enum ld_plugin_status oncleanup (void);
+
+/* Helper for calling plugin api message function.  */
+#define TV_MESSAGE if (tv_message) (*tv_message)
+
+/* Struct for recording files to claim / files claimed.  */
+typedef struct claim_file
+{
+  struct claim_file *next;
+  struct ld_plugin_input_file file;
+  bfd_boolean claimed;
+  struct ld_plugin_symbol *symbols;
+  int n_syms_allocated;
+  int n_syms_used;
+} claim_file_t;
+
+/* Types of things that can be added at all symbols read time.  */
+typedef enum addfile_enum
+{
+  ADD_FILE,
+  ADD_LIB,
+  ADD_DIR
+} addfile_enum_t;
+
+/* Struct for recording files to add to final link.  */
+typedef struct add_file
+{
+  struct add_file *next;
+  const char *name;
+  addfile_enum_t type;
+} add_file_t;
+
+/* Helper macro for defining array of transfer vector tags and names.  */
+#define ADDENTRY(tag) { tag, #tag }
+
+/* Struct for looking up human-readable versions of tag names.  */
+typedef struct tag_name
+{
+  enum ld_plugin_tag tag;
+  const char *name;
+} tag_name_t;
+
+/* Array of all known tags and their names.  */
+static const tag_name_t tag_names[] =
+{
+  ADDENTRY(LDPT_NULL),
+  ADDENTRY(LDPT_API_VERSION),
+  ADDENTRY(LDPT_GOLD_VERSION),
+  ADDENTRY(LDPT_LINKER_OUTPUT),
+  ADDENTRY(LDPT_OPTION),
+  ADDENTRY(LDPT_REGISTER_CLAIM_FILE_HOOK),
+  ADDENTRY(LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK),
+  ADDENTRY(LDPT_REGISTER_CLEANUP_HOOK),
+  ADDENTRY(LDPT_ADD_SYMBOLS),
+  ADDENTRY(LDPT_GET_SYMBOLS),
+  ADDENTRY(LDPT_GET_SYMBOLS_V2),
+  ADDENTRY(LDPT_ADD_INPUT_FILE),
+  ADDENTRY(LDPT_MESSAGE),
+  ADDENTRY(LDPT_GET_INPUT_FILE),
+  ADDENTRY(LDPT_GET_VIEW),
+  ADDENTRY(LDPT_RELEASE_INPUT_FILE),
+  ADDENTRY(LDPT_ADD_INPUT_LIBRARY),
+  ADDENTRY(LDPT_OUTPUT_NAME),
+  ADDENTRY(LDPT_SET_EXTRA_LIBRARY_PATH),
+  ADDENTRY(LDPT_GNU_LD_VERSION)
+};
+
+/* Function pointers to cache hooks passed at onload time.  */
+static ld_plugin_register_claim_file tv_register_claim_file = 0;
+static ld_plugin_register_all_symbols_read tv_register_all_symbols_read = 0;
+static ld_plugin_register_cleanup tv_register_cleanup = 0;
+static ld_plugin_add_symbols tv_add_symbols = 0;
+static ld_plugin_get_symbols tv_get_symbols = 0;
+static ld_plugin_get_symbols tv_get_symbols_v2 = 0;
+static ld_plugin_add_input_file tv_add_input_file = 0;
+static ld_plugin_message tv_message = 0;
+static ld_plugin_get_input_file tv_get_input_file = 0;
+static ld_plugin_get_view tv_get_view = 0;
+static ld_plugin_release_input_file tv_release_input_file = 0;
+static ld_plugin_add_input_library tv_add_input_library = 0;
+static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
+
+/* Other cached info from the transfer vector.  */
+static enum ld_plugin_output_file_type linker_output;
+static const char *output_name;
+
+/* Behaviour control flags set by plugin options.  */
+static enum ld_plugin_status onload_ret = LDPS_OK;
+static enum ld_plugin_status claim_file_ret = LDPS_OK;
+static enum ld_plugin_status all_symbols_read_ret = LDPS_OK;
+static enum ld_plugin_status cleanup_ret = LDPS_OK;
+static bfd_boolean register_claimfile_hook = TRUE;
+static bfd_boolean register_allsymbolsread_hook = FALSE;
+static bfd_boolean register_cleanup_hook = FALSE;
+static bfd_boolean dumpresolutions = FALSE;
+
+/* The master list of all claimable/claimed files.  */
+static claim_file_t *claimfiles_list = NULL;
+
+/* We keep a tail pointer for easy linking on the end.  */
+static claim_file_t **claimfiles_tail_chain_ptr = &claimfiles_list;
+
+/* The last claimed file added to the list, for receiving syms.  */
+static claim_file_t *last_claimfile = NULL;
+
+/* The master list of all files to add to the final link.  */
+static add_file_t *addfiles_list = NULL;
+
+/* We keep a tail pointer for easy linking on the end.  */
+static add_file_t **addfiles_tail_chain_ptr = &addfiles_list;
+
+/* Add a new claimfile on the end of the chain.  */
+static enum ld_plugin_status
+record_claim_file (const char *file, off_t filesize)
+{
+  claim_file_t *newfile;
+
+  newfile = malloc (sizeof *newfile);
+  if (!newfile)
+    return LDPS_ERR;
+  memset (newfile, 0, sizeof *newfile);
+  /* Only setup for now is remembering the name to look for.  */
+  newfile->file.name = file;
+  newfile->file.filesize = filesize;
+  /* Chain it on the end of the list.  */
+  *claimfiles_tail_chain_ptr = newfile;
+  claimfiles_tail_chain_ptr = &newfile->next;
+  /* Record it as active for receiving symbols to register.  */
+  last_claimfile = newfile;
+  return LDPS_OK;
+}
+
+/* Add a new addfile on the end of the chain.  */
+static enum ld_plugin_status
+record_add_file (const char *file, addfile_enum_t type)
+{
+  add_file_t *newfile;
+
+  newfile = malloc (sizeof *newfile);
+  if (!newfile)
+    return LDPS_ERR;
+  newfile->next = NULL;
+  newfile->name = file;
+  newfile->type = type;
+  /* Chain it on the end of the list.  */
+  *addfiles_tail_chain_ptr = newfile;
+  addfiles_tail_chain_ptr = &newfile->next;
+  return LDPS_OK;
+}
+
+/* Parse a command-line argument string into a symbol definition.
+   Symbol-strings follow the colon-separated format:
+	NAME:VERSION:def:vis:size:COMDATKEY
+   where the fields in capitals are strings and those in lower
+   case are integers.  We don't allow to specify a resolution as
+   doing so is not meaningful when calling the add symbols hook.  */
+static enum ld_plugin_status
+parse_symdefstr (const char *str, struct ld_plugin_symbol *sym)
+{
+  int n;
+  long long size;
+  const char *colon1, *colon2, *colon5;
+
+  /* Locate the colons separating the first two strings.  */
+  colon1 = strchr (str, ':');
+  if (!colon1)
+    return LDPS_ERR;
+  colon2 = strchr (colon1+1, ':');
+  if (!colon2)
+    return LDPS_ERR;
+  /* Name must not be empty (version may be).  */
+  if (colon1 == str)
+    return LDPS_ERR;
+
+  /* The fifth colon and trailing comdat key string are optional,
+     but the intermediate ones must all be present.  */
+  colon5 = strchr (colon2+1, ':');	/* Actually only third so far.  */
+  if (!colon5)
+    return LDPS_ERR;
+  colon5 = strchr (colon5+1, ':');	/* Hopefully fourth now.  */
+  if (!colon5)
+    return LDPS_ERR;
+  colon5 = strchr (colon5+1, ':');	/* Optional fifth now.  */
+
+  /* Finally we'll use sscanf to parse the numeric fields, then
+     we'll split out the strings which we need to allocate separate
+     storage for anyway so that we can add nul termination.  */
+  n = sscanf (colon2 + 1, "%i:%i:%lli", &sym->def, &sym->visibility, &size);
+  if (n != 3)
+    return LDPS_ERR;
+
+  /* Parsed successfully, so allocate strings and fill out fields.  */
+  sym->size = size;
+  sym->resolution = LDPR_UNKNOWN;
+  sym->name = malloc (colon1 - str + 1);
+  if (!sym->name)
+    return LDPS_ERR;
+  memcpy (sym->name, str, colon1 - str);
+  sym->name[colon1 - str] = '\0';
+  if (colon2 > (colon1 + 1))
+    {
+      sym->version = malloc (colon2 - colon1);
+      if (!sym->version)
+	return LDPS_ERR;
+      memcpy (sym->version, colon1 + 1, colon2 - (colon1 + 1));
+      sym->version[colon2 - (colon1 + 1)] = '\0';
+    }
+  else
+    sym->version = NULL;
+  if (colon5 && colon5[1])
+    {
+      sym->comdat_key = malloc (strlen (colon5 + 1) + 1);
+      if (!sym->comdat_key)
+	return LDPS_ERR;
+      strcpy (sym->comdat_key, colon5 + 1);
+    }
+  else
+    sym->comdat_key = 0;
+  return LDPS_OK;
+}
+
+/* Record a symbol to be added for the last-added claimfile.  */
+static enum ld_plugin_status
+record_claimed_file_symbol (const char *symdefstr)
+{
+  struct ld_plugin_symbol sym;
+
+  /* Can't add symbols except as belonging to claimed files.  */
+  if (!last_claimfile)
+    return LDPS_ERR;
+
+  /* If string doesn't parse correctly, give an error.  */
+  if (parse_symdefstr (symdefstr, &sym) != LDPS_OK)
+    return LDPS_ERR;
+
+  /* Check for enough space, resize array if needed, and add it.  */
+  if (last_claimfile->n_syms_allocated == last_claimfile->n_syms_used)
+    {
+      int new_n_syms = last_claimfile->n_syms_allocated
+			? 2 * last_claimfile->n_syms_allocated
+			: 10;
+      last_claimfile->symbols = realloc (last_claimfile->symbols,
+			new_n_syms * sizeof *last_claimfile->symbols);
+      if (!last_claimfile->symbols)
+	return LDPS_ERR;
+      last_claimfile->n_syms_allocated = new_n_syms;
+    }
+  last_claimfile->symbols[last_claimfile->n_syms_used++] = sym;
+
+  return LDPS_OK;
+}
+
+/* Records the status to return from one of the registered hooks.  */
+static enum ld_plugin_status
+set_ret_val (const char *whichval, enum ld_plugin_status retval)
+{
+  if (!strcmp ("onload", whichval))
+    onload_ret = retval;
+  else if (!strcmp ("claimfile", whichval))
+    claim_file_ret = retval;
+  else if (!strcmp ("allsymbolsread", whichval))
+    all_symbols_read_ret = retval;
+  else if (!strcmp ("cleanup", whichval))
+    cleanup_ret = retval;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Records hooks which should be registered.  */
+static enum ld_plugin_status
+set_register_hook (const char *whichhook, bfd_boolean yesno)
+{
+  if (!strcmp ("claimfile", whichhook))
+    register_claimfile_hook = yesno;
+  else if (!strcmp ("allsymbolsread", whichhook))
+    register_allsymbolsread_hook = yesno;
+  else if (!strcmp ("cleanup", whichhook))
+    register_cleanup_hook = yesno;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Determine type of plugin option and pass to individual parsers.  */
+static enum ld_plugin_status
+parse_option (const char *opt)
+{
+  if (!strncmp ("fail", opt, 4))
+    return set_ret_val (opt + 4, LDPS_ERR);
+  else if (!strncmp ("pass", opt, 4))
+    return set_ret_val (opt + 4, LDPS_OK);
+  else if (!strncmp ("register", opt, 8))
+    return set_register_hook (opt + 8, TRUE);
+  else if (!strncmp ("noregister", opt, 10))
+    return set_register_hook (opt + 10, FALSE);
+  else if (!strncmp ("claim:", opt, 6))
+    return record_claim_file (opt + 6, 0);
+  else if (!strncmp ("sym:", opt, 4))
+    return record_claimed_file_symbol (opt + 4);
+  else if (!strncmp ("add:", opt, 4))
+    return record_add_file (opt + 4, ADD_FILE);
+  else if (!strncmp ("lib:", opt, 4))
+    return record_add_file (opt + 4, ADD_LIB);
+  else if (!strncmp ("dir:", opt, 4))
+    return record_add_file (opt + 4, ADD_DIR);
+  else if (!strcmp ("dumpresolutions", opt))
+    dumpresolutions = TRUE;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Output contents of transfer vector array entry in human-readable form.  */
+static void
+dump_tv_tag (size_t n, struct ld_plugin_tv *tv)
+{
+  size_t tag;
+  char unknownbuf[40];
+  const char *name;
+
+  for (tag = 0; tag < ARRAY_SIZE (tag_names); tag++)
+    if (tag_names[tag].tag == tv->tv_tag)
+      break;
+  sprintf (unknownbuf, "unknown tag #%d", tv->tv_tag);
+  name = (tag < ARRAY_SIZE (tag_names)) ? tag_names[tag].name : unknownbuf;
+  switch (tv->tv_tag)
+    {
+      case LDPT_OPTION:
+      case LDPT_OUTPUT_NAME:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s '%s'", n, name,
+		    tv->tv_u.tv_string);
+        break;
+      case LDPT_REGISTER_CLAIM_FILE_HOOK:
+      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+      case LDPT_REGISTER_CLEANUP_HOOK:
+      case LDPT_ADD_SYMBOLS:
+      case LDPT_GET_SYMBOLS:
+      case LDPT_GET_SYMBOLS_V2:
+      case LDPT_ADD_INPUT_FILE:
+      case LDPT_MESSAGE:
+      case LDPT_GET_INPUT_FILE:
+      case LDPT_GET_VIEW:
+      case LDPT_RELEASE_INPUT_FILE:
+      case LDPT_ADD_INPUT_LIBRARY:
+      case LDPT_SET_EXTRA_LIBRARY_PATH:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s func@0x%p", n, name,
+		    (void *)(tv->tv_u.tv_message));
+        break;
+      case LDPT_NULL:
+      case LDPT_API_VERSION:
+      case LDPT_GOLD_VERSION:
+      case LDPT_LINKER_OUTPUT:
+      case LDPT_GNU_LD_VERSION:
+      default:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s value %W (%d)", n, name,
+		    (bfd_vma)tv->tv_u.tv_val, tv->tv_u.tv_val);
+	break;
+    }
+}
+
+/* Handle/record information received in a transfer vector entry.  */
+static enum ld_plugin_status
+parse_tv_tag (struct ld_plugin_tv *tv)
+{
+#define SETVAR(x) x = tv->tv_u.x
+  switch (tv->tv_tag)
+    {
+      case LDPT_OPTION:
+	return parse_option (tv->tv_u.tv_string);
+      case LDPT_NULL:
+      case LDPT_GOLD_VERSION:
+      case LDPT_GNU_LD_VERSION:
+      case LDPT_API_VERSION:
+      default:
+	break;
+      case LDPT_OUTPUT_NAME:
+	output_name = tv->tv_u.tv_string;
+	break;
+      case LDPT_LINKER_OUTPUT:
+	linker_output = tv->tv_u.tv_val;
+	break;
+      case LDPT_REGISTER_CLAIM_FILE_HOOK:
+	SETVAR(tv_register_claim_file);
+	break;
+      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+	SETVAR(tv_register_all_symbols_read);
+	break;
+      case LDPT_REGISTER_CLEANUP_HOOK:
+	SETVAR(tv_register_cleanup);
+	break;
+      case LDPT_ADD_SYMBOLS:
+	SETVAR(tv_add_symbols);
+	break;
+      case LDPT_GET_SYMBOLS:
+	SETVAR(tv_get_symbols);
+	break;
+      case LDPT_GET_SYMBOLS_V2:
+	tv_get_symbols_v2 = tv->tv_u.tv_get_symbols;
+	break;
+      case LDPT_ADD_INPUT_FILE:
+	SETVAR(tv_add_input_file);
+	break;
+      case LDPT_MESSAGE:
+	SETVAR(tv_message);
+	break;
+      case LDPT_GET_INPUT_FILE:
+	SETVAR(tv_get_input_file);
+	break;
+      case LDPT_GET_VIEW:
+	SETVAR(tv_get_view);
+	break;
+      case LDPT_RELEASE_INPUT_FILE:
+	SETVAR(tv_release_input_file);
+	break;
+      case LDPT_ADD_INPUT_LIBRARY:
+	SETVAR(tv_add_input_library);
+	break;
+      case LDPT_SET_EXTRA_LIBRARY_PATH:
+	SETVAR(tv_set_extra_library_path);
+	break;
+    }
+#undef SETVAR
+  return LDPS_OK;
+}
+
+/* Standard plugin API entry point.  */
+enum ld_plugin_status
+onload (struct ld_plugin_tv *tv)
+{
+  enum ld_plugin_status rv;
+
+  /* This plugin does nothing but dump the tv array.  It would
+     be an error if this function was called without one.  */
+  if (!tv)
+    return LDPS_ERR;
+
+  /* First entry should always be LDPT_MESSAGE, letting us get
+     hold of it easily so we can send output straight away.  */
+  if (tv[0].tv_tag == LDPT_MESSAGE)
+    tv_message = tv[0].tv_u.tv_message;
+
+  do
+    if ((rv = parse_tv_tag (tv)) != LDPS_OK)
+      return rv;
+  while ((tv++)->tv_tag != LDPT_NULL);
+
+  /* Register hooks only if instructed by options.  */
+  if (register_claimfile_hook)
+    {
+      if (!tv_register_claim_file)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_claim_file) (onclaim_file);
+    }
+  if (register_allsymbolsread_hook)
+    {
+      if (!tv_register_all_symbols_read)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_all_symbols_read) (onall_symbols_read);
+    }
+  if (register_cleanup_hook)
+    {
+      if (!tv_register_cleanup)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_cleanup) (oncleanup);
+    }
+
+  /* Claim testsuite/ld-plugin/func.c, standalone or in a library.  Its
+     size must be SIZE_OF_FUNC_C bytes.  */
+#define SIZE_OF_FUNC_C	248
+  if (onload_ret == LDPS_OK
+      && (record_claim_file ("func.c", SIZE_OF_FUNC_C) != LDPS_OK
+	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
+	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK
+	  || record_claim_file ("libfunc.a", SIZE_OF_FUNC_C) != LDPS_OK
+	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
+	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK))
+    onload_ret = LDPS_ERR;
+
+  return onload_ret;
+}
+
+char *
+xstrdup (const char *s)
+{
+  size_t len = strlen (s) + 1;
+  char *ret = malloc (len + 1);
+  return (char *) memcpy (ret, s, len);
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
+{
+  /* Let's see if we want to claim this file.  */
+  claim_file_t *claimfile = claimfiles_list;
+  size_t len = strlen (file->name);
+  char *name = xstrdup (file->name);
+  char *p = name + len;
+  bfd_boolean islib;
+
+  /* Only match the file name without the directory part.  */
+  islib = *p == 'a' && *(p - 1) == '.';
+  for (; p != name; p--)
+    if (IS_DIR_SEPARATOR (*p))
+      {
+	p++;
+	break;
+      }
+
+  while (claimfile)
+    {
+      /* Claim the file only if the file name and size match and don't
+	 match the whole library.  */
+      if (!strcmp (p, claimfile->file.name)
+	  && claimfile->file.filesize == file->filesize
+	  && (!islib || file->offset != 0))
+	break;
+      claimfile = claimfile->next;
+    }
+
+  free (name);
+
+  /* If we decided to claim it, record that fact, and add any symbols
+     that were defined for it by plugin options.  */
+  *claimed = (claimfile != 0);
+  if (claimfile)
+    {
+      claimfile->claimed = TRUE;
+      claimfile->file = *file;
+      if (claimfile->n_syms_used && !tv_add_symbols)
+	return LDPS_ERR;
+      else if (claimfile->n_syms_used)
+	return (*tv_add_symbols) (claimfile->file.handle,
+				claimfile->n_syms_used, claimfile->symbols);
+    }
+
+  return claim_file_ret;
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+onall_symbols_read (void)
+{
+  static const char *resolutions[] =
+    {
+      "LDPR_UNKNOWN",
+      "LDPR_UNDEF",
+      "LDPR_PREVAILING_DEF",
+      "LDPR_PREVAILING_DEF_IRONLY",
+      "LDPR_PREEMPTED_REG",
+      "LDPR_PREEMPTED_IR",
+      "LDPR_RESOLVED_IR",
+      "LDPR_RESOLVED_EXEC",
+      "LDPR_RESOLVED_DYN",
+      "LDPR_PREVAILING_DEF_IRONLY_EXP",
+    };
+  claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
+  add_file_t *addfile = addfiles_list;
+  struct ld_plugin_input_file file;
+  const void *view;
+  char buffer[30];
+  int fd;
+  char *filename;
+  TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
+  for ( ; claimfile; claimfile = claimfile->next)
+    {
+      enum ld_plugin_status rv;
+      int n;
+      if (claimfile->n_syms_used && !tv_get_symbols_v2)
+	return LDPS_ERR;
+      else if (!claimfile->n_syms_used)
+        continue;
+      else if (!claimfile->file.handle)
+        continue;
+      rv = tv_get_input_file (claimfile->file.handle, &file);
+      if (rv != LDPS_OK)
+	return rv;
+      TV_MESSAGE (LDPL_INFO, "Input: %s (%s)", file.name,
+		  claimfile->file.name);
+      rv = tv_get_view (claimfile->file.handle, &view);
+      if (rv != LDPS_OK)
+	return rv;
+#define EXPECTED_VIEW "/* The first line of this file must match the expectation of"
+#define EXPECTED_VIEW_LENGTH (sizeof (EXPECTED_VIEW) - 1)
+      if (file.filesize != SIZE_OF_FUNC_C
+	  || SIZE_OF_FUNC_C < sizeof EXPECTED_VIEW_LENGTH
+	  || memcmp (view, EXPECTED_VIEW, EXPECTED_VIEW_LENGTH) != 0)
+	{
+	  ((char *) view)[EXPECTED_VIEW_LENGTH] = '\0';
+	  TV_MESSAGE (LDPL_INFO, "Incorrect view:");
+	  TV_MESSAGE (LDPL_INFO, "  Expect: " EXPECTED_VIEW);
+	  TV_MESSAGE (LDPL_INFO, "  Result: %s", view);
+	}
+      rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
+			      claimfile->symbols);
+      if (rv != LDPS_OK)
+	return rv;
+      for (n = 0; n < claimfile->n_syms_used; n++)
+	TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
+		    claimfile->symbols[n].name,
+		    claimfile->symbols[n].version ? "@" : "",
+		    (claimfile->symbols[n].version
+		     ? claimfile->symbols[n].version : ""),
+		    resolutions[claimfile->symbols[n].resolution]);
+      fd = claimfile->file.fd;
+      filename = xstrdup (claimfile->file.name);
+      rv = tv_release_input_file (claimfile->file.handle);
+      if (rv != LDPS_OK)
+	{
+	  free (filename);
+	  return rv;
+	}
+      if (read (fd, buffer, sizeof (buffer)) >= 0)
+	{
+	  rv == LDPS_ERR;
+	  TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s",
+		      claimfile->file.name);
+	}
+      free (filename);
+    }
+  for ( ; addfile ; addfile = addfile->next)
+    {
+      enum ld_plugin_status rv;
+      if (addfile->type == ADD_LIB && tv_add_input_library)
+	rv = (*tv_add_input_library) (addfile->name);
+      else if (addfile->type == ADD_FILE && tv_add_input_file)
+	rv = (*tv_add_input_file) (addfile->name);
+      else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
+	rv = (*tv_set_extra_library_path) (addfile->name);
+      else
+	rv = LDPS_ERR;
+      if (rv != LDPS_OK)
+	return rv;
+    }
+  fflush (NULL);
+  return all_symbols_read_ret;
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+oncleanup (void)
+{
+  TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
+  fflush (NULL);
+  return cleanup_ret;
+}
diff --git a/ld/testplug3.c b/ld/testplug3.c
new file mode 100644
index 0000000..a45991b
--- /dev/null
+++ b/ld/testplug3.c
@@ -0,0 +1,674 @@
+/* Test plugin for the GNU linker.  Check non-object IR file and calling
+   release_input_file from onclaim_file.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+   This file is part of the GNU Binutils.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "plugin-api.h"
+#include "filenames.h"
+/* For ARRAY_SIZE macro only - we don't link the library itself.  */
+#include "libiberty.h"
+
+extern enum ld_plugin_status onload (struct ld_plugin_tv *tv);
+static enum ld_plugin_status onclaim_file (const struct ld_plugin_input_file *file,
+				int *claimed);
+static enum ld_plugin_status onall_symbols_read (void);
+static enum ld_plugin_status oncleanup (void);
+
+/* Helper for calling plugin api message function.  */
+#define TV_MESSAGE if (tv_message) (*tv_message)
+
+/* Struct for recording files to claim / files claimed.  */
+typedef struct claim_file
+{
+  struct claim_file *next;
+  struct ld_plugin_input_file file;
+  bfd_boolean claimed;
+  struct ld_plugin_symbol *symbols;
+  int n_syms_allocated;
+  int n_syms_used;
+} claim_file_t;
+
+/* Types of things that can be added at all symbols read time.  */
+typedef enum addfile_enum
+{
+  ADD_FILE,
+  ADD_LIB,
+  ADD_DIR
+} addfile_enum_t;
+
+/* Struct for recording files to add to final link.  */
+typedef struct add_file
+{
+  struct add_file *next;
+  const char *name;
+  addfile_enum_t type;
+} add_file_t;
+
+/* Helper macro for defining array of transfer vector tags and names.  */
+#define ADDENTRY(tag) { tag, #tag }
+
+/* Struct for looking up human-readable versions of tag names.  */
+typedef struct tag_name
+{
+  enum ld_plugin_tag tag;
+  const char *name;
+} tag_name_t;
+
+/* Array of all known tags and their names.  */
+static const tag_name_t tag_names[] =
+{
+  ADDENTRY(LDPT_NULL),
+  ADDENTRY(LDPT_API_VERSION),
+  ADDENTRY(LDPT_GOLD_VERSION),
+  ADDENTRY(LDPT_LINKER_OUTPUT),
+  ADDENTRY(LDPT_OPTION),
+  ADDENTRY(LDPT_REGISTER_CLAIM_FILE_HOOK),
+  ADDENTRY(LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK),
+  ADDENTRY(LDPT_REGISTER_CLEANUP_HOOK),
+  ADDENTRY(LDPT_ADD_SYMBOLS),
+  ADDENTRY(LDPT_GET_SYMBOLS),
+  ADDENTRY(LDPT_GET_SYMBOLS_V2),
+  ADDENTRY(LDPT_ADD_INPUT_FILE),
+  ADDENTRY(LDPT_MESSAGE),
+  ADDENTRY(LDPT_GET_INPUT_FILE),
+  ADDENTRY(LDPT_GET_VIEW),
+  ADDENTRY(LDPT_RELEASE_INPUT_FILE),
+  ADDENTRY(LDPT_ADD_INPUT_LIBRARY),
+  ADDENTRY(LDPT_OUTPUT_NAME),
+  ADDENTRY(LDPT_SET_EXTRA_LIBRARY_PATH),
+  ADDENTRY(LDPT_GNU_LD_VERSION)
+};
+
+/* Function pointers to cache hooks passed at onload time.  */
+static ld_plugin_register_claim_file tv_register_claim_file = 0;
+static ld_plugin_register_all_symbols_read tv_register_all_symbols_read = 0;
+static ld_plugin_register_cleanup tv_register_cleanup = 0;
+static ld_plugin_add_symbols tv_add_symbols = 0;
+static ld_plugin_get_symbols tv_get_symbols = 0;
+static ld_plugin_get_symbols tv_get_symbols_v2 = 0;
+static ld_plugin_add_input_file tv_add_input_file = 0;
+static ld_plugin_message tv_message = 0;
+static ld_plugin_get_input_file tv_get_input_file = 0;
+static ld_plugin_get_view tv_get_view = 0;
+static ld_plugin_release_input_file tv_release_input_file = 0;
+static ld_plugin_add_input_library tv_add_input_library = 0;
+static ld_plugin_set_extra_library_path tv_set_extra_library_path = 0;
+
+/* Other cached info from the transfer vector.  */
+static enum ld_plugin_output_file_type linker_output;
+static const char *output_name;
+
+/* Behaviour control flags set by plugin options.  */
+static enum ld_plugin_status onload_ret = LDPS_OK;
+static enum ld_plugin_status claim_file_ret = LDPS_OK;
+static enum ld_plugin_status all_symbols_read_ret = LDPS_OK;
+static enum ld_plugin_status cleanup_ret = LDPS_OK;
+static bfd_boolean register_claimfile_hook = TRUE;
+static bfd_boolean register_allsymbolsread_hook = FALSE;
+static bfd_boolean register_cleanup_hook = FALSE;
+static bfd_boolean dumpresolutions = FALSE;
+
+/* The master list of all claimable/claimed files.  */
+static claim_file_t *claimfiles_list = NULL;
+
+/* We keep a tail pointer for easy linking on the end.  */
+static claim_file_t **claimfiles_tail_chain_ptr = &claimfiles_list;
+
+/* The last claimed file added to the list, for receiving syms.  */
+static claim_file_t *last_claimfile = NULL;
+
+/* The master list of all files to add to the final link.  */
+static add_file_t *addfiles_list = NULL;
+
+/* We keep a tail pointer for easy linking on the end.  */
+static add_file_t **addfiles_tail_chain_ptr = &addfiles_list;
+
+/* Add a new claimfile on the end of the chain.  */
+static enum ld_plugin_status
+record_claim_file (const char *file, off_t filesize)
+{
+  claim_file_t *newfile;
+
+  newfile = malloc (sizeof *newfile);
+  if (!newfile)
+    return LDPS_ERR;
+  memset (newfile, 0, sizeof *newfile);
+  /* Only setup for now is remembering the name to look for.  */
+  newfile->file.name = file;
+  newfile->file.filesize = filesize;
+  /* Chain it on the end of the list.  */
+  *claimfiles_tail_chain_ptr = newfile;
+  claimfiles_tail_chain_ptr = &newfile->next;
+  /* Record it as active for receiving symbols to register.  */
+  last_claimfile = newfile;
+  return LDPS_OK;
+}
+
+/* Add a new addfile on the end of the chain.  */
+static enum ld_plugin_status
+record_add_file (const char *file, addfile_enum_t type)
+{
+  add_file_t *newfile;
+
+  newfile = malloc (sizeof *newfile);
+  if (!newfile)
+    return LDPS_ERR;
+  newfile->next = NULL;
+  newfile->name = file;
+  newfile->type = type;
+  /* Chain it on the end of the list.  */
+  *addfiles_tail_chain_ptr = newfile;
+  addfiles_tail_chain_ptr = &newfile->next;
+  return LDPS_OK;
+}
+
+/* Parse a command-line argument string into a symbol definition.
+   Symbol-strings follow the colon-separated format:
+	NAME:VERSION:def:vis:size:COMDATKEY
+   where the fields in capitals are strings and those in lower
+   case are integers.  We don't allow to specify a resolution as
+   doing so is not meaningful when calling the add symbols hook.  */
+static enum ld_plugin_status
+parse_symdefstr (const char *str, struct ld_plugin_symbol *sym)
+{
+  int n;
+  long long size;
+  const char *colon1, *colon2, *colon5;
+
+  /* Locate the colons separating the first two strings.  */
+  colon1 = strchr (str, ':');
+  if (!colon1)
+    return LDPS_ERR;
+  colon2 = strchr (colon1+1, ':');
+  if (!colon2)
+    return LDPS_ERR;
+  /* Name must not be empty (version may be).  */
+  if (colon1 == str)
+    return LDPS_ERR;
+
+  /* The fifth colon and trailing comdat key string are optional,
+     but the intermediate ones must all be present.  */
+  colon5 = strchr (colon2+1, ':');	/* Actually only third so far.  */
+  if (!colon5)
+    return LDPS_ERR;
+  colon5 = strchr (colon5+1, ':');	/* Hopefully fourth now.  */
+  if (!colon5)
+    return LDPS_ERR;
+  colon5 = strchr (colon5+1, ':');	/* Optional fifth now.  */
+
+  /* Finally we'll use sscanf to parse the numeric fields, then
+     we'll split out the strings which we need to allocate separate
+     storage for anyway so that we can add nul termination.  */
+  n = sscanf (colon2 + 1, "%i:%i:%lli", &sym->def, &sym->visibility, &size);
+  if (n != 3)
+    return LDPS_ERR;
+
+  /* Parsed successfully, so allocate strings and fill out fields.  */
+  sym->size = size;
+  sym->resolution = LDPR_UNKNOWN;
+  sym->name = malloc (colon1 - str + 1);
+  if (!sym->name)
+    return LDPS_ERR;
+  memcpy (sym->name, str, colon1 - str);
+  sym->name[colon1 - str] = '\0';
+  if (colon2 > (colon1 + 1))
+    {
+      sym->version = malloc (colon2 - colon1);
+      if (!sym->version)
+	return LDPS_ERR;
+      memcpy (sym->version, colon1 + 1, colon2 - (colon1 + 1));
+      sym->version[colon2 - (colon1 + 1)] = '\0';
+    }
+  else
+    sym->version = NULL;
+  if (colon5 && colon5[1])
+    {
+      sym->comdat_key = malloc (strlen (colon5 + 1) + 1);
+      if (!sym->comdat_key)
+	return LDPS_ERR;
+      strcpy (sym->comdat_key, colon5 + 1);
+    }
+  else
+    sym->comdat_key = 0;
+  return LDPS_OK;
+}
+
+/* Record a symbol to be added for the last-added claimfile.  */
+static enum ld_plugin_status
+record_claimed_file_symbol (const char *symdefstr)
+{
+  struct ld_plugin_symbol sym;
+
+  /* Can't add symbols except as belonging to claimed files.  */
+  if (!last_claimfile)
+    return LDPS_ERR;
+
+  /* If string doesn't parse correctly, give an error.  */
+  if (parse_symdefstr (symdefstr, &sym) != LDPS_OK)
+    return LDPS_ERR;
+
+  /* Check for enough space, resize array if needed, and add it.  */
+  if (last_claimfile->n_syms_allocated == last_claimfile->n_syms_used)
+    {
+      int new_n_syms = last_claimfile->n_syms_allocated
+			? 2 * last_claimfile->n_syms_allocated
+			: 10;
+      last_claimfile->symbols = realloc (last_claimfile->symbols,
+			new_n_syms * sizeof *last_claimfile->symbols);
+      if (!last_claimfile->symbols)
+	return LDPS_ERR;
+      last_claimfile->n_syms_allocated = new_n_syms;
+    }
+  last_claimfile->symbols[last_claimfile->n_syms_used++] = sym;
+
+  return LDPS_OK;
+}
+
+/* Records the status to return from one of the registered hooks.  */
+static enum ld_plugin_status
+set_ret_val (const char *whichval, enum ld_plugin_status retval)
+{
+  if (!strcmp ("onload", whichval))
+    onload_ret = retval;
+  else if (!strcmp ("claimfile", whichval))
+    claim_file_ret = retval;
+  else if (!strcmp ("allsymbolsread", whichval))
+    all_symbols_read_ret = retval;
+  else if (!strcmp ("cleanup", whichval))
+    cleanup_ret = retval;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Records hooks which should be registered.  */
+static enum ld_plugin_status
+set_register_hook (const char *whichhook, bfd_boolean yesno)
+{
+  if (!strcmp ("claimfile", whichhook))
+    register_claimfile_hook = yesno;
+  else if (!strcmp ("allsymbolsread", whichhook))
+    register_allsymbolsread_hook = yesno;
+  else if (!strcmp ("cleanup", whichhook))
+    register_cleanup_hook = yesno;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Determine type of plugin option and pass to individual parsers.  */
+static enum ld_plugin_status
+parse_option (const char *opt)
+{
+  if (!strncmp ("fail", opt, 4))
+    return set_ret_val (opt + 4, LDPS_ERR);
+  else if (!strncmp ("pass", opt, 4))
+    return set_ret_val (opt + 4, LDPS_OK);
+  else if (!strncmp ("register", opt, 8))
+    return set_register_hook (opt + 8, TRUE);
+  else if (!strncmp ("noregister", opt, 10))
+    return set_register_hook (opt + 10, FALSE);
+  else if (!strncmp ("claim:", opt, 6))
+    return record_claim_file (opt + 6, 0);
+  else if (!strncmp ("sym:", opt, 4))
+    return record_claimed_file_symbol (opt + 4);
+  else if (!strncmp ("add:", opt, 4))
+    return record_add_file (opt + 4, ADD_FILE);
+  else if (!strncmp ("lib:", opt, 4))
+    return record_add_file (opt + 4, ADD_LIB);
+  else if (!strncmp ("dir:", opt, 4))
+    return record_add_file (opt + 4, ADD_DIR);
+  else if (!strcmp ("dumpresolutions", opt))
+    dumpresolutions = TRUE;
+  else
+    return LDPS_ERR;
+  return LDPS_OK;
+}
+
+/* Output contents of transfer vector array entry in human-readable form.  */
+static void
+dump_tv_tag (size_t n, struct ld_plugin_tv *tv)
+{
+  size_t tag;
+  char unknownbuf[40];
+  const char *name;
+
+  for (tag = 0; tag < ARRAY_SIZE (tag_names); tag++)
+    if (tag_names[tag].tag == tv->tv_tag)
+      break;
+  sprintf (unknownbuf, "unknown tag #%d", tv->tv_tag);
+  name = (tag < ARRAY_SIZE (tag_names)) ? tag_names[tag].name : unknownbuf;
+  switch (tv->tv_tag)
+    {
+      case LDPT_OPTION:
+      case LDPT_OUTPUT_NAME:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s '%s'", n, name,
+		    tv->tv_u.tv_string);
+        break;
+      case LDPT_REGISTER_CLAIM_FILE_HOOK:
+      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+      case LDPT_REGISTER_CLEANUP_HOOK:
+      case LDPT_ADD_SYMBOLS:
+      case LDPT_GET_SYMBOLS:
+      case LDPT_GET_SYMBOLS_V2:
+      case LDPT_ADD_INPUT_FILE:
+      case LDPT_MESSAGE:
+      case LDPT_GET_INPUT_FILE:
+      case LDPT_GET_VIEW:
+      case LDPT_RELEASE_INPUT_FILE:
+      case LDPT_ADD_INPUT_LIBRARY:
+      case LDPT_SET_EXTRA_LIBRARY_PATH:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s func@0x%p", n, name,
+		    (void *)(tv->tv_u.tv_message));
+        break;
+      case LDPT_NULL:
+      case LDPT_API_VERSION:
+      case LDPT_GOLD_VERSION:
+      case LDPT_LINKER_OUTPUT:
+      case LDPT_GNU_LD_VERSION:
+      default:
+	TV_MESSAGE (LDPL_INFO, "tv[%d]: %s value %W (%d)", n, name,
+		    (bfd_vma)tv->tv_u.tv_val, tv->tv_u.tv_val);
+	break;
+    }
+}
+
+/* Handle/record information received in a transfer vector entry.  */
+static enum ld_plugin_status
+parse_tv_tag (struct ld_plugin_tv *tv)
+{
+#define SETVAR(x) x = tv->tv_u.x
+  switch (tv->tv_tag)
+    {
+      case LDPT_OPTION:
+	return parse_option (tv->tv_u.tv_string);
+      case LDPT_NULL:
+      case LDPT_GOLD_VERSION:
+      case LDPT_GNU_LD_VERSION:
+      case LDPT_API_VERSION:
+      default:
+	break;
+      case LDPT_OUTPUT_NAME:
+	output_name = tv->tv_u.tv_string;
+	break;
+      case LDPT_LINKER_OUTPUT:
+	linker_output = tv->tv_u.tv_val;
+	break;
+      case LDPT_REGISTER_CLAIM_FILE_HOOK:
+	SETVAR(tv_register_claim_file);
+	break;
+      case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+	SETVAR(tv_register_all_symbols_read);
+	break;
+      case LDPT_REGISTER_CLEANUP_HOOK:
+	SETVAR(tv_register_cleanup);
+	break;
+      case LDPT_ADD_SYMBOLS:
+	SETVAR(tv_add_symbols);
+	break;
+      case LDPT_GET_SYMBOLS:
+	SETVAR(tv_get_symbols);
+	break;
+      case LDPT_GET_SYMBOLS_V2:
+	tv_get_symbols_v2 = tv->tv_u.tv_get_symbols;
+	break;
+      case LDPT_ADD_INPUT_FILE:
+	SETVAR(tv_add_input_file);
+	break;
+      case LDPT_MESSAGE:
+	SETVAR(tv_message);
+	break;
+      case LDPT_GET_INPUT_FILE:
+	SETVAR(tv_get_input_file);
+	break;
+      case LDPT_GET_VIEW:
+	SETVAR(tv_get_view);
+	break;
+      case LDPT_RELEASE_INPUT_FILE:
+	SETVAR(tv_release_input_file);
+	break;
+      case LDPT_ADD_INPUT_LIBRARY:
+	SETVAR(tv_add_input_library);
+	break;
+      case LDPT_SET_EXTRA_LIBRARY_PATH:
+	SETVAR(tv_set_extra_library_path);
+	break;
+    }
+#undef SETVAR
+  return LDPS_OK;
+}
+
+/* Standard plugin API entry point.  */
+enum ld_plugin_status
+onload (struct ld_plugin_tv *tv)
+{
+  enum ld_plugin_status rv;
+
+  /* This plugin does nothing but dump the tv array.  It would
+     be an error if this function was called without one.  */
+  if (!tv)
+    return LDPS_ERR;
+
+  /* First entry should always be LDPT_MESSAGE, letting us get
+     hold of it easily so we can send output straight away.  */
+  if (tv[0].tv_tag == LDPT_MESSAGE)
+    tv_message = tv[0].tv_u.tv_message;
+
+  do
+    if ((rv = parse_tv_tag (tv)) != LDPS_OK)
+      return rv;
+  while ((tv++)->tv_tag != LDPT_NULL);
+
+  /* Register hooks only if instructed by options.  */
+  if (register_claimfile_hook)
+    {
+      if (!tv_register_claim_file)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_claim_file hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_claim_file) (onclaim_file);
+    }
+  if (register_allsymbolsread_hook)
+    {
+      if (!tv_register_all_symbols_read)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_all_symbols_read hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_all_symbols_read) (onall_symbols_read);
+    }
+  if (register_cleanup_hook)
+    {
+      if (!tv_register_cleanup)
+	{
+	  TV_MESSAGE (LDPL_FATAL, "No register_cleanup hook");
+	  fflush (NULL);
+	  return LDPS_ERR;
+	}
+      (*tv_register_cleanup) (oncleanup);
+    }
+
+  /* Claim testsuite/ld-plugin/func.c, standalone or in a library.  Its
+     size must be SIZE_OF_FUNC_C bytes.  */
+#define SIZE_OF_FUNC_C	248
+  if (onload_ret == LDPS_OK
+      && (record_claim_file ("func.c", SIZE_OF_FUNC_C) != LDPS_OK
+	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
+	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK
+	  || record_claim_file ("libfunc.a", SIZE_OF_FUNC_C) != LDPS_OK
+	  || record_claimed_file_symbol ("func::0:0:0") != LDPS_OK
+	  || record_claimed_file_symbol ("_func::0:0:0") != LDPS_OK))
+    onload_ret = LDPS_ERR;
+
+  return onload_ret;
+}
+
+char *
+xstrdup (const char *s)
+{
+  size_t len = strlen (s) + 1;
+  char *ret = malloc (len + 1);
+  return (char *) memcpy (ret, s, len);
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+onclaim_file (const struct ld_plugin_input_file *file, int *claimed)
+{
+  /* Let's see if we want to claim this file.  */
+  claim_file_t *claimfile = claimfiles_list;
+  size_t len = strlen (file->name);
+  char *name = xstrdup (file->name);
+  char *p = name + len;
+  bfd_boolean islib;
+
+  /* Only match the file name without the directory part.  */
+  islib = *p == 'a' && *(p - 1) == '.';
+  for (; p != name; p--)
+    if (IS_DIR_SEPARATOR (*p))
+      {
+	p++;
+	break;
+      }
+
+  while (claimfile)
+    {
+      /* Claim the file only if the file name and size match and don't
+	 match the whole library.  */
+      if (!strcmp (p, claimfile->file.name)
+	  && claimfile->file.filesize == file->filesize
+	  && (!islib || file->offset != 0))
+	break;
+      claimfile = claimfile->next;
+    }
+
+  free (name);
+
+  /* If we decided to claim it, record that fact, and add any symbols
+     that were defined for it by plugin options.  */
+  *claimed = (claimfile != 0);
+  if (claimfile)
+    {
+      char buffer[30];
+      int fd;
+
+      TV_MESSAGE (LDPL_INFO, "Claimed: %s [@%ld/%ld]", file->name,
+		  (long)file->offset, (long)file->filesize);
+
+      claimfile->claimed = TRUE;
+      claimfile->file = *file;
+      if (claimfile->n_syms_used && !tv_add_symbols)
+	claim_file_ret = LDPS_ERR;
+      else if (claimfile->n_syms_used)
+	claim_file_ret = (*tv_add_symbols) (claimfile->file.handle,
+					    claimfile->n_syms_used,
+					    claimfile->symbols);
+
+      fd = claimfile->file.fd;
+      name = xstrdup (claimfile->file.name);
+      claim_file_ret = tv_release_input_file (claimfile->file.handle);
+      if (claim_file_ret != LDPS_OK)
+	{
+	  free (name);
+	  return claim_file_ret;
+	}
+      if (read (fd, buffer, sizeof (buffer)) >= 0)
+	{
+	  claim_file_ret == LDPS_ERR;
+	  TV_MESSAGE (LDPL_FATAL, "Unreleased file descriptor on: %s", name);
+	}
+      free (name);
+    }
+
+  return claim_file_ret;
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+onall_symbols_read (void)
+{
+  static const char *resolutions[] =
+    {
+      "LDPR_UNKNOWN",
+      "LDPR_UNDEF",
+      "LDPR_PREVAILING_DEF",
+      "LDPR_PREVAILING_DEF_IRONLY",
+      "LDPR_PREEMPTED_REG",
+      "LDPR_PREEMPTED_IR",
+      "LDPR_RESOLVED_IR",
+      "LDPR_RESOLVED_EXEC",
+      "LDPR_RESOLVED_DYN",
+      "LDPR_PREVAILING_DEF_IRONLY_EXP",
+    };
+  claim_file_t *claimfile = dumpresolutions ? claimfiles_list : NULL;
+  add_file_t *addfile = addfiles_list;
+  TV_MESSAGE (LDPL_INFO, "hook called: all symbols read.");
+  for ( ; claimfile; claimfile = claimfile->next)
+    {
+      enum ld_plugin_status rv;
+      int n;
+      if (claimfile->n_syms_used && !tv_get_symbols_v2)
+	return LDPS_ERR;
+      else if (!claimfile->n_syms_used)
+        continue;
+      else if (!claimfile->file.handle)
+        continue;
+      rv = tv_get_symbols_v2 (claimfile->file.handle, claimfile->n_syms_used,
+			      claimfile->symbols);
+      if (rv != LDPS_OK)
+	return rv;
+      for (n = 0; n < claimfile->n_syms_used; n++)
+	TV_MESSAGE (LDPL_INFO, "Sym: '%s%s%s' Resolution: %s",
+		    claimfile->symbols[n].name,
+		    claimfile->symbols[n].version ? "@" : "",
+		    (claimfile->symbols[n].version
+		     ? claimfile->symbols[n].version : ""),
+		    resolutions[claimfile->symbols[n].resolution]);
+    }
+  for ( ; addfile ; addfile = addfile->next)
+    {
+      enum ld_plugin_status rv;
+      if (addfile->type == ADD_LIB && tv_add_input_library)
+	rv = (*tv_add_input_library) (addfile->name);
+      else if (addfile->type == ADD_FILE && tv_add_input_file)
+	rv = (*tv_add_input_file) (addfile->name);
+      else if (addfile->type == ADD_DIR && tv_set_extra_library_path)
+	rv = (*tv_set_extra_library_path) (addfile->name);
+      else
+	rv = LDPS_ERR;
+      if (rv != LDPS_OK)
+	return rv;
+    }
+  fflush (NULL);
+  return all_symbols_read_ret;
+}
+
+/* Standard plugin API registerable hook.  */
+static enum ld_plugin_status
+oncleanup (void)
+{
+  TV_MESSAGE (LDPL_INFO, "hook called: cleanup.");
+  fflush (NULL);
+  return cleanup_ret;
+}
diff --git a/ld/testsuite/ld-plugin/func.c b/ld/testsuite/ld-plugin/func.c
index 8c668db..7b0c043 100644
--- a/ld/testsuite/ld-plugin/func.c
+++ b/ld/testsuite/ld-plugin/func.c
@@ -1,3 +1,6 @@
+/* The first line of this file must match the expectation of
+   onall_symbols_read in testplug2.c and the size of this file
+   must match the expectation of onclaim_file in testplug2.c.  */
 
 extern int retval;
 
diff --git a/ld/testsuite/ld-plugin/plugin-13.d b/ld/testsuite/ld-plugin/plugin-13.d
new file mode 100644
index 0000000..d7a73fb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-13.d
@@ -0,0 +1,22 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-14.d b/ld/testsuite/ld-plugin/plugin-14.d
new file mode 100644
index 0000000..96e1703
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-14.d
@@ -0,0 +1,33 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+hook called: claim_file tmpdir/text.o \[@0/.* not claimed
+#...
+hook called: all symbols read.
+tmpdir/main.o: In function `main':
+.*main.c.*: undefined reference to `func'
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-15.d b/ld/testsuite/ld-plugin/plugin-15.d
new file mode 100644
index 0000000..caa486b
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-15.d
@@ -0,0 +1,33 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_OPTION 'sym:_?func::0:0:0'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+hook called: claim_file tmpdir/text.o \[@0/.* not claimed
+#...
+hook called: all symbols read.
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-16.d b/ld/testsuite/ld-plugin/plugin-16.d
new file mode 100644
index 0000000..6ce96c2
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-16.d
@@ -0,0 +1,37 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_OPTION 'sym:_?func::0:0:0'
+.*: LDPT_OPTION 'sym:_?func2::0:0:0'
+.*: LDPT_OPTION 'dumpresolutions'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+hook called: claim_file tmpdir/text.o \[@0/.* not claimed
+#...
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
+Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-17.d b/ld/testsuite/ld-plugin/plugin-17.d
new file mode 100644
index 0000000..159d4e4
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-17.d
@@ -0,0 +1,37 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_OPTION 'sym:_?func::0:0:0'
+.*: LDPT_OPTION 'sym:_?func2::0:0:0'
+.*: LDPT_OPTION 'dumpresolutions'
+.*: LDPT_OPTION 'add:tmpdir/func.o'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+hook called: claim_file tmpdir/text.o \[@0/.* not claimed
+#...
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
+Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-18.d b/ld/testsuite/ld-plugin/plugin-18.d
new file mode 100644
index 0000000..0200a05
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-18.d
@@ -0,0 +1,38 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_OPTION 'sym:_?func::0:0:0'
+.*: LDPT_OPTION 'sym:_?func2::0:0:0'
+.*: LDPT_OPTION 'dumpresolutions'
+.*: LDPT_OPTION 'add:tmpdir/func.o'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+#...
+hook called: claim_file tmpdir/libtext.a \[@.* not claimed
+#...
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
+Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-19.d b/ld/testsuite/ld-plugin/plugin-19.d
new file mode 100644
index 0000000..e838028
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-19.d
@@ -0,0 +1,42 @@
+Hello from testplugin.
+.*: LDPT_MESSAGE func@0x.*
+.*: LDPT_API_VERSION value        0x1 \(1\)
+.*: LDPT_GNU_LD_VERSION value       0x.*
+.*: LDPT_LINKER_OUTPUT value        0x1 \(1\)
+.*: LDPT_OUTPUT_NAME 'tmpdir/main.x'
+.*: LDPT_REGISTER_CLAIM_FILE_HOOK func@0x.*
+.*: LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK func@0x.*
+.*: LDPT_REGISTER_CLEANUP_HOOK func@0x.*
+.*: LDPT_ADD_SYMBOLS func@0x.*
+.*: LDPT_GET_INPUT_FILE func@0x.*
+.*: LDPT_GET_VIEW func@0x.*
+.*: LDPT_RELEASE_INPUT_FILE func@0x.*
+.*: LDPT_GET_SYMBOLS func@0x.*
+.*: LDPT_GET_SYMBOLS_V2 func@0x.*
+.*: LDPT_ADD_INPUT_FILE func@0x.*
+.*: LDPT_ADD_INPUT_LIBRARY func@0x.*
+.*: LDPT_SET_EXTRA_LIBRARY_PATH func@0x.*
+.*: LDPT_OPTION 'registerclaimfile'
+.*: LDPT_OPTION 'registerallsymbolsread'
+.*: LDPT_OPTION 'registercleanup'
+.*: LDPT_OPTION 'claim:.*/ld/testsuite/ld-plugin/func.c'
+.*: LDPT_OPTION 'sym:_?func::0:0:0'
+.*: LDPT_OPTION 'sym:_?func2::0:0:0'
+.*: LDPT_OPTION 'dumpresolutions'
+.*: LDPT_OPTION 'add:tmpdir/func.o'
+.*: LDPT_OPTION 'claim:tmpdir/libtext.a'
+.*: LDPT_OPTION 'sym:_?text::0:0:0'
+.*: LDPT_OPTION 'add:tmpdir/text.o'
+.*: LDPT_NULL value        0x0 \(0\)
+#...
+hook called: claim_file tmpdir/main.o \[@0/.* not claimed
+hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
+#...
+hook called: claim_file tmpdir/libtext.a \[@.* CLAIMED
+#...
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
+Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+Sym: '_?text' Resolution: LDPR_PREVAILING_DEF
+hook called: cleanup.
+#...
diff --git a/ld/testsuite/ld-plugin/plugin-20.d b/ld/testsuite/ld-plugin/plugin-20.d
new file mode 100644
index 0000000..b019df2
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-20.d
@@ -0,0 +1,6 @@
+hook called: all symbols read.
+Input: func.c \(tmpdir/libfunc.a\)
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-21.d b/ld/testsuite/ld-plugin/plugin-21.d
new file mode 100644
index 0000000..abfd27f
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-21.d
@@ -0,0 +1,6 @@
+hook called: all symbols read.
+Input: .*/ld/testsuite/ld-plugin/func.c \(.*/ld/testsuite/ld-plugin/func.c\)
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-22.d b/ld/testsuite/ld-plugin/plugin-22.d
new file mode 100644
index 0000000..dcd4f24
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-22.d
@@ -0,0 +1,6 @@
+Claimed: tmpdir/libfunc.a \[@.*
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-23.d b/ld/testsuite/ld-plugin/plugin-23.d
new file mode 100644
index 0000000..35b48bd
--- /dev/null
+++ b/ld/testsuite/ld-plugin/plugin-23.d
@@ -0,0 +1,6 @@
+Claimed: .*/ld/testsuite/ld-plugin/func.c \[@0.*
+hook called: all symbols read.
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+`_?func' referenced in section `\.text.*' of tmpdir/main.o: defined in discarded section .*
+hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin.exp b/ld/testsuite/ld-plugin/plugin.exp
index 23a8cfb..1d7e7f3 100644
--- a/ld/testsuite/ld-plugin/plugin.exp
+++ b/ld/testsuite/ld-plugin/plugin.exp
@@ -41,6 +41,14 @@ set plugin_name [file_contents "$base_dir/libldtestplug.la"]
 set plugin_name [regsub "'.*" [regsub ".*dlname='" "$plugin_name" ""] ""]
 verbose "plugin name is '$plugin_name'"
 
+set plugin2_name [file_contents "$base_dir/libldtestplug2.la"]
+set plugin2_name [regsub "'.*" [regsub ".*dlname='" "$plugin2_name" ""] ""]
+verbose "plugin2 name is '$plugin2_name'"
+
+set plugin3_name [file_contents "$base_dir/libldtestplug3.la"]
+set plugin3_name [regsub "'.*" [regsub ".*dlname='" "$plugin3_name" ""] ""]
+verbose "plugin3 name is '$plugin3_name'"
+
 # Use libtool to find full path to plugin rather than worrying
 # about run paths or anything like that.
 catch "exec $base_dir/libtool --config" lt_config
@@ -50,7 +58,11 @@ regexp -line "^objdir=.*$" "$lt_config" lt_objdir
 verbose "lt_objdir line is '$lt_objdir'" 3
 set lt_objdir [regsub "objdir=" "$lt_objdir" ""]
 set plugin_path "$base_dir/$lt_objdir/$plugin_name"
+set plugin2_path "$base_dir/$lt_objdir/$plugin2_name"
+set plugin3_path "$base_dir/$lt_objdir/$plugin3_name"
 verbose "Full plugin path $plugin_path" 2
+verbose "Full plugin2 path $plugin2_path" 2
+verbose "Full plugin3 path $plugin3_path" 2
 
 set regclm "-plugin-opt registerclaimfile"
 set regas "-plugin-opt registerallsymbolsread"
@@ -88,6 +100,8 @@ if { $can_compile && !$failed_compile } {
 
 set testobjfiles "tmpdir/main.o tmpdir/func.o tmpdir/text.o"
 set testobjfiles_notext "tmpdir/main.o tmpdir/func.o"
+set testsrcfiles "tmpdir/main.o $srcdir/$subdir/func.c tmpdir/text.o"
+set testsrcfiles_notext "tmpdir/main.o $srcdir/$subdir/func.c"
 # Rather than having libs we just define dummy values for anything
 # we may need to link a target exe; we aren't going to run it anyway.
 set libs "[ld_simple_link_defsyms] --defsym ${_}printf=${_}main --defsym ${_}puts=${_}main"
@@ -125,6 +139,33 @@ set plugin_tests [list \
 			-plugin-opt dumpresolutions \
 			-plugin-opt add:tmpdir/func.o \
     $testobjfiles $libs" "" "" "" {{ld plugin-9.d}} "main.x" ] \
+    [list "load plugin with source" "-plugin $plugin_path $regclm \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-13.d}} "main.x" ] \
+    [list "plugin claimfile lost symbol with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-14.d}} "main.x" ] \
+    [list "plugin claimfile replace symbol with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-15.d}} "main.x" ] \
+    [list "plugin claimfile resolve symbol with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+			-plugin-opt sym:${_}func2::0:0:0 \
+			-plugin-opt dumpresolutions \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-16.d}} "main.x" ] \
+    [list "plugin claimfile replace file with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+			-plugin-opt sym:${_}func2::0:0:0 \
+			-plugin-opt dumpresolutions \
+			-plugin-opt add:tmpdir/func.o \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-17.d}} "main.x" ] \
 ]
 
 set plugin_lib_tests [list \
@@ -145,6 +186,25 @@ set plugin_lib_tests [list \
 			-plugin-opt sym:${_}text::0:0:0 \
 			-plugin-opt add:tmpdir/text.o \
     $testobjfiles_notext -Ltmpdir -ltext $libs" "" "" "" {{ld plugin-11.d}} "main.x" ] \
+    [list "plugin ignore lib with source" \
+	               "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+			-plugin-opt sym:${_}func2::0:0:0 \
+			-plugin-opt dumpresolutions \
+			-plugin-opt add:tmpdir/func.o \
+    $testsrcfiles_notext -Ltmpdir -ltext $libs" "" "" "" {{ld plugin-18.d}} "main.x" ] \
+    [list "plugin claimfile replace lib with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+			-plugin-opt sym:${_}func2::0:0:0 \
+			-plugin-opt dumpresolutions \
+			-plugin-opt add:tmpdir/func.o \
+			-plugin-opt claim:tmpdir/libtext.a \
+			-plugin-opt sym:${_}text::0:0:0 \
+			-plugin-opt add:tmpdir/text.o \
+    $testsrcfiles_notext -Ltmpdir -ltext $libs" "" "" "" {{ld plugin-19.d}} "main.x" ] \
 ]
 
 set plugin_extra_elf_tests [list \
@@ -161,6 +221,20 @@ set plugin_extra_elf_tests [list \
 			-plugin-opt add:tmpdir/func3h.o \
     $testobjfiles $libs --verbose=2" "" "" "" {{ld plugin-12.d} \
 				{readelf -s plugin-vis-1.d}} "main.x" ] \
+    [list "plugin set symbol visibility with source" \
+		       "-plugin $plugin_path $regclm $regas $regcln \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+			-plugin-opt sym:${_}func::0:0:0 \
+			-plugin-opt sym:${_}func1::0:1:0 \
+			-plugin-opt sym:${_}func2::0:2:0 \
+			-plugin-opt sym:${_}func3::0:3:0 \
+			-plugin-opt dumpresolutions \
+			-plugin-opt add:tmpdir/func.o \
+			-plugin-opt add:tmpdir/func1p.o \
+			-plugin-opt add:tmpdir/func2i.o \
+			-plugin-opt add:tmpdir/func3h.o \
+    $testsrcfiles $libs --verbose=2" "" "" "" {{ld plugin-12.d} \
+				{readelf -s plugin-vis-1.d}} "main.x" ] \
 ]
 
 if { !$can_compile || $failed_compile } {
@@ -191,3 +265,57 @@ if ![ar_simple_create $ar "" "tmpdir/libtext.a" "tmpdir/text.o"] {
 } else {
     run_ld_link_tests $plugin_lib_tests
 }
+
+set plugin_src_tests [list \
+    [list "plugin with source lib" \
+	               "-plugin $plugin2_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+     tmpdir/main.o -Ltmpdir -ltext -lfunc $libs" "" "" "" {{ld plugin-20.d}} "main.x" ] \
+    [list "load plugin with source" \
+	               "-plugin $plugin2_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-21.d}} "main.x" ] \
+    [list "load plugin with source and -r" \
+	               "-r -plugin $plugin2_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-21.d}} "main.x" ] \
+    [list "plugin with source lib" \
+	               "-plugin $plugin3_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+     tmpdir/main.o -Ltmpdir -ltext -lfunc $libs" "" "" "" {{ld plugin-22.d}} "main.x" ] \
+    [list "load plugin with source" \
+	               "-plugin $plugin3_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-23.d}} "main.x" ] \
+    [list "load plugin with source and -r" \
+	               "-r -plugin $plugin3_path $regclm $regas $regcln \
+			-plugin-opt dumpresolutions \
+			-plugin-opt claim:$srcdir/$subdir/func.c \
+    $testsrcfiles $libs" "" "" "" {{ld plugin-23.d}} "main.x" ] \
+]
+
+# Check if nm --plugin works.
+set testname "nm --plugin"
+set nm_plugin "$NM --plugin $plugin2_path $srcdir/$subdir/func.c"
+catch "exec $nm_plugin" plugin_nm_output
+send_log "$nm_plugin\n"
+send_log "$plugin_nm_output\n"
+if { [regexp "0+ T func" "$plugin_nm_output"] &&
+     [regexp "0+ T _func" "$plugin_nm_output"] } {
+    pass $testname
+} else {
+    fail $testname
+}
+
+# Check if ar --plugin works.
+if [ar_simple_create $ar "--plugin $plugin2_path" "tmpdir/libfunc.a" \
+			 "$srcdir/$subdir/func.c"] {
+    run_ld_link_tests $plugin_src_tests
+} else {
+    foreach testitem $plugin_src_tests {
+	unresolved [lindex $testitem 0]
+    }
+}
-- 
2.1.0

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-05 13:54 [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p H.J. Lu
@ 2015-02-07  9:42 ` Alan Modra
  2015-02-07 12:50   ` H.J. Lu
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2015-02-07  9:42 UTC (permalink / raw)
  To: H.J. Lu; +Cc: binutils

On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
> This patch adds bfd_maybe_object_p which is similar to
> 
> bfd_check_format (abfd, bfd_object)
> 
> The difference is bfd_maybe_object_p takes an argument to indicate if a
> compiler plug-in library is applied.  When a compiler plug-in library is
> active, it also returns TRUE if the file is not an archive or a coredump
> file.

Hmm, in other words, if it is unknown.  (bfd_format takes the values
bfd_unknown, bfd_object, bfd_archive, bfd_core.)

> +bfd_boolean
> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
> +{
> +  /* LTO IR object file may look like a bfd_object file or a file which
> +     is not bfd_core nor bfd_archive.  */
> +  return (bfd_check_format (abfd, bfd_object)
> +	  || (plugin_active_p
> +	      && !bfd_check_format (abfd, bfd_core)
> +	      && !bfd_check_format (abfd, bfd_archive)));
> +}

I find this really strange.  If plugins are active then you're
willing to accept anything except cores and archives.  To throw out
cores and archives you'll be iterating over all compiled-in bfd
targets, asking "is this a core file", then asking "is this an
archive".  That's quite a bit of processing, and won't exclude your
average text file!

I think you need to find a way of answering the question "is this a
file accepted by a plugin?" in a more robust way.  One possibility is
merging the linker handling of plugins into the bfd plugin support.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-07  9:42 ` Alan Modra
@ 2015-02-07 12:50   ` H.J. Lu
  2015-02-07 19:10     ` H.J. Lu
  2015-02-09  4:36     ` H.J. Lu
  0 siblings, 2 replies; 15+ messages in thread
From: H.J. Lu @ 2015-02-07 12:50 UTC (permalink / raw)
  To: Binutils

On Sat, Feb 7, 2015 at 1:42 AM, Alan Modra <amodra@gmail.com> wrote:
> On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
>> This patch adds bfd_maybe_object_p which is similar to
>>
>> bfd_check_format (abfd, bfd_object)
>>
>> The difference is bfd_maybe_object_p takes an argument to indicate if a
>> compiler plug-in library is applied.  When a compiler plug-in library is
>> active, it also returns TRUE if the file is not an archive or a coredump
>> file.
>
> Hmm, in other words, if it is unknown.  (bfd_format takes the values
> bfd_unknown, bfd_object, bfd_archive, bfd_core.)

Yes.

>> +bfd_boolean
>> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
>> +{
>> +  /* LTO IR object file may look like a bfd_object file or a file which
>> +     is not bfd_core nor bfd_archive.  */
>> +  return (bfd_check_format (abfd, bfd_object)
>> +       || (plugin_active_p
>> +           && !bfd_check_format (abfd, bfd_core)
>> +           && !bfd_check_format (abfd, bfd_archive)));
>> +}
>
> I find this really strange.  If plugins are active then you're
> willing to accept anything except cores and archives.  To throw out
> cores and archives you'll be iterating over all compiled-in bfd
> targets, asking "is this a core file", then asking "is this an
> archive".  That's quite a bit of processing, and won't exclude your
> average text file!

LTO IR could be stored in the average text file.  The new plug tests
use this feature.   We can add a new type, bfd_maybe_object.

> I think you need to find a way of answering the question "is this a
> file accepted by a plugin?" in a more robust way.  One possibility is
> merging the linker handling of plugins into the bfd plugin support.
>

I have considered it before.  This approach has many implications.
If we do this, we need to add bfd_plugin_object and bfd_all_object.
bfd_all_object includes bfd_object and bfd_plugin_object.  We need
bfd_plugin_object so that we won't update dummy BFD info from the
LTO IR input.  Let me take another look.

-- 
H.J.

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-07 12:50   ` H.J. Lu
@ 2015-02-07 19:10     ` H.J. Lu
  2015-02-07 20:47       ` H.J. Lu
  2015-02-07 20:51       ` H.J. Lu
  2015-02-09  4:36     ` H.J. Lu
  1 sibling, 2 replies; 15+ messages in thread
From: H.J. Lu @ 2015-02-07 19:10 UTC (permalink / raw)
  To: Binutils

On Sat, Feb 07, 2015 at 04:50:27AM -0800, H.J. Lu wrote:
> > I think you need to find a way of answering the question "is this a
> > file accepted by a plugin?" in a more robust way.  One possibility is
> > merging the linker handling of plugins into the bfd plugin support.
> >
> 
> I have considered it before.  This approach has many implications.
> If we do this, we need to add bfd_plugin_object and bfd_all_object.
> bfd_all_object includes bfd_object and bfd_plugin_object.  We need
> bfd_plugin_object so that we won't update dummy BFD info from the
> LTO IR input.  Let me take another look.
> 

We can extract a plugin_object_p out of plugin_maybe_claim for BFD.
Here is the first patch.  I am checking it in.


H.J.
----
From 35a1e5f3055fc28f129e4d5d0a993218d8af1baf Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sat, 7 Feb 2015 11:01:22 -0800
Subject: [PATCH] Update plugin_maybe_claim

This patch removes the argument of pointer to struct ld_plugin_input_file.
This is the first step to extract a plugin_object_p out of
plugin_maybe_claim for BFD.

	* plugin.c: Include "libbfd.h".
	(plugin_strdup): New.
	(plugin_maybe_claim): Remove the argument of pointer to struct
	ld_plugin_input_file.  Open and handle input entry.
	* plugin.h (plugin_maybe_claim): Updated.
	* ldfile.c (ldfile_try_open_bfd): Call plugin_maybe_claim directly
	without passing a pointer to struct ld_plugin_input_file.
	* ldmain.c: Don't include "libbfd.h".
	(add_archive_element): Call plugin_maybe_claim directly without
	passing a pointer to struct ld_plugin_input_file.
---
 ld/ChangeLog | 13 ++++++++++
 ld/ldfile.c  | 14 +---------
 ld/ldmain.c  | 25 +++---------------
 ld/plugin.c  | 85 +++++++++++++++++++++++++++++++++++++++++++++---------------
 ld/plugin.h  |  3 +--
 5 files changed, 83 insertions(+), 57 deletions(-)

diff --git a/ld/ChangeLog b/ld/ChangeLog
index 52c3ba0..d7125ff 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,16 @@
+2015-02-07  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* plugin.c: Include "libbfd.h".
+	(plugin_strdup): New.
+	(plugin_maybe_claim): Remove the argument of pointer to struct
+	ld_plugin_input_file.  Open and handle input entry.
+	* plugin.h (plugin_maybe_claim): Updated.
+	* ldfile.c (ldfile_try_open_bfd): Call plugin_maybe_claim directly
+	without passing a pointer to struct ld_plugin_input_file.
+	* ldmain.c: Don't include "libbfd.h".
+	(add_archive_element): Call plugin_maybe_claim directly without
+	passing a pointer to struct ld_plugin_input_file.
+
 2015-02-06  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* ld.texinfo: Document -z text, -z notext and -z textoff.
diff --git a/ld/ldfile.c b/ld/ldfile.c
index c9c9541..05889f2 100644
--- a/ld/ldfile.c
+++ b/ld/ldfile.c
@@ -304,19 +304,7 @@ success:
   if (bfd_check_format (entry->the_bfd, bfd_object)
       && link_info.lto_plugin_active
       && !no_more_claiming)
-    {
-      int fd = open (attempt, O_RDONLY | O_BINARY);
-      if (fd >= 0)
-	{
-	  struct ld_plugin_input_file file;
-
-	  file.name = attempt;
-	  file.offset = 0;
-	  file.filesize = lseek (fd, 0, SEEK_END);
-	  file.fd = fd;
-	  plugin_maybe_claim (&file, entry);
-	}
-    }
+    plugin_maybe_claim (entry);
 #endif /* ENABLE_PLUGINS */
 
   /* It opened OK, the format checked out, and the plugins have had
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 86f02a6..4b41288 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -41,7 +41,6 @@
 #ifdef ENABLE_PLUGINS
 #include "plugin.h"
 #include "plugin-api.h"
-#include "libbfd.h"
 #endif /* ENABLE_PLUGINS */
 
 /* Somewhere above, sys/stat.h got included.  */
@@ -793,27 +792,11 @@ add_archive_element (struct bfd_link_info *info,
   if (link_info.lto_plugin_active && !no_more_claiming)
     {
       /* We must offer this archive member to the plugins to claim.  */
-      const char *filename = (bfd_my_archive (abfd) != NULL
-			      ? bfd_my_archive (abfd)->filename : abfd->filename);
-      int fd = open (filename, O_RDONLY | O_BINARY);
-      if (fd >= 0)
+      plugin_maybe_claim (input);
+      if (input->flags.claimed)
 	{
-	  struct ld_plugin_input_file file;
-
-	  /* 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
-	     origin field of the bfd and in the arelt_data.  */
-	  file.name = filename;
-	  file.offset = abfd->origin;
-	  file.filesize = arelt_size (abfd);
-	  file.fd = fd;
-	  plugin_maybe_claim (&file, input);
-	  if (input->flags.claimed)
-	    {
-	      input->flags.claim_archive = TRUE;
-	      *subsbfd = input->the_bfd;
-	    }
+	  input->flags.claim_archive = TRUE;
+	  *subsbfd = input->the_bfd;
 	}
     }
 #endif /* ENABLE_PLUGINS */
diff --git a/ld/plugin.c b/ld/plugin.c
index 7ee45a2..30e4ab4 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -21,6 +21,7 @@
 #include "sysdep.h"
 #include "libiberty.h"
 #include "bfd.h"
+#include "libbfd.h"
 #include "bfdlink.h"
 #include "bfdver.h"
 #include "ld.h"
@@ -980,41 +981,83 @@ plugin_call_claim_file (const struct ld_plugin_input_file *file, int *claimed)
   return plugin_error_p () ? -1 : 0;
 }
 
+/* Duplicates a character string with memory attached to ABFD.  */
+
+static char *
+plugin_strdup (bfd *abfd, const char *str)
+{
+  size_t strlength;
+  char *copy;
+  strlength = strlen (str) + 1;
+  copy = bfd_alloc (abfd, strlength);
+  if (copy == NULL)
+    einfo (_("%P%F: plugin_strdup failed to allocate memory: %s\n"),
+	   bfd_get_error ());
+  memcpy (copy, str, strlength);
+  return copy;
+}
+
 void
-plugin_maybe_claim (struct ld_plugin_input_file *file,
-		    lang_input_statement_type *entry)
+plugin_maybe_claim (lang_input_statement_type *entry)
 {
   int claimed = 0;
   plugin_input_file_t *input;
-  size_t namelength;
+  off_t offset, filesize;
+  struct ld_plugin_input_file file;
+  bfd *abfd;
+  bfd *ibfd = entry->the_bfd;
+  bfd_boolean inarchive = bfd_my_archive (ibfd) != NULL;
+  const char *name
+    = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
+  int fd = open (name, O_RDONLY | O_BINARY);
+
+  if (fd < 0)
+    return;
 
   /* We create a dummy BFD, initially empty, to house whatever symbols
      the plugin may want to add.  */
-  bfd *abfd = plugin_get_ir_dummy_bfd (entry->the_bfd->filename,
-				       entry->the_bfd);
+  abfd = plugin_get_ir_dummy_bfd (ibfd->filename, ibfd);
 
   input = bfd_alloc (abfd, sizeof (*input));
   if (input == NULL)
     einfo (_("%P%F: plugin failed to allocate memory for input: %s\n"),
 	   bfd_get_error ());
 
+  if (inarchive)
+    {
+      /* 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
+	 origin field of the bfd and in the arelt_data.  */
+      offset = ibfd->origin;
+      filesize = arelt_size (ibfd);
+    }
+  else
+    {
+      offset = 0;
+      filesize = lseek (fd, 0, SEEK_END);
+
+      /* We must copy filename attached to ibfd if it is not an archive
+	 member since it may be freed by bfd_close below.  */
+      name = plugin_strdup (abfd, name);
+    }
+
+  file.name = name;
+  file.offset = offset;
+  file.filesize = filesize;
+  file.fd = fd;
+  file.handle = input;
+
   input->abfd = abfd;
   input->view_buffer.addr = NULL;
   input->view_buffer.filesize = 0;
   input->view_buffer.offset = 0;
-  input->fd = file->fd;
-  input->offset  = file->offset;
-  input->filesize = file->filesize;
-  namelength = strlen (entry->the_bfd->filename) + 1;
-  input->name = bfd_alloc (abfd, namelength);
-  if (input->name == NULL)
-    einfo (_("%P%F: plugin failed to allocate memory for input filename: %s\n"),
-	   bfd_get_error ());
-  memcpy (input->name, entry->the_bfd->filename, namelength);
-
-  file->handle = input;
+  input->fd = fd;
+  input->offset = offset;
+  input->filesize = filesize;
+  input->name = plugin_strdup (abfd, ibfd->filename);
 
-  if (plugin_call_claim_file (file, &claimed))
+  if (plugin_call_claim_file (&file, &claimed))
     einfo (_("%P%F: %s: plugin reported error claiming file\n"),
 	   plugin_error_plugin ());
 
@@ -1028,7 +1071,7 @@ plugin_maybe_claim (struct ld_plugin_input_file *file,
 	 calls release_input_file after it is done, is stored in
 	 non-bfd_object file.  This scheme doesn't work when a plugin
 	 needs fd and its IR is stored in bfd_object file.  */
-      close (file->fd);
+      close (fd);
       input->fd = -1;
     }
 
@@ -1038,11 +1081,11 @@ plugin_maybe_claim (struct ld_plugin_input_file *file,
 
       /* 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);
+      if (!inarchive)
+	bfd_close (ibfd);
+      bfd_make_readable (abfd);
       entry->the_bfd = abfd;
       entry->flags.claimed = TRUE;
-      bfd_make_readable (entry->the_bfd);
     }
   else
     {
diff --git a/ld/plugin.h b/ld/plugin.h
index 15532cd..59c0df7 100644
--- a/ld/plugin.h
+++ b/ld/plugin.h
@@ -46,8 +46,7 @@ extern void plugin_load_plugins (void);
 extern const char *plugin_error_plugin (void);
 
 /* Call 'claim file' hook for all plugins.  */
-extern void plugin_maybe_claim (struct ld_plugin_input_file *,
-				lang_input_statement_type *);
+extern void plugin_maybe_claim (lang_input_statement_type *);
 
 /* Call 'all symbols read' hook for all plugins.  */
 extern int plugin_call_all_symbols_read (void);
-- 
2.1.0

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-07 19:10     ` H.J. Lu
@ 2015-02-07 20:47       ` H.J. Lu
  2015-02-07 20:51       ` H.J. Lu
  1 sibling, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2015-02-07 20:47 UTC (permalink / raw)
  To: Binutils

On Sat, Feb 07, 2015 at 11:10:22AM -0800, H.J. Lu wrote:
> On Sat, Feb 07, 2015 at 04:50:27AM -0800, H.J. Lu wrote:
> > > I think you need to find a way of answering the question "is this a
> > > file accepted by a plugin?" in a more robust way.  One possibility is
> > > merging the linker handling of plugins into the bfd plugin support.
> > >
> > 
> > I have considered it before.  This approach has many implications.
> > If we do this, we need to add bfd_plugin_object and bfd_all_object.
> > bfd_all_object includes bfd_object and bfd_plugin_object.  We need
> > bfd_plugin_object so that we won't update dummy BFD info from the
> > LTO IR input.  Let me take another look.
> > 
> 
> We can extract a plugin_object_p out of plugin_maybe_claim for BFD.
> Here is the first patch.  I am checking it in.
> 
> H.J.

Here is a patch to add plugin_object_p.


H.J.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index df34f03..6765d41 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6428,6 +6428,13 @@ struct bfd
   /* Set if this is the linker output BFD.  */
   unsigned int is_linker_output : 1;
 
+  /* Set if this is claimed by a compiler plug-in library.  */
+  unsigned int claimed : 1;
+
+  /* Set to dummy BFD created when claimed by a compiler plug-in
+     library.  */
+  bfd *cbfd;
+
   /* Currently my_archive is tested before adding origin to
      anything. I believe that this can become always an add of
      origin, with origin set to 0 for non archive files.  */
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 29a7c5d..f579ab7 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -200,6 +200,13 @@ CODE_FRAGMENT
 .  {* Set if this is the linker output BFD.  *}
 .  unsigned int is_linker_output : 1;
 .
+.  {* Set if this is claimed by a compiler plug-in library.  *}
+.  unsigned int claimed : 1;
+.
+.  {* Set to dummy BFD created when claimed by a compiler plug-in
+.     library.  *}
+.  bfd *cbfd;
+.
 .  {* Currently my_archive is tested before adding origin to
 .     anything. I believe that this can become always an add of
 .     origin, with origin set to 0 for non archive files.  *}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 5c4581f..a7b1273 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -5869,7 +5869,7 @@ lang_check (void)
     {
 #ifdef ENABLE_PLUGINS
       /* Don't check format of files claimed by plugin.  */
-      if (file->input_statement.flags.claimed)
+      if (file->input_statement.the_bfd->claimed)
 	continue;
 #endif /* ENABLE_PLUGINS */
       input_bfd = file->input_statement.the_bfd;
@@ -6387,7 +6387,7 @@ lang_gc_sections (void)
 	{
 	  asection *sec;
 #ifdef ENABLE_PLUGINS
-	  if (f->flags.claimed)
+	  if (f->the_bfd->claimed)
 	    continue;
 #endif
 	  for (sec = f->the_bfd->sections; sec != NULL; sec = sec->next)
@@ -6553,7 +6553,7 @@ find_replacements_insert_point (void)
        claim1 != NULL;
        claim1 = &claim1->next->input_statement)
     {
-      if (claim1->flags.claimed)
+      if (claim1->the_bfd->claimed)
 	return claim1->flags.claim_archive ? lastobject : claim1;
       /* Update lastobject if this is a real object file.  */
       if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 69d21a7..bb41f9c 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -278,9 +278,6 @@ struct lang_input_statement_flags
   unsigned int reload : 1;
 
 #ifdef ENABLE_PLUGINS
-  /* Set if the file was claimed by a plugin.  */
-  unsigned int claimed : 1;
-
   /* Set if the file was claimed from an archive.  */
   unsigned int claim_archive : 1;
 #endif /* ENABLE_PLUGINS */
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 4b41288..7a6080f 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -793,7 +793,7 @@ add_archive_element (struct bfd_link_info *info,
     {
       /* We must offer this archive member to the plugins to claim.  */
       plugin_maybe_claim (input);
-      if (input->flags.claimed)
+      if (input->the_bfd->claimed)
 	{
 	  input->flags.claim_archive = TRUE;
 	  *subsbfd = input->the_bfd;
diff --git a/ld/plugin.c b/ld/plugin.c
index de91fa9..7d3ada9 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -1003,22 +1003,24 @@ plugin_strdup (bfd *abfd, const char *str)
   return copy;
 }
 
-void
-plugin_maybe_claim (lang_input_statement_type *entry)
+static const bfd_target *
+plugin_object_p (bfd *ibfd)
 {
   int claimed = 0;
   plugin_input_file_t *input;
   off_t offset, filesize;
   struct ld_plugin_input_file file;
   bfd *abfd;
-  bfd *ibfd = entry->the_bfd;
   bfd_boolean inarchive = bfd_my_archive (ibfd) != NULL;
   const char *name
     = inarchive ? bfd_my_archive (ibfd)->filename : ibfd->filename;
   int fd = open (name, O_RDONLY | O_BINARY);
 
+  if (ibfd->cbfd)
+    return ibfd->cbfd->xvec;
+
   if (fd < 0)
-    return;
+    return NULL;
 
   /* We create a dummy BFD, initially empty, to house whatever symbols
      the plugin may want to add.  */
@@ -1067,7 +1069,7 @@ plugin_maybe_claim (lang_input_statement_type *entry)
     einfo (_("%P%F: %s: plugin reported error claiming file\n"),
 	   plugin_error_plugin ());
 
-  if (input->fd != -1 && bfd_check_format (entry->the_bfd, bfd_object))
+  if (input->fd != -1 && bfd_check_format (ibfd, bfd_object))
     {
       /* FIXME: fd belongs to us, not the plugin.  IR for GCC plugin,
 	 which doesn't need fd after plugin_call_claim_file, is
@@ -1083,22 +1085,33 @@ plugin_maybe_claim (lang_input_statement_type *entry)
 
   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 (!inarchive)
-	bfd_close (ibfd);
+      ibfd->cbfd = abfd;
       bfd_make_readable (abfd);
-      entry->the_bfd = abfd;
-      entry->flags.claimed = TRUE;
+      abfd->claimed = 1;
+      return abfd->xvec;
     }
   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 (abfd);
-      entry->flags.claimed = FALSE;
+      return NULL;
+    }
+}
+
+void
+plugin_maybe_claim (lang_input_statement_type *entry)
+{
+  if (plugin_object_p (entry->the_bfd))
+    {
+      /* Discard the real file's BFD andsSubstitute the dummy one.  */
+      bfd *abfd = entry->the_bfd->cbfd;
+
+      /* 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 = abfd;
     }
 }
 

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-07 19:10     ` H.J. Lu
  2015-02-07 20:47       ` H.J. Lu
@ 2015-02-07 20:51       ` H.J. Lu
  1 sibling, 0 replies; 15+ messages in thread
From: H.J. Lu @ 2015-02-07 20:51 UTC (permalink / raw)
  To: Binutils

On Sat, Feb 07, 2015 at 11:10:22AM -0800, H.J. Lu wrote:
> On Sat, Feb 07, 2015 at 04:50:27AM -0800, H.J. Lu wrote:
> > > I think you need to find a way of answering the question "is this a
> > > file accepted by a plugin?" in a more robust way.  One possibility is
> > > merging the linker handling of plugins into the bfd plugin support.
> > >
> > 
> > I have considered it before.  This approach has many implications.
> > If we do this, we need to add bfd_plugin_object and bfd_all_object.
> > bfd_all_object includes bfd_object and bfd_plugin_object.  We need
> > bfd_plugin_object so that we won't update dummy BFD info from the
> > LTO IR input.  Let me take another look.
> > 
> 
> We can extract a plugin_object_p out of plugin_maybe_claim for BFD.
> Here is the first patch.  I am checking it in.
> 
> 
> H.J.
> ----
> From 35a1e5f3055fc28f129e4d5d0a993218d8af1baf Mon Sep 17 00:00:00 2001
> From: "H.J. Lu" <hjl.tools@gmail.com>
> Date: Sat, 7 Feb 2015 11:01:22 -0800
> Subject: [PATCH] Update plugin_maybe_claim
> 
> This patch removes the argument of pointer to struct ld_plugin_input_file.
> This is the first step to extract a plugin_object_p out of
> plugin_maybe_claim for BFD.
> 
> 	* plugin.c: Include "libbfd.h".
> 	(plugin_strdup): New.
> 	(plugin_maybe_claim): Remove the argument of pointer to struct
> 	ld_plugin_input_file.  Open and handle input entry.
> 	* plugin.h (plugin_maybe_claim): Updated.
> 	* ldfile.c (ldfile_try_open_bfd): Call plugin_maybe_claim directly
> 	without passing a pointer to struct ld_plugin_input_file.
> 	* ldmain.c: Don't include "libbfd.h".
> 	(add_archive_element): Call plugin_maybe_claim directly without
> 	passing a pointer to struct ld_plugin_input_file.

I checked in this small update.


H.J.
---
diff --git a/ld/ChangeLog b/ld/ChangeLog
index d7125ff..00c9466 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,10 @@
 2015-02-07  H.J. Lu  <hongjiu.lu@intel.com>
 
+	* plugin.c (plugin_maybe_claim): Replace entry->the_bfd with
+	ibfd.
+
+2015-02-07  H.J. Lu  <hongjiu.lu@intel.com>
+
 	* plugin.c: Include "libbfd.h".
 	(plugin_strdup): New.
 	(plugin_maybe_claim): Remove the argument of pointer to struct
diff --git a/ld/plugin.c b/ld/plugin.c
index de91fa9..51c7a6b 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -1067,7 +1067,7 @@ plugin_maybe_claim (lang_input_statement_type *entry)
     einfo (_("%P%F: %s: plugin reported error claiming file\n"),
 	   plugin_error_plugin ());
 
-  if (input->fd != -1 && bfd_check_format (entry->the_bfd, bfd_object))
+  if (input->fd != -1 && bfd_check_format (ibfd, bfd_object))
     {
       /* FIXME: fd belongs to us, not the plugin.  IR for GCC plugin,
 	 which doesn't need fd after plugin_call_claim_file, is

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

* Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-07 12:50   ` H.J. Lu
  2015-02-07 19:10     ` H.J. Lu
@ 2015-02-09  4:36     ` H.J. Lu
  2015-02-19 16:55       ` Alex Velenko
  1 sibling, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2015-02-09  4:36 UTC (permalink / raw)
  To: Binutils

On Sat, Feb 7, 2015 at 4:50 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Sat, Feb 7, 2015 at 1:42 AM, Alan Modra <amodra@gmail.com> wrote:
>> On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
>>> This patch adds bfd_maybe_object_p which is similar to
>>>
>>> bfd_check_format (abfd, bfd_object)
>>>
>>> The difference is bfd_maybe_object_p takes an argument to indicate if a
>>> compiler plug-in library is applied.  When a compiler plug-in library is
>>> active, it also returns TRUE if the file is not an archive or a coredump
>>> file.
>>
>> Hmm, in other words, if it is unknown.  (bfd_format takes the values
>> bfd_unknown, bfd_object, bfd_archive, bfd_core.)
>
> Yes.
>
>>> +bfd_boolean
>>> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
>>> +{
>>> +  /* LTO IR object file may look like a bfd_object file or a file which
>>> +     is not bfd_core nor bfd_archive.  */
>>> +  return (bfd_check_format (abfd, bfd_object)
>>> +       || (plugin_active_p
>>> +           && !bfd_check_format (abfd, bfd_core)
>>> +           && !bfd_check_format (abfd, bfd_archive)));
>>> +}
>>
>> I find this really strange.  If plugins are active then you're
>> willing to accept anything except cores and archives.  To throw out
>> cores and archives you'll be iterating over all compiled-in bfd
>> targets, asking "is this a core file", then asking "is this an
>> archive".  That's quite a bit of processing, and won't exclude your
>> average text file!
>
> LTO IR could be stored in the average text file.  The new plug tests
> use this feature.   We can add a new type, bfd_maybe_object.
>
>> I think you need to find a way of answering the question "is this a
>> file accepted by a plugin?" in a more robust way.  One possibility is
>> merging the linker handling of plugins into the bfd plugin support.
>>
>
> I have considered it before.  This approach has many implications.
> If we do this, we need to add bfd_plugin_object and bfd_all_object.
> bfd_all_object includes bfd_object and bfd_plugin_object.  We need
> bfd_plugin_object so that we won't update dummy BFD info from the
> LTO IR input.  Let me take another look.
>

Here is a draft to make linker plugin_object_p available to BFD:

https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=23903a326cd1cb205902698bb61f9deb1d1bf9a9

I will submit a proper patch tomorrow.

-- 
H.J.

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

* Re: Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-09  4:36     ` H.J. Lu
@ 2015-02-19 16:55       ` Alex Velenko
  2015-02-19 16:59         ` H.J. Lu
  0 siblings, 1 reply; 15+ messages in thread
From: Alex Velenko @ 2015-02-19 16:55 UTC (permalink / raw)
  To: H.J. Lu, Binutils



On 09/02/15 04:36, H.J. Lu wrote:
> On Sat, Feb 7, 2015 at 4:50 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>> On Sat, Feb 7, 2015 at 1:42 AM, Alan Modra <amodra@gmail.com> wrote:
>>> On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
>>>> This patch adds bfd_maybe_object_p which is similar to
>>>>
>>>> bfd_check_format (abfd, bfd_object)
>>>>
>>>> The difference is bfd_maybe_object_p takes an argument to indicate if a
>>>> compiler plug-in library is applied.  When a compiler plug-in library is
>>>> active, it also returns TRUE if the file is not an archive or a coredump
>>>> file.
>>>
>>> Hmm, in other words, if it is unknown.  (bfd_format takes the values
>>> bfd_unknown, bfd_object, bfd_archive, bfd_core.)
>>
>> Yes.
>>
>>>> +bfd_boolean
>>>> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
>>>> +{
>>>> +  /* LTO IR object file may look like a bfd_object file or a file which
>>>> +     is not bfd_core nor bfd_archive.  */
>>>> +  return (bfd_check_format (abfd, bfd_object)
>>>> +       || (plugin_active_p
>>>> +           && !bfd_check_format (abfd, bfd_core)
>>>> +           && !bfd_check_format (abfd, bfd_archive)));
>>>> +}
>>>
>>> I find this really strange.  If plugins are active then you're
>>> willing to accept anything except cores and archives.  To throw out
>>> cores and archives you'll be iterating over all compiled-in bfd
>>> targets, asking "is this a core file", then asking "is this an
>>> archive".  That's quite a bit of processing, and won't exclude your
>>> average text file!
>>
>> LTO IR could be stored in the average text file.  The new plug tests
>> use this feature.   We can add a new type, bfd_maybe_object.
>>
>>> I think you need to find a way of answering the question "is this a
>>> file accepted by a plugin?" in a more robust way.  One possibility is
>>> merging the linker handling of plugins into the bfd plugin support.
>>>
>>
>> I have considered it before.  This approach has many implications.
>> If we do this, we need to add bfd_plugin_object and bfd_all_object.
>> bfd_all_object includes bfd_object and bfd_plugin_object.  We need
>> bfd_plugin_object so that we won't update dummy BFD info from the
>> LTO IR input.  Let me take another look.
>>
>
> Here is a draft to make linker plugin_object_p available to BFD:
>
> https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=23903a326cd1cb205902698bb61f9deb1d1bf9a9
>
> I will submit a proper patch tomorrow.
>

Hi Lu,
After this patch on arm-none-eabi and arm-none-linux-gnueabihf I see 
following regressions:
FAIL: load plugin 2 with source
FAIL: load plugin 3 with source
FAIL: plugin 2 with source lib
FAIL: plugin 3 with source lib
FAIL: plugin claimfile replace symbol with source
FAIL: plugin claimfile resolve symbol with source

when I run test src/binutils-gdb/ld/testsuite/ld-plugin/func.c
, I see:
/work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc 
-B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/ 
-I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2 
-specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c 
/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/text.c -o 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o
/work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc 
-B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/ 
-I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2 
-specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c 
/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/main.c -o 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new   -o 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.x 
-L/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -plugin 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/.libs/libldtestplug2.so.0 
-plugin-opt registerclaimfile -plugin-opt registerallsymbolsread 
-plugin-opt registercleanup  -plugin-opt dumpresolutions 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o 
/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o 
--defsym __stack_chk_fail=0 --defsym __gccmain=0 --defsym printf=main 
--defsym puts=main
hook called: all symbols read.
Input: /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c 
(/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c)
Sym: 'func' Resolution: LDPR_PREVAILING_DEF
Sym: '_func' Resolution: LDPR_PREVAILING_DEF_IRONLY
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new: 
/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol 
from plugin)(func): warning: interworking not enabled.
   first occurrence: 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: 
Thumb call to ARM
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new: 
/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol 
from plugin)(func): warning: interworking not enabled.
   first occurrence: 
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: 
Thumb call to ARM
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new: warning: 
cannot find entry symbol _start; defaulting to 0000000000008000
/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: In 
function `main':
main.c:(.text.startup+0xa): undefined reference to `func'
hook called: cleanup.

Kind regards,
Alex

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

* Re: Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-19 16:55       ` Alex Velenko
@ 2015-02-19 16:59         ` H.J. Lu
  2015-02-19 20:10           ` H.J. Lu
  0 siblings, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2015-02-19 16:59 UTC (permalink / raw)
  To: Alex Velenko; +Cc: Binutils

On Thu, Feb 19, 2015 at 8:55 AM, Alex Velenko <Alex.Velenko@arm.com> wrote:
>
>
> On 09/02/15 04:36, H.J. Lu wrote:
>>
>> On Sat, Feb 7, 2015 at 4:50 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>>
>>> On Sat, Feb 7, 2015 at 1:42 AM, Alan Modra <amodra@gmail.com> wrote:
>>>>
>>>> On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
>>>>>
>>>>> This patch adds bfd_maybe_object_p which is similar to
>>>>>
>>>>> bfd_check_format (abfd, bfd_object)
>>>>>
>>>>> The difference is bfd_maybe_object_p takes an argument to indicate if a
>>>>> compiler plug-in library is applied.  When a compiler plug-in library
>>>>> is
>>>>> active, it also returns TRUE if the file is not an archive or a
>>>>> coredump
>>>>> file.
>>>>
>>>>
>>>> Hmm, in other words, if it is unknown.  (bfd_format takes the values
>>>> bfd_unknown, bfd_object, bfd_archive, bfd_core.)
>>>
>>>
>>> Yes.
>>>
>>>>> +bfd_boolean
>>>>> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
>>>>> +{
>>>>> +  /* LTO IR object file may look like a bfd_object file or a file
>>>>> which
>>>>> +     is not bfd_core nor bfd_archive.  */
>>>>> +  return (bfd_check_format (abfd, bfd_object)
>>>>> +       || (plugin_active_p
>>>>> +           && !bfd_check_format (abfd, bfd_core)
>>>>> +           && !bfd_check_format (abfd, bfd_archive)));
>>>>> +}
>>>>
>>>>
>>>> I find this really strange.  If plugins are active then you're
>>>> willing to accept anything except cores and archives.  To throw out
>>>> cores and archives you'll be iterating over all compiled-in bfd
>>>> targets, asking "is this a core file", then asking "is this an
>>>> archive".  That's quite a bit of processing, and won't exclude your
>>>> average text file!
>>>
>>>
>>> LTO IR could be stored in the average text file.  The new plug tests
>>> use this feature.   We can add a new type, bfd_maybe_object.
>>>
>>>> I think you need to find a way of answering the question "is this a
>>>> file accepted by a plugin?" in a more robust way.  One possibility is
>>>> merging the linker handling of plugins into the bfd plugin support.
>>>>
>>>
>>> I have considered it before.  This approach has many implications.
>>> If we do this, we need to add bfd_plugin_object and bfd_all_object.
>>> bfd_all_object includes bfd_object and bfd_plugin_object.  We need
>>> bfd_plugin_object so that we won't update dummy BFD info from the
>>> LTO IR input.  Let me take another look.
>>>
>>
>> Here is a draft to make linker plugin_object_p available to BFD:
>>
>>
>> https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=23903a326cd1cb205902698bb61f9deb1d1bf9a9
>>
>> I will submit a proper patch tomorrow.
>>
>
> Hi Lu,
> After this patch on arm-none-eabi and arm-none-linux-gnueabihf I see
> following regressions:
> FAIL: load plugin 2 with source
> FAIL: load plugin 3 with source
> FAIL: plugin 2 with source lib
> FAIL: plugin 3 with source lib
> FAIL: plugin claimfile replace symbol with source
> FAIL: plugin claimfile resolve symbol with source
>
> when I run test src/binutils-gdb/ld/testsuite/ld-plugin/func.c
> , I see:
> /work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc
> -B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/
> -I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2
> -specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c
> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/text.c -o
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o
> /work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc
> -B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/
> -I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2
> -specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c
> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/main.c -o
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new   -o
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.x
> -L/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -plugin
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/.libs/libldtestplug2.so.0
> -plugin-opt registerclaimfile -plugin-opt registerallsymbolsread -plugin-opt
> registercleanup  -plugin-opt dumpresolutions
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o
> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o --defsym
> __stack_chk_fail=0 --defsym __gccmain=0 --defsym printf=main --defsym
> puts=main
> hook called: all symbols read.
> Input: /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
> (/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c)
> Sym: 'func' Resolution: LDPR_PREVAILING_DEF
> Sym: '_func' Resolution: LDPR_PREVAILING_DEF_IRONLY
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new:
> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol
> from plugin)(func): warning: interworking not enabled.
>   first occurrence:
> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: Thumb
> call to ARM

I think those failures are caused by those extra messages.
I am not familiar with ARM linker.  I can skip those tests
for ARM.


-- 
H.J.

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

* Re: Re: [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p
  2015-02-19 16:59         ` H.J. Lu
@ 2015-02-19 20:10           ` H.J. Lu
  2017-02-13 16:03             ` [ld, testsuite] Relax the expectation pattern for several plugin-* tests Jiong Wang
  0 siblings, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2015-02-19 20:10 UTC (permalink / raw)
  To: Alex Velenko; +Cc: Binutils

On Thu, Feb 19, 2015 at 8:59 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Thu, Feb 19, 2015 at 8:55 AM, Alex Velenko <Alex.Velenko@arm.com> wrote:
>>
>>
>> On 09/02/15 04:36, H.J. Lu wrote:
>>>
>>> On Sat, Feb 7, 2015 at 4:50 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>>>
>>>> On Sat, Feb 7, 2015 at 1:42 AM, Alan Modra <amodra@gmail.com> wrote:
>>>>>
>>>>> On Thu, Feb 05, 2015 at 05:54:40AM -0800, H.J. Lu wrote:
>>>>>>
>>>>>> This patch adds bfd_maybe_object_p which is similar to
>>>>>>
>>>>>> bfd_check_format (abfd, bfd_object)
>>>>>>
>>>>>> The difference is bfd_maybe_object_p takes an argument to indicate if a
>>>>>> compiler plug-in library is applied.  When a compiler plug-in library
>>>>>> is
>>>>>> active, it also returns TRUE if the file is not an archive or a
>>>>>> coredump
>>>>>> file.
>>>>>
>>>>>
>>>>> Hmm, in other words, if it is unknown.  (bfd_format takes the values
>>>>> bfd_unknown, bfd_object, bfd_archive, bfd_core.)
>>>>
>>>>
>>>> Yes.
>>>>
>>>>>> +bfd_boolean
>>>>>> +bfd_maybe_object_p (bfd *abfd, bfd_boolean plugin_active_p)
>>>>>> +{
>>>>>> +  /* LTO IR object file may look like a bfd_object file or a file
>>>>>> which
>>>>>> +     is not bfd_core nor bfd_archive.  */
>>>>>> +  return (bfd_check_format (abfd, bfd_object)
>>>>>> +       || (plugin_active_p
>>>>>> +           && !bfd_check_format (abfd, bfd_core)
>>>>>> +           && !bfd_check_format (abfd, bfd_archive)));
>>>>>> +}
>>>>>
>>>>>
>>>>> I find this really strange.  If plugins are active then you're
>>>>> willing to accept anything except cores and archives.  To throw out
>>>>> cores and archives you'll be iterating over all compiled-in bfd
>>>>> targets, asking "is this a core file", then asking "is this an
>>>>> archive".  That's quite a bit of processing, and won't exclude your
>>>>> average text file!
>>>>
>>>>
>>>> LTO IR could be stored in the average text file.  The new plug tests
>>>> use this feature.   We can add a new type, bfd_maybe_object.
>>>>
>>>>> I think you need to find a way of answering the question "is this a
>>>>> file accepted by a plugin?" in a more robust way.  One possibility is
>>>>> merging the linker handling of plugins into the bfd plugin support.
>>>>>
>>>>
>>>> I have considered it before.  This approach has many implications.
>>>> If we do this, we need to add bfd_plugin_object and bfd_all_object.
>>>> bfd_all_object includes bfd_object and bfd_plugin_object.  We need
>>>> bfd_plugin_object so that we won't update dummy BFD info from the
>>>> LTO IR input.  Let me take another look.
>>>>
>>>
>>> Here is a draft to make linker plugin_object_p available to BFD:
>>>
>>>
>>> https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=23903a326cd1cb205902698bb61f9deb1d1bf9a9
>>>
>>> I will submit a proper patch tomorrow.
>>>
>>
>> Hi Lu,
>> After this patch on arm-none-eabi and arm-none-linux-gnueabihf I see
>> following regressions:
>> FAIL: load plugin 2 with source
>> FAIL: load plugin 3 with source
>> FAIL: plugin 2 with source lib
>> FAIL: plugin 3 with source lib
>> FAIL: plugin claimfile replace symbol with source
>> FAIL: plugin claimfile resolve symbol with source
>>
>> when I run test src/binutils-gdb/ld/testsuite/ld-plugin/func.c
>> , I see:
>> /work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc
>> -B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/
>> -I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2
>> -specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c
>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/text.c -o
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o
>> /work/fsf-trunk-3/build-arm-none-eabi/install/bin/arm-none-eabi-gcc
>> -B/work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/ld/
>> -I/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -O2
>> -specs=rdimon.specs -Wa,-mno-warn-deprecated    -mthumb  -O2 -c
>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/main.c -o
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new   -o
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.x
>> -L/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin -plugin
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/.libs/libldtestplug2.so.0
>> -plugin-opt registerclaimfile -plugin-opt registerallsymbolsread -plugin-opt
>> registercleanup  -plugin-opt dumpresolutions
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o
>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/text.o --defsym
>> __stack_chk_fail=0 --defsym __gccmain=0 --defsym printf=main --defsym
>> puts=main
>> hook called: all symbols read.
>> Input: /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
>> (/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c)
>> Sym: 'func' Resolution: LDPR_PREVAILING_DEF
>> Sym: '_func' Resolution: LDPR_PREVAILING_DEF_IRONLY
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new:
>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol
>> from plugin)(func): warning: interworking not enabled.
>>   first occurrence:
>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: Thumb
>> call to ARM
>
> I think those failures are caused by those extra messages.
> I am not familiar with ARM linker.  I can skip those tests
> for ARM.
>

It looks like an ARM linker bug.  ARM linker shouldn't complain
anything on input BFDs with BFD_PLUGIN since it is a dummy
input file.

-- 
H.J.

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

* [ld, testsuite] Relax the expectation pattern for several plugin-* tests
  2015-02-19 20:10           ` H.J. Lu
@ 2017-02-13 16:03             ` Jiong Wang
  2017-02-13 16:57               ` H.J. Lu
  0 siblings, 1 reply; 15+ messages in thread
From: Jiong Wang @ 2017-02-13 16:03 UTC (permalink / raw)
  To: Binutils; +Cc: H.J. Lu

[-- Attachment #1: Type: text/plain, Size: 1713 bytes --]

>>> hook called: all symbols read.
>>> Input: /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
>>> (/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c)
>>> Sym: 'func' Resolution: LDPR_PREVAILING_DEF
>>> Sym: '_func' Resolution: LDPR_PREVAILING_DEF_IRONLY
>>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new:
>>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol
>>> from plugin)(func): warning: interworking not enabled.
>>>   first occurrence:
>>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o: Thumb
>>> call to ARM
>>
>> I think those failures are caused by those extra messages.
>> I am not familiar with ARM linker.  I can skip those tests
>> for ARM.
>
> It looks like an ARM linker bug.  ARM linker shouldn't complain
> anything on input BFDs with BFD_PLUGIN since it is a dummy
> input file.

Or can we simply relax the testcase expectation result a little bit while
we still keeps those essential outputs that we want to catch?

Is this patch OK for master?

IMHO, keeping the warning might be better than silently accepting it.  As the
dummy input file really doesn't have proper elf header flags.  I am not sure
if relax the checking on BFD_PLUGIN will cause hiding silent issue once there
is future change on BFD_PLUGIN.

ld/
2017-02-10  Jiong Wang  <jiong.wang@arm.com>

         * testsuite/ld-plugin/plugin-15.d: Relax the match pattern.
         * testsuite/ld-plugin/plugin-16.d: Likewise.
         * testsuite/ld-plugin/plugin-20.d: Likewise.
         * testsuite/ld-plugin/plugin-21.d: Likewise.
         * testsuite/ld-plugin/plugin-22.d: Likewise.
         * testsuite/ld-plugin/plugin-23.d: Likewise.


[-- Attachment #2: fix-test.patch --]
[-- Type: text/x-diff, Size: 3419 bytes --]

diff --git a/ld/testsuite/ld-plugin/plugin-15.d b/ld/testsuite/ld-plugin/plugin-15.d
index 0481c5fb054b257410716c5a49b4a045e280e4ce..78f168626fb76eb33595de80205a25aa301b83c8 100644
--- a/ld/testsuite/ld-plugin/plugin-15.d
+++ b/ld/testsuite/ld-plugin/plugin-15.d
@@ -28,6 +28,7 @@ hook called: claim_file .*/ld/testsuite/ld-plugin/func.c \[@0/.* CLAIMED
 hook called: claim_file tmpdir/text.o \[@0/.* not claimed
 #...
 hook called: all symbols read.
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-16.d b/ld/testsuite/ld-plugin/plugin-16.d
index ae54f0c24a1b90686e17ffc31e5dc4ab331e1e2c..a1f32a507920b72be55776614ca9f5b23d34a567 100644
--- a/ld/testsuite/ld-plugin/plugin-16.d
+++ b/ld/testsuite/ld-plugin/plugin-16.d
@@ -32,6 +32,7 @@ hook called: claim_file tmpdir/text.o \[@0/.* not claimed
 hook called: all symbols read.
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF
 Sym: '_?func2' Resolution: LDPR_PREVAILING_DEF_IRONLY
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-20.d b/ld/testsuite/ld-plugin/plugin-20.d
index 373a3ff2a3b037c1959710654c17a3c4008cd8a6..28ffc46a6876c0a40b835800663fc3382ac447f9 100644
--- a/ld/testsuite/ld-plugin/plugin-20.d
+++ b/ld/testsuite/ld-plugin/plugin-20.d
@@ -2,6 +2,7 @@ hook called: all symbols read.
 Input: func.c \(tmpdir/libfunc.a\)
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-21.d b/ld/testsuite/ld-plugin/plugin-21.d
index 7b922c11e116f9f081f70782b7bdbcafb8a666bc..a5a5b59f891bf3c83d820bfba09b8765e79db402 100644
--- a/ld/testsuite/ld-plugin/plugin-21.d
+++ b/ld/testsuite/ld-plugin/plugin-21.d
@@ -2,6 +2,7 @@ hook called: all symbols read.
 Input: .*/ld/testsuite/ld-plugin/func.c \(.*/ld/testsuite/ld-plugin/func.c\)
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-22.d b/ld/testsuite/ld-plugin/plugin-22.d
index 151267624f906a95d030e85efb99169810d26642..438a1f098d67596325171a2ebd08829a24ad3780 100644
--- a/ld/testsuite/ld-plugin/plugin-22.d
+++ b/ld/testsuite/ld-plugin/plugin-22.d
@@ -2,6 +2,7 @@ Claimed: tmpdir/libfunc.a \[@.*
 hook called: all symbols read.
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.
diff --git a/ld/testsuite/ld-plugin/plugin-23.d b/ld/testsuite/ld-plugin/plugin-23.d
index e05f7bdfcf75a94331beca610b6aac122996d9c2..c279130ffdb0be5d5392fd6d77a0189c96333951 100644
--- a/ld/testsuite/ld-plugin/plugin-23.d
+++ b/ld/testsuite/ld-plugin/plugin-23.d
@@ -2,6 +2,7 @@ Claimed: .*/ld/testsuite/ld-plugin/func.c \[@0.*
 hook called: all symbols read.
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
 Sym: '_?func' Resolution: LDPR_PREVAILING_DEF.*
+#...
 tmpdir/main.o: In function `main':
 .*main.c.*: undefined reference to `\.?func'
 hook called: cleanup.

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

* Re: [ld, testsuite] Relax the expectation pattern for several plugin-* tests
  2017-02-13 16:03             ` [ld, testsuite] Relax the expectation pattern for several plugin-* tests Jiong Wang
@ 2017-02-13 16:57               ` H.J. Lu
  2017-02-15 17:46                 ` Jiong Wang
  0 siblings, 1 reply; 15+ messages in thread
From: H.J. Lu @ 2017-02-13 16:57 UTC (permalink / raw)
  To: Jiong Wang; +Cc: Binutils

On Mon, Feb 13, 2017 at 8:03 AM, Jiong Wang <jiong.wang@foss.arm.com> wrote:
>>>> hook called: all symbols read.
>>>> Input: /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c
>>>> (/work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c)
>>>> Sym: 'func' Resolution: LDPR_PREVAILING_DEF
>>>> Sym: '_func' Resolution: LDPR_PREVAILING_DEF_IRONLY
>>>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/ld-new:
>>>> /work/fsf-trunk-3/src/binutils-gdb/ld/testsuite/ld-plugin/func.c (symbol
>>>> from plugin)(func): warning: interworking not enabled.
>>>>   first occurrence:
>>>> /work/fsf-trunk-3/build-arm-none-eabi/obj/binutils/ld/tmpdir/main.o:
>>>> Thumb
>>>> call to ARM
>>>
>>>
>>> I think those failures are caused by those extra messages.
>>> I am not familiar with ARM linker.  I can skip those tests
>>> for ARM.
>>
>>
>> It looks like an ARM linker bug.  ARM linker shouldn't complain
>> anything on input BFDs with BFD_PLUGIN since it is a dummy
>> input file.
>
>
> Or can we simply relax the testcase expectation result a little bit while
> we still keeps those essential outputs that we want to catch?
>
> Is this patch OK for master?
>
> IMHO, keeping the warning might be better than silently accepting it.  As
> the
> dummy input file really doesn't have proper elf header flags.  I am not sure
> if relax the checking on BFD_PLUGIN will cause hiding silent issue once
> there
> is future change on BFD_PLUGIN.
>
> ld/
> 2017-02-10  Jiong Wang  <jiong.wang@arm.com>
>
>         * testsuite/ld-plugin/plugin-15.d: Relax the match pattern.
>         * testsuite/ld-plugin/plugin-16.d: Likewise.
>         * testsuite/ld-plugin/plugin-20.d: Likewise.
>         * testsuite/ld-plugin/plugin-21.d: Likewise.
>         * testsuite/ld-plugin/plugin-22.d: Likewise.
>         * testsuite/ld-plugin/plugin-23.d: Likewise.
>

I agree that ARM linker shouldn't complain IR symbols in this case.
Can you update ARM linker like this?

-- 
H.J.
--
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 8171b0b..c3d99df 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -2115,7 +2115,7 @@ typedef unsigned short int insn16;
 #define INTERWORK_FLAG(abfd)  \
   (EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags) >= EF_ARM_EABI_VER4 \
   || (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK) \
-  || ((abfd)->flags & BFD_LINKER_CREATED))
+  || ((abfd)->flags & (BFD_LINKER_CREATED | BFD_PLUGIN)))

 /* The linker script knows the section names for placement.
    The entry_names are used to do simple name mangling on the stubs.

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

* Re: [ld, testsuite] Relax the expectation pattern for several plugin-* tests
  2017-02-13 16:57               ` H.J. Lu
@ 2017-02-15 17:46                 ` Jiong Wang
  2017-02-15 23:42                   ` Alan Modra
  0 siblings, 1 reply; 15+ messages in thread
From: Jiong Wang @ 2017-02-15 17:46 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils

On 13/02/17 16:57, H.J. Lu wrote:
> I agree that ARM linker shouldn't complain IR symbols in this case.
> Can you update ARM linker like this?

Hmm, I saw BFD_PLUGIN is set together with BFD_LINKER_CREATED, so the current
check in INTERWORK_FLAG should have covered this.  While it is not, so I guess
in some place bfd linker dropped the BFD_LINKER_CREATED bit.

Some search in the code, it looks to me we should also save "BFD_LINKER_CREATED"
in BFD_FLAGS_SAVED in bfd.c/bfd-in2.h?  I have made this change locally, and
these failures gone away on arm native ld check without regression.

Regards,
Jiong

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

* Re: [ld, testsuite] Relax the expectation pattern for several plugin-* tests
  2017-02-15 17:46                 ` Jiong Wang
@ 2017-02-15 23:42                   ` Alan Modra
  2017-02-16 10:16                     ` Jiong Wang
  0 siblings, 1 reply; 15+ messages in thread
From: Alan Modra @ 2017-02-15 23:42 UTC (permalink / raw)
  To: Jiong Wang; +Cc: H.J. Lu, Binutils

On Wed, Feb 15, 2017 at 05:46:46PM +0000, Jiong Wang wrote:
> On 13/02/17 16:57, H.J. Lu wrote:
> >I agree that ARM linker shouldn't complain IR symbols in this case.
> >Can you update ARM linker like this?
> 
> Hmm, I saw BFD_PLUGIN is set together with BFD_LINKER_CREATED, so the current
> check in INTERWORK_FLAG should have covered this.  While it is not, so I guess
> in some place bfd linker dropped the BFD_LINKER_CREATED bit.
> 
> Some search in the code, it looks to me we should also save "BFD_LINKER_CREATED"
> in BFD_FLAGS_SAVED in bfd.c/bfd-in2.h?  I have made this change locally, and
> these failures gone away on arm native ld check without regression.

A patch to add that to BFD_FLAGS_SAVED in bfd.c is preapproved.

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: [ld, testsuite] Relax the expectation pattern for several plugin-* tests
  2017-02-15 23:42                   ` Alan Modra
@ 2017-02-16 10:16                     ` Jiong Wang
  0 siblings, 0 replies; 15+ messages in thread
From: Jiong Wang @ 2017-02-16 10:16 UTC (permalink / raw)
  To: Alan Modra; +Cc: H.J. Lu, Binutils

[-- Attachment #1: Type: text/plain, Size: 1099 bytes --]

On 15/02/17 23:42, Alan Modra wrote:
> On Wed, Feb 15, 2017 at 05:46:46PM +0000, Jiong Wang wrote:
>> On 13/02/17 16:57, H.J. Lu wrote:
>>> I agree that ARM linker shouldn't complain IR symbols in this case.
>>> Can you update ARM linker like this?
>> Hmm, I saw BFD_PLUGIN is set together with BFD_LINKER_CREATED, so the current
>> check in INTERWORK_FLAG should have covered this.  While it is not, so I guess
>> in some place bfd linker dropped the BFD_LINKER_CREATED bit.
>>
>> Some search in the code, it looks to me we should also save "BFD_LINKER_CREATED"
>> in BFD_FLAGS_SAVED in bfd.c/bfd-in2.h?  I have made this change locally, and
>> these failures gone away on arm native ld check without regression.
> A patch to add that to BFD_FLAGS_SAVED in bfd.c is preapproved.
>
Thanks.  Committed attached patch after x86/arm native check-ld/as/binutils OK.

I followed BFD_FLAGS_FOR_BFD_USE_MASK to put BFD_LINKER_CREATED and BFD_PLUGIN together.

bfd/
2017-02-16  Jiong Wang <jiong.wang@arm.com>

         * bfd.c (BFD_FLAGS_SAVED): Add BFD_LINKER_CREATED.
         * bfd-in2.h: Regenerated.


[-- Attachment #2: 1.patch --]
[-- Type: text/x-diff, Size: 1934 bytes --]

commit 905712060597d0c7a13ffccbca40330c7ad3e3a8
Author: Jiong Wang <jiong.wang@arm.com>
Date:   Thu Feb 16 09:40:03 2017 +0000

    [Patch] Add BFD_LINKER_CREATED to BFD_FLAGS_SAVED
    
    bfd/
    	* bfd.c (BFD_FLAGS_SAVED): Add BFD_LINKER_CREATED.
    	* bfd-in2.h: Regenerated.
    
    Bug exposed by https://sourceware.org/ml/binutils/2017-02/msg00128.html

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 789915c..a6a4c64 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2017-02-16  Jiong Wang <jiong.wang@arm.com>
+
+	* bfd.c (BFD_FLAGS_SAVED): Add BFD_LINKER_CREATED.
+	* bfd-in2.h: Regenerated.
+
 2017-02-15  H.J. Lu  <hongjiu.lu@intel.com>
 
 	PR ld/21168
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 80d60cb..f90bb8c 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6806,8 +6806,9 @@ struct bfd
 
   /* Flags bits to be saved in bfd_preserve_save.  */
 #define BFD_FLAGS_SAVED \
-  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN \
-   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
+  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
+   | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
+   | BFD_USE_ELF_STT_COMMON)
 
   /* Flags bits which are for BFD use only.  */
 #define BFD_FLAGS_FOR_BFD_USE_MASK \
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 1607f39..a9402e48 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -180,8 +180,9 @@ CODE_FRAGMENT
 .
 .  {* Flags bits to be saved in bfd_preserve_save.  *}
 .#define BFD_FLAGS_SAVED \
-.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN \
-.   | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON | BFD_USE_ELF_STT_COMMON)
+.  (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \
+.   | BFD_PLUGIN | BFD_COMPRESS_GABI | BFD_CONVERT_ELF_COMMON \
+.   | BFD_USE_ELF_STT_COMMON)
 .
 .  {* Flags bits which are for BFD use only.  *}
 .#define BFD_FLAGS_FOR_BFD_USE_MASK \

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

end of thread, other threads:[~2017-02-16 10:16 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-05 13:54 [PATCH 1/8] PR ld/17878: Add bfd_maybe_object_p H.J. Lu
2015-02-07  9:42 ` Alan Modra
2015-02-07 12:50   ` H.J. Lu
2015-02-07 19:10     ` H.J. Lu
2015-02-07 20:47       ` H.J. Lu
2015-02-07 20:51       ` H.J. Lu
2015-02-09  4:36     ` H.J. Lu
2015-02-19 16:55       ` Alex Velenko
2015-02-19 16:59         ` H.J. Lu
2015-02-19 20:10           ` H.J. Lu
2017-02-13 16:03             ` [ld, testsuite] Relax the expectation pattern for several plugin-* tests Jiong Wang
2017-02-13 16:57               ` H.J. Lu
2017-02-15 17:46                 ` Jiong Wang
2017-02-15 23:42                   ` Alan Modra
2017-02-16 10:16                     ` Jiong Wang

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).