From: Tristan G. <gi...@ad...> - 2012-06-08 12:14:45
|
On Jun 8, 2012, at 1:55 PM, JonY wrote: > On 6/8/2012 18:27, Tristan Gingold wrote: >> Hi, >> >> I am currently working on porting our toolset to gcc 4.7 compiled to fully support SEH, and I have compiled gdb. This gdb crashes frequently, and I traced that to the use of setjmp/longjmp. >> >> When compiled with SEH enabled, mingw64 makes longjmp use RtlUnwinEx, and to achieve that it calls _setjmp with a non-null establisher frame. >> Currently, it uses mingw_getsp() for that. Unfortunately, this is wrong. This establisher frame is the frame pointer defined in the Frame Pointer field of the UNWIND_INFO structure (and rsp if this field is nul). In case of mismatch, longjmp is not able to find the target frame and aborts the program. >> >> The easiest fix is to use __builtin_frame_address (0), which forces the use of a frame pointer and returns its value. This is not optimal (would be nice not to force the user of a frame pointer), but I am not sure gcc could do better. >> >> Here is the patch, with a little bit of reformatting (because I found the nested directives hard to read). >> >> There are also some bugs in the generation of SEH directive in gcc 4.7, and I plan to send patch to the gcc ML for that. >> >> Tristan. > > Hi, > > Can you please use unified diff? Sure. Note that I prefer to consider this as an request for comment. I haven't seen yet any precise definition of what is an establisher frame, so this might still be wrong. Tristan. --- setjmp.h~ 2012-05-07 17:11:59.000000000 +0200 +++ setjmp.h 2012-06-08 11:37:34.000000000 +0200 @@ -148,34 +148,32 @@ #define _JMP_BUF_DEFINED #endif - void * __cdecl __attribute__ ((__nothrow__)) mingw_getsp(void); - #ifndef USE_NO_MINGW_SETJMP_TWO_ARGS -#ifndef _INC_SETJMPEX -#ifdef _WIN64 -#define setjmp(BUF) _setjmp((BUF), mingw_getsp()) -#else -#define setjmp(BUF) _setjmp3((BUF), NULL) -#endif +# ifndef _INC_SETJMPEX +# ifdef _WIN64 +# define setjmp(BUF) _setjmp((BUF), __builtin_frame_address (0)) +# else +# define setjmp(BUF) _setjmp3((BUF), NULL) +# endif int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) _setjmp(jmp_buf _Buf, void *_Ctx); int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) _setjmp3(jmp_buf _Buf, void *_Ctx); -#else -#undef setjmp -#ifdef _WIN64 -#define setjmp(BUF) _setjmpex((BUF), mingw_getsp()) -#define setjmpex(BUF) _setjmpex((BUF), mingw_getsp()) -#else -#define setjmp(BUF) _setjmpex((BUF), NULL) -#define setjmpex(BUF) _setjmpex((BUF), NULL) -#endif +# else +# undef setjmp +# ifdef _WIN64 +# define setjmp(BUF) _setjmpex((BUF), __builtin_frame_address (0)) +# define setjmpex(BUF) _setjmpex((BUF), __builtin_frame_address (0)) +# else +# define setjmp(BUF) _setjmpex((BUF), NULL) +# define setjmpex(BUF) _setjmpex((BUF), NULL) +# endif int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) _setjmpex(jmp_buf _Buf,void *_Ctx); -#endif +# endif #else -#ifndef _INC_SETJMPEX -#define setjmp _setjmp -#endif +# ifndef _INC_SETJMPEX +# define setjmp _setjmp +# endif int __cdecl __attribute__ ((__nothrow__,__returns_twice__)) setjmp(jmp_buf _Buf); #endif |