Udostępnij za pomocą


Włączanie debugowania postmortem

Obsługa wyjątków trybu użytkownika

Wyjątki i punkty przerwania

Najczęstsze błędy aplikacji są nazywane wyjątkami. Obejmują one naruszenia dostępu, błędy dzielenia według zera, przepełnienia liczbowe, wyjątki CLR i wiele innych rodzajów błędów. Aplikacje mogą również powodować przerwania punktów kontrolnych. Występują one, gdy system Windows nie może uruchomić aplikacji (na przykład gdy nie można załadować niezbędnego modułu) lub gdy napotkany jest punkt przerwania. Punkty przerwania można wstawić do kodu przez debuger lub wywołać za pomocą funkcji, takiej jak DebugBreak.

Pierwszeństwo procedur obsługi wyjątków

Na podstawie wartości konfiguracji i aktywnych debugerów system Windows obsługuje błędy trybu użytkownika na różne sposoby. Poniższa sekwencja przedstawia pierwszeństwo używane do obsługi błędów trybu użytkownika:

  1. Jeśli debuger trybu użytkownika jest obecnie dołączony do procesu błędów, wszystkie błędy spowodują włamanie do tego debugera.

    Tak długo, jak debuger trybu użytkownika jest dołączony, nie będą używane żadne inne metody obsługi błędów — nawet jeśli jest używane polecenie gn (Go With Exception Not Handled).

  2. Jeśli debuger trybu użytkownika nie jest dołączony, a wykonywanie kodu ma własne procedury obsługi wyjątków (na przykład spróbuj — z wyjątkiem), ta rutyna obsługi wyjątków spróbuje poradzić sobie z błędem.

  3. Jeśli debuger trybu użytkownika nie jest podłączony, system Windows ma otwarte połączenie do debugowania jądra, a błąd jest punktem przerwania, system Windows spróbuje nawiązać kontakt z debugerem jądra.

    Połączenia debugowania jądra muszą być otwarte podczas procesu rozruchu systemu Windows. Jeśli chcesz uniemożliwić przerwanie trybu użytkownika przed włamaniem do debugera jądra, możesz użyć narzędzia KDbgCtrl z parametrem -du . Aby uzyskać szczegółowe informacje na temat konfigurowania połączeń debugowania jądra i używania biblioteki KDbgCtrl, zobacz Getting Set Up for Debug (Konfigurowanie debugowania).

    W debugerze jądra można użyć gh (Przejdź z obsłużeniem wyjątku), aby zignorować błąd i kontynuować uruchamianie obiektu docelowego. Aby pominąć debuger jądra i przejść do kroku 4, możesz użyć gn (Go With Exception Not Handled).

  4. Jeśli warunki opisane w krokach 1, 2 i 3 nie mają zastosowania, system Windows aktywuje narzędzie debugowania skonfigurowane w wartościach rejestru AeDebug. Każdy program można wybrać z wyprzedzeniem jako narzędzie do użycia w tej sytuacji. Wybrany program jest określany jako debuger postmortem.

  5. Jeśli warunki w krokach 1, 2 i 3 nie mają zastosowania i nie ma zarejestrowanego debugera pośmiertnego, funkcja Raportowanie błędów systemu Windows (WER) wyświetla komunikat i udostępnia rozwiązania, jeśli są dostępne. Usługa WER zapisuje również plik zrzutu pamięci, jeśli odpowiednie wartości są ustawione w Rejestrze. Aby uzyskać więcej informacji, zobacz Użycie WER i Zbieranie zrzutów User-Mode.

Funkcja DebugBreak

Jeśli został zainstalowany debuger postmortem, możesz celowo włamać się do debugera z poziomu aplikacji trybu użytkownika, wywołując funkcję DebugBreak .

Określanie debugera Postmortem

W tej sekcji opisano sposób konfigurowania narzędzi, takich jak WinDbg, jako debugera postmortem. Po skonfigurowaniu debuger postmortem zostanie automatycznie uruchomiony za każdym razem, gdy aplikacja ulegnie awarii.

Klucze rejestru Debuggera Post Mortem

