[PATCH] [gold] Unlock external members of thin archives.

Cary Coutant ccoutant@google.com
Wed Feb 4 04:32:00 GMT 2015


> gold/
>         * archive.cc (Archive::get_elf_object_for_member): Unlock external
>         members of thin archives so that they may be used by plugins.

Thanks! This is the problem, but Archive::include_member() is supposed
to be responsible for unlocking external members of thin archives, and
does it properly except in the plugin case. I've chosen to fix this by
adding an RAII class to unlock the object when include_member()
returns. I've also modified the test plugin library a bit to make it
easy to add a test case for claiming members of a thin archive.

The failure to unlock these objects is actually the cause of PR 15660
(at least I'm pretty certain of that), which complains that the linker
is running out of file descriptors when linking a very large
application using LTO. The gcc LTO plugin doesn't use the
get_input_file API, so the problem went undetected until actually
running out of available file descriptors.

-cary



2015-02-03  Cary Coutant  <ccoutant@google.com>
            Peter Collingbourne  <pcc@google.com>

gold/
        PR gold/15660
        * archive.cc (Thin_archive_object_unlocker): New class.
        (Archive::include_member): Unlock external members of thin archives.
        * testsuite/Makefile.am (plugin_test_1): Rename .syms files.
        (plugin_test_2): Likewise.
        (plugin_test_3): Likewise.
        (plugin_test_4): Likewise.
        (plugin_test_5): Likewise.
        (plugin_test_6): Likewise.
        (plugin_test_7): Likewise.
        (plugin_test_8): Likewise.
        (plugin_test_9): Likewise.
        (plugin_test_10): Likewise.
        (plugin_test_11): New test case.
        * testsuite/Makefile.in: Regenerate.
        * testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
        file to decide whether to claim file.
        (all_symbols_read_hook): Likewise.
        * testsuite/plugin_test_1.sh: Adjust expected output.
        * testsuite/plugin_test_2.sh: Likewise.
        * testsuite/plugin_test_3.sh: Likewise.
        * testsuite/plugin_test_6.sh: Likewise.
        * testsuite/plugin_test_tls.sh: Likewise.
        * testsuite/plugin_test_11.sh: New testcase.
-------------- next part --------------
Fix a file descriptor leak in gold.

When an LTO linker plugin claims an external member of a thin archive, gold
does not properly unlock the file and make its file descriptor available for
reuse. This patch fixes the problem by modifying Archive::include_member to
unlock the object file via an RAII class instance, ensuring that it will be
unlocked no matter what path is taken through the function.  I've also
added a new test case using thin archives with a plugin, and modified the
test plugin library to claim any .o file where a corresponding .o.syms file
exists.


2015-02-03  Cary Coutant  <ccoutant@google.com>
	    Peter Collingbourne  <pcc@google.com>

gold/
	PR gold/15660
	* archive.cc (Thin_archive_object_unlocker): New class.
	(Archive::include_member): Unlock external members of thin archives.
	* testsuite/Makefile.am (plugin_test_1): Rename .syms files.
	(plugin_test_2): Likewise.
	(plugin_test_3): Likewise.
	(plugin_test_4): Likewise.
	(plugin_test_5): Likewise.
	(plugin_test_6): Likewise.
	(plugin_test_7): Likewise.
	(plugin_test_8): Likewise.
	(plugin_test_9): Likewise.
	(plugin_test_10): Likewise.
	(plugin_test_11): New test case.
	* testsuite/Makefile.in: Regenerate.
	* testsuite/plugin_test.c (claim_file_hook): Check for parallel .syms
	file to decide whether to claim file.
	(all_symbols_read_hook): Likewise.
	* testsuite/plugin_test_1.sh: Adjust expected output.
	* testsuite/plugin_test_2.sh: Likewise.
	* testsuite/plugin_test_3.sh: Likewise.
	* testsuite/plugin_test_6.sh: Likewise.
	* testsuite/plugin_test_tls.sh: Likewise.
	* testsuite/plugin_test_11.sh: New testcase.

diff --git a/gold/archive.cc b/gold/archive.cc
index 69107f5..6d25980 100644
--- a/gold/archive.cc
+++ b/gold/archive.cc
@@ -930,6 +930,32 @@ Archive::count_members()
   return ret;
 }
 
