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;
@@ -94,8 +96,11 @@
void (*register_frame_fn) (const void *, struct object *);
HANDLE h = GetModuleHandle (LIBGCC_SONAME);
- 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");
register_frame_fn = __register_frame_info;
@@ -124,13 +129,16 @@
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");
deregister_frame_fn = __deregister_frame_info;
+ if (libgcc_dll)
+ FreeLibrary (libgcc_dll);
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.
Ups, this bug didn't shown up in my search-list ...
Issue fixed for 4.7, 4.8, and trunk at rev 204635-204637.
(In reply to Kai Tietz from comment #1)
> Ups, this bug didn't shown up in my search-list ...
> Issue fixed for 4.7, 4.8, and trunk at rev 204635-204637.
I recently stumbled on a similar problem again with a recent Cygwin/GCC combination.
Looking at the fix included in GCC, it does look slightly different from what was first suggested here.
Could someone more knowledgeable than me have a look and tell whether the included fix is fine or incomplete?
If incomplete, I'll be happy to open a new bug report.
See here for my report on cygwin's mailing-list:
The problem here is the use of weak on pe-coff. The change you see on gcc is just addressing the fact that for 64-bit the weak symbol never can get 0 due relocation-limitations.
We try to address this.
On the other hand we have here to work-a-round a binutils quirk that default-implementation of a weak is used in its definition TU always, even if a none-weak symbol is present in a different TU. This can be worked-a-round by moving default-implementation into different TU.
Hope this answered some of your questions.
(anyway IMHO, in general we should have used here a variant without any weak-symbol)