Debugereignisse
Ein Debugereignis ist ein Vorfall im debuggten Prozess, der bewirkt, dass das System den Debugger benachrichtigt. Debugereignisse umfassen das Erstellen eines Prozesses, das Erstellen eines Threads, das Laden einer DLL (Dynamic Link Library), das Entladen einer DLL, das Senden einer Ausgabezeichenfolge und das Generieren einer Ausnahme.
Wenn ein Debugereignis auftritt, während ein Debugger auf eines wartet, füllt das System die von WaitForDebugEvent angegebene DEBUG_EVENT Struktur mit Informationen, die das Ereignis beschreiben.
Wenn das System den Debugger über ein Debugereignis benachrichtigt, wird auch alle Threads im betroffenen Prozess angehalten. Die Ausführung der Threads wird erst fortgesetzt, wenn der Debugger das Debugereignis mithilfe von ContinueDebugEvent fortsetzt. Die folgenden Debugereignisse können auftreten, während ein Prozess debuggt wird.
Debugereignis | BESCHREIBUNG |
---|---|
CREATE_PROCESS_DEBUG_EVENT |
Wird generiert, wenn ein neuer Prozess in einem Prozess erstellt wird, der gedebuggt wird, oder wenn der Debugger mit dem Debuggen eines bereits aktiven Prozesses beginnt. Das System generiert dieses Debugereignis, bevor der Prozess im Benutzermodus ausgeführt wird und bevor das System andere Debugereignisse für den neuen Prozess generiert. Die DEBUG_EVENT-Struktur enthält eine CREATE_PROCESS_DEBUG_INFO-Struktur . Diese Struktur umfasst ein Handle für den neuen Prozess, ein Handle für die Imagedatei des Prozesses, ein Handle für den anfänglichen Thread des Prozesses und andere Informationen, die den neuen Prozess beschreiben. Das Handle für den Prozess verfügt über PROCESS_VM_READ und PROCESS_VM_WRITE Zugriff. Wenn ein Debugger über diese Arten von Zugriff auf einen Thread verfügt, kann er mithilfe der Funktionen ReadProcessMemory und WriteProcessMemory lesen und in den Arbeitsspeicher des Prozesses schreiben. Wenn das System zuvor ein EXIT_PROCESS_DEBUG_EVENT-Ereignis gemeldet hat, schließt das System dieses Handle, wenn der Debugger die ContinueDebugEvent-Funktion aufruft . Das Handle für die Imagedatei des Prozesses hat GENERIC_READ Zugriff und wird für die Lesefreigabe geöffnet. Der Debugger sollte dieses Handle während der Verarbeitung CREATE_PROCESS_DEBUG_EVENT schließen. Das Handle für den anfänglichen Thread des Prozesses verfügt über THREAD_GET_CONTEXT, THREAD_SET_CONTEXT und THREAD_SUSPEND_RESUME Zugriff auf den Thread. Wenn ein Debugger über diese Arten von Zugriff auf einen Thread verfügt, kann er mithilfe der Funktionen GetThreadContext und SetThreadContext aus den Registern des Threads lesen und in die Register schreiben und den Thread anhalten und fortsetzen, indem er die Funktionen SuspendThread und ResumeThread verwendet. Wenn das System zuvor ein EXIT_PROCESS_DEBUG_EVENT-Ereignis gemeldet hat, schließt das System dieses Handle, wenn der Debugger die ContinueDebugEvent-Funktion aufruft . |
CREATE_THREAD_DEBUG_EVENT |
Wird generiert, wenn ein neuer Thread in einem Prozess erstellt wird, der gedebuggt wird, oder wenn der Debugger mit dem Debuggen eines bereits aktiven Prozesses beginnt. Dieses Debugereignis wird generiert, bevor der neue Thread im Benutzermodus ausgeführt wird. Die DEBUG_EVENT-Struktur enthält eine CREATE_THREAD_DEBUG_INFO-Struktur . Diese Struktur enthält ein Handle für den neuen Thread und die Startadresse des Threads. Das Handle verfügt über THREAD_GET_CONTEXT, THREAD_SET_CONTEXT und THREAD_SUSPEND_RESUME Zugriff auf den Thread. Wenn ein Debugger über diese Arten von Zugriff auf einen Thread verfügt, kann er mithilfe der Funktionen GetThreadContext und SetThreadContext aus den Registern des Threads lesen und in die Register schreiben und den Thread anhalten und fortsetzen, indem er die Funktionen SuspendThread und ResumeThread verwendet. Wenn das System zuvor ein EXIT_THREAD_DEBUG_EVENT-Ereignis gemeldet hat, schließt das System das Handle für den neuen Thread, wenn der Debugger die ContinueDebugEvent-Funktion aufruft . |
EXCEPTION_DEBUG_EVENT |
Wird generiert, wenn im debuggten Prozess eine Ausnahme auftritt. Mögliche Ausnahmen sind der Versuch, auf nicht zugänglichen Arbeitsspeicher zuzugreifen, Die Ausführung von Haltepunktanweisungen, der Versuch, durch null zu dividieren, oder eine andere Ausnahme, die in der strukturierten Ausnahmebehandlung notiert ist. Die DEBUG_EVENT-Struktur enthält eine EXCEPTION_DEBUG_INFO-Struktur . Diese Struktur beschreibt die Ausnahme, die das Debugereignis verursacht hat. Neben den Standard-Ausnahmebedingungen kann während des Debuggens des Konsolenprozesses ein zusätzlicher Ausnahmecode auftreten. Das System generiert einen DBG_CONTROL_C Ausnahmecode, wenn STRG+C in einen Konsolenprozess eingegeben wird, der STRG+C-Signale verarbeitet und debuggt wird. Dieser Ausnahmecode ist nicht für die Verarbeitung von Anwendungen vorgesehen. Eine Anwendung sollte niemals einen Ausnahmehandler verwenden, um damit umzugehen. Es wird nur zum Nutzen des Debuggers ausgelöst und nur verwendet, wenn ein Debugger an den Konsolenprozess angefügt wird. Wenn ein Prozess nicht debuggt wird oder der Debugger die DBG_CONTROL_C Ausnahme unbehandelt übergibt (über den Befehl gn), wird die Liste der Handlerfunktionen der Anwendung durchsucht, wie für die SetConsoleCtrlHandler-Funktion dokumentiert. Wenn der Debugger die DBG_CONTROL_C-Ausnahme (über den Befehl gh) behandelt, wird eine Anwendung strg+C außer in Code wie diesem nicht bemerken. while ((inputChar = getchar()) != EOF) ... Daher kann der Debugger nicht verwendet werden, um zu verhindern, dass die Lesewarte in einem solchen Code beendet wird. |
EXIT_PROCESS_DEBUG_EVENT |
Wird generiert, wenn der letzte Thread in einem Prozess, der debuggt wird, beendet wird. Dieses Debugereignis tritt unmittelbar auf, nachdem das System die DLLs des Prozesses entladen und den Exitcode des Prozesses aktualisiert hat. Die DEBUG_EVENT-Struktur enthält eine EXIT_PROCESS_DEBUG_INFO-Struktur , die den Exitcode angibt. Der Debugger entfernt alle internen Strukturen, die dem Prozess zugeordnet sind, wenn dieses Debugereignis empfangen wird. Das System schließt das Handle des Debuggers mit dem beendenden Prozess und allen Threads des Prozesses. Der Debugger sollte diese Handles nicht schließen. Der Kernelmodusteil des Herunterfahrens des Prozesses kann erst abgeschlossen werden, wenn der Debugger, der dieses Ereignis empfängt , ContinueDebugEvent aufruft. Bis dahin sind die Prozesshandles geöffnet, und der virtuelle Adressraum wird nicht freigegeben, sodass der Debugger den untergeordneten Prozess untersuchen kann. Um eine Benachrichtigung zu erhalten, wenn der Kernelmodusteil des Herunterfahrens des Prozesses abgeschlossen ist, duplizieren Sie das mit CREATE_PROCESS_DEBUG_EVENT zurückgegebene Handle, rufen Sie ContinueDebugEvent auf, und warten Sie dann, bis das duplizierte Prozesshandle signalisiert wird. |
EXIT_THREAD_DEBUG_EVENT |
Wird generiert, wenn ein Thread, der Teil eines zu debuggenden Prozesses ist, beendet wird. Das System generiert dieses Debugereignis unmittelbar nach dem Aktualisieren des Exitcodes des Threads. Die DEBUG_EVENT-Struktur enthält eine EXIT_THREAD_DEBUG_INFO-Struktur , die den Exitcode angibt. Dieses Debugereignis tritt nicht auf, wenn der beendende Thread der letzte Thread eines Prozesses ist. In diesem Fall tritt stattdessen das EXIT_PROCESS_DEBUG_EVENT Debugereignis auf. Der Debugger entfernt alle internen Strukturen, die dem Thread zugeordnet sind, wenn dieses Debugereignis empfangen wird. Das System schließt das Handle des Debuggers mit dem beendenden Thread. Der Debugger sollte dieses Handle nicht schließen. |
LOAD_DLL_DEBUG_EVENT |
Wird generiert, wenn ein Prozess, der gedebuggt wird, eine DLL lädt. Dieses Debugereignis tritt auf, wenn der Systemladeprogramm Links zu einer DLL auflöst oder wenn der debuggierte Prozess die LoadLibrary-Funktion verwendet. Dieses Debugereignis tritt nur auf, wenn das System zum ersten Mal eine DLL an den virtuellen Adressraum eines Prozesses anfügt. Die DEBUG_EVENT-Struktur enthält eine LOAD_DLL_DEBUG_INFO-Struktur . Diese Struktur enthält ein Handle für die neu geladene DLL, die Basisadresse der DLL und andere Informationen, die die DLL beschreiben. Der Debugger sollte das Handle für das DLL-Handle während der Verarbeitung LOAD_DLL_DEBUG_EVENT schließen. In der Regel lädt ein Debugger beim Empfang dieses Debugereignisses eine der DLL zugeordnete Symboltabelle. |
OUTPUT_DEBUG_STRING_EVENT |
Wird generiert, wenn ein prozess, der gedebuggt wird, die OutputDebugString-Funktion . Die DEBUG_EVENT-Struktur enthält eine OUTPUT_DEBUG_STRING_INFO-Struktur . Diese Struktur gibt die Adresse, Die Länge und das Format der Debugzeichenfolge an. |
UNLOAD_DLL_DEBUG_EVENT |
Wird generiert, wenn ein prozess, der gedebuggt wird, eine DLL mithilfe der FreeLibrary-Funktion entladen wird. Dieses Debugereignis tritt nur auf, wenn eine DLL das letzte Mal aus dem Adressraum eines Prozesses entladen wird (das heißt, wenn die Dll-Nutzungsanzahl null ist). Die DEBUG_EVENT-Struktur enthält eine UNLOAD_DLL_DEBUG_INFO-Struktur . Diese Struktur gibt die Basisadresse der DLL im Adressraum des Prozesses an, der die DLL entlädt. In der Regel entlädt ein Debugger beim Empfang dieses Debugereignisses eine der DLL zugeordnete Symboltabelle. Wenn ein Prozess beendet wird, entlädt das System automatisch die DLLs des Prozesses, generiert jedoch kein UNLOAD_DLL_DEBUG_EVENT Debugereignis. |
RIP_EVENT |
Wird generiert, wenn ein Prozess, der gedebuggt wird, außerhalb der Kontrolle des Systemdebuggers stirbt. Die DEBUG_EVENT-Struktur enthält eine RIP_INFO-Struktur . Diese Struktur gibt den Fehler und den Typ des Fehlers an. |