[MinGW] Clang issues with static libstdc++

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[MinGW] Clang issues with static libstdc++

Xin Wang via cfe-dev

Clang doesn't work very well with static libstdc++ build for MinGW resulting in "multiple definition ..." or "undefined reference" to the symbols.

Let's consider following code (removed includes and main for readability):

  1. multiple definition:

    std::string a = "a";
    std::string b = '@' + a;

    This simple code build with `-static` flag will cause this error:

    D:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\6.3.0\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): multiple definition of `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
    D:\msys64\tmp\string-e39e30.o:(.text[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): first defined here
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

  2. undefined reference

    std::u16string b;

    This time adding `-static` to clang arguments will cause this error (note: `__imp___cxa_call_unexpected` exists only in dynamic libstdc++):

    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEED2Ev]+0x4a): undefined reference to `__imp___cxa_call_unexpected'
    D:\msys64\tmp\string-7062fd.o:(.text[__clang_call_terminate]+0x7): undefined reference to `__imp___cxa_begin_catch'
    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEE10_M_destroyEy]+0x72): undefined reference to `__imp___cxa_call_unexpected'
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

It is probably related to the way the symbols are build into static libstdc++ for MinGW.
Let's take a look at weak symbol from different test cases:

  1. MinGW, dynamic libstdc++:
    0000000000000000 I __imp__ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  2. MinGW, static libstdc++:
    0000000000000000 p .pdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 t .text$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 r .xdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  3. Linux, static libstdc++:
    0000000000000000 W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

This greatly reduces Clang usefulness on Windows with MinGW.
All responses are welcome.

Best Regards,
Mateusz


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [MinGW] Clang issues with static libstdc++

Xin Wang via cfe-dev
The __imp___cxa_begin_catch error seems related to this code in CodeGenModule::CreateRuntimeFunction:
      if (!Local && getTriple().isOSBinFormatCOFF() &&
          !getCodeGenOpts().LTOVisibilityPublicStd) {
        const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
        if (!FD || FD->hasAttr<DLLImportAttr>()) {
          F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
          F->setLinkage(llvm::GlobalValue::ExternalLinkage);
        }
      }

This code assumes that all compiler-referenced runtime functions on COFF are dllimport, unless we happen to see a prototype for them during compilation that says otherwise. Saleem felt we shouldn't rely on the import thunks that the linker generates when you reference an imported function but forget to declare it as dllimport during compilation. It has some performance benefits, but it never really bothered me. Most users don't complain about the extra absolute branch imposed by the PLT on ELF, and those that do are getting -fno-plt soon.

Anyway, you can see the code difference easily here:

$ cat t.cpp
void g();
void f() {
  try {
    g();
  } catch (...) {
  }
}

$ clang -O1 -S t.cpp --target=x86_64-windows-gnu -o - | grep __cxa
        callq   *__imp___cxa_begin_catch(%rip)
        rex64 jmpq      *__imp___cxa_end_catch(%rip) # TAILCALL

$ gcc -O1 -S t.cpp -o - | grep __cxa
        call    __cxa_begin_catch
        call    __cxa_end_catch
        .def    __cxa_begin_catch;      .scl    2;      .type   32;     .endef
        .def    __cxa_end_catch;        .scl    2;      .type   32;     .endef

The other error looks like some kind of COMDAT disagreement between GCC and Clang that will require further investigation. It might relate to our choice to stop using ".text$function_name" for the section.

On Mon, Apr 17, 2017 at 11:06 AM, Mateusz Mikuła via cfe-dev <[hidden email]> wrote:

Clang doesn't work very well with static libstdc++ build for MinGW resulting in "multiple definition ..." or "undefined reference" to the symbols.

Let's consider following code (removed includes and main for readability):

  1. multiple definition:

    std::string a = "a";
    std::string b = '@' + a;

    This simple code build with `-static` flag will cause this error:

    D:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\6.3.0\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): multiple definition of `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
    D:\msys64\tmp\string-e39e30.o:(.text[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): first defined here
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

  2. undefined reference

    std::u16string b;

    This time adding `-static` to clang arguments will cause this error (note: `__imp___cxa_call_unexpected` exists only in dynamic libstdc++):

    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEED2Ev]+0x4a): undefined reference to `__imp___cxa_call_unexpected'
    D:\msys64\tmp\string-7062fd.o:(.text[__clang_call_terminate]+0x7): undefined reference to `__imp___cxa_begin_catch'
    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEE10_M_destroyEy]+0x72): undefined reference to `__imp___cxa_call_unexpected'
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

