http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57982
Bug ID: 57982 Summary: GetModuleHandle in __register_frame_info causes abort on unload Product: gcc Version: 4.7.3 Status: UNCONFIRMED Severity: major Priority: P3 Component: libgcc Assignee: unassigned at gcc dot gnu.org Reporter: dancol at dancol dot org Say we have modules Foo and Bar. Foo links against shared libgcc, but Bar does not. Now, if we load Foo, load Bar, unload Foo, then unload Bar, then Bar's initialization code finds libgcc and registers itself with it, but Bar's deinitializaton code doesn't find libgcc, tries to instead unregister with Foo's internal data structures, finds them uninitialized, and aborts. The right fix for libgcc looks something like this: --- config/i386/cygming-crtbegin.c.orig 2013-07-25 00:07:35.000000000 -0800 +++ config/i386/cygming-crtbegin.c 2013-07-25 00:33:11.000000000 -0800 @@ -82,6 +82,8 @@ extern void __gcc_register_frame (void); extern void __gcc_deregister_frame (void); +static HANDLE libgcc_dll; + void __gcc_register_frame (void) { @@ -94,8 +96,11 @@ void (*register_frame_fn) (const void *, struct object *); HANDLE h = GetModuleHandle (LIBGCC_SONAME); if (h) - register_frame_fn = (void (*) (const void *, struct object *)) - GetProcAddress (h, "__register_frame_info"); + { + libgcc_dll = LoadLibrary (LIBGCC_SONAME); /* Hold reference */ + register_frame_fn = (void (*) (const void *, struct object *)) + GetProcAddress (h, "__register_frame_info"); + } else register_frame_fn = __register_frame_info; if (register_frame_fn) @@ -124,13 +129,16 @@ { #if DWARF2_UNWIND_INFO void * (*deregister_frame_fn) (const void *); - HANDLE h = GetModuleHandle (LIBGCC_SONAME); - if (h) + if (libgcc_dll) deregister_frame_fn = (void* (*) (const void *)) - GetProcAddress (libgcc_dl, "__deregister_frame_info"); + GetProcAddress (libgcc_dll, "__deregister_frame_info"); else deregister_frame_fn = __deregister_frame_info; if (deregister_frame_fn) deregister_frame_fn (__EH_FRAME_BEGIN__); + + if (libgcc_dll) + FreeLibrary (libgcc_dll); + #endif The problem is that this code is baked into every module compiled with the buggy libgcc. You have to recompile the world to fix it for good.