Почему 64-битная Windows не может отменить исключения пользователя-ядра-пользователя?

Почему 64-битная Windows не может разматывать стек во время исключения, если стек пересекает границу ядра - когда 32-битная Windows может?

Контекст всего этого вопроса исходит из:

Случай исчезновения исключения OnLoad & # x2013; исключения обратного вызова в пользовательском режиме в x64

Background

В 32-битной Windows, если я выброшу исключение в моемuser mode код, который был отозван изkernel mode код, который был вызван из моегоuser mode код, например:

User mode                     Kernel Mode
------------------            -------------------
CreateWindow(...);   ------>  NtCreateWindow(...)
                                   |
WindowProc   <---------------------+                                   

Структурная обработка исключений (SEH) в Windows может разматывать стек, разматывая обратно через режим ядра, обратно в мой код пользователя, где я могу обработать исключение и вижу правильную трассировку стека.

But not in 64-bit Windows

64-разрядные версии Windows не могут сделать это:

For complicated reasons, we cannot propagate the exception back on 64-bit operating systems (amd64 and IA64). This has been the case ever since the first 64-bit release of Server 2003. On x86, this isn’t the case – the exception gets propagated through the kernel boundary and would end up walking the frames back

И поскольку в этом случае невозможно вернуться к надежной трассировке стека, пришлось принять решение: позволить вам увидеть несущественное исключение или спрятать его полностью:

The kernel architects at the time decided to take the conservative AppCompat-friendly approach – hide the exception, and hope for the best.

Далее в статье рассказывается, как все 64-битные операционные системы Windows вели себя так:

Windows XP 64-bit Windows Server 2003 64-bit Windows Vista 64-bit Windows Server 2008 64-bit

Но начиная с Windows 7 (и Windows Server 2008), архитекторы изменили свое мнение - вроде как. Заonly 64-битные приложения (не 32-битные), они будут (по умолчанию)stop подавление этих исключений user-kernel-user. Итак, по умолчанию, на:

Windows 7 64-bit Windows Server 2008

все 64-битные приложения будутsee эти исключения, где они никогда не видели их.

In Windows 7, when a native x64 application crashes in this fashion, the Program Compatibility Assistant is notified. If the application doesn’t have a Windows 7 Manifest, we show a dialog telling you that PCA has applied an Application Compatibility shim. What does this mean? This means, that the next time you run your application, Windows will emulate the Server 2003 behavior and make the exception disappear. Keep in mind, that PCA doesn’t exist on Server 2008 R2, so this advice doesn’t apply.

So the question

Вопрос в томwhy 64-битная Windows не может размотать стек обратно через переход ядра,while 32-bit editions of Windows can?

Единственный совет:

For complicated reasons, we cannot propagate the exception back on 64-bit operating systems (amd64 and IA64).

Подсказкаit's complicated.

Я не понимаю объяснения, так как я не разработчик операционной системы, но мне хотелось бы узнать, почему.

Update: Hotfix to stop suppressing 32-bit apps

Microsoft выпустилаhotfix enables 32-bit applications также больше не исключаются исключения:

KB976038: Exceptions that are thrown from an application that runs in a 64-bit version of Windows are ignored An exception that is thrown in a callback routine runs in the user mode.

In this scenario, this exception does not cause the application to crash. Instead, the application enters into an inconsistent state. Then, the application throws a different exception and crashes.

A user mode callback function is typically an application-defined function that is called by a kernel mode component. Examples of user mode callback functions are Windows procedures and hook procedures. These functions are called by Windows to process Windows messages or to process Windows hook events.

Затем исправление позволяет вам запретить Windows использовать глобальные исключения:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
DisableUserModeCallbackFilter: DWORD = 1

или для каждого приложения:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Notepad.exe
DisableUserModeCallbackFilter: DWORD = 1

Поведение было также задокументировано на XP и Server 2003 в KB973460:

Exceptions that are thrown from a 64-bit application that is running in the 64-bit editions of Windows Server 2003 or of Windows XP Professional are silently ignored A hint

я обнаружил другую подсказку при исследовании использования xperf для захвата следов стека в 64-битной Windows:

Stack Walking in Xperf

Disable Paging Executive

In order for tracing to work on 64-bit Windows you need to set the DisablePagingExecutive registry key. This tells the operating system not to page kernel mode drivers and system code to disk, which is a prerequisite for getting 64-bit call stacks using xperf, because 64-bit stack walking depends on metadata in the executable images, and in some situations the xperf stack walk code is not allowed to touch paged out pages. Running the following command from an elevated command prompt will set this registry key for you.

 REG ADD "HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management" -v 
 DisablePagingExecutive -d 0x1 -t REG_DWORD -f

After setting this registry key you will need to reboot your system before you can record call stacks. Having this flag set means that the Windows kernel locks more pages into RAM, so this will probably consume about 10 MB of additional physical memory.

Это создает впечатление, что в 64-битной Windows (и только в 64-битной Windows) вам не разрешается проходить стеки ядра, поскольку на диске могут быть страницы.

Ответы на вопрос(2)

Ваш ответ на вопрос