Given following C++ source code: test.cpp: #include <typeinfo> class A { }; int #ifndef LTO foo() #else bar() #endif { return typeid(A).hash_code(); } If compiled twice using following commands with g++ with the x86_64-w64-mingw32 target: g++ -c test.cpp -o test1.o g++ -c test.cpp -DLTO -flto -fno-fat-lto-objects -o test2.o And then attempted to be linked together using: g++ -shared test1.o test2.o yields following linker errors: c:/gcc/bin/../lib/gcc/x86_64-w64-mingw32/10/../../../../x86_64-w64-mingw32/bin/ld.exe: test2.o (symbol from plugin):(.gnu.linkonce.t._ZNKSt9type_info4nameEv+0x0): multiple definition of `std::type_info::name() const'; test1.o:test.cpp:(.text$_ZNKSt9type_info4nameEv[_ZNKSt9type_info4nameEv]+0x0): first defined here c:/gcc/bin/../lib/gcc/x86_64-w64-mingw32/10/../../../../x86_64-w64-mingw32/bin/ld.exe: test2.o (symbol from plugin):(.gnu.linkonce.t._ZNKSt9type_info9hash_codeEv+0x0): multiple definition of `std::type_info::hash_code() const'; test1.o:test.cpp:(.text$_ZNKSt9type_info9hash_codeEv[_ZNKSt9type_info9hash_codeEv]+0x0): first defined here c:/gcc/bin/../lib/gcc/x86_64-w64-mingw32/10/../../../../x86_64-w64-mingw32/bin/ld.exe: test2.o (symbol from plugin):(.gnu.linkonce.t._ZTI1A+0x0): multiple definition of `typeinfo for A'; test1.o:test.cpp:(.rdata$_ZTI1A[_ZTI1A]+0x0): first defined here c:/gcc/bin/../lib/gcc/x86_64-w64-mingw32/10/../../../../x86_64-w64-mingw32/bin/ld.exe: test2.o (symbol from plugin):(.gnu.linkonce.t._ZTS1A+0x0): multiple definition of `typeinfo name for A'; test1.o:test.cpp:(.rdata$_ZTS1A[_ZTS1A]+0x0): first defined here collect2.exe: error: ld returned 1 exit status Failed to reproduce this issue with a linux target GCC version used was from the GCC 10 Branch at revision d73846862b5e4cd381bb43024efdcbf6bd61e888 and binutils trunk at revision 33d1369f183f1c276e3f0f52b5573fb2f5843b1c nm output of test1.o: 0000000000000000 b .bss 0000000000000000 d .data 0000000000000000 p .pdata 0000000000000000 p .pdata$_ZNKSt9type_info4nameEv 0000000000000000 p .pdata$_ZNKSt9type_info9hash_codeEv 0000000000000000 r .rdata$_ZTI1A 0000000000000000 r .rdata$_ZTS1A 0000000000000000 r .rdata$zzz 0000000000000000 t .text 0000000000000000 t .text$_ZNKSt9type_info4nameEv 0000000000000000 t .text$_ZNKSt9type_info9hash_codeEv 0000000000000000 r .xdata 0000000000000000 r .xdata$_ZNKSt9type_info4nameEv 0000000000000000 r .xdata$_ZNKSt9type_info9hash_codeEv U __gxx_personality_seh0 0000000000000000 T _Z3foov 0000000000000000 T _ZNKSt9type_info4nameEv 0000000000000000 T _ZNKSt9type_info9hash_codeEv U _ZSt11_Hash_bytesPKvyy 0000000000000000 R _ZTI1A 0000000000000000 R _ZTS1A U _ZTVN10__cxxabiv117__class_type_infoE U strlen gcc-nm output of test2.o: U __gxx_personality_seh0 00000000 T _Z3barv 00000000 T _ZNKSt9type_info4nameEv 00000000 T _ZNKSt9type_info9hash_codeEv U _ZSt11_Hash_bytesPKvyy 00000000 D _ZTI1A 00000000 D _ZTS1A U _ZTVN10__cxxabiv117__class_type_infoE
(In reply to Markus Böck from comment #0) Hi Markus, > c:/gcc/bin/../lib/gcc/x86_64-w64-mingw32/10/../../../../x86_64-w64-mingw32/ > bin/ld.exe: test2.o (symbol from > plugin):(.gnu.linkonce.t._ZNKSt9type_info4nameEv+0x0): multiple definition > of `std::type_info::name() const'; > test1.o:test.cpp:(. > Failed to reproduce this issue with a linux target I think that this might be a compiler issue, rather than an assembler issue... > nm output of test1.o: > 0000000000000000 T _ZNKSt9type_info4nameEv > 0000000000000000 T _ZNKSt9type_info9hash_codeEv > gcc-nm output of test2.o: > 00000000 T _ZNKSt9type_info4nameEv > 00000000 T _ZNKSt9type_info9hash_codeEv Using gcc v9 on an x86_64 linux box to compile the test I found that those symbols are declared as weak: % gcc-nm test1.o [...] 0000000000000000 W _ZNKSt9type_info4nameEv 0000000000000000 W _ZNKSt9type_info9hash_codeEv % gcc-nm test2.o [...] 00000000 W _ZNKSt9type_info4nameEv 00000000 W _ZNKSt9type_info9hash_codeEv Which explains why it works for me. My guess is that gcc thinks that it cannot generate weak symbols for the COFF/PE environment of Mingw, or something along those lines. Perhaps you can investigate the output from your gcc to see if this guess is correct ? Cheers Nick
I posted a patch on the mailing list that should resolve this issue. The problem was how comdat between a native object and a LTO object was handled. When the LTO object was linked first and had a symbol in its gnu.linkonce section it correctly merged it with the comdat of the same symbol from a native object file. Yet when the LTO symbol was linked second it did not.
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e8a83e931e09357437c29093ffeeab2afc79ad5c commit e8a83e931e09357437c29093ffeeab2afc79ad5c Author: Markus Böck <markus.boeck02@gmail.com> Date: Wed Jul 15 08:31:30 2020 +0930 PR26198 MinGW failure to link regular object file and LTO object file PR 26198 * coffgen.c (_bfd_coff_section_already_linked): Allow for plugin objects both before and after normal object files. * elflink.c (_bfd_elf_section_already_linked): Likewise.
Fixed.