Udostępnij za pomocą


Debugowanie zdarzeń

Zdarzenie debugowania to zdarzenie w procesie debugowania, które powoduje, że system powiadamia debuger. Zdarzenia debugowania obejmują tworzenie procesu, tworzenie wątku, ładowanie biblioteki dll dynamicznej, zwalnianie biblioteki DLL, wysyłanie ciągu wyjściowego i generowanie wyjątku.

Jeśli wystąpi zdarzenie debugowania podczas oczekiwania debugera, system wypełnia strukturę DEBUG_EVENT określoną przez WaitForDebugEvent z informacjami opisującym zdarzenie.

Gdy system powiadamia debugera zdarzenia debugowania, zawiesza również wszystkie wątki w procesie, którego dotyczy problem. Wątki nie wznawiają wykonywania, dopóki debuger nie kontynuuje debugowania zdarzenia przy użyciu ContinueDebugEvent. Podczas debugowania procesu mogą wystąpić następujące zdarzenia debugowania.

Zdarzenie debugowania Opis
CREATE_PROCESS_DEBUG_EVENT
Generowane za każdym razem, gdy nowy proces jest tworzony w trakcie debugowania lub za każdym razem, gdy debuger rozpoczyna debugowanie już aktywnego procesu. System generuje to zdarzenie debugowania przed rozpoczęciem wykonywania procesu w trybie użytkownika i przed wygenerowaniem przez system innych zdarzeń debugowania dla nowego procesu.
Struktura DEBUG_EVENT zawiera strukturę CREATE_PROCESS_DEBUG_INFO. Ta struktura obejmuje dojście do nowego procesu, dojście do pliku obrazu procesu, dojście do początkowego wątku procesu i inne informacje opisujące nowy proces.
Dojście do procesu ma dostęp PROCESS_VM_READ i PROCESS_VM_WRITE. Jeśli debuger ma dostęp do wątku tego typu, może odczytywać i zapisywać w pamięci procesu przy użyciu funkcji ReadProcessMemory i WriteProcessMemory. Jeśli system wcześniej zgłosił zdarzenie EXIT_PROCESS_DEBUG_EVENT, system zamyka ten uchwyt, gdy debuger wywołuje funkcję ContinueDebugEvent.
Dojście do pliku obrazu procesu ma GENERIC_READ dostęp i jest otwarty do udostępniania odczytu. Debuger powinien zamknąć ten uchwyt podczas przetwarzania CREATE_PROCESS_DEBUG_EVENT.
Dojście do początkowego wątku procesu ma THREAD_GET_CONTEXT, THREAD_SET_CONTEXT i THREAD_SUSPEND_RESUME dostęp do wątku. Jeśli debuger ma dostęp do wątku tego typu, może odczytywać i zapisywać w rejestrach wątku przy użyciu GetThreadContext i funkcji SetThreadContext oraz może zawiesić i wznowić wątek przy użyciu funkcji SuspendThread i ResumeThread. Jeśli system wcześniej zgłosił zdarzenie EXIT_PROCESS_DEBUG_EVENT, system zamyka ten uchwyt, gdy debuger wywołuje funkcję ContinueDebugEvent.
CREATE_THREAD_DEBUG_EVENT
Generowane za każdym razem, gdy nowy wątek zostanie utworzony podczas debugowania lub za każdym razem, gdy debuger rozpoczyna debugowanie już aktywnego procesu. To zdarzenie debugowania jest generowane przed rozpoczęciem wykonywania nowego wątku w trybie użytkownika.
Struktura DEBUG_EVENT zawiera strukturę CREATE_THREAD_DEBUG_INFO. Ta struktura zawiera uchwyt dla nowego wątku i adresu początkowego wątku. Dojście ma dostęp THREAD_GET_CONTEXT, THREAD_SET_CONTEXT i THREAD_SUSPEND_RESUME do wątku. Jeśli debuger ma dostęp do wątku tego typu, może odczytywać i zapisywać w rejestrach wątku przy użyciu GetThreadContext i funkcji SetThreadContext oraz może zawiesić i wznowić wątek przy użyciu funkcji SuspendThread i ResumeThread.
Jeśli system wcześniej zgłosił zdarzenie EXIT_THREAD_DEBUG_EVENT, system zamyka dojście do nowego wątku, gdy debuger wywołuje funkcję ContinueDebugEvent.
EXCEPTION_DEBUG_EVENT
Generowane za każdym razem, gdy wystąpi wyjątek podczas debugowania procesu. Możliwe wyjątki obejmują próbę uzyskania dostępu do niedostępnej pamięci, wykonanie instrukcji punktu przerwania, próbę podzielenia przez zero lub inny wyjątek zanotowany w obsługi wyjątków strukturalnych.
Struktura DEBUG_EVENT zawiera strukturę EXCEPTION_DEBUG_INFO. Ta struktura opisuje wyjątek, który spowodował zdarzenie debugowania.
Oprócz standardowych warunków wyjątku podczas debugowania procesu konsoli może wystąpić dodatkowy kod wyjątku. System generuje kod wyjątku DBG_CONTROL_C, gdy ctrl+C jest wejściowy do procesu konsoli obsługującego sygnały CTRL+C i jest debugowany. Ten kod wyjątku nie jest przeznaczony do obsługi przez aplikacje. Aplikacja nigdy nie powinna używać procedury obsługi wyjątków, aby sobie z nią poradzić. Jest on zgłaszany tylko dla korzyści debugera i jest używany tylko wtedy, gdy debuger jest dołączony do procesu konsoli.
Jeśli proces nie jest debugowany lub debuger przekazuje wyjątek DBG_CONTROL_C nieobsługiwany (za pomocą polecenia gn), lista funkcji obsługi aplikacji jest przeszukiwana zgodnie z dokumentacją funkcji SetConsoleCtrlHandler.
Jeśli debuger obsługuje wyjątek DBG_CONTROL_C (za pomocą polecenia gh), aplikacja nie zauważy CTRL+C z wyjątkiem kodu takiego jak ten.
while ((inputChar = getchar()) != EOF) ...
W związku z tym debuger nie może służyć do zatrzymania oczekiwania na odczyt w takim kodzie z kończeniem.
EXIT_PROCESS_DEBUG_EVENT
Generowane za każdym razem, gdy ostatni wątek w procesie jest debugowany kończy działanie. To zdarzenie debugowania występuje natychmiast po tym, jak system zwalnia biblioteki DLL procesu i aktualizuje kod zakończenia procesu.
Struktura DEBUG_EVENT zawiera strukturę EXIT_PROCESS_DEBUG_INFO, która określa kod zakończenia.
Debuger cofa przydział wszelkich struktur wewnętrznych skojarzonych z procesem po otrzymaniu tego zdarzenia debugowania. System zamyka dojście debugera do procesu zakończenia i wszystkich wątków procesu. Debuger nie powinien zamykać tych dojść.
Nie można ukończyć części zamykania procesu w trybie jądra, dopóki debuger odbierający to zdarzenie wywołuje ContinueDebugEvent. Do tego czasu dojścia procesu są otwarte, a wirtualna przestrzeń adresowa nie jest zwalniana, więc debuger może zbadać proces podrzędny. Aby otrzymywać powiadomienie po zakończeniu części zamknięcia procesu w trybie jądra, zduplikuj dojście zwrócone przy użyciu CREATE_PROCESS_DEBUG_EVENT, wywołaj ContinueDebugEvent, a następnie zaczekaj na zasygnalizowane zduplikowane dojście procesu.
EXIT_THREAD_DEBUG_EVENT
Generowane za każdym razem, gdy wątek będący częścią debugowanego procesu kończy działanie. System generuje to zdarzenie debugowania natychmiast po zaktualizowaniu kodu zakończenia wątku.
Struktura DEBUG_EVENT zawiera strukturę EXIT_THREAD_DEBUG_INFO, która określa kod zakończenia.
To zdarzenie debugowania nie występuje, jeśli wątek zakończenia jest ostatnim wątkiem procesu. W takim przypadku zamiast tego wystąpi zdarzenie debugowania EXIT_PROCESS_DEBUG_EVENT.
Debuger cofa przydział wszelkich struktur wewnętrznych skojarzonych z wątkiem po otrzymaniu tego zdarzenia debugowania. System zamyka dojście debugera do wątku zakończenia. Debuger nie powinien zamknąć tego uchwytu.
LOAD_DLL_DEBUG_EVENT
Generowane za każdym razem, gdy debugowany proces ładuje bibliotekę DLL. To zdarzenie debugowania występuje, gdy moduł ładujący systemu rozpoznaje łącza do biblioteki DLL lub gdy debugowany proces używa funkcji LoadLibrary. To zdarzenie debugowania występuje tylko po raz pierwszy, gdy system dołącza bibliotekę DLL do wirtualnej przestrzeni adresowej procesu.
Struktura DEBUG_EVENT zawiera strukturę LOAD_DLL_DEBUG_INFO. Ta struktura zawiera dojście do nowo załadowanej biblioteki DLL, podstawowy adres biblioteki DLL i inne informacje opisujące bibliotekę DLL. Debuger powinien zamknąć dojście do dojścia DLL podczas przetwarzania LOAD_DLL_DEBUG_EVENT.
Zazwyczaj debuger ładuje tabelę symboli skojarzona z biblioteką DLL po otrzymaniu tego zdarzenia debugowania.
OUTPUT_DEBUG_STRING_EVENT
Generowane, gdy debugowany proces używa elementu
funkcja OutputDebugString. Struktura DEBUG_EVENT zawiera strukturę OUTPUT_DEBUG_STRING_INFO. Ta struktura określa adres, długość i format ciągu debugowania.
UNLOAD_DLL_DEBUG_EVENT
Generowane za każdym razem, gdy debugowany proces zwalnia bibliotekę DLL przy użyciu funkcji FreeLibrary. To zdarzenie debugowania występuje tylko podczas ostatniego zwolnienia biblioteki DLL z przestrzeni adresowej procesu (czyli wtedy, gdy liczba użycia bibliotek DLL wynosi zero).
Struktura DEBUG_EVENT zawiera strukturę UNLOAD_DLL_DEBUG_INFO. Ta struktura określa podstawowy adres biblioteki DLL w przestrzeni adresowej procesu, który zwalnia bibliotekę DLL.
Zazwyczaj debuger zwalnia tabelę symboli skojarzona z biblioteką DLL po otrzymaniu tego zdarzenia debugowania.
Po zakończeniu procesu system automatycznie zwalnia biblioteki DLL procesu, ale nie generuje zdarzenia debugowania UNLOAD_DLL_DEBUG_EVENT.
RIP_EVENT
Generowane za każdym razem, gdy debugowany proces umiera poza kontrolą debugera systemu.
Struktura DEBUG_EVENT zawiera strukturę RIP_INFO. Ta struktura określa błąd i typ błędu.