aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2008-02-13 09:42:22 +0000
committerCorinna Vinschen <corinna@vinschen.de>2008-02-13 09:42:22 +0000
commit5cb998e66c8a342dad9ea03fcb5126f12ec50156 (patch)
treea5ae719b8e10a5ac8cb4537b0a20dc28d557ed7b
parent9cb5dea0e22c3fdde4f0c638b052a0186587cf8f (diff)
downloadnewlib-5cb998e66c8a342dad9ea03fcb5126f12ec50156.zip
newlib-5cb998e66c8a342dad9ea03fcb5126f12ec50156.tar.gz
newlib-5cb998e66c8a342dad9ea03fcb5126f12ec50156.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.cc15
-rw-r--r--winsup/cygwin/wincap.h2
5 files changed, 58 insertions, 5 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 969dd03..0163a57 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-02-11 Corinna Vinschen <corinna@vinschen.de>
* fhandler_disk_file.cc (fhandler_disk_file::fgetxattr): Remove unused
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index 2bc7e85..af2723e 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 = &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 fc361b5..05cc916 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 e8b44c0..0a808e5 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 55dc19c..167ea5e 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
};