+// RAII class to ensure we unlock the object if it's a member of a
+// thin archive. We can't use Task_lock_obj in Archive::include_member
+// because the object file is already locked when it's opened by
+// get_elf_object_for_member.
+
+class Thin_archive_object_unlocker
+{
+ public:
+  Thin_archive_object_unlocker(const Task *task, Object* obj)
+    : task_(task), obj_(obj)
+  { }
+
+  ~Thin_archive_object_unlocker()
+  {
+    if (this->obj_->offset() == 0)
+      this->obj_->unlock(this->task_);
+  }
+
+ private:
+  Thin_archive_object_unlocker(const Thin_archive_object_unlocker&);
+  Thin_archive_object_unlocker& operator=(const Thin_archive_object_unlocker&);
+
+  const Task* task_;
+  Object* obj_;
+};
+
 // Include an archive member in the link.  OFF is the file offset of
 // the member header.  WHY is the reason we are including this member.
 // Return true if we added the member or if we had an error, return
@@ -978,6 +1004,10 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
       return unconfigured ? false : true;
     }
 
+  // If the object is an external member of a thin archive,
+  // unlock it when we're done here.
+  Thin_archive_object_unlocker unlocker(this->task_, obj);
+
   if (mapfile != NULL)
     mapfile->report_include_archive_member(obj->name(), sym, why);
 
@@ -991,31 +1021,21 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
 
   if (!input_objects->add_object(obj))
     {
-      // If this is an external member of a thin archive, unlock the
-      // file.
-      if (obj->offset() == 0)
-	obj->unlock(this->task_);
       delete obj;
+      return true;
     }
-  else
-    {
-      {
-	if (layout->incremental_inputs() != NULL)
-	  layout->incremental_inputs()->report_object(obj, 0, this, NULL);
-	Read_symbols_data sd;
-	obj->read_symbols(&sd);
-	obj->layout(symtab, layout, &sd);
-	obj->add_symbols(symtab, &sd, layout);
-      }
-
-      // If this is an external member of a thin archive, unlock the file
-      // for the next task.
-      if (obj->offset() == 0)
-        obj->unlock(this->task_);
 
-      this->included_member_ = true;
-    }
+  if (layout->incremental_inputs() != NULL)
+    layout->incremental_inputs()->report_object(obj, 0, this, NULL);
+
+  {
+    Read_symbols_data sd;
+    obj->read_symbols(&sd);
+    obj->layout(symtab, layout, &sd);
+    obj->add_symbols(symtab, &sd, layout);
+  }
 
+  this->included_member_ = true;
   return true;
 }
 
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index aca2a41..be3b278 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -1564,8 +1564,8 @@ check_PROGRAMS += plugin_test_1
 check_SCRIPTS += plugin_test_1.sh
 check_DATA += plugin_test_1.err
 MOSTLYCLEANFILES += plugin_test_1.err
-plugin_test_1: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_1.err
+plugin_test_1: two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms empty.o.syms gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms empty.o.syms 2>plugin_test_1.err
 plugin_test_1.err: plugin_test_1
 	@touch plugin_test_1.err
 
@@ -1573,8 +1573,8 @@ check_PROGRAMS += plugin_test_2
 check_SCRIPTS += plugin_test_2.sh
 check_DATA += plugin_test_2.err
 MOSTLYCLEANFILES += plugin_test_2.err
-plugin_test_2: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,-R,.,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_shared_2.so 2>plugin_test_2.err
+plugin_test_2: two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_shared_2.so gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,-R,.,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_shared_2.so 2>plugin_test_2.err
 plugin_test_2.err: plugin_test_2
 	@touch plugin_test_2.err
 
@@ -1582,8 +1582,8 @@ check_PROGRAMS += plugin_test_3
 check_SCRIPTS += plugin_test_3.sh
 check_DATA += plugin_test_3.err
 MOSTLYCLEANFILES += plugin_test_3.err
-plugin_test_3: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--export-dynamic -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms empty.syms 2>plugin_test_3.err
+plugin_test_3: two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms empty.o.syms gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--export-dynamic -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms empty.o.syms 2>plugin_test_3.err
 plugin_test_3.err: plugin_test_3
 	@touch plugin_test_3.err
 
@@ -1596,35 +1596,35 @@ plugin_test_4: two_file_test_main.o plugin_test_4.a gcctestdir/ld plugin_test.so
 plugin_test_4.err: plugin_test_4
 	@touch plugin_test_4.err
 
-plugin_test_4.a: two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms
+plugin_test_4.a: two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms
 	$(TEST_AR) cr $@ $^
 
 check_PROGRAMS += plugin_test_5
