SuspendThread WOW64暂停内核代码

Zac*_*Saw 6 c++ windows winapi wow64

更新:微软尚未在Windows 8.1中修复它.

编辑:这被证明是WOW64中的一个错误 - 当线程在长模式ring-3(用户模式)中挂起时,GetThreadContext()可能会返回过时的内容.我建议微软使用ring-2来执行翻译.然后,SuspendThread只会挂起ring-3中的线程(就像现在一样 - 不需要进行任何更改),而ring-2中的崩溃/故障/漏洞不会影响内核 - 它只会影响ring-2和ring- 3.

这些更改将需要更改一些WinAPI函数,例如Wow64Get/SetThreadContext等.这会破坏依赖于未记录的功能的应用程序,但这是可以预期的.当然,转换速度会慢一些,因为需要几个CPU周期才能从ring-3转换到ring-2(取决于CPU系列),但我认为操作系统的作用首先是确保正确操作.翻译已经增加了在WOW64下运行的应用程序的开销,所以这也是预期的.

我确实希望微软能解决这个问题 - 否则依赖于WOW64下的GetThreadContext()的调试器/ Mono应用程序/ Boehm GC /应用程序将无法工作(对于初学者,我看到调试器显示过时的堆栈跟踪).

EDIT2:坏消息.从我与MSFT的Alexey谈话(这里)看起来似乎根本不会修复,因为担心修复会破坏依赖于无证功能的应用程序.


原始问题

  • 有些人似乎对以下内容感到困惑.我最初认为这是由于SuspendThread在内核模式代码中挂起一个线程.事实并非如此.以下仅仅是我最初的怀疑,结果与实际的根本原因无关 - 这是由于返回的陈旧内容GetThreadContext().

来自MSDN:

Suspending a thread causes the thread to stop executing user-mode (application) code.

然而,我发现我的Windows 7中的32位应用程序在WOW64下运行,线程A调用线程B上的SuspendThread可以在运行64位代码时暂停它(我希望它不是用户模式代码).EIP显示停止的线程已停止

wow64cpu!X86SwitchTo64BitMode:
00000000`759c31b0 ea27369c753300  jmp     0033:759C3627
Run Code Online (Sandbox Code Playgroud)

ESP改变了(我知道这是因为,虽然ESP指向与该线程堆栈相同的页面,但它的地址比当前堆栈指针高得多).如果我在上面返回的指令处放置断点,然后让线程恢复,我发现ESP更改回X86SwitchTo64BitMode调用之前的值(这是正确的堆栈指针).我还发现,当单步进入同一个函数时,我无法在单步的任何一点获得更高的地址ESP值.实际上,当单步执行时,ESP值在X86SwitchTo64BitMode调用之前和之后都不会发生变化.

此外,我确实通过检查(DWORD)-1确保SuspendThread成功.

所有这些让我相信线程在内核模式代码中被挂起.

什么可能导致操作系统在运行非用户模式代码时挂起线程?我该如何预防呢?这基本上阻止我获取线程B的实际当前堆栈指针.请注意,当应用程序在WOW64之外运行时(在本机x86 OS上),不存在此类问题.

Zac*_*Saw 3

我已确认这是在 WOW64 下调用 GetThreadContext 时返回陈旧内容的操作系统问题。

更多信息请点击这里

感谢所有试图回答这个问题的人。我正在与 MS 合作解决此问题。