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

Saleem Abdulrasool via cfe-dev cfe-dev at lists.llvm.org
Sun Sep 17 09:49:14 PDT 2017


I think that making it conditional to Windows and not the MSVC ABI and a
static link to the C++ runtime sounds reasonable.

On Sun, Sep 17, 2017 at 4:40 AM, Mateusz Mikuła <mati865 at gmail.com> wrote:

> Sorry Saleem, looks like this topic got lost on my TODO.
> Adding `-flto-visibility-public-std` to CC1 helps with undefined reference
> to `_imp___cxa*` errors.
>
> Is it safe enough to make it default flag for MSYS2?
> If so I'll patch clang to use it by default.
>
>
> ------ Original Message ------
> Subject: Re: [cfe-dev] [MinGW] Clang issues with static libstdc++
> Date: Mon, 26 Jun 2017 21:51:19 -0700
> To: Mateusz Mikuła, Reid Kleckner, Cfe-dev
> From: Saleem Abdulrasool
>
> 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 <mati865 at gmail.com> 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::DLLImportStorageCla
>> ss);
>>           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_traitsIcESaIcEENSt
>>    7__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_traits
>>    IcESaIcEENSt7__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_st
>>    ringIDsSt11char_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_st
>>    ringIDsSt11char_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_str
>>    ingIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20f
>>    orward_iterator_tag
>>    0000000000000000 T _ZNSt7__cxx1112basic_stringIcS
>>    t11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward
>>    _iterator_tag
>>
>>    2. MinGW, static libstdc++:
>>    0000000000000000 p .pdata$_ZNSt7__cxx1112basic_st
>>    ringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20
>>    forward_iterator_tag
>>    0000000000000000 t .text$_ZNSt7__cxx1112basic_str
>>    ingIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20f
>>    orward_iterator_tag
>>    0000000000000000 r .xdata$_ZNSt7__cxx1112basic_st
>>    ringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20
>>    forward_iterator_tag
>>    0000000000000000 T _ZNSt7__cxx1112basic_stringIcS
>>    t11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward
>>    _iterator_tag
>>
>>    3. Linux, static libstdc++:
>>    0000000000000000 W _ZNSt7__cxx1112basic_stringIcS
>>    t11char_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
>>
>>
>>
>
>
> --
> Saleem Abdulrasool
> compnerd (at) compnerd (dot) org
>
>
>


-- 
Saleem Abdulrasool
compnerd (at) compnerd (dot) org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170917/755facbe/attachment.html>


More information about the cfe-dev mailing list