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