Raportowanie błędów systemu Windows (WER) tworzy proces debugowania postmortem, korzystając z wartości ustawionych w kluczu rejestru AeDebug.

HKLM\Oprogramowanie\Microsoft\Windows NT\CurrentVersion\AeDebug

Istnieją dwie podstawowe wartości rejestru, Debugger i Auto. Wartość rejestru debugera określa wiersz polecenia debugera postmortem. Wartość rejestru Auto określa, czy debuger postmortem jest uruchamiany automatycznie, czy najpierw wyświetlane jest okno komunikatu potwierdzenia.

Debugger (REG_SZ)

Ta wartość REG_SZ określa debuger, który będzie obsługiwał debugowanie pośmiertne.

Pełna ścieżka do debugera musi być wyświetlana, chyba że debuger znajduje się w katalogu znajdującym się w ścieżce domyślnej.

Wiersz polecenia jest generowany na podstawie ciągu debugera za pośrednictwem wywołania stylu printf, które zawiera 3 parametry. Mimo że kolejność jest stała, nie trzeba używać żadnych ani wszystkich dostępnych parametrów.

DWORD (%ld) — identyfikator procesu docelowego.

DWORD (%ld) — obsługa zdarzeń zduplikowana do procesu debugera postmortem. Jeśli debuger postmortem sygnalizuje zdarzenie, usługa WER będzie kontynuować proces docelowy bez oczekiwania na zakończenie debugera postmortem. Zdarzenie powinno być zasygnalizowane tylko wtedy, gdy problem został rozwiązany. Jeśli debuger postmortem zakończy się bez sygnalizowania zdarzenia, WER kontynuuje zbieranie informacji o procesach docelowych.

void* (%p) — adres struktury JIT_DEBUG_INFO przydzielonej w przestrzeni adresowej procesu docelowego. Struktura zawiera dodatkowe informacje o wyjątku i kontekście.

Auto (REG_SZ) Ta wartość REG_SZ zawsze wynosi 0 lub 1.

Jeśli wartość Auto jest ustawiona na 0, przed rozpoczęciem procesu debugowania po zakończeniu zostanie wyświetlone okno komunikatu z potwierdzeniem.

Jeśli ustawienie Auto ma wartość 1, debuger postmortem zostanie natychmiast utworzony.

Podczas ręcznej edycji rejestru należy to zrobić bardzo ostrożnie, ponieważ nieprawidłowe zmiany w rejestrze mogą nie zezwalać na rozruch systemu Windows.

Przykładowe użycie wiersza polecenia

Wiele debugerów postmortem używa wiersza polecenia, który zawiera -p i przełączniki -e, aby wskazać, że parametry są identyfikatorem PID i zdarzeniem (odpowiednio). Na przykład zainstalowanie windbg za pomocą polecenia windbg.exe -I tworzy następujące wartości:

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

Istnieje elastyczność w sposobie użycia parametrów usługi WER %ld %ld %p. Na przykład. nie trzeba określać żadnych przełączników lub między parametrami usługi WER. Na przykład zainstalowanie programu Windows Sysinternals ProcDump przy użyciu polecenia procdump.exe -i tworzy następujące wartości bez przełączników między parametrami %ld %ld %p usługi WER:

Debugger = "<Path>\procdump.exe" -accepteula -j "c:\Dumps" %ld %ld %p
Auto = 1

Debugery 32 i 64-bitowe

Na 64-bitowej platformie wartości rejestru Debuger (REG_SZ) i Auto (REG_SZ) są definiowane indywidualnie dla aplikacji 64-bitowych i 32-bitowych. Dodatkowy klucz Windows dla Windowsa (WOW) służy do przechowywania 32-bitowych wartości debugowania post mortem aplikacji.

HKLM\Oprogramowanie\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug

Na 64-bitowej platformie użyj 32-bitowego debugera pośmiertnego dla procesów 32-bitowych i 64-bitowego debugera dla procesów 64-bitowych. Pozwala to uniknąć 64-bitowego debugera koncentrującego się na wątkach WOW64 zamiast wątków 32-bitowych w procesie 32-bitowym.

