diff options
author | Christopher Faylor <me@cgf.cx> | 2005-12-03 04:23:35 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2005-12-03 04:23:35 +0000 |
commit | f153e6b2804f06315d748bd1c8cad9f76798db09 (patch) | |
tree | 0ca55fa4e5dbf0332d9a3d587104236d51b1fb59 /winsup/cygwin/exceptions.cc | |
parent | e7f6a31bb07e96eed5ffb7b8d137051292532930 (diff) | |
download | cygnal-f153e6b2804f06315d748bd1c8cad9f76798db09.tar.gz cygnal-f153e6b2804f06315d748bd1c8cad9f76798db09.tar.bz2 cygnal-f153e6b2804f06315d748bd1c8cad9f76798db09.zip |
* cygtls.h (_cygtls::el): New field.
(_cygtls::handle_exceptions): New function declaration.
(_cygtls::handle_threadlist_exception): Ditto.
(_cygtls::init_exception_handler): Ditto.
(_cygtls::init_threadlist_exceptions): Remove arg from declaration.
* cygtls.cc (_cygtls::call2): Don't initialize exceptions here.
(_cygtls::init_thread): Do it here instead and use member function.
(_cygtls::handle_threadlist_exception): Move into _cygtls class.
(_cygtls::init_exception_handler): Ditto. Rely on existence of 'el' memmber in
_cygtls.
(_cygtls::init_threadlist_exceptions): Ditto.
* dcrt0.cc (dll_crt0_1): Remove exception_list definition and setting since it
now commonly resides in the tls.
* exceptions.cc (init_exception_handler): Move to cygtls.cc.
(init_exceptions): Ditto.
(rtl_unwind): New, safe wrapper function for RtlUnwind.
(_cygtls::handle_exceptions): Move to _cygtls. Call rtl_unwind to unwind
frames and eliminate copying of structures. Put address of failing instruction
in si_addr, not the address on the stack. Return 0 to indicate that we've
handled this exception.
* external.cc (cygwin_internal): Make CW_INIT_EXCEPTIONS a no-op.
* sigproc.cc (wait_sig): Accommodate argument change to
_cygtls::init_threadlist_exceptions.
* tlsoffsets.h: Regenerate.
* include/exceptions.h (exception_list): Add more stuff to the exception list.
Apparently windows needs this?
(init_exceptions): Remove bogus declaration.
* include/cygwin/signal.h (SI_USER): Redefine as zero as per SUSv3.
* thread.cc (pthread_kill): Set si_pid and si_uid.
* timer.cc (timer_thread): Set si_code to SI_TIMER.
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 80 |
1 files changed, 36 insertions, 44 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index bc0ea739a..9851183fc 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -36,7 +36,6 @@ details. */ char debugger_command[2 * CYG_MAX_PATH + 20]; extern "C" { -static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *); extern void sigdelayed (); }; @@ -94,28 +93,6 @@ NO_COPY static struct /* Initialization code. */ -// Set up the exception handler for the current thread. The PowerPC & Mips -// use compiler generated tables to set up the exception handlers for each -// region of code, and the kernel walks the call list until it finds a region -// of code that handles exceptions. The x86 on the other hand uses segment -// register fs, offset 0 to point to the current exception handler. - -extern exception_list *_except_list asm ("%fs:0"); - -void -init_exception_handler (exception_list *el, exception_handler *eh) -{ - el->handler = eh; - el->prev = _except_list; - _except_list = el; -} - -extern "C" void -init_exceptions (exception_list *el) -{ - init_exception_handler (el, handle_exceptions); -} - BOOL WINAPI dummy_ctrl_c_handler (DWORD dwCtrlType) { @@ -403,11 +380,31 @@ try_to_debug (bool waitloop) return dbg; } +extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); +static void __stdcall rtl_unwind (void *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3))); +void __stdcall +rtl_unwind (void *frame, PEXCEPTION_RECORD e) +{ + __asm__ ("\n\ + pushl %%ebx \n\ + pushl %%edi \n\ + pushl %%esi \n\ + pushl $0 \n\ + pushl %1 \n\ + pushl $1f \n\ + pushl %0 \n\ + call _RtlUnwind@16 \n\ +1: \n\ + popl %%esi \n\ + popl %%edi \n\ + popl %%ebx \n\ +": : "r" (frame), "r" (e)); +} + /* Main exception handler. */ -extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); -static int -handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) +int +_cygtls::handle_exceptions (EXCEPTION_RECORD *e, void *frame, CONTEXT *in, void *) { static bool NO_COPY debugging; static int NO_COPY recursed; @@ -421,16 +418,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) /* If we've already exited, don't do anything here. Returning 1 tells Windows to keep looking for an exception handler. */ - if (exit_already) + if (exit_already || e->ExceptionFlags) return 1; - EXCEPTION_RECORD e = *e0; - CONTEXT in = *in0; - siginfo_t si; si.si_code = SI_KERNEL; /* Coerce win32 value to posix value. */ - switch (e.ExceptionCode) + switch (e->ExceptionCode) { case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: @@ -514,8 +508,9 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) return 1; } - debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e.ExceptionCode, in.Eip, in.Esp); - debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in.Eip); + rtl_unwind (frame, e); + debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp); + debug_printf ("In cygwin_except_handler sig %d at %p", si.si_signo, in->Eip); if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo)) syscall_printf ("signal %d, masked %p", si.si_signo, @@ -524,9 +519,9 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) debug_printf ("In cygwin_except_handler calling %p", global_sigs[si.si_signo].sa_handler); - DWORD *ebp = (DWORD *)in.Esp; + DWORD *ebp = (DWORD *) in->Esp; for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--) - if (*ebp == in.SegCs && ebp[-1] == in.Eip) + if (*ebp == in->SegCs && ebp[-1] == in->Eip) { ebp -= 2; break; @@ -534,7 +529,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) if (!me.fault_guarded () && (!cygwin_finished_initializing - || &_my_tls == _sig_tls + || &me == _sig_tls || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)) @@ -542,7 +537,7 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) /* Print the exception to the console */ if (!myself->cygstarted) for (int i = 0; status_info[i].name; i++) - if (status_info[i].code == e.ExceptionCode) + if (status_info[i].code == e->ExceptionCode) { system_printf ("Exception: %s", status_info[i].name); break; @@ -561,25 +556,22 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) } open_stackdumpfile (); - exception (&e, &in); + exception (e, in); stackdump ((DWORD) ebp, 0, 1); } signal_exit (0x80 | si.si_signo); // Flag signal + core dump } - extern DWORD ret_here[]; - RtlUnwind (frame, ret_here, e0, 0); - __asm__ volatile (".equ _ret_here,."); - if (me.fault_guarded ()) me.return_from_fault (); - si.si_addr = ebp; + si.si_addr = (void *) in->Eip; si.si_errno = si.si_pid = si.si_uid = 0; me.push ((__stack_t) ebp, true); sig_send (NULL, si, &me); // Signal myself - return 1; + e->ExceptionFlags = 0; + return 0; } /* Utilities to call a user supplied exception handler. */ |