-plugin_test_5: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv",--gc-sections two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.syms unused.syms
+plugin_test_5: two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms unused.o.syms gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv",--gc-sections two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms unused.o.syms
 
 check_PROGRAMS += plugin_test_6
 check_SCRIPTS += plugin_test_6.sh
 check_DATA += plugin_test_6.err
 MOSTLYCLEANFILES += plugin_test_6.err
-plugin_test_6: plugin_common_test_1.syms plugin_common_test_2.syms gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so" plugin_common_test_1.syms plugin_common_test_2.syms 2>plugin_test_6.err
+plugin_test_6: plugin_common_test_1.o.syms plugin_common_test_2.o.syms gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so" plugin_common_test_1.o.syms plugin_common_test_2.o.syms 2>plugin_test_6.err
 plugin_test_6.err: plugin_test_6
 	@touch plugin_test_6.err
 
 check_PROGRAMS += plugin_test_7
 check_SCRIPTS += plugin_test_7.sh
-check_DATA += plugin_test_7.err plugin_test_7.syms
+check_DATA += plugin_test_7.err plugin_test_7.o.syms
 MOSTLYCLEANFILES += plugin_test_7.err
-plugin_test_7: plugin_test_7_1.o plugin_test_7_1.syms plugin_test_7_2.o gcctestdir/ld plugin_test.so
-	$(LINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--gc-sections,--print-gc-sections plugin_test_7_1.syms plugin_test_7_2.o 2>plugin_test_7.err
-plugin_test_7.syms: plugin_test_7
+plugin_test_7: plugin_test_7_1.o plugin_test_7_1.o.syms plugin_test_7_2.o gcctestdir/ld plugin_test.so
+	$(LINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--gc-sections,--print-gc-sections plugin_test_7_1.o.syms plugin_test_7_2.o 2>plugin_test_7.err
+plugin_test_7.o.syms: plugin_test_7
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
 plugin_test_7_1.o: plugin_test_7_1.c
 	$(COMPILE) -DLTO -O0 -c -ffunction-sections -fdata-sections -o $@ $<
 plugin_test_7_1_orig.o: plugin_test_7_1.c
 	$(COMPILE) -O0 -c -ffunction-sections -fdata-sections -o $@ $<
-plugin_test_7_1.syms: plugin_test_7_1_orig.o
+plugin_test_7_1.o.syms: plugin_test_7_1_orig.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
 plugin_test_7_2.o: plugin_test_7_2.c
 	$(COMPILE) -O0 -c -ffunction-sections -fdata-sections -o $@ $<
@@ -1632,8 +1632,8 @@ plugin_test_7.err: plugin_test_7
 
 # Test plugins with -r.
 check_PROGRAMS += plugin_test_8
-plugin_test_8.o: two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.o ../ld-new plugin_test.so
-	../ld-new -r -o $@ --no-demangle --plugin "./plugin_test.so" two_file_test_main.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2.o
+plugin_test_8.o: two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o ../ld-new plugin_test.so
+	../ld-new -r -o $@ --no-demangle --plugin "./plugin_test.so" two_file_test_main.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o
 plugin_test_8: plugin_test_8.o gcctestdir/ld
 	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle plugin_test_8.o
 
@@ -1641,17 +1641,17 @@ plugin_test_8: plugin_test_8.o gcctestdir/ld
 # produce an unresolved symbol error.
 check_DATA += plugin_test_9.err
 MOSTLYCLEANFILES += plugin_test_9.err
-plugin_test_9.err: two_file_test_main.o two_file_test_1c.syms two_file_test_2.syms gcctestdir/ld plugin_test.so
-	@echo $(CXXLINK) -Bgcctestdir/ -o plugin_test_9 -Wl,--no-demangle,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1c.syms two_file_test_2.syms "2>$@"
-	@if $(CXXLINK) -Bgcctestdir/ -o plugin_test_9 -Wl,--no-demangle,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1c.syms two_file_test_2.syms 2>$@; then \
+plugin_test_9.err: two_file_test_main.o two_file_test_1c.o.syms two_file_test_2.o.syms gcctestdir/ld plugin_test.so
+	@echo $(CXXLINK) -Bgcctestdir/ -o plugin_test_9 -Wl,--no-demangle,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1c.o.syms two_file_test_2.o.syms "2>$@"
+	@if $(CXXLINK) -Bgcctestdir/ -o plugin_test_9 -Wl,--no-demangle,--plugin,"./plugin_test.so" two_file_test_main.o two_file_test_1c.o.syms two_file_test_2.o.syms 2>$@; then \
 	  echo 1>&2 "Link of plugin_test_9 should have failed"; \
 	  rm -f $@; \
 	  exit 1; \
 	fi
 # Make a .syms file that claims to define the symbol _Z4t16av.
-two_file_test_1c.syms: two_file_test_1.syms two_file_test_1c.o
-	cp two_file_test_1.syms $@.tmp
-	grep "_Z4t16av" two_file_test_1b.syms >> $@.tmp
+two_file_test_1c.o.syms: two_file_test_1.o.syms two_file_test_1c.o
+	cp two_file_test_1.o.syms $@.tmp
+	grep "_Z4t16av" two_file_test_1b.o.syms >> $@.tmp
 	mv -f $@.tmp $@
 # Make a copy of two_file_test_1.o, which does not define the symbol _Z4t16av.
 MOSTLYCLEANFILES += two_file_test_1c.o
@@ -1662,32 +1662,43 @@ check_PROGRAMS += plugin_test_10
 check_SCRIPTS += plugin_test_10.sh
 check_DATA += plugin_test_10.sections
 MOSTLYCLEANFILES += plugin_test_10.sections
-plugin_test_10: plugin_common_test_1.syms plugin_common_test_2.o  gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so" plugin_common_test_1.syms plugin_common_test_2.o
+plugin_test_10: plugin_common_test_1.o.syms plugin_common_test_2.o  gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so" plugin_common_test_1.o.syms plugin_common_test_2.o
 plugin_test_10.sections: plugin_test_10
 	$(TEST_READELF) -SW $< >$@ 2>/dev/null
 
-
+check_PROGRAMS += plugin_test_11
+check_SCRIPTS += plugin_test_11.sh
+check_DATA += plugin_test_11.err
+MOSTLYCLEANFILES += plugin_test_11.err
+PLUGIN_TEST_11_SYMS = two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2.o.syms
+plugin_test_11: two_file_test_main.o plugin_test_thin.a gcctestdir/ld plugin_test.so $(PLUGIN_TEST_11_SYMS)
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_main.o plugin_test_thin.a 2>plugin_test_11.err
+plugin_test_11.err: plugin_test_11
+	@touch plugin_test_11.err
+plugin_test_thin.a: two_file_test_1.o two_file_test_1b.o two_file_test_2.o
+	rm -f $@
+	$(TEST_AR) crT $@ $^
 
 plugin_test.so: plugin_test.o
 	$(LINK) -Bgcctestdir/ -shared plugin_test.o
 plugin_test.o: plugin_test.c
 	$(COMPILE) -O0 -c -fpic -o $@ $<
 
-two_file_test_main.syms: two_file_test_main.o
+two_file_test_main.o.syms: two_file_test_main.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
-two_file_test_1.syms: two_file_test_1.o
+two_file_test_1.o.syms: two_file_test_1.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
-two_file_test_1b.syms: two_file_test_1b.o
+two_file_test_1b.o.syms: two_file_test_1b.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
-two_file_test_2.syms: two_file_test_2.o
+two_file_test_2.o.syms: two_file_test_2.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
-plugin_common_test_1.syms: plugin_common_test_1.o
+plugin_common_test_1.o.syms: plugin_common_test_1.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
-plugin_common_test_2.syms: plugin_common_test_2.o
+plugin_common_test_2.o.syms: plugin_common_test_2.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
 
-empty.syms:
+empty.o.syms:
 	@echo "" >$@
 	@echo "Symbol table" >>$@
 
@@ -1697,18 +1708,18 @@ check_PROGRAMS += plugin_test_tls
 check_SCRIPTS += plugin_test_tls.sh
 check_DATA += plugin_test_tls.err
 MOSTLYCLEANFILES += plugin_test_tls.err
-plugin_test_tls: two_file_test_tls.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2_tls.syms gcctestdir/ld plugin_test.so
-	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_tls.o two_file_test_1.syms two_file_test_1b.syms two_file_test_2_tls.syms 2>plugin_test_tls.err
+plugin_test_tls: two_file_test_tls.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2_tls.o.syms gcctestdir/ld plugin_test.so
+	$(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_Z4f13iv" two_file_test_tls.o two_file_test_1.o.syms two_file_test_1b.o.syms two_file_test_2_tls.o.syms 2>plugin_test_tls.err
 plugin_test_tls.err: plugin_test_tls
 	@touch plugin_test_tls.err
 
-two_file_test_2_tls.syms: two_file_test_2_tls.o
+two_file_test_2_tls.o.syms: two_file_test_2_tls.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
 
 endif TLS
 
 MOSTLYCLEANFILES += unused.c
-unused.syms: unused.o
+unused.o.syms: unused.o
 	$(TEST_READELF) -sW $< >$@ 2>/dev/null
 	@echo "     1: 00000000     4 FUNC    GLOBAL DEFAULT    1 UNUSED" >>$@
 unused.o: unused.c
diff --git a/gold/testsuite/plugin_test.c b/gold/testsuite/plugin_test.c
index d2175e8..cf6adf3 100644
--- a/gold/testsuite/plugin_test.c
+++ b/gold/testsuite/plugin_test.c
@@ -263,15 +263,35 @@ claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
   int vis;
   int is_comdat;
   int i;
+  int irfile_was_opened = 0;
+  char syms_name[80];
 
   (*message)(LDPL_INFO,
              "%s: claim file hook called (offset = %ld, size = %ld)",
              file->name, (long)file->offset, (long)file->filesize);
 
+  /* Look for matching syms file for an archive member.  */
+  if (file->offset == 0)
+    snprintf(syms_name, sizeof(syms_name), "%s.syms", file->name);
+  else
+    snprintf(syms_name, sizeof(syms_name), "%s-%d.syms",
+	     file->name, (int)file->offset);
+  irfile = fopen(syms_name, "r");
+  if (irfile != NULL)
+    {
+      irfile_was_opened = 1;
+      end_offset = 1 << 20;
+    }
+
+  /* Otherwise, see if the file itself is a syms file.  */
+  if (!irfile_was_opened)
+    {
+      irfile = fdopen(file->fd, "r");
+      (void)fseek(irfile, file->offset, SEEK_SET);
+      end_offset = file->offset + file->filesize;
+    }
+
   /* Look for the beginning of output from readelf -s.  */
-  irfile = fdopen(file->fd, "r");
-  (void)fseek(irfile, file->offset, SEEK_SET);
-  end_offset = file->offset + file->filesize;
   len = fread(buf, 1, 13, irfile);
   if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0)
     return LDPS_OK;
@@ -378,6 +398,8 @@ claim_file_hook (const struct ld_plugin_input_file* file, int* claimed)
     (*add_symbols)(file->handle, nsyms, syms);
 
   *claimed = 1;
+  if (irfile_was_opened)
+    fclose(irfile);
   return LDPS_OK;
 }
 
@@ -474,12 +496,31 @@ all_symbols_read_hook(void)
        claimed_file != NULL;
        claimed_file = claimed_file->next)
     {
+      int irfile_was_opened = 0;
+      char syms_name[80];
+
       (*get_input_file) (claimed_file->handle, &file);
 
+      if (file.offset == 0)
+	snprintf(syms_name, sizeof(syms_name), "%s.syms", file.name);
+      else
+	snprintf(syms_name, sizeof(syms_name), "%s-%d.syms",
+		 file.name, (int)file.offset);
+      irfile = fopen(syms_name, "r");
+      if (irfile != NULL)
+	{
+	  irfile_was_opened = 1;
+	  end_offset = 1 << 20;
+	}
+
+      if (!irfile_was_opened)
+	{
+	  irfile = fdopen(file.fd, "r");
+	  (void)fseek(irfile, file.offset, SEEK_SET);
+	  end_offset = file.offset + file.filesize;
+	}
+
       /* Look for the beginning of output from readelf -s.  */
-      irfile = fdopen(file.fd, "r");
-      (void)fseek(irfile, file.offset, SEEK_SET);
-      end_offset = file.offset + file.filesize;
       len = fread(buf, 1, 13, irfile);
       if (len < 13 || strncmp(buf, "\nSymbol table", 13) != 0)
         {
@@ -509,6 +550,9 @@ all_symbols_read_hook(void)
             }
         }
 