W przypadku wielu debugerów postmortem, w tym narzędzi debugowania dla debugerów postmortem systemu Windows, obejmuje to dwukrotne uruchomienie polecenia instalacji; raz z wersją x86 i raz z wersją x64. Na przykład, aby użyć WinDbg jako interaktywnego debugera postmortem, polecenie windbg.exe -I zostanie uruchomione dwa razy, raz dla każdej wersji.

Instalacja 64-bitowa:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I

Spowoduje to zaktualizowanie klucza rejestru przy użyciu tych wartości.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe" -p %ld -e %ld –g

Instalacja 32-bitowa:

C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

Spowoduje to zaktualizowanie klucza rejestru przy użyciu tych wartości.

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug
Debugger = "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe" -p %ld -e %ld –g

Konfigurowanie debugerów post mortem

Narzędzia debugowania dla systemu Windows

Narzędzia Debuggery dla systemu Windows wszystkie obsługują konfigurację jako debuger postmortem. Polecenie instalacji planuje, aby proces był debugowany interaktywnie.

WinDbg

Aby ustawić debuger postmortem na WinDbg, uruchom polecenie windbg -I. (Wartość I musi być pisana wielką literą). To polecenie wyświetla komunikat o powodzeniu lub niepowodzeniu po jego użyciu. Aby pracować z aplikacjami 32 i 64-bitowymi, uruchom polecenie zarówno dla debugerów 64, jak i 32.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\windbg.exe –I
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\windbg.exe –I

W ten sposób wpis rejestru AeDebug zostanie skonfigurowany, gdy uruchamiane jest windbg -I.

Debugger = "<Path>\WinDbg -p %ld -e %ld -g"
Auto = 1

W przykładach <ścieżka> to katalog, w którym znajduje się debuger.

Parametry -p i -e przekazują identyfikator procesu i zdarzenie, zgodnie z wcześniejszym opisem.

-g przekazuje polecenie „g” (Go) do „WinDbg” i kontynuuje wykonywanie z bieżącej instrukcji.

Uwaga Istnieje istotny problem z przekazywaniem polecenia g (Go). Problem z tym podejściem polega na tym, że wyjątki nie zawsze powtarzają się, zazwyczaj z powodu przejściowego warunku, który już nie istnieje po ponownym uruchomieniu kodu. Aby uzyskać więcej informacji na temat tego problemu, zobacz .jdinfo (Użyj JIT_DEBUG_INFO).

Aby uniknąć tego problemu, użyj polecenia .jdinfo lub .dump /j. Takie podejście pozwala debugerowi być w kontekście błędu w kodzie. Aby uzyskać więcej informacji, zobacz debugowanie Just In Time (JIT) później w tym temacie.

CDB

Aby ustawić debuger postmortem na CDB, uruchom polecenie cdb -iae (Install AeDebug) lub cdb -iaecKeyString (Zainstaluj AeDebug za pomocą polecenia).

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iae

Gdy jest używany parametr -iaec , KeyString określa ciąg, który ma zostać dołączony na końcu wiersza polecenia używanego do uruchomienia debugera postmortem. Jeśli KeyString zawiera spacje, musi być ujęty w cudzysłów.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\cdb.exe -iaec [KeyString]

To polecenie nie wyświetla niczego, jeśli zakończy się powodzeniem, i komunikat o błędzie, jeśli zakończy się niepowodzeniem.

NTSD

Aby ustawić debuger postmortem na NTSD, uruchom ntsd -iae (Zainstaluj AeDebug) lub ntsd -iaecKeyString (Zainstaluj AeDebug z komendą).

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iae
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iae

Gdy jest używany parametr -iaec , KeyString określa ciąg, który ma zostać dołączony na końcu wiersza polecenia używanego do uruchomienia debugera postmortem. Jeśli KeyString zawiera spacje, musi być ujęta w cudzysłowie.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\ntsd.exe -iaec [KeyString]
C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\ntsd.exe -iaec [KeyString]

To polecenie nie wyświetla niczego, jeśli się powiedzie, a w przypadku niepowodzenia pojawi się błąd w nowym oknie konsoli.

