aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-02-13 09:42:24 +0000
committerCorinna Vinschen <corinna@vinschen.de>2008-02-13 09:42:24 +0000
commit7c25e1f0e3f541c22f6e59a9c0dbd68f48e3a5a7 (patch)
treeb7a1cffd0d195b9e3648ca14a4da1786c2018228
parent08f2354b8f60a9cae88f530bb030655265575dd7 (diff)
downloadnewlib-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/ChangeLog11
-rw-r--r--winsup/cygwin/cygtls.cc18
-rw-r--r--winsup/cygwin/exceptions.cc17
-rw-r--r--winsup/cygwin/wincap.cc18
-rw-r--r--winsup/cygwin/wincap.h2
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 = &el;
+ /* 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 = &el;). 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 = &el;
}
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
};