+      if (irfile_was_opened)
+	fclose(irfile);
+
       (*release_input_file) (claimed_file->handle);
 
       if (filename == NULL)
diff --git a/gold/testsuite/plugin_test_1.sh b/gold/testsuite/plugin_test_1.sh
index 34da267..c54a74f 100755
--- a/gold/testsuite/plugin_test_1.sh
+++ b/gold/testsuite/plugin_test_1.sh
@@ -43,14 +43,14 @@ check plugin_test_1.err "API version:"
 check plugin_test_1.err "gold version:"
 check plugin_test_1.err "option: _Z4f13iv"
 check plugin_test_1.err "two_file_test_main.o: claim file hook called"
-check plugin_test_1.err "two_file_test_1.syms: claim file hook called"
-check plugin_test_1.err "two_file_test_1b.syms: claim file hook called"
-check plugin_test_1.err "two_file_test_2.syms: claim file hook called"
-check plugin_test_1.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY"
-check plugin_test_1.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG"
-check plugin_test_1.err "two_file_test_1.syms: v2: RESOLVED_IR"
-check plugin_test_1.err "two_file_test_1.syms: t17data: RESOLVED_IR"
-check plugin_test_1.err "two_file_test_2.syms: _Z4f13iv: PREEMPTED_IR"
+check plugin_test_1.err "two_file_test_1.o.syms: claim file hook called"
+check plugin_test_1.err "two_file_test_1b.o.syms: claim file hook called"
+check plugin_test_1.err "two_file_test_2.o.syms: claim file hook called"
+check plugin_test_1.err "two_file_test_1.o.syms: _Z4f13iv: PREVAILING_DEF_IRONLY"
+check plugin_test_1.err "two_file_test_1.o.syms: _Z2t2v: PREVAILING_DEF_REG"
+check plugin_test_1.err "two_file_test_1.o.syms: v2: RESOLVED_IR"
+check plugin_test_1.err "two_file_test_1.o.syms: t17data: RESOLVED_IR"
+check plugin_test_1.err "two_file_test_2.o.syms: _Z4f13iv: PREEMPTED_IR"
 check plugin_test_1.err "two_file_test_1.o: adding new input file"
 check plugin_test_1.err "two_file_test_1b.o: adding new input file"
 check plugin_test_1.err "two_file_test_2.o: adding new input file"
