Dlaczego 64-bitowy system Windows nie może wyłączyć wyjątków użytkowników-jądra?

Dlaczego 64-bitowy system Windows nie może rozwinąć stosu podczas wyjątku, jeśli stos przekracza granicę jądra - gdy może działać 32-bitowy system Windows?

Kontekst tego całego pytania pochodzi z:

Przypadek znikającego wyjątku OnLoad - wyjątki wywołania zwrotnego w trybie użytkownika w x64

tło

W 32-bitowym systemie Windows, jeśli rzucę wyjątek w moimtryb użytkownika kod, z którego oddzwonionotryb jądra kod, który został wywołany z mojegotryb użytkownika kod, np .:

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

Strukturalna obsługa wyjątków (SEH) w systemie Windows może rozwinąć stos, odwijając się z powrotem w tryb jądra, z powrotem do mojego kodu użytkownika, gdzie mogę obsłużyć wyjątek i zobaczyć poprawny ślad stosu.

Ale nie w 64-bitowym systemie Windows

64-bitowe wersje systemu Windows nie mogą tego zrobić:

Ze skomplikowanych powodów mynie może propagować wyjątku z powrotem w 64-bitowych systemach operacyjnych (amd64 i IA64). Dzieje się tak od pierwszego wydania 64-bitowego serwera Server 2003. W przypadku x86 nie jest tak - wyjątek jest propagowany przez granicę jądra i kończy się cofaniem ramek

A ponieważ w tym przypadku nie ma możliwości powrotu do niezawodnego śledzenia stosu, musieli podjąć decyzję: pozwolić ci zobaczyć wyjątek bez znaczenia lub całkowicie go ukryć:

Architekci jądra w owym czasie postanowili zastosować konserwatywne podejście przyjazne AppCompat - ukryć wyjątek i mieć nadzieję na najlepsze.

Artykuł mówi o tym, jak zachowały się wszystkie 64-bitowe systemy operacyjne Windows:

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

Ale począwszy od Windows 7 (i Windows Server 2008) architekci zmienili zdanie - coś w tym rodzaju. Dlatylko Aplikacje 64-bitowe (nie 32-bitowe), byłyby (domyślnie)zatrzymać tłumienie wyjątków użytkowników-jądra. Tak więc domyślnie:

Windows 7 64-bitWindows Server 2008

wszystkie aplikacje 64-bitowe będąwidzieć te wyjątki, w których nigdy ich nie widzieli.

W systemie Windows 7, gdy anatywny x64 aplikacja ulega awarii w ten sposóbAsystent zgodności programów jest powiadomiony. Jeśli aplikacja nie maWindows 7 Manifest, pokazujemy okno dialogowe informujące, że PCA zastosowałoPodkładka kompatybilności aplikacji. Co to znaczy? Oznacza to, że przy następnym uruchomieniu aplikacji system Windows będzie emulować zachowanie serwera 2003 i sprawić, że wyjątek zniknie. Pamiętaj, że PCA nie istnieje w Server 2008 R2, więc ta rada nie ma zastosowania.

Więc pytanie

Pytanie brzmiczemu 64-bitowy system Windows nie jest w stanie przywrócić stosu przez przejście jądra,podczas gdy 32-bitowe wersje systemu Windows mogą?

Jedyna wskazówka to:

Ze skomplikowanych powodów mynie może propagować wyjątku z powrotem w 64-bitowych systemach operacyjnych (amd64 i IA64).

Wskazówka jestto skomplikowane.

nie rozumiem wyjaśnienia, ponieważ nie jestem programistą systemu operacyjnego - ale chciałbym wiedzieć, dlaczego.

Aktualizacja: poprawka, aby przestać tłumić aplikacje 32-bitowe

Microsoft wydała poprawka włącza aplikacje 32-bitowe nie ma już także wyłączonych wyjątków:

KB976038: Wyjątki zgłaszane z aplikacji działającej w 64-bitowej wersji systemu Windows są ignorowaneWyjątek zgłoszony w procedurze wywołania zwrotnego działa w trybie użytkownika.

W tym scenariuszu ten wyjątek nie powoduje awarii aplikacji. Zamiast tego aplikacja przechodzi w niespójny stan. Następnie aplikacja zgłasza inny wyjątek i ulega awarii.

Funkcja wywołania zwrotnego w trybie użytkownika jest zazwyczaj funkcją zdefiniowaną przez aplikację, która jest wywoływana przez składnik trybu jądra. Przykładami funkcji zwrotnych w trybie użytkownika są procedury systemu Windows i procedury przechwytywania. Funkcje te są wywoływane przez system Windows do przetwarzania komunikatów systemu Windows lub do przetwarzania zdarzeń przechwytywania systemu Windows.

Poprawka pozwala następnie powstrzymać system Windows od spożywania wyjątków na całym świecie:

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

lub na aplikację:

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

Zachowanie zostało również udokumentowane na XP i Server 2003 w KB973460:

Wyjątki zgłaszane z 64-bitowej aplikacji uruchomionej w 64-bitowych wersjach systemu Windows Server 2003 lub Windows XP Professional są po cichu ignorowaneWskazówka

znalazłem kolejną wskazówkę przy badaniu Xperf do przechwytywania śladów stosu w 64-bitowym systemie Windows:

Stack Walking w Xperf

Wyłącz aplikację Paging Executive

Aby śledzenie działało na 64-bitowym systemie Windows, musisz ustawićDisablePagingExecutive klucz rejestru. Mówi to systemowi operacyjnemu, aby nie kierował stron na sterowniki trybu jądra i kod systemowy na dysk, co jest warunkiem uzyskania 64-bitowych stosów wywołań przy użyciu xperf, ponieważ 64-bitowe chodzenie po stosie zależy od metadanych w plikach wykonywalnych, aw niektórych sytuacjach xperfkod chodu stosu nie może dotykać stronicowanych stron. Uruchomienie następującego polecenia z wiersza polecenia z podwyższonym poziomem uprawnień spowoduje ustawienie tego klucza rejestru.

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

Po ustawieniu tego klucza rejestru będziesz musiał ponownie uruchomić system, aby móc nagrywać stosy połączeń. Posiadanie tego zestawu flag oznacza, że ​​jądro systemu Windows blokuje więcej stron w pamięci RAM, więc prawdopodobnie zajmie to około 10 MB dodatkowej pamięci fizycznej.

Daje to wrażenie, że w 64-bitowym systemie Windows (i tylko w 64-bitowym systemie Windows) nie można przechodzić stosów jądra, ponieważ na dysku mogą znajdować się strony.

questionAnswers(2)

yourAnswerToTheQuestion