It is probably related to the way the symbols are build into static libstdc++ for MinGW.
Let's take a look at weak symbol from different test cases:

  1. MinGW, dynamic libstdc++:
    0000000000000000 I __imp__ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  2. MinGW, static libstdc++:
    0000000000000000 p .pdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 t .text$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 r .xdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  3. Linux, static libstdc++:
    0000000000000000 W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

This greatly reduces Clang usefulness on Windows with MinGW.
All responses are welcome.

Best Regards,
Mateusz


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [MinGW] Clang issues with static libstdc++

Xin Wang via cfe-dev
I've been quite busy lately and lost track on recent fixes.
Is there any progress on this or should I apply for bugzilla account and forward it there?

On Mon, 2017-04-17 at 11∶56 -0700, Reid Kleckner wrote:
The __imp___cxa_begin_catch error seems related to this code in CodeGenModule::CreateRuntimeFunction:
      if (!Local && getTriple().isOSBinFormatCOFF() &&
          !getCodeGenOpts().LTOVisibilityPublicStd) {
        const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
        if (!FD || FD->hasAttr<DLLImportAttr>()) {
          F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
          F->setLinkage(llvm::GlobalValue::ExternalLinkage);
        }
      }

This code assumes that all compiler-referenced runtime functions on COFF are dllimport, unless we happen to see a prototype for them during compilation that says otherwise. Saleem felt we shouldn't rely on the import thunks that the linker generates when you reference an imported function but forget to declare it as dllimport during compilation. It has some performance benefits, but it never really bothered me. Most users don't complain about the extra absolute branch imposed by the PLT on ELF, and those that do are getting -fno-plt soon.

Anyway, you can see the code difference easily here:

$ cat t.cpp
void g();
void f() {
  try {
    g();
  } catch (...) {
  }
}

$ clang -O1 -S t.cpp --target=x86_64-windows-gnu -o - | grep __cxa
        callq   *__imp___cxa_begin_catch(%rip)
        rex64 jmpq      *__imp___cxa_end_catch(%rip) # TAILCALL

$ gcc -O1 -S t.cpp -o - | grep __cxa
        call    __cxa_begin_catch
        call    __cxa_end_catch
        .def    __cxa_begin_catch;      .scl    2;      .type   32;     .endef
        .def    __cxa_end_catch;        .scl    2;      .type   32;     .endef

The other error looks like some kind of COMDAT disagreement between GCC and Clang that will require further investigation. It might relate to our choice to stop using ".text$function_name" for the section.

On Mon, Apr 17, 2017 at 11:06 AM, Mateusz Mikuła via cfe-dev <[hidden email]> wrote:

Clang doesn't work very well with static libstdc++ build for MinGW resulting in "multiple definition ..." or "undefined reference" to the symbols.

Let's consider following code (removed includes and main for readability):

  1. multiple definition:

    std::string a = "a";
    std::string b = '@' + a;

    This simple code build with `-static` flag will cause this error:

    D:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\6.3.0\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): multiple definition of `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
    D:\msys64\tmp\string-e39e30.o:(.text[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): first defined here
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

  2. undefined reference

    std::u16string b;

    This time adding `-static` to clang arguments will cause this error (note: `__imp___cxa_call_unexpected` exists only in dynamic libstdc++):

    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEED2Ev]+0x4a): undefined reference to `__imp___cxa_call_unexpected'
    D:\msys64\tmp\string-7062fd.o:(.text[__clang_call_terminate]+0x7): undefined reference to `__imp___cxa_begin_catch'
    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEE10_M_destroyEy]+0x72): undefined reference to `__imp___cxa_call_unexpected'
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

It is probably related to the way the symbols are build into static libstdc++ for MinGW.
Let's take a look at weak symbol from different test cases:

  1. MinGW, dynamic libstdc++:
    0000000000000000 I __imp__ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  2. MinGW, static libstdc++:
    0000000000000000 p .pdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 t .text$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 r .xdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  3. Linux, static libstdc++:
    0000000000000000 W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

This greatly reduces Clang usefulness on Windows with MinGW.
All responses are welcome.

Best Regards,
Mateusz


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [MinGW] Clang issues with static libstdc++

Xin Wang via cfe-dev
Building with `-flto-visibility-public-std` should allow the static build to work.  I think that having support for a static c++ library makes sense, but need to expose it through a flag to have it behave like `/MT` vs `/MD`.