diff --git a/gold/testsuite/plugin_test_11.sh b/gold/testsuite/plugin_test_11.sh
new file mode 100755
index 0000000..4e1057a
--- /dev/null
+++ b/gold/testsuite/plugin_test_11.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+# plugin_test_11.sh -- a test case for the plugin API.
+
+# Copyright (C) 2008-2015 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+# This file goes with plugin_test_1.c, a simple plug-in library that
+# exercises the basic interfaces and prints out version numbers and
+# options passed to the plugin.
+
+check()
+{
+    if ! grep -q "$2" "$1"
+    then
+	echo "Did not find expected output in $1:"
+	echo "   $2"
+	echo ""
+	echo "Actual output below:"
+	cat "$1"
+	exit 1
+    fi
+}
+
+check plugin_test_11.err "API version:"
+check plugin_test_11.err "gold version:"
+check plugin_test_11.err "option: _Z4f13iv"
+check plugin_test_11.err "two_file_test_main.o: claim file hook called"
+check plugin_test_11.err "two_file_test_1.o: claim file hook called"
+check plugin_test_11.err "two_file_test_1b.o: claim file hook called"
+check plugin_test_11.err "two_file_test_2.o: claim file hook called"
+check plugin_test_11.err "two_file_test_1.o: _Z4f13iv: PREVAILING_DEF_IRONLY"
+check plugin_test_11.err "two_file_test_1.o: _Z2t2v: PREVAILING_DEF_REG"
+check plugin_test_11.err "two_file_test_1.o: v2: RESOLVED_IR"
+check plugin_test_11.err "two_file_test_1.o: t17data: RESOLVED_IR"
+check plugin_test_11.err "two_file_test_2.o: _Z4f13iv: PREEMPTED_IR"
+check plugin_test_11.err "two_file_test_1.o: adding new input file"
+check plugin_test_11.err "two_file_test_1b.o: adding new input file"
+check plugin_test_11.err "two_file_test_2.o: adding new input file"
+check plugin_test_11.err "cleanup hook called"
+
+exit 0
diff --git a/gold/testsuite/plugin_test_2.sh b/gold/testsuite/plugin_test_2.sh
index 5dffab2..cb8c71c 100755
--- a/gold/testsuite/plugin_test_2.sh
+++ b/gold/testsuite/plugin_test_2.sh
@@ -42,13 +42,13 @@ check()
 check plugin_test_2.err "API version:"
 check plugin_test_2.err "gold version:"
 check plugin_test_2.err "two_file_test_main.o: claim file hook called"
