Fix problem where gold fails to issue an undefined symbol error during LTO. During LTO, if (1) an IR file contains a COMDAT group that is kept, (2) a later non-claimed file contains the same group, which we discard, and (3) the plugin fails to provide a definition of the symbols in that COMDAT group, gold silently resolves any references to those symbols to 0. This patch adds a check for a placeholder symbol when deciding whether to issue an undefined symbol error. It also adds an extra note after any undefined placeholder symbol error that explains that a definition was expected from the plugin. 2016-03-21 Cary Coutant gold/ PR gold/19842 * errors.cc (Errors::undefined_symbol): Add info message when symbol should have been provided by a plugin. * target-reloc.h (issue_undefined_symbol_error): Check for placeholder symbols defined in discarded sections. * testsuite/Makefile.am (plugin_test_9b): New test case. * testsuite/Makefile.in: Regenerate. * testsuite/plugin_test_9b_elf.cc: New test source file. * testsuite/plugin_test_9b_ir.cc: New test source file. diff --git a/gold/errors.cc b/gold/errors.cc index f90e53f..27392cc 100644 --- a/gold/errors.cc +++ b/gold/errors.cc @@ -198,6 +198,9 @@ Errors::undefined_symbol(const Symbol* sym, const std::string& location) gold_info(_("%s: the vtable symbol may be undefined because " "the class is missing its key function"), program_name); + if (sym->is_placeholder()) + gold_info(_("%s: the symbol should have been defined by a plugin"), + program_name); } // Issue a debugging message. diff --git a/gold/target-reloc.h b/gold/target-reloc.h index bdf673d..e275d33 100644 --- a/gold/target-reloc.h +++ b/gold/target-reloc.h @@ -186,8 +186,10 @@ issue_undefined_symbol_error(const Symbol* sym) if (sym->is_weak_undefined()) return false; - // We don't report symbols defined in discarded sections. - if (sym->is_defined_in_discarded_section()) + // We don't report symbols defined in discarded sections, + // unless they're placeholder symbols that should have been + // provided by a plugin. + if (sym->is_defined_in_discarded_section() && !sym->is_placeholder()) return false; // If the target defines this symbol, don't report it here. diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index fbaee16..bf222c3 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -2015,6 +2015,25 @@ MOSTLYCLEANFILES += two_file_test_1c.o two_file_test_1c.o: two_file_test_1.o cp two_file_test_1.o $@ +# As above, but check COMDAT case, where a non-IR file contains a duplicate +# of a COMDAT group in an IR file. +check_DATA += plugin_test_9b.err +MOSTLYCLEANFILES += plugin_test_9b.err +plugin_test_9b.err: plugin_test_9b_ir.o.syms plugin_test_9b_ir.o plugin_test_9b_elf.o gcctestdir/ld plugin_test.so + @echo $(CXXLINK) -Bgcctestdir/ -o plugin_test_9b -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_ZN1A5printEv" plugin_test_9b_ir.o plugin_test_9b_elf.o "2>$@" + @if $(CXXLINK) -Bgcctestdir/ -o plugin_test_9b -Wl,--no-demangle,--plugin,"./plugin_test.so",--plugin-opt,"_ZN1A5printEv" plugin_test_9b_ir.o plugin_test_9b_elf.o 2>$@; then \ + echo 1>&2 "Link of plugin_test_9b should have failed"; \ + rm -f $@; \ + exit 1; \ + fi +# Make a .syms file that claims to define a method in class A in a COMDAT group. +# The real plugin_test_9b_ir.o will be compiled without the -D, and will not +# define any methods in class A. +plugin_test_9b_ir.o.syms: plugin_test_9b_ir_witha.o + $(TEST_READELF) -sW $< >$@ 2>/dev/null +plugin_test_9b_ir_witha.o: plugin_test_9b_ir.cc + $(CXXCOMPILE) -c -DUSE_CLASS_A -o $@ $< + check_PROGRAMS += plugin_test_10 check_SCRIPTS += plugin_test_10.sh check_DATA += plugin_test_10.sections