There is a small performance cost for the thunks, plus binary size benefits for very large binaries (especially with the BFD linker).  IIRC, some versions of lldb also had trouble with the import thunks when generated by the BFD linker.  I would rather have this be the default and have an opt-out mechanism rather than the inverse (a la `-fno-plt`).

On Sun, Jun 25, 2017 at 1:20 PM, Mateusz Mikuła <[hidden email]> wrote:
I've been quite busy lately and lost track on recent fixes.
Is there any progress on this or should I apply for bugzilla account and forward it there?

On Mon, 2017-04-17 at 11∶56 -0700, Reid Kleckner wrote:
The __imp___cxa_begin_catch error seems related to this code in CodeGenModule::CreateRuntimeFunction:
      if (!Local && getTriple().isOSBinFormatCOFF() &&
          !getCodeGenOpts().LTOVisibilityPublicStd) {
        const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
        if (!FD || FD->hasAttr<DLLImportAttr>()) {
          F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
          F->setLinkage(llvm::GlobalValue::ExternalLinkage);
        }
      }

This code assumes that all compiler-referenced runtime functions on COFF are dllimport, unless we happen to see a prototype for them during compilation that says otherwise. Saleem felt we shouldn't rely on the import thunks that the linker generates when you reference an imported function but forget to declare it as dllimport during compilation. It has some performance benefits, but it never really bothered me. Most users don't complain about the extra absolute branch imposed by the PLT on ELF, and those that do are getting -fno-plt soon.

Anyway, you can see the code difference easily here:

$ cat t.cpp
void g();
void f() {
  try {
    g();
  } catch (...) {
  }
}

$ clang -O1 -S t.cpp --target=x86_64-windows-gnu -o - | grep __cxa
        callq   *__imp___cxa_begin_catch(%rip)
        rex64 jmpq      *__imp___cxa_end_catch(%rip) # TAILCALL

$ gcc -O1 -S t.cpp -o - | grep __cxa
        call    __cxa_begin_catch
        call    __cxa_end_catch
        .def    __cxa_begin_catch;      .scl    2;      .type   32;     .endef
        .def    __cxa_end_catch;        .scl    2;      .type   32;     .endef

The other error looks like some kind of COMDAT disagreement between GCC and Clang that will require further investigation. It might relate to our choice to stop using ".text$function_name" for the section.

On Mon, Apr 17, 2017 at 11:06 AM, Mateusz Mikuła via cfe-dev <[hidden email]> wrote:

Clang doesn't work very well with static libstdc++ build for MinGW resulting in "multiple definition ..." or "undefined reference" to the symbols.

Let's consider following code (removed includes and main for readability):

  1. multiple definition:

    std::string a = "a";
    std::string b = '@' + a;

    This simple code build with `-static` flag will cause this error:

    D:\msys64\mingw64\lib\gcc\x86_64-w64-mingw32\6.3.0\libstdc++.a(string-inst.o):(.text$_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): multiple definition of `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
    D:\msys64\tmp\string-e39e30.o:(.text[_ZStplIcSt11char_traitsIcESaIcEENSt7__cxx1112basic_stringIT_T0_T1_EES5_RKS8_]+0x0): first defined here
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

  2. undefined reference

    std::u16string b;

    This time adding `-static` to clang arguments will cause this error (note: `__imp___cxa_call_unexpected` exists only in dynamic libstdc++):

    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEED2Ev]+0x4a): undefined reference to `__imp___cxa_call_unexpected'
    D:\msys64\tmp\string-7062fd.o:(.text[__clang_call_terminate]+0x7): undefined reference to `__imp___cxa_begin_catch'
    D:\msys64\tmp\string-7062fd.o:(.text[_ZNSt7__cxx1112basic_stringIDsSt11char_traitsIDsESaIDsEE10_M_destroyEy]+0x72): undefined reference to `__imp___cxa_call_unexpected'
    clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation)

It is probably related to the way the symbols are build into static libstdc++ for MinGW.
Let's take a look at weak symbol from different test cases:

  1. MinGW, dynamic libstdc++:
    0000000000000000 I __imp__ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  2. MinGW, static libstdc++:
    0000000000000000 p .pdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 t .text$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 r .xdata$_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag
    0000000000000000 T _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

  3. Linux, static libstdc++:
    0000000000000000 W _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag

This greatly reduces Clang usefulness on Windows with MinGW.
All responses are welcome.

Best Regards,
Mateusz


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev





--
Saleem Abdulrasool
compnerd (at) compnerd (dot) org

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Loading...