* 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.
This commit is contained in:
@ -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. */
|
||||
|
Reference in New Issue
Block a user