ОБНОВЛЕНИЕ : Microsoft еще не исправила это в Windows 8.1.
РЕДАКТИРОВАТЬ : Получилосьчтобы быть ошибкой в WOW64 - GetThreadContext () может вернуть устаревшее содержимое, когда поток приостановлен в длинном режиме ring-3 (пользовательский режим).Я предложил Microsoft использовать кольцо-2 для выполнения перевода.В этом случае SuspendThread будет только приостанавливать поток в кольце-3 (как это происходит сейчас - никаких изменений не требуется), а сбой / ошибка / эксплойт в кольце-2 не повлияет на ядро - это повлияет только на кольцо-2 и кольцо-3.
Такие изменения потребуют изменения некоторых функций WinAPI, таких как Wow64Get / SetThreadContext и т. Д. Это приведет к поломке приложений, использующих недокументированные функции, но этого и следовало ожидать.Конечно, трансляция будет медленнее, поскольку для перехода от кольца 3 к кольцу 2 (в зависимости от семейства процессоров) требуется несколько циклов ЦП, но я думаю, что роль ОС - это прежде всего обеспечение правильной работы.Трансляция уже добавляет накладные расходы на приложения, работающие под WOW64, поэтому этого тоже следует ожидать.
Я действительно надеюсь, что Microsoft исправит эту проблему - в противном случае отладчики / моно-приложения / Boehm GC / приложения, использующие GetThreadContext () в разделеWOW64 не будет работать (для начала я видел, как отладчики показывают трассировку устаревшего стека).
EDIT2 : плохие новости.Из моего разговора с Алексеем из MSFT ( здесь ) это выглядит так, как будто оно вообще не может быть исправлено, опасаясь, что это исправит приложения, использующие недокументированные функции.
Оригинальный вопрос
- Некоторые люди, похоже, смущены следующим.Первоначально я думал, что это произошло из-за приостановки потока SuspendThread в то время как в коде режима ядра.Не былоСледующее было просто моим первоначальным подозрением, которое, как оказалось, не имело ничего общего с действительной первопричиной - устаревшим содержимым, возвращаемым
GetThreadContext()
.
из MSDN:
Suspending a thread causes the thread to stop executing user-mode (application) code.
Однако я обнаружил, что мое 32-разрядное приложение в Windows 7, работающее под управлением WOW64, поток A, вызывающий SuspendThread в потоке B, может приостановить его, пока выполняется 64-разрядный код (который яможно ожидать, что не код режима пользователя).EIP показывает, что приостановленный поток остановился на
wow64cpu!X86SwitchTo64BitMode:
00000000`759c31b0 ea27369c753300 jmp 0033:759C3627
с измененным ESP (я знаю это, потому что, хотя ESP указывает на ту же страницу, что и стек этого потока, он имеет гораздо более высокий адрес, чем текущийуказатель стека).Если я поместил точку останова в инструкцию, к которой вернулось вышеизложенное, и затем возобновил поток, я обнаружил, что ESP возвращается к значению до вызова X86SwitchTo64BitMode (который является правильным указателем стека).Я также обнаружил, что при одном шаге в одну и ту же функцию я никогда не смогу получить более высокое значение ESP адреса в любой точке одного шага.На самом деле, при однократном шаге значение ESP никогда не изменяется до и после вызова X86SwitchTo64BitMode.
Кроме того, я удостоверился, что SuspendThread преуспел, проверив (DWORD) -1.
Все этизаставляет меня поверить, что поток приостановлен в коде режима ядра.
Что может быть причиной того, что ОС приостанавливает поток, пока выполняется код не в режиме пользователя?Как мне это предотвратить?Это в основном мешает мне получить фактический текущий указатель стека потока B. Обратите внимание, что когда приложение работает за пределами WOW64 (на собственной операционной системе x86), такой проблемы не существует.