#982 Mingw (and Cygwin) C++ bug in recent gcc versions

closed-fixed
binutils (105)
2008-06-16
2006-11-09
No

Using declaration "extern template class C< Type >;"
and the corresponding instanciation in a DLL makes
execution fail with message "he application has failed
to initialize properly (0xc0000005).". This error is
new in MinGW, it happens on gcc 3.3 and gcc 3.4 but not
gcc 3.2.

Here is a description of my environement and a tarrball
with an example of code (one tiny command and one tiny
dll).

OS: Windows XP
gcc: 3.4.5 (mingw special)
ld: 2.17.50 20060824
MinGW: 5.0.2
Build environment: MSYS
MSYS: MINGW_NT-5.1 IS120578 1.0.11(0.46/3/2) 2004-04-30
unknown
MinGW runtime: 3.10
w32api: 3.7

Discussion

  • Yann Cointepas

    Yann Cointepas - 2006-11-09

    Small code to reproduce the error (with makefile)

     
  • Danny Smith

    Danny Smith - 2006-11-09

    Logged In: YES
    user_id=11494

    If you get rid of the --enable-auto-import from command lines
    you will see:
    Info: resolving vtable for TypedObject<Toto>by linking to __imp___ZTV11TypedObjectI4TotoE
    (auto-import)
    Info: resolving vtable for GenericObjectby linking to __imp___ZTV13GenericObject (auto-
    import)
    Info: resolving typeinfo for TypedObject<Toto>by linking to
    __imp___ZTI11TypedObjectI4TotoE (auto-import)

    Now the vtable and typeinfo objects are readonly data and so get put into the
    .rdata section (of the dll, where the objects are instantiated),

    In order for auto-import to work, the linker needs to "cast" the
    readonly section writeable. While there is code for that when data is in
    .text section, nobody is brave enough to submit a patch to ld that tells
    it "Whoops, readonly sections are not readonly after all".

    The typoinfo object is the real problem, since it needs to be "pseudo-relocated"

    In gcc 3.2 readonly data was put in .text section. Now it is in .rdata section.

    This has come up before on both mingw and cygwin list. FWIW, your
    testcase works okay with a w32-specific patch for the handling of class
    infrastucture (vtables, typeinfo) at the cost of some code
    bloat when code actually specifies class __declspec(dllimport) rather than relying
    on auto-import. Sigh, maybe it will get into gcc 4.3

    Thanks very much for the simple and clear test case. May I cite it in
    when I try to justify the patch?

    Danny

     
  • Yann Cointepas

    Yann Cointepas - 2006-11-12

    Logged In: YES
    user_id=1544262

    Yes, you can use this code for whatever you need.

    Unfortunately, it is sometime too much work to use __declspec. For instance, I work on a project containing lot of existing (more or less clean) C++ code that have been developped on Unix (Solaris and
    Linux) for 10 years in a research environment (many developpers stay only 2-3 years). We choosed to go back to gcc 3.2 on Windows until we find a better solution.

     
  • Ralf Habacker

    Ralf Habacker - 2006-12-29

    Logged In: YES
    user_id=66738
    Originator: NO

    A solution for this problem is to use a specific linker script which places all readonly data into the data section. I have used this script for QT/X11 and KDE on cygwin, which uses code without any dllimport/dllexport decorations.

    I've extended the testcase with a dll and exe with '1' suffix using this linker script. It works without any problems.

    Unfortunally I have no upload button in this tracker, so I have added the added the related Makefile parts and the linker script.

    ================= Makefile =================
    all: AimsDebug.exe AimsDebug1.exe

    libdebug.dll: debug.cc debug.h Makefile
    g++ -shared -o libdebug.dll -mthreads -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -DCARTO_NO_BOOST -I . debug.cc

    AimsDebug.exe: AimsDebug.cc libdebug.dll Makefile
    g++ -o AimsDebug -mthreads -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -DCARTO_NO_BOOST -I . AimsDebug.cc -L . -ldebug

    libdebug1.dll: debug.cc debug.h Makefile
    g++ -shared -o libdebug1.dll -mthreads -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -DCARTO_NO_BOOST -I . debug.cc -Wl,--script,i386pe.x-no-rdata

    AimsDebug1.exe: AimsDebug.cc libdebug1.dll Makefile
    g++ -o AimsDebug1 -mthreads -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -DCARTO_NO_BOOST -I . AimsDebug.cc -L . -ldebug -Wl,--script,i386pe.x-no-rdata

    clean:
    rm libdebug.dll AimsDebug.exe libdebug1.dll AimsDebug1.exe

    clean1:
    del libdebug.dll AimsDebug.exe libdebug1.dll AimsDebug1.exe

    ===============================================

    ================= Linker script ===============

    /* specific linker script avoiding .rdata sections, for normal executables
    for a reference see
    http://www.cygwin.com/ml/cygwin/2004-09/msg01101.html
    http://www.cygwin.com/ml/cygwin-apps/2004-09/msg00309.html
    */
    OUTPUT_FORMAT(pei-i386)
    SEARCH_DIR("/usr/i686-pc-cygwin/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/lib/w32api");
    ENTRY(_mainCRTStartup)
    SECTIONS
    {
    .text __image_base__ + __section_alignment__ :
    {
    *(.init)
    *(.text)
    *(SORT(.text$*))
    *(.glue_7t)
    *(.glue_7)
    ___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
    LONG (-1);*(.ctors); *(.ctor); *(SORT(.ctors.*)); LONG (0);
    ___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
    LONG (-1); *(.dtors); *(.dtor); *(SORT(.dtors.*)); LONG (0);
    *(.fini)
    /* ??? Why is .gcc_exc here? */
    *(.gcc_exc)
    PROVIDE (etext = .);
    *(.gcc_except_table)
    }
    /* The Cygwin32 library uses a section to avoid copying certain data
    on fork. This used to be named ".data". The linker used
    to include this between __data_start__ and __data_end__, but that
    breaks building the cygwin32 dll. Instead, we name the section
    ".data_cygwin_nocopy" and explictly include it after __data_end__. */
    .data BLOCK(__section_alignment__) :
    {
    __data_start__ = . ;
    *(.data)
    *(.data2)
    *(SORT(.data$*))
    *(.rdata)
    *(SORT(.rdata$*))
    *(.eh_frame)
    ___RUNTIME_PSEUDO_RELOC_LIST__ = .;
    __RUNTIME_PSEUDO_RELOC_LIST__ = .;
    *(.rdata_runtime_pseudo_reloc)
    ___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
    __RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
    __data_end__ = . ;
    *(.data_cygwin_nocopy)
    }
    .rdata BLOCK(__section_alignment__) :
    {
    }
    .pdata BLOCK(__section_alignment__) :
    {
    *(.pdata)
    }
    .bss BLOCK(__section_alignment__) :
    {
    __bss_start__ = . ;
    *(.bss)
    *(COMMON)
    __bss_end__ = . ;
    }
    .edata BLOCK(__section_alignment__) :
    {
    *(.edata)
    }
    /DISCARD/ :
    {
    *(.debug$S)
    *(.debug$T)
    *(.debug$F)
    *(.drectve)
    }
    .idata BLOCK(__section_alignment__) :
    {
    /* This cannot currently be handled with grouped sections.
    See pe.em:sort_sections. */
    SORT(*)(.idata$2)
    SORT(*)(.idata$3)
    /* These zeroes mark the end of the import list. */
    LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
    SORT(*)(.idata$4)
    SORT(*)(.idata$5)
    SORT(*)(.idata$6)
    SORT(*)(.idata$7)
    }
    .CRT BLOCK(__section_alignment__) :
    {
    ___crt_xc_start__ = . ;
    *(SORT(.CRT$XC*)) /* C initialization */
    ___crt_xc_end__ = . ;
    ___crt_xi_start__ = . ;
    *(SORT(.CRT$XI*)) /* C++ initialization */
    ___crt_xi_end__ = . ;
    ___crt_xl_start__ = . ;
    *(SORT(.CRT$XL*)) /* TLS callbacks */
    /* ___crt_xl_end__ is defined in the TLS Directory support code */
    ___crt_xp_start__ = . ;
    *(SORT(.CRT$XP*)) /* Pre-termination */
    ___crt_xp_end__ = . ;
    ___crt_xt_start__ = . ;
    *(SORT(.CRT$XT*)) /* Termination */
    ___crt_xt_end__ = . ;
    }
    .tls BLOCK(__section_alignment__) :
    {
    ___tls_start__ = . ;
    *(.tls)
    *(.tls$)
    *(SORT(.tls$*))
    ___tls_end__ = . ;
    }
    .endjunk BLOCK(__section_alignment__) :
    {
    /* end is deprecated, don't use it */
    PROVIDE (end = .);
    PROVIDE ( _end = .);
    __end__ = .;
    }
    .rsrc BLOCK(__section_alignment__) :
    {
    *(.rsrc)
    *(SORT(.rsrc$*))
    }
    .reloc BLOCK(__section_alignment__) :
    {
    *(.reloc)
    }
    .stab BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.stab)
    }
    .stabstr BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.stabstr)
    }
    /* DWARF debug sections.
    Symbols in the DWARF debugging sections are relative to the beginning
    of the section. Unlike other targets that fake this by putting the
    section VMA at 0, the PE format will not allow it. */
    /* DWARF 1.1 and DWARF 2. */
    .debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_aranges)
    }
    .debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_pubnames)
    }
    /* DWARF 2. */
    .debug_info BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_info) *(.gnu.linkonce.wi.*)
    }
    .debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_abbrev)
    }
    .debug_line BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_line)
    }
    .debug_frame BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_frame)
    }
    .debug_str BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_str)
    }
    .debug_loc BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_loc)
    }
    .debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_macinfo)
    }
    /* SGI/MIPS DWARF 2 extensions. */
    .debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_weaknames)
    }
    .debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_funcnames)
    }
    .debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_typenames)
    }
    .debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_varnames)
    }
    /* DWARF 3. */
    .debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
    {
    *(.debug_ranges)
    }
    }

    ===============================================

     
  • Ralf Habacker

    Ralf Habacker - 2006-12-29

    Logged In: YES
    user_id=66738
    Originator: NO

    Danny Smith wrote:
    >In order for auto-import to work, the linker needs to "cast" the
    >readonly section writeable. While there is code for that when data is in
    >.text section, nobody is brave enough to submit a patch to ld that tells
    >it "Whoops, readonly sections are not readonly after all".

    It's long time ago (2001) since I took Paul Sokolosky's initial auto-import stuff working with mingw's ld and applied it to cygwin's ld for the KDE on cygwin project. In the meantime my knowledge of the ld internals is out of date, which means I'm currently not able to provide a working patch, but I think a build in solution will be near.

    Does not shows the solution using a specific linker script into the right direction ? Would it not be possible to add this linker script to the ld binary and to use it every time the auto-import switch is set or to manipulate a default build in linker script in this case ?

     
  • Danny Smith

    Danny Smith - 2008-06-16

    Logged In: YES
    user_id=11494
    Originator: NO

    A version of your script is now in binutils, so closing as fixed.

     
  • Danny Smith

    Danny Smith - 2008-06-16
    • labels: 103944 --> binutils
    • status: open --> closed-fixed
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks