[M3devel] EXT: proposal for getting wow64 context/stack reliably?

Coleburn, Randy rcolebur at SCIRES.COM
Thu Jan 23 12:59:34 CET 2014


Jay,

If I'm following you correctly, you are saying that this bug happens when running on 64bit Windows, but not on 32bit, since it applies only to SysWOW64.

Since the thread test program also misbehaves on 32bit Windows, there must yet be some other bug in the underlying implementation affecting both 32 & 64 bit platforms.

Thus, the SysWOW64 issue is a 2nd, additional problem for 64bit.

Has anyone made any progress in solving the 1st, underlying problem affecting both 32/64 bit Windows?

--Randy

Sent from my iPhone

On Jan 23, 2014, at 2:58 AM, "Jay K" <jay.krell at cornell.edu<mailto:jay.krell at cornell.edu>> wrote:

  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:
    1 kernel32!Sleep
    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..


 - Jay

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20140123/ab6f0152/attachment-0002.html>


More information about the M3devel mailing list