This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug libgcc/57982] New: GetModuleHandle in __register_frame_info causes abort on unload
- From: "dancol at dancol dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Thu, 25 Jul 2013 09:07:32 +0000
- Subject: [Bug libgcc/57982] New: GetModuleHandle in __register_frame_info causes abort on unload
- Auto-submitted: auto-generated
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.