Menu

#2065 "gcc --shared" links with libgcc_s_dw2-1.dll when using 64-bit division in C

OTHER
upstream
nobody
None
Support
self-service
Behaves_as_Documented
False
2017-01-26
2013-09-26
No

Minimal example function "div50.c":

long long div50(long long value){
    return value/50;
}

Compile this program as a dll, and looking at its dependencies:

$ gcc -shared -o div50.dll div50.c
$ mingw32-objdump -p div50.dll  |grep "DLL Name"
    DLL Name: kernel32.dll
    DLL Name: msvcrt.dll
    DLL Name: libgcc_s_dw2-1.dll

It appears that the __divdi3() function, needed for the
"long long" division, is taken from libgcc_s_dw2-1.dll
in stead of from the static gcc library. This example
does not use any exception handling (it is C, not C++),
so the resulting dll should not depend on libgcc_s_dw2-1.dll.

A workaround is available:

$ gcc -shared -static-libgcc -o div50.dll div50.c
$ mingw32-objdump -p div50.dll  |grep "DLL Name"
    DLL Name: kernel32.dll
    DLL Name: msvcrt.dll

Using -static-libgcc the unwanted dependency is gone.
However, -static-libgcc should be the default when using C already.

Discussion

  • Keith Marshall

    Keith Marshall - 2013-09-26

    However, -static-libgcc should be the default when using C already.

    Not as I read the relevant GCC Online Docs ...

    If GCC finds, at its configuration time, that you have a non-GNU linker or a GNU linker that does not support option --eh-frame-hdr, it links the shared version of libgcc into shared libraries by default.

    Looking onward, to the relevant binutils documentation ...

    --eh-frame-hdr
    Request creation of .eh_frame_hdr section and ELF PT_GNU_EH_FRAME segment header.

    I see a strong inference that --eh-frame-hdr is specific to ELF, and therefore I would not expect it to be supported by Windows' PECOFF format. Therefore, I deduce that GCC will always choose to link with shared libgcc by default, when creating shared libraries on Windows.

     
  • Jan Nijtmans

    Jan Nijtmans - 2013-09-26

    Trying the same with mingw-w64:

    $ i686-w64-mingw32-gcc -shared -o div50.dll div50.c
    $ i686-w64-mingw32-objdump  -p div50.dll  |grep "DLL Name"
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: libgcc_s_sjlj-1.dll
    

    So, it indeed looks like a binutils issue. Mingw-w64 has exactly the same problem.

    Maybe this should be a feature request then: I would not expect this to
    depend on the link format.

     
  • Keith Marshall

    Keith Marshall - 2013-09-26
    • status: unread --> upstream
    • Group: WSL --> OTHER
    • Type: Bug --> Support
    • Resolution: none --> self-service
    • Category: Unknown --> Behaves_as_Documented
     
  • Keith Marshall

    Keith Marshall - 2013-09-26

    I would not expect this to depend on the link format.

    It does seem sort of counter intuitive, but right now it seems to behave as documented. If you want to take it further, I suggest filing a GCC bug -- it hardly seems to be a binutils issue, that GCC makes this choice based on support for an ELF specific feature of the linker.

     
  • Jan Nijtmans

    Jan Nijtmans - 2013-09-27

    The strange thing is that code which doesn't use any exception handling (just a
    64-bit divide in this example) causes libgcc_s_dw2-1.dll to be linked in. Only
    4 functions are affected this way: __divdi3, __moddi3, __udivdi3 and __umoddi3.

    The workaround, using -static-libgcc, is nothing more than a workaround. I
    don't understand why gcc produces calls to dw2-versions of those 4 functions,
    maybe it should generate calls to non-exception-aware versions of those, or
    inline code. That would make me happy as well, and it could be much simpler
    than other solutions.

    I don't know if this bug should be filed for GCC, but it clearly appears
    to be MinGW (x86) only. I tried this example with Win64 (x86_64) as well,
    but no such unexpected function calls are generated: My guess is that
    x86_64 has processor instructions for 64-bit divide.

     

    Last edit: Earnie Boyd 2013-09-27
  • Earnie Boyd

    Earnie Boyd - 2013-09-27

    We're not (and neither is MS) providing those functions so the code is coming from the library provided by GCC.

    I would entertain a patch for inline functions if you wish to provide the code.

     
  • Jason Hood

    Jason Hood - 2017-01-26

    I had this issue when building file - in previous versions I just used TDM, but this time I decided to investigate further (using gcc 5.3.0). Comparing the verbose output of -shared (which includes libgcc_s_dw2-1.dll) against -mdll (which does not), I noticed that -shared includes -lgcc_s -lgcc whereas -mdll has -lgcc -lgcc_eh. I created a custom spec to use -lgcc -lgcc_s and that made libgcc_s_dw2-1.dll go away.