From 5cb998e66c8a342dad9ea03fcb5126f12ec50156 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 13 Feb 2008 09:42:22 +0000 Subject: * cygtls.cc (_cygtls::init_exception_handler): Revert patch from 2005-12-02. * exceptions.cc (stack_info::walk): Add workaround for NT 5.2 64 bit OSes. * wincap.h (wincaps::has_restricted_stack_args): New element. * wincap.cc: Implement above element throughout. (wincapc::init): Reset has_restricted_stack_args if not running under WOW64. --- winsup/cygwin/ChangeLog | 11 +++++++++++ winsup/cygwin/cygtls.cc | 18 +++++++++++++++++- winsup/cygwin/exceptions.cc | 17 ++++++++++++++--- winsup/cygwin/wincap.cc | 15 ++++++++++++++- winsup/cygwin/wincap.h | 2 ++ 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 969dd03f6..0163a57d2 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2008-02-13 Corinna Vinschen + + * cygtls.cc (_cygtls::init_exception_handler): Revert patch + from 2005-12-02. + * exceptions.cc (stack_info::walk): Add workaround for NT 5.2 + 64 bit OSes. + * wincap.h (wincaps::has_restricted_stack_args): New element. + * wincap.cc: Implement above element throughout. + (wincapc::init): Reset has_restricted_stack_args if not running + under WOW64. + 2008-02-11 Corinna Vinschen * fhandler_disk_file.cc (fhandler_disk_file::fgetxattr): Remove unused diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 2bc7e85ba..af2723e95 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -260,7 +260,23 @@ void _cygtls::init_exception_handler (exception_handler *eh) { el.handler = eh; - el.prev = ⪙ + /* Apparently Windows stores some information about an exception and tries + to figure out if the SEH which returned 0 last time actually solved the + problem, or if the problem still persists (e.g. same exception at same + address). In this case Windows seems to decide that it can't trust + that SEH and calls the next handler in the chain instead. + + At one point this was a loop (el.prev = ⪙). This outsmarted the + above behaviour. Unfortunately this trick doesn't work anymore with + Windows 2008, which irremediably gets into an endless loop, taking 100% + CPU. That's why we reverted to a normal SEH chain. + + On the bright side, Windows' behaviour is covered by POSIX: + + "If and when the function returns, if the value of sig was SIGFPE, + SIGILL, or SIGSEGV or any other implementation-defined value + corresponding to a computational exception, the behavior is undefined." */ + el.prev = _except_list; _except_list = ⪙ } diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index fc361b59b..05cc91696 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -245,9 +245,20 @@ stack_info::walk () sf.AddrReturn.Offset = (DWORD) *++ebp; if (needargs) - /* The arguments follow the return address */ - for (unsigned i = 0; i < NPARAMS; i++) - sf.Params[i] = (DWORD) *++ebp; + { + unsigned nparams = NPARAMS; + + /* The arguments follow the return address */ + sf.Params[0] = (DWORD) *++ebp; + /* Hack for XP/2K3 WOW64. If the first stack param points to the + application entry point, we can only fetch one additional + parameter. Accessing anything beyond this address results in + a SEGV. This is fixed in Vista/2K8 WOW64. */ + if (wincap.has_restricted_stack_args () && sf.Params[0] == 0x401000) + nparams = 2; + for (unsigned i = 0; i < nparams; i++) + sf.Params[i] = (DWORD) *++ebp; + } return 1; } diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index e8b44c0e6..0a808e563 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -40,6 +40,7 @@ static NO_COPY wincaps wincap_unknown = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_nt4 = { @@ -69,6 +70,7 @@ static NO_COPY wincaps wincap_nt4 = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_nt4sp4 = { @@ -98,6 +100,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_2000 = { @@ -127,6 +130,7 @@ static NO_COPY wincaps wincap_2000 = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_2000sp4 = { @@ -156,6 +160,7 @@ static NO_COPY wincaps wincap_2000sp4 = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_xp = { @@ -185,6 +190,7 @@ static NO_COPY wincaps wincap_xp = { has_gaa_prefixes:false, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_xpsp1 = { @@ -214,6 +220,7 @@ static NO_COPY wincaps wincap_xpsp1 = { has_gaa_prefixes:true, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_xpsp2 = { @@ -243,6 +250,7 @@ static NO_COPY wincaps wincap_xpsp2 = { has_gaa_prefixes:true, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_2003 = { @@ -272,6 +280,7 @@ static NO_COPY wincaps wincap_2003 = { has_gaa_prefixes:true, has_gaa_on_link_prefix:false, supports_all_posix_ai_flags:false, + has_restricted_stack_args:true, }; static NO_COPY wincaps wincap_vista = { @@ -301,6 +310,7 @@ static NO_COPY wincaps wincap_vista = { has_gaa_prefixes:true, has_gaa_on_link_prefix:true, supports_all_posix_ai_flags:true, + has_restricted_stack_args:false, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); @@ -388,7 +398,10 @@ wincapc::init () if (IsWow64Process (GetCurrentProcess (), &is_wow64_proc)) wow64 = is_wow64_proc; else - ((wincaps *)this->caps)->needs_count_in_si_lpres2 = false; + { + ((wincaps *)this->caps)->needs_count_in_si_lpres2 = false; + ((wincaps *)this->caps)->has_restricted_stack_args = false; + } __small_sprintf (osnam, "NT-%d.%d", version.dwMajorVersion, version.dwMinorVersion); diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 55dc19cdb..167ea5e19 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -39,6 +39,7 @@ struct wincaps unsigned has_gaa_prefixes : 1; unsigned has_gaa_on_link_prefix : 1; unsigned supports_all_posix_ai_flags : 1; + unsigned has_restricted_stack_args : 1; }; class wincapc @@ -84,6 +85,7 @@ public: bool IMPLEMENT (has_gaa_prefixes) bool IMPLEMENT (has_gaa_on_link_prefix) bool IMPLEMENT (supports_all_posix_ai_flags) + bool IMPLEMENT (has_restricted_stack_args) #undef IMPLEMENT }; -- cgit v1.2.3