This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libgcc/57982] New: GetModuleHandle in __register_frame_info causes abort on unload


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]