From 646ec4c2c1bc89c4243b69643f172eb20d5876c1 Mon Sep 17 00:00:00 2001 From: Jon TURNEY Date: Fri, 3 Apr 2015 22:26:21 +0100 Subject: [PATCH] Avoid random crashes in RtlCaptureContext on x86 RtlCaptureContext requires the framepointer of the calling function in ebp, which it uses to report the rip and rsp of it's caller. But it seems that gcc may decide to optimize the setting of the framepointer away, irrespective of -fomit-frame-pointer. If _cygtls::call_signal_handler() is called with ebp pointing to an invalid memory address, as seems to happen occasionally, we will fault in RtlCaptureContext. This patch manually creates a stcall callframe around RtlCaptureContext to be safe, but I'm not sure that's the best approach. RtlCaptureContext does so little, it's probably just as effective to write our own version. This is heading further in the wrong direction, as the context that is wanted isn't the current context, but the context at the time of the signal. There are a couple of other uses of RtlCaptureContext(), are they ok? --- winsup/cygwin/exceptions.cc | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 0d1f36d..0ca6dd8 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1496,8 +1496,24 @@ _cygtls::call_signal_handler () if (thissi.si_cyg) memcpy (&thiscontext.uc_mcontext, ((cygwin_exception *)thissi.si_cyg)->context(), sizeof(CONTEXT)); else - RtlCaptureContext ((CONTEXT *)&thiscontext.uc_mcontext); - /* FIXME: Really this should be the context which the signal interrupted? */ + { + /* FIXME: Really this should be the context which the signal interrupted? */ +#ifdef __x86_64__ + RtlCaptureContext ((CONTEXT *)&thiscontext.uc_mcontext); +#else + memset(&thiscontext.uc_mcontext, 0, sizeof(struct __mcontext)); + thiscontext.uc_mcontext.ctxflags = CONTEXT_FULL; + /* RtlCaptureContext requires the framepointer of the calling function + in ebp, which it uses to report the rip and rsp of it's caller. + But it seems that gcc may decide to optimize the setting of the + framepointer away, irrespective of -fomit-frame-pointer. Manually + create a stcall callframe to be safe. */ + __asm__ ( "mov %%esp,%%ebp\n" + "push %0\n" + "call _RtlCaptureContext@4\n" + : : "r" (&thiscontext.uc_mcontext) : "%ebp", "%eax", "%ecx", "%edx" ); +#endif + } /* FIXME: If/when sigaltstack is implemented, this will need to do something more complicated */ -- 2.1.4