This patch changes the logic in "crtbegin" that looks for libgcc.dll such that the test is only done once, guaranteeing consistent results between the register and deregister cases.
Previously, a crash occurred if the application (directly or indirectly) caused libgcc.dll to load after main() was called (i.e. dlopen'd a DLL which required libgcc). In that case, the register test would return "no libgcc" and register with the local copy, yet the deregister test would return "yes libgcc" and try to deregister something with libgcc.dll that hadn't been registered. Index: cygming-crtbegin.c =================================================================== --- cygming-crtbegin.c (revision 212915) +++ cygming-crtbegin.c (working copy) @@ -99,12 +99,13 @@ static EH_FRAME_SECTION_CONST char __EH_ = { }; static struct object obj; /* Handle of libgcc's DLL reference. */ HANDLE hmod_libgcc; +static void * (*deregister_frame_fn) (const void *) == NULL; #endif #if TARGET_USE_JCR_SECTION static void *__JCR_LIST__[] __attribute__ ((used, section(JCR_SECTION_NAME), aligned(4))) = { }; @@ -130,15 +131,20 @@ __gcc_register_frame (void) if (h) { /* Increasing the load-count of LIBGCC_SONAME DLL. */ hmod_libgcc = LoadLibrary (LIBGCC_SONAME); register_frame_fn = (void (*) (const void *, struct object *)) GetProcAddress (h, "__register_frame_info"); + deregister_frame_fn = (void* (*) (const void *)) + GetProcAddress (h, "__deregister_frame_info"); + } + else + { + register_frame_fn = __register_frame_info; + deregister_frame_fn = __deregister_frame_info; } - else - register_frame_fn = __register_frame_info; if (register_frame_fn) register_frame_fn (__EH_FRAME_BEGIN__, &obj); #endif #if TARGET_USE_JCR_SECTION if (__JCR_LIST__[0]) @@ -158,19 +164,12 @@ __gcc_register_frame (void) } void __gcc_deregister_frame (void) { #if DWARF2_UNWIND_INFO - void * (*deregister_frame_fn) (const void *); - HANDLE h = GetModuleHandle (LIBGCC_SONAME); - if (h) - deregister_frame_fn = (void* (*) (const void *)) - GetProcAddress (h, "__deregister_frame_info"); - else - deregister_frame_fn = __deregister_frame_info; if (deregister_frame_fn) deregister_frame_fn (__EH_FRAME_BEGIN__); if (hmod_libgcc) FreeLibrary (hmod_libgcc); #endif }