diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-02-13 09:42:24 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-02-13 09:42:24 +0000 |
commit | 7c25e1f0e3f541c22f6e59a9c0dbd68f48e3a5a7 (patch) | |
tree | b7a1cffd0d195b9e3648ca14a4da1786c2018228 | |
parent | 08f2354b8f60a9cae88f530bb030655265575dd7 (diff) | |
download | newlib-7c25e1f0e3f541c22f6e59a9c0dbd68f48e3a5a7.zip newlib-7c25e1f0e3f541c22f6e59a9c0dbd68f48e3a5a7.tar.gz newlib-7c25e1f0e3f541c22f6e59a9c0dbd68f48e3a5a7.tar.bz2 |
* 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.
-rw-r--r-- | winsup/cygwin/ChangeLog | 11 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.cc | 18 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 17 | ||||
-rw-r--r-- | winsup/cygwin/wincap.cc | 18 | ||||
-rw-r--r-- | winsup/cygwin/wincap.h | 2 |
5 files changed, 61 insertions, 5 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b7572d2..66da517 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2008-02-13 Corinna Vinschen <corinna@vinschen.de> + + * 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-01-24 Corinna Vinschen <corinna@vinschen.de> * path.cc (fs_info::update): Fix Samba test to support recent as well diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index e03175a..0b37ed6 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -261,7 +261,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 2280f82..d4c14e2 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -254,9 +254,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 = 1; i < nparams; i++) + sf.Params[i] = (DWORD) *++ebp; + } return 1; } diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index a8b94fc..3a96880 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -69,6 +69,7 @@ static NO_COPY wincaps wincap_unknown = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_95 = { @@ -129,6 +130,7 @@ static NO_COPY wincaps wincap_95 = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_95osr2 = { @@ -189,6 +191,7 @@ static NO_COPY wincaps wincap_95osr2 = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_98 = { @@ -249,6 +252,7 @@ static NO_COPY wincaps wincap_98 = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_98se = { @@ -309,6 +313,7 @@ static NO_COPY wincaps wincap_98se = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_me = { @@ -369,6 +374,7 @@ static NO_COPY wincaps wincap_me = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_nt3 = { @@ -429,6 +435,7 @@ static NO_COPY wincaps wincap_nt3 = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_nt4 = { @@ -489,6 +496,7 @@ static NO_COPY wincaps wincap_nt4 = { has_exclusiveaddruse:false, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_nt4sp4 = { @@ -549,6 +557,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_exclusiveaddruse:true, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_2000 = { @@ -609,6 +618,7 @@ static NO_COPY wincaps wincap_2000 = { has_exclusiveaddruse:true, has_buggy_restart_scan:true, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_xp = { @@ -669,6 +679,7 @@ static NO_COPY wincaps wincap_xp = { has_exclusiveaddruse:true, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:false, }; static NO_COPY wincaps wincap_2003 = { @@ -729,6 +740,7 @@ static NO_COPY wincaps wincap_2003 = { has_exclusiveaddruse:true, has_buggy_restart_scan:false, needs_count_in_si_lpres2:false, + has_restricted_stack_args:true, }; static NO_COPY wincaps wincap_vista = { @@ -789,6 +801,7 @@ static NO_COPY wincaps wincap_vista = { has_exclusiveaddruse:true, has_buggy_restart_scan:false, needs_count_in_si_lpres2:true, + has_restricted_stack_args:false, }; wincapc wincap __attribute__((section (".cygwin_dll_common"), shared)); @@ -902,7 +915,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, "%s-%d.%d", os, version.dwMajorVersion, version.dwMinorVersion); diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index f9b86a7..1a9227c 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -70,6 +70,7 @@ struct wincaps unsigned has_exclusiveaddruse : 1; unsigned has_buggy_restart_scan : 1; unsigned needs_count_in_si_lpres2 : 1; + unsigned has_restricted_stack_args : 1; }; class wincapc @@ -146,6 +147,7 @@ public: bool IMPLEMENT (has_exclusiveaddruse) bool IMPLEMENT (has_buggy_restart_scan) bool IMPLEMENT (needs_count_in_si_lpres2) + bool IMPLEMENT (has_restricted_stack_args) #undef IMPLEMENT }; |