summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2014-03-28 22:31:53 +0000
committerCorinna Vinschen <corinna@vinschen.de>2014-03-28 22:31:53 +0000
commit20738749f60c85f58329015b7285289f6eb2b7c9 (patch)
treeddbd470d565d1bf74bb8c661633efe2b3afbc3ce
parent58cc7a6498ce0da7f4acb79d837eadcf29c8a381 (diff)
downloadcygnal-20738749f60c85f58329015b7285289f6eb2b7c9.tar.gz
cygnal-20738749f60c85f58329015b7285289f6eb2b7c9.tar.bz2
cygnal-20738749f60c85f58329015b7285289f6eb2b7c9.zip
* dcrt0.cc (dll_crt0_0): Install myfault exception handler on x86_64.
* exception.h (exception_list): Typedef as void on x86_64. (exception::handler_installed): Remove. (exception::handle_while_being_debugged): Remove. (exception::myfault_handle): Declare for x86_64. (exception::handle): Declare as ordinary exception handler on x86_64 as well. (exception::exception): Drop previous code (again). Install exception::handle as SEH handler. (exception::install_myfault_handler): New x86_64-only method to install exception::myfault_handle as VEH handler. Explain why. (exception::~exception): For x86_64, define frame end label (again). * exceptions.cc (CYG_EXC_CONTINUE_EXECUTION): Drop definition. (CYG_EXC_CONTINUE_SEARCH): Ditto. (exception::myfault_handle): New x86_64-only method, VEH handler to handle myfault exceptions. (exception::handle): Define as ordinary exception handler on x86_64 as well. Use ExceptionContinueExecution and ExceptionContinueSearch throughout instead of deleted Cygwin macros. Don't handle myfault exceptions on x86_64.
-rw-r--r--winsup/cygwin/ChangeLog23
-rw-r--r--winsup/cygwin/dcrt0.cc4
-rw-r--r--winsup/cygwin/exception.h63
-rw-r--r--winsup/cygwin/exceptions.cc48
4 files changed, 97 insertions, 41 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 5bad8b00e..1713b984e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,28 @@
2014-03-28 Corinna Vinschen <corinna@vinschen.de>
+ * dcrt0.cc (dll_crt0_0): Install myfault exception handler on x86_64.
+ * exception.h (exception_list): Typedef as void on x86_64.
+ (exception::handler_installed): Remove.
+ (exception::handle_while_being_debugged): Remove.
+ (exception::myfault_handle): Declare for x86_64.
+ (exception::handle): Declare as ordinary exception handler on x86_64
+ as well.
+ (exception::exception): Drop previous code (again). Install
+ exception::handle as SEH handler.
+ (exception::install_myfault_handler): New x86_64-only method to
+ install exception::myfault_handle as VEH handler. Explain why.
+ (exception::~exception): For x86_64, define frame end label (again).
+ * exceptions.cc (CYG_EXC_CONTINUE_EXECUTION): Drop definition.
+ (CYG_EXC_CONTINUE_SEARCH): Ditto.
+ (exception::myfault_handle): New x86_64-only method, VEH handler to
+ handle myfault exceptions.
+ (exception::handle): Define as ordinary exception handler on x86_64
+ as well. Use ExceptionContinueExecution and ExceptionContinueSearch
+ throughout instead of deleted Cygwin macros. Don't handle myfault
+ exceptions on x86_64.
+
+2014-03-28 Corinna Vinschen <corinna@vinschen.de>
+
* sec_auth.cc (create_token): Initialize lsa handle to NULL, rather than
to INVALID_HANDLE_VALUE.
(lsaauth): Ditto.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index c27079b33..f72cbb0be 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -795,6 +795,10 @@ dll_crt0_0 ()
_main_tls = &_my_tls;
+#ifdef __x86_64__
+ exception::install_myfault_handler ();
+#endif
+
/* Initialize signal processing here, early, in the hopes that the creation
of a thread early in the process will cause more predictability in memory
layout for the main thread. */
diff --git a/winsup/cygwin/exception.h b/winsup/cygwin/exception.h
index 673f3b3b5..83cb21fcf 100644
--- a/winsup/cygwin/exception.h
+++ b/winsup/cygwin/exception.h
@@ -104,29 +104,33 @@ typedef struct _exception_list
} exception_list;
extern exception_list *_except_list asm ("%fs:0");
+#else
+typedef void exception_list;
#endif /* !__x86_64 */
class exception
{
#ifdef __x86_64__
- static bool handler_installed;
- static int handle (LPEXCEPTION_POINTERS);
- static int handle_while_being_debugged (LPEXCEPTION_POINTERS);
+ static LONG myfault_handle (LPEXCEPTION_POINTERS ep);
#else
exception_list el;
exception_list *save;
- static int handle (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *);
#endif /* __x86_64__ */
+ static int handle (EXCEPTION_RECORD *, exception_list *, CONTEXT *, void *);
public:
exception () __attribute__ ((always_inline))
{
+ /* Install SEH handler. */
#ifdef __x86_64__
- if (!handler_installed)
- {
- handler_installed = true;
- SetUnhandledExceptionFilter (handle);
- AddVectoredExceptionHandler (1, handle_while_being_debugged);
- }
+ asm volatile ("\n\
+ 1: \n\
+ .seh_handler \
+ _ZN9exception6handleEP17_EXCEPTION_RECORDPvP8_CONTEXTS2_, \
+ @except \n\
+ .seh_handlerdata \n\
+ .long 1 \n\
+ .rva 1b, 2f, 2f, 2f \n\
+ .seh_code \n");
#else
save = _except_list;
el.handler = handle;
@@ -134,7 +138,44 @@ public:
_except_list = &el;
#endif /* __x86_64__ */
};
-#ifndef __x86_64__
+#ifdef __x86_64__
+ static void install_myfault_handler () __attribute__ ((always_inline))
+ {
+ /* Install myfault exception handler as VEH. Here's what happens:
+ Some Windows DLLs (advapi32, for instance) are using SEH to catch
+ exceptions inside its own functions. If we install a VEH handler
+ to catch all exceptions, our Cygwin VEH handler would illegitimatly
+ handle exceptions inside of Windows DLLs which are usually handled
+ by its own SEH handler. So, for standard exceptions we use an SEH
+ handler as installed in the constructor above so as not to override
+ the SEH handlers in Windows DLLs.
+ But we have a special case, myfault handling. The myfault handling
+ catches exceptions inside of the Cygwin DLL, some of them entirely
+ expected as in verifyable_object_isvalid. The ultimately right thing
+ to do would be to install SEH handlers for each of these cases.
+ But there are two problems with that:
+
+ 1. It would be a massive and, partially unreliable change in the
+ calling functions due to the incomplete SEH support in GCC.
+
+ 2. It doesn't always work. Certain DLLs appear to call Cygwin
+ functions during DLL initialization while the SEH handler is
+ not installed in the active call frame. For these cases we
+ need a more generic approach.
+
+ So, what we do here is to install a myfault VEH handler. This
+ function is called from dll_crt0_0, so the myfault handler is
+ available very early. */
+ AddVectoredExceptionHandler (1, myfault_handle);
+ }
+ ~exception () __attribute__ ((always_inline))
+ {
+ asm volatile ("\n\
+ nop \n\
+ 2: \n\
+ nop \n");
+ }
+#else
~exception () __attribute__ ((always_inline)) { _except_list = save; }
#endif /* !__x86_64__ */
};
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index d335a0807..c288913bd 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -545,55 +545,43 @@ rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
popl %%ebx \n\
": : "r" (frame), "r" (e));
}
-#endif
-
-/* Main exception handler. */
+#endif /* __x86_64 */
#ifdef __x86_64__
-#define CYG_EXC_CONTINUE_EXECUTION EXCEPTION_CONTINUE_EXECUTION
-#define CYG_EXC_CONTINUE_SEARCH EXCEPTION_CONTINUE_SEARCH
-
-bool exception::handler_installed NO_COPY;
-
-int
-exception::handle_while_being_debugged (LPEXCEPTION_POINTERS ep)
+/* myfault vectored exception handler */
+LONG
+exception::myfault_handle (LPEXCEPTION_POINTERS ep)
{
- if (being_debugged ())
- return handle (ep);
+ _cygtls& me = _my_tls;
+
+ if (me.andreas)
+ me.andreas->leave (); /* Return from a "san" caught fault */
return EXCEPTION_CONTINUE_SEARCH;
}
+#endif /* __x86_64 */
-int
-exception::handle (LPEXCEPTION_POINTERS ep)
-#else
-#define CYG_EXC_CONTINUE_EXECUTION ExceptionContinueExecution
-#define CYG_EXC_CONTINUE_SEARCH ExceptionContinueSearch
-
+/* Main exception handler. */
int
exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
-#endif
{
static bool NO_COPY debugging;
_cygtls& me = _my_tls;
+#ifndef __x86_64__
if (me.andreas)
me.andreas->leave (); /* Return from a "san" caught fault */
-
-#ifdef __x86_64__
- EXCEPTION_RECORD *e = ep->ExceptionRecord;
- CONTEXT *in = ep->ContextRecord;
#endif
if (debugging && ++debugging < 500000)
{
SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
- return CYG_EXC_CONTINUE_EXECUTION;
+ return ExceptionContinueExecution;
}
/* If we're exiting, tell Windows to keep looking for an
exception handler. */
if (exit_state || e->ExceptionFlags)
- return CYG_EXC_CONTINUE_SEARCH;
+ return ExceptionContinueSearch;
siginfo_t si = {};
si.si_code = SI_KERNEL;
@@ -662,7 +650,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
1))
{
case MMAP_NORESERVE_COMMITED:
- return CYG_EXC_CONTINUE_EXECUTION;
+ return ExceptionContinueExecution;
case MMAP_RAISE_SIGBUS: /* MAP_NORESERVE page, commit failed, or
access to mmap page beyond EOF. */
si.si_signo = SIGBUS;
@@ -696,13 +684,13 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
want CloseHandle to return an error. This can be revisited
if gcc ever supports Windows style structured exception
handling. */
- return CYG_EXC_CONTINUE_EXECUTION;
+ return ExceptionContinueExecution;
default:
/* If we don't recognize the exception, we have to assume that
we are doing structured exception handling, and we let
something else handle it. */
- return CYG_EXC_CONTINUE_SEARCH;
+ return ExceptionContinueSearch;
}
debug_printf ("In cygwin_except_handler exception %y at %p sp %p", e->ExceptionCode, in->_GR(ip), in->_GR(sp));
@@ -738,7 +726,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
else
{
debugging = true;
- return CYG_EXC_CONTINUE_EXECUTION;
+ return ExceptionContinueExecution;
}
/* FIXME: Probably should be handled in signal processing code */
@@ -773,7 +761,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
sig_send (NULL, si, &me); /* Signal myself */
me.incyg--;
e->ExceptionFlags = 0;
- return CYG_EXC_CONTINUE_EXECUTION;
+ return ExceptionContinueExecution;
}
/* Utilities to call a user supplied exception handler. */