-check plugin_test_2.err "two_file_test_1.syms: claim file hook called"
-check plugin_test_2.err "two_file_test_1b.syms: claim file hook called"
+check plugin_test_2.err "two_file_test_1.o.syms: claim file hook called"
+check plugin_test_2.err "two_file_test_1b.o.syms: claim file hook called"
 check plugin_test_2.err "two_file_shared_2.so: claim file hook called"
-check plugin_test_2.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY_EXP"
-check plugin_test_2.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG"
-check plugin_test_2.err "two_file_test_1.syms: v2: RESOLVED_DYN"
-check plugin_test_2.err "two_file_test_1.syms: t17data: RESOLVED_DYN"
+check plugin_test_2.err "two_file_test_1.o.syms: _Z4f13iv: PREVAILING_DEF_IRONLY_EXP"
+check plugin_test_2.err "two_file_test_1.o.syms: _Z2t2v: PREVAILING_DEF_REG"
+check plugin_test_2.err "two_file_test_1.o.syms: v2: RESOLVED_DYN"
+check plugin_test_2.err "two_file_test_1.o.syms: t17data: RESOLVED_DYN"
 check plugin_test_2.err "two_file_test_1.o: adding new input file"
 check plugin_test_2.err "two_file_test_1b.o: adding new input file"
 check plugin_test_2.err "cleanup hook called"
