https://sourceware.org/bugzilla/show_bug.cgi?id=19842
Cary Coutant <ccoutant at gmail dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |ASSIGNED --- Comment #4 from Cary Coutant <ccoutant at gmail dot com> --- The std::function destructor is defined as a pair of comdat symbols in SystemExit.o (compiled with LTO): SYMBOLS: 82 out/haswell/main/SystemExit.o 0: WD D _ZNSt8functionIFvvEED2Ev [comdat: _ZNSt8functionIFvvEED5Ev] 1: WD D _ZNSt8functionIFvvEED1Ev [comdat: _ZNSt8functionIFvvEED5Ev] and also in Server.cpp.o (not compiled with LTO): 2096: 0000000000000000 27 FUNC WEAK DEFAULT 846 _ZNSt8functionIFvvEED2Ev 2097: 0000000000000000 27 FUNC WEAK DEFAULT 846 _ZNSt8functionIFvvEED1Ev These are also declared in the _ZNSt8functionIFvvEED5Ev comdat group. (Because the D1 and D2 destructors are the same for this case, the two symbols are simply aliased to each other.) The call from std::_List_node<std::function<void ()> >::~_List_node() is to the D1 destructor: Relocation section '.rela.text._ZNSt10_List_nodeISt8functionIFvvEEED2Ev' at offset 0x1446b0 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000018 0000083100000004 R_X86_64_PLT32 0000000000000000 _ZNSt8functionIFvvEED1Ev - 4 When processing SystemExit.o, the plugin claims it, and provides those two symbols to the linker. This is the first instance of a _ZNSt8functionIFvvEED5Ev comdat group, so the linker treats this as the "kept" group. When we later see Server.cpp.o, we discard its copy of that comdat group, and the reference to the destructor is expected to resolve to the earlier definition. When the LTO plugin is ready to generate final code, it asks the linker for the status of those two symbols, and is told (via the -lm.res file): out/haswell/main/SystemExit.o 82 10879 24ebb94a838bed5c PREVAILING_DEF _ZNSt8functionIFvvEED2Ev 10842 24ebb94a838bed5c PREVAILING_DEF _ZNSt8functionIFvvEED1Ev PREVAILING_DEF indicates that the IR contains a prevailing definition of the symbol, but that there are references to that symbol from outside the set of IR code (i.e., from Server.cpp.o). That tells the plugin that the compiler must generate a global definition of those symbols. (If there were no other references to the symbol, the resolution would have been PREVAILING_DEF_IRONLY. That would have allowed the compiler to generate a local definition.) But when the compiler sends back the generated file hippo.ltrans1.ltrans.o, it has defined these symbols as local: 30: 0000000000000270 33 FUNC LOCAL DEFAULT 1 _ZNSt8functionIFvvEED2Ev 32: 0000000000000270 33 FUNC LOCAL DEFAULT 1 _ZNSt8functionIFvvEED1Ev As a result, the "placeholder" symbols that the linker has kept remain undefined, and we end up resolving the reference from Server.cpp.o to 0. Gold should not be silently resolving this symbol to 0 -- instead, it should diagnose the compiler's failure to provide the expected definition and print an error message. I don't know how or why Gnu ld is resolving the symbol; I would expect the same behavior from it. So it looks to me (at the moment, at least) like this is a GCC bug. I'll try to come up with a simple test case, but it's often hard to reproduce the exact set of conditions that cause the optimizer to make a particular decision. It's possible this has been fixed since GCC 5.2 -- have you tried a newer GCC? -cary -- You are receiving this mail because: You are on the CC list for the bug. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org https://lists.gnu.org/mailman/listinfo/bug-binutils