* exceptions.cc (interruptible): New function, code stripped from
_cygtls::interrupt_now. (_cygtls::handle_exceptions): Handle STATUS_DATATYPE_MISALIGNMENT as SIGBUS error. Differ between unmapped memory (SEGV_MAPERR) and access violation (SEGV_ACCERR) in case of STATUS_ACCESS_VIOLATION. Write kernel log message in case of uncatched STATUS_ACCESS_VIOLATION. (_cygtls::interrupt_now): Just call interruptible now instead of evaluating interruptibility here.
This commit is contained in:
parent
19556072f6
commit
4f12275501
@ -1,3 +1,14 @@
|
|||||||
|
2005-12-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* exceptions.cc (interruptible): New function, code stripped from
|
||||||
|
_cygtls::interrupt_now.
|
||||||
|
(_cygtls::handle_exceptions): Handle STATUS_DATATYPE_MISALIGNMENT as
|
||||||
|
SIGBUS error. Differ between unmapped memory (SEGV_MAPERR) and access
|
||||||
|
violation (SEGV_ACCERR) in case of STATUS_ACCESS_VIOLATION. Write
|
||||||
|
kernel log message in case of uncatched STATUS_ACCESS_VIOLATION.
|
||||||
|
(_cygtls::interrupt_now): Just call interruptible now instead of
|
||||||
|
evaluating interruptibility here.
|
||||||
|
|
||||||
2005-12-27 Corinna Vinschen <corinna@vinschen.de>
|
2005-12-27 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* path.cc (path_conv::check): Rework loop removing trailing dots
|
* path.cc (path_conv::check): Rework loop removing trailing dots
|
||||||
|
@ -16,6 +16,7 @@ details. */
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
@ -285,6 +286,37 @@ stackdump (DWORD ebp, int open_file, bool isexception)
|
|||||||
i == 16 ? " (more stack frames may be present)" : "");
|
i == 16 ? " (more stack frames may be present)" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
interruptible (CONTEXT *cx)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
MEMORY_BASIC_INFORMATION m;
|
||||||
|
|
||||||
|
memset (&m, 0, sizeof m);
|
||||||
|
if (!VirtualQuery ((LPCVOID) cx->Eip, &m, sizeof m))
|
||||||
|
sigproc_printf ("couldn't get memory info, pc %p, %E", cx->Eip);
|
||||||
|
|
||||||
|
char *checkdir = (char *) alloca (windows_system_directory_length + 4);
|
||||||
|
memset (checkdir, 0, sizeof (checkdir));
|
||||||
|
|
||||||
|
# define h ((HMODULE) m.AllocationBase)
|
||||||
|
/* Apparently Windows 95 can sometimes return bogus addresses from
|
||||||
|
GetThreadContext. These resolve to a strange allocation base.
|
||||||
|
These should *never* be treated as interruptible. */
|
||||||
|
if (!h || m.State != MEM_COMMIT)
|
||||||
|
res = false;
|
||||||
|
else if (h == user_data->hmodule)
|
||||||
|
res = true;
|
||||||
|
else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
|
||||||
|
res = false;
|
||||||
|
else
|
||||||
|
res = !strncasematch (windows_system_directory, checkdir,
|
||||||
|
windows_system_directory_length);
|
||||||
|
sigproc_printf ("pc %p, h %p, interruptible %d", cx->Eip, h, res);
|
||||||
|
# undef h
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* Temporary (?) function for external callers to get a stack dump */
|
/* Temporary (?) function for external callers to get a stack dump */
|
||||||
extern "C" void
|
extern "C" void
|
||||||
cygwin_stackdump ()
|
cygwin_stackdump ()
|
||||||
@ -403,6 +435,7 @@ rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e)
|
|||||||
|
|
||||||
/* Main exception handler. */
|
/* Main exception handler. */
|
||||||
|
|
||||||
|
extern "C" char *__progname;
|
||||||
int
|
int
|
||||||
_cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
|
_cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void *)
|
||||||
{
|
{
|
||||||
@ -478,6 +511,11 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
|
|||||||
si.si_code = BUS_OBJERR;
|
si.si_code = BUS_OBJERR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STATUS_DATATYPE_MISALIGNMENT:
|
||||||
|
si.si_signo = SIGBUS;
|
||||||
|
si.si_code = BUS_ADRALN;
|
||||||
|
break;
|
||||||
|
|
||||||
case STATUS_ACCESS_VIOLATION:
|
case STATUS_ACCESS_VIOLATION:
|
||||||
if (mmap_is_attached_page (e->ExceptionInformation[1]))
|
if (mmap_is_attached_page (e->ExceptionInformation[1]))
|
||||||
{
|
{
|
||||||
@ -485,8 +523,15 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
|
|||||||
si.si_code = BUS_OBJERR;
|
si.si_code = BUS_OBJERR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*FALLTHRU*/
|
else
|
||||||
case STATUS_DATATYPE_MISALIGNMENT:
|
{
|
||||||
|
MEMORY_BASIC_INFORMATION m;
|
||||||
|
VirtualQuery ((PVOID) e->ExceptionInformation[1], &m, sizeof m);
|
||||||
|
si.si_signo = SIGSEGV;
|
||||||
|
si.si_code = m.State == MEM_FREE ? SEGV_MAPERR : SEGV_ACCERR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case STATUS_ARRAY_BOUNDS_EXCEEDED:
|
case STATUS_ARRAY_BOUNDS_EXCEEDED:
|
||||||
case STATUS_IN_PAGE_ERROR:
|
case STATUS_IN_PAGE_ERROR:
|
||||||
case STATUS_NO_MEMORY:
|
case STATUS_NO_MEMORY:
|
||||||
@ -568,6 +613,22 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT
|
|||||||
stackdump ((DWORD) ebp, 0, 1);
|
stackdump ((DWORD) ebp, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e->ExceptionCode == STATUS_ACCESS_VIOLATION)
|
||||||
|
{
|
||||||
|
int error_code = 0;
|
||||||
|
if (si.si_code == SEGV_ACCERR) /* Address present */
|
||||||
|
error_code |= 1;
|
||||||
|
if (e->ExceptionInformation[0]) /* Write access */
|
||||||
|
error_code |= 2;
|
||||||
|
if (!interruptible (in)) /* User space */
|
||||||
|
error_code |= 4;
|
||||||
|
klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d",
|
||||||
|
__progname, myself->pid,
|
||||||
|
e->ExceptionInformation[1], in->Eip, in->Esp,
|
||||||
|
((in->Eip >= 0x61000000 && in->Eip < 0x61200000)
|
||||||
|
? 0 : 4) | (e->ExceptionInformation[0] << 1));
|
||||||
|
}
|
||||||
|
|
||||||
signal_exit (0x80 | si.si_signo); // Flag signal + core dump
|
signal_exit (0x80 | si.si_signo); // Flag signal + core dump
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,34 +723,9 @@ bool
|
|||||||
_cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
|
_cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler,
|
||||||
struct sigaction& siga)
|
struct sigaction& siga)
|
||||||
{
|
{
|
||||||
int res;
|
|
||||||
bool interrupted;
|
bool interrupted;
|
||||||
MEMORY_BASIC_INFORMATION m;
|
|
||||||
|
|
||||||
memset (&m, 0, sizeof m);
|
if (!interruptible (cx) || (incyg || spinning || locked ()))
|
||||||
if (!VirtualQuery ((LPCVOID) cx->Eip, &m, sizeof m))
|
|
||||||
sigproc_printf ("couldn't get memory info, pc %p, %E", cx->Eip);
|
|
||||||
|
|
||||||
char *checkdir = (char *) alloca (windows_system_directory_length + 4);
|
|
||||||
memset (checkdir, 0, sizeof (checkdir));
|
|
||||||
|
|
||||||
# define h ((HMODULE) m.AllocationBase)
|
|
||||||
/* Apparently Windows 95 can sometimes return bogus addresses from
|
|
||||||
GetThreadContext. These resolve to a strange allocation base.
|
|
||||||
These should *never* be treated as interruptible. */
|
|
||||||
if (!h || m.State != MEM_COMMIT)
|
|
||||||
res = false;
|
|
||||||
else if (h == user_data->hmodule)
|
|
||||||
res = true;
|
|
||||||
else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
|
|
||||||
res = false;
|
|
||||||
else
|
|
||||||
res = !strncasematch (windows_system_directory, checkdir,
|
|
||||||
windows_system_directory_length);
|
|
||||||
sigproc_printf ("pc %p, h %p, interruptible %d", cx->Eip, h, res);
|
|
||||||
# undef h
|
|
||||||
|
|
||||||
if (!res || (incyg || spinning || locked ()))
|
|
||||||
interrupted = false;
|
interrupted = false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user