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
 }

Reply via email to