diff --git a/gold/testsuite/plugin_test_3.sh b/gold/testsuite/plugin_test_3.sh
index 203c86b..c61a662 100755
--- a/gold/testsuite/plugin_test_3.sh
+++ b/gold/testsuite/plugin_test_3.sh
@@ -43,14 +43,14 @@ check plugin_test_3.err "API version:"
 check plugin_test_3.err "gold version:"
 check plugin_test_3.err "option: _Z4f13iv"
 check plugin_test_3.err "two_file_test_main.o: claim file hook called"
-check plugin_test_3.err "two_file_test_1.syms: claim file hook called"
-check plugin_test_3.err "two_file_test_1b.syms: claim file hook called"
-check plugin_test_3.err "two_file_test_2.syms: claim file hook called"
-check plugin_test_3.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY_EXP"
-check plugin_test_3.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG"
-check plugin_test_3.err "two_file_test_1.syms: v2: RESOLVED_IR"
-check plugin_test_3.err "two_file_test_1.syms: t17data: RESOLVED_IR"
-check plugin_test_3.err "two_file_test_2.syms: _Z4f13iv: PREEMPTED_IR"
+check plugin_test_3.err "two_file_test_1.o.syms: claim file hook called"
+check plugin_test_3.err "two_file_test_1b.o.syms: claim file hook called"
+check plugin_test_3.err "two_file_test_2.o.syms: claim file hook called"
+check plugin_test_3.err "two_file_test_1.o.syms: _Z4f13iv: PREVAILING_DEF_IRONLY_EXP"
+check plugin_test_3.err "two_file_test_1.o.syms: _Z2t2v: PREVAILING_DEF_REG"
+check plugin_test_3.err "two_file_test_1.o.syms: v2: RESOLVED_IR"
+check plugin_test_3.err "two_file_test_1.o.syms: t17data: RESOLVED_IR"
+check plugin_test_3.err "two_file_test_2.o.syms: _Z4f13iv: PREEMPTED_IR"
 check plugin_test_3.err "two_file_test_1.o: adding new input file"
 check plugin_test_3.err "two_file_test_1b.o: adding new input file"
 check plugin_test_3.err "two_file_test_2.o: adding new input file"
diff --git a/gold/testsuite/plugin_test_6.sh b/gold/testsuite/plugin_test_6.sh
index f15db1b..b81ef3e 100755
--- a/gold/testsuite/plugin_test_6.sh
+++ b/gold/testsuite/plugin_test_6.sh
@@ -41,18 +41,18 @@ check()
 
 check plugin_test_6.err "API version:"
 check plugin_test_6.err "gold version:"
