Bug 26198 - Failure to merge read only data of machine code object file and LTO object file on MinGW
Summary: Failure to merge read only data of machine code object file and LTO object fi...
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.35
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-07-02 20:25 UTC by Markus Böck
Modified: 2020-07-16 18:38 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Böck 2020-07-02 20:25:47 UTC
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
Comment 1 Nick Clifton 2020-07-09 13:58:22 UTC
(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
Comment 2 Markus Böck 2020-07-10 15:24:59 UTC
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.
Comment 3 Sourceware Commits 2020-07-14 23:02:18 UTC
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.
Comment 4 Markus Böck 2020-07-16 18:38:45 UTC
Fixed.