Nuta Ponieważ parametry -p %ld -e %ld -g zawsze pojawiają się najpierw w wierszu polecenia debugera postmortem, nie należy używać przełącznika -iaec w celu określenia parametru -server, ponieważ -server nie będzie działać, chyba że pojawi się on jako pierwszy w wierszu polecenia. Aby zainstalować debuger postmortem zawierający ten parametr, należy ręcznie edytować rejestr.

Debuger JIT programu Visual Studio

Jeśli program Visual Studio został zainstalowany, vsjitdebugger.exe zostanie zarejestrowany jako debuger po awarii. Debuger JIT programu Visual Studio zamierza debugować proces interaktywnie.

Debugger = "C:\WINDOWS\system32\vsjitdebugger.exe" -p %ld -e %ld

Jeśli program Visual Studio zostanie zaktualizowany lub ponownie zainstalowany, ten wpis zostanie ponownie napisany, zastępując wszystkie alternatywne wartości ustawione.

Windows Sysinternals ProcDump

Narzędzie ProcDump systemu Windows Sysinternals może być używane do przechwytywania zrzutów postmortem. Aby uzyskać więcej informacji na temat korzystania z narzędzia ProcDump i pobierania go, zobacz ProcDump.

Podobnie jak polecenie .dump WinDbg, ProcDump może przechwycić zrzut awarii nieinterakcyjnej. Przechwytywanie może wystąpić w dowolnej sesji systemu Windows.

ProcDump kończy działanie po zakończeniu przechwytywania pliku zrzutu, następnie usługa WER zgłasza błąd, a wadliwy proces zostaje zakończony.

Użyj procdump -i polecenia, aby zainstalować narzędzie ProcDump i -u, aby odinstalować narzędzie ProcDump zarówno dla debugowania 32-bitowego, jak i 64-bitowego.

<Path>\procdump.exe -i

Polecenia instalowania i odinstalowywania wyświetlają wartości rejestru zmodyfikowane w przypadku powodzenia oraz błędy w przypadku niepowodzenia.

Opcje wiersza polecenia ProcDump w rejestrze są ustawione na:

Debugger = <Path>\ProcDump.exe -accepteula -j "<DumpFolder>" %ld %ld %p

ProcDump używa wszystkich 3 parametrów — PID, Event i JIT_DEBUG_INFO. Aby uzyskać więcej informacji na temat parametru JIT_DEBUG_INFO, zobacz Just In Time (JIT) Debugging (debugowanie Just In Time) poniżej.

Domyślny rozmiar przechwyconego zrzutu to Mini (proces/wątki/uchwyty/moduły/przestrzeń adresowa) bez ustawionej opcji rozmiaru, MiniPlus (Mini plus strony MEM_PRIVATE) gdy ustawiono -mp, lub Pełny (cała pamięć — równoważne ".dump /mA") gdy ustawiono -ma.

W przypadku systemów z wystarczającą ilością miejsca na dysku zaleca się pełne przechwytywanie (-ma).

Użyj -ma z opcją -i, aby określić wszystkie przechwytywanie pamięci. Opcjonalnie podaj ścieżkę do plików zrzutu.

<Path>\procdump.exe -ma -i c:\Dumps

W systemach z ograniczoną przestrzenią dyskową zaleca się zapis MiniPlus (-mp).

<Path>\procdump.exe -mp -i c:\Dumps

Folder do zapisania pliku zrzutu jest opcjonalny. Wartość domyślna to bieżący folder. Folder powinien być zabezpieczony listą ACL, która jest równa lub lepsza niż to, co jest używane dla C:\Windows\Temp. Aby uzyskać więcej informacji na temat zarządzania zabezpieczeniami powiązanymi z folderami, zobacz Zabezpieczenia podczas debugowania pośmiertnego.

Aby odinstalować narzędzie ProcDump jako debuger postmortem i przywrócić poprzednie ustawienia, użyj opcji -u (Odinstaluj).

<Path>\procdump.exe -u