-check plugin_test_6.err "plugin_common_test_1.syms: claim file hook called"
-check plugin_test_6.err "plugin_common_test_2.syms: claim file hook called"
-check plugin_test_6.err "plugin_common_test_1.syms: c1: PREVAILING_DEF_IRONLY"
-check plugin_test_6.err "plugin_common_test_1.syms: c2: PREVAILING_DEF_IRONLY"
-check plugin_test_6.err "plugin_common_test_1.syms: c3: RESOLVED_IR"
-check plugin_test_6.err "plugin_common_test_1.syms: c4: RESOLVED_IR"
-check plugin_test_6.err "plugin_common_test_1.syms: c5: PREVAILING_DEF_IRONLY"
-check plugin_test_6.err "plugin_common_test_2.syms: c1: RESOLVED_IR"
-check plugin_test_6.err "plugin_common_test_2.syms: c2: RESOLVED_IR"
-check plugin_test_6.err "plugin_common_test_2.syms: c3: PREVAILING_DEF_IRONLY"
-check plugin_test_6.err "plugin_common_test_2.syms: c4: PREVAILING_DEF_IRONLY"
-check plugin_test_6.err "plugin_common_test_2.syms: c5: RESOLVED_IR"
+check plugin_test_6.err "plugin_common_test_1.o.syms: claim file hook called"
+check plugin_test_6.err "plugin_common_test_2.o.syms: claim file hook called"
+check plugin_test_6.err "plugin_common_test_1.o.syms: c1: PREVAILING_DEF_IRONLY"
+check plugin_test_6.err "plugin_common_test_1.o.syms: c2: PREVAILING_DEF_IRONLY"
+check plugin_test_6.err "plugin_common_test_1.o.syms: c3: RESOLVED_IR"
+check plugin_test_6.err "plugin_common_test_1.o.syms: c4: RESOLVED_IR"
+check plugin_test_6.err "plugin_common_test_1.o.syms: c5: PREVAILING_DEF_IRONLY"
+check plugin_test_6.err "plugin_common_test_2.o.syms: c1: RESOLVED_IR"
+check plugin_test_6.err "plugin_common_test_2.o.syms: c2: RESOLVED_IR"
+check plugin_test_6.err "plugin_common_test_2.o.syms: c3: PREVAILING_DEF_IRONLY"
+check plugin_test_6.err "plugin_common_test_2.o.syms: c4: PREVAILING_DEF_IRONLY"
+check plugin_test_6.err "plugin_common_test_2.o.syms: c5: RESOLVED_IR"
 check plugin_test_6.err "cleanup hook called"
 
 exit 0
diff --git a/gold/testsuite/plugin_test_tls.sh b/gold/testsuite/plugin_test_tls.sh
index 594f8f5..9873f2e 100755
--- a/gold/testsuite/plugin_test_tls.sh
+++ b/gold/testsuite/plugin_test_tls.sh
@@ -43,15 +43,15 @@ check plugin_test_tls.err "API version:"
 check plugin_test_tls.err "gold version:"
 check plugin_test_tls.err "option: _Z4f13iv"
 check plugin_test_tls.err "two_file_test_tls.o: claim file hook called"
-check plugin_test_tls.err "two_file_test_1.syms: claim file hook called"
-check plugin_test_tls.err "two_file_test_1b.syms: claim file hook called"
-check plugin_test_tls.err "two_file_test_2_tls.syms: claim file hook called"
-check plugin_test_tls.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY"
-check plugin_test_tls.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG"
-check plugin_test_tls.err "two_file_test_1.syms: v2: RESOLVED_IR"
-check plugin_test_tls.err "two_file_test_1.syms: t17data: RESOLVED_IR"
-check plugin_test_tls.err "two_file_test_2_tls.syms: _Z4f13iv: PREEMPTED_IR"
-check plugin_test_tls.err "two_file_test_2_tls.syms: tls1: PREVAILING_DEF_REG"
+check plugin_test_tls.err "two_file_test_1.o.syms: claim file hook called"
+check plugin_test_tls.err "two_file_test_1b.o.syms: claim file hook called"
+check plugin_test_tls.err "two_file_test_2_tls.o.syms: claim file hook called"
+check plugin_test_tls.err "two_file_test_1.o.syms: _Z4f13iv: PREVAILING_DEF_IRONLY"
+check plugin_test_tls.err "two_file_test_1.o.syms: _Z2t2v: PREVAILING_DEF_REG"
+check plugin_test_tls.err "two_file_test_1.o.syms: v2: RESOLVED_IR"
+check plugin_test_tls.err "two_file_test_1.o.syms: t17data: RESOLVED_IR"
+check plugin_test_tls.err "two_file_test_2_tls.o.syms: _Z4f13iv: PREEMPTED_IR"
+check plugin_test_tls.err "two_file_test_2_tls.o.syms: tls1: PREVAILING_DEF_REG"
 check plugin_test_tls.err "two_file_test_1.o: adding new input file"
 check plugin_test_tls.err "two_file_test_1b.o: adding new input file"
 check plugin_test_tls.err "two_file_test_2_tls.o: adding new input file"


More information about the Binutils mailing list