<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 12pt;
font-family:Calibri
}
--></style></head>
<body class='hmmessage'><div dir='ltr'> There is a behavior/bug in wow64. <br> Bing for "wow64 GetThreadContext" "wow64 stack pointer", etc.<br><br><br><br> SuspendThread / GetThreadContext work like this: <br><br><br> 32bit processes consist almost entirely of 32bit code. <br> There is a small amount of 64bit code. <br><br><br> If you suspend while running 32bit code, GetThreadContext works. <br> if you suspend while running 64bit code, GetThreadContext usually but not always works. <br><br><br> 64bit code is run en route to syscalls. <br> For example you call: <br> 1 kernel32!Sleep <br> 2 it calls 32bit NtDelayExecution <br> 3 that calls wow64NtDelayExecutation (via a cross segment "far" jmp or call) <br> 4 which calls native NtDelayExecuation <br><br> <br> In between 2 and 3, within 64bit code, the 32bit context is saved. <br> You can step through it very easily in a debugger. Really. <br> Where GetThreadContext knows where to get it. <br> The problem is that saving context is not atomic. <br> You can suspend while saving context. <br><br><br> What to do? <br><br><br> scratch/wow64stack contains a program that detects the bug.<br> I believe it is the basis of a workaround for the bug. <br><br><br> Proposal is that in the compiler, for I386_NT/NT386/I386_MINGWIN/I386_CYGWIN/I386_INTERIX platforms, <br> not only functions that use exception handling, but also functions that call "extern" functions <br> call GetActivation / SetActivation and therein save/set/restore the stack pointer. And garbage collection<br> use that, if it isn't zero. <br> Normally it will be zero. <br> Syscalls do nest -- I can call SendMessage and in my window proc call CreateFile. <br> That is why it isn't a set/set-zero pattern (like in the test program). <br><br><br> Downside: We would like to get rid of GetActivation / SetActivation, i.e. and reuse efficient C++ exception handling. <br><br><br> Rejected counter proposal: <br> Don't suspend/gc when running a syscall. <br> No -- you can Sleep() a while. You can/should-be-able-to suspend and GC during that. <br><br><br> Possible augmentation: if running native, short circuit most of this <br><br><br> Rejected counter proposal: Have I386_NT_NATIVE that doesn't do this stuff. Relegate <br> compatibility to I386_NT_COMPATIBLE. I don't like having more platforms/targets. <br><br><br> AMD64_NT wouldn't have this stuff. Nor would other hypothetical platforms like ARM32_NT, <br> until/unless there is another 32bit platform runable on some similar 64bit platforms. <br><br><br> Performance impact: hypothetically large but probably not noticable. <br><br><br> Furthe refinements: It isn't extern/native code per se, it is syscalls.<br> We could further augment pragmas to discern them. <br><br><br> We could leave it to writing "syscall wrappers" and informally (no enforcement) ban direct calls <br> to any functions that make syscalls. This is likely too hard to maintain and too unfriendly. <br> It pretty viable in m3core, but then also libm3 and Trestle and Qt wrappers, etc... <br><br><br><br> Agreed? I'll make the compiler change? <br><br><br>Oh, also, not just stack pointer, but other registers, at least non-volatiles?<br><br><br>Eventually cooperative suspend will cause this to fall away as a problem..<br><br><br> - Jay<br> <br> </div></body>
</html>