Aby uzyskać dodatkowe informacje na temat ProcDump, zobacz ProcDump i Windows SysInternals Administrator's Reference autorstwa Marka Russinovicha i Aarona Margosisa, opublikowane przez Microsoft Press.

Debugowanie just in time (JIT)

Konfigurowanie kontekstu dla aplikacji z błędami

Jak wspomniano wcześniej, bardzo wskazane jest ustawienie kontekstu dla wyjątku, który spowodował awarię, przy użyciu parametru JIT_DEBUG_INFO. Aby uzyskać więcej informacji na ten temat, zobacz .jdinfo (Użyj JIT_DEBUG_INFO).

narzędzia debugowania dla systemu Windows

W tym przykładzie pokazano, jak edytować rejestr, aby uruchomić początkowe polecenie (-c), które używa komendy .jdinfo <address>, aby wyświetlić dodatkowe informacje o wyjątku i zmienić kontekst na lokalizację wyjątku (podobnie jak .ecxr jest używane do ustawiania kontekstu na rekord wyjątku).

Debugger = "<Path>\windbg.exe -p %ld -e %ld -c ".jdinfo 0x%p"
Auto = 1

Parametr %p jest adresem struktury JIT_DEBUG_INFO w przestrzeni adresowej procesu docelowego. Parametr %p jest poprzedzony 0x, dzięki czemu jest interpretowany jako wartość szesnastkową. Aby uzyskać więcej informacji, zobacz .jdinfo (Używanie JIT_DEBUG_INFO).

Aby debugować kombinację 32-bitowych i 64-bitowych aplikacji, skonfiguruj zarówno 32-bitowe, jak i 64-bitowe klucze rejestru (opisane powyżej), ustawiając właściwą ścieżkę do lokalizacji 64-bitowych i 32-bitowych aplikacji WinDbg.exe.

Tworzenie pliku zrzutu przy użyciu .dump

Aby przechwycić plik zrzutu za każdym razem, gdy wystąpi błąd zawierający dane JIT_DEBUG_INFO, użyj adresu> .dump /j<.

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd"

Użyj opcji /u, aby wygenerować unikatową nazwę pliku, aby zezwolić na automatyczne tworzenie wielu plików zrzutu. Aby uzyskać więcej informacji na temat opcji, zobacz .dump (Create Dump File).

Utworzony zrzut będzie miał dane JITDEBUG_INFO przechowywane jako domyślny kontekst wyjątku. Zamiast używać .jdinfo, aby wyświetlić informacje o wyjątku i ustawić kontekst, użyj .exr -1, aby wyświetlić rekord wyjątku i ecxr, aby ustawić kontekst. Aby uzyskać więcej informacji, zobacz .exr (Display Exception Record) i .ecxr (Display Exception Context Record).

Raportowanie błędów systemu Windows — q/qd

Sposób zakończenia sesji debugowania określa, czy raportowanie błędów systemu Windows zgłasza błąd.

Jeśli sesja debugowania jest odłączona za pomocą qd przed zamknięciem debuggera, WER zgłosi awarię.

Jeśli sesja debugowania zostanie zakończona przy użyciu funkcji q (lub jeśli debuger jest zamknięty bez odłączania), usługa WER nie zgłosi błędu.

Dołącz ; q lub ; qd na końcu ciągu polecenia, aby wywołać żądane zachowanie.

Aby na przykład umożliwić usłudze WER zgłaszanie awarii po tym, jak CDB przechwyci zrzut, skonfiguruj ten ciąg polecenia.

<Path>\cdb.exe -p %ld -e %ld -c ".dump /j 0x%p /u c:\Dumps\AeDebug.dmp; qd"

Ten przykład umożliwia WER zgłaszanie awarii po przechwyceniu zrzutu przez WinDbg.

<Path>\windbg.exe -p %ld -e %ld -c ".dump /j %p /u <DumpPath>\AeDebug.dmp; qd""

Luki w zabezpieczeniach

Jeśli rozważasz włączenie debugowania pośmiertnego na komputerze, który udostępniasz innym osobom, zobacz Zabezpieczenia podczas debugowania postmortem.