[cfe-dev] [MinGW] Clang issues with static libstdc++

Reid Kleckner via cfe-dev cfe-dev at lists.llvm.org
Mon Apr 17 11:56:21 PDT 2017


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 <
cfe-dev at lists.llvm.org> 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
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170417/345ea95b/attachment.html>


More information about the cfe-dev mailing list