Condividi tramite


Eventi di debug

Un evento di debug è un evento imprevisto nel processo di debug che causa la notifica al debugger da parte del sistema. Gli eventi di debug includono la creazione di un processo, la creazione di un thread, il caricamento di una libreria a collegamento dinamico (DLL), lo scaricamento di una DLL, l'invio di una stringa di output e la generazione di un'eccezione.

Se si verifica un evento di debug mentre un debugger è in attesa di uno, il sistema riempie la struttura DEBUG_EVENT specificata da WaitForDebugEvent con informazioni che descrivono l'evento.

Quando il sistema notifica al debugger di un evento di debug, sospende anche tutti i thread nel processo interessato. I thread non riprendono l'esecuzione finché il debugger continua l'evento di debug usando ContinueDebugEvent. Durante il debug di un processo possono verificarsi gli eventi di debug seguenti.

Evento di debug Descrizione
CREATE_PROCESS_DEBUG_EVENT
Generato ogni volta che viene creato un nuovo processo in un processo di cui viene eseguito il debug o ogni volta che il debugger avvia il debug di un processo già attivo. Il sistema genera questo evento di debug prima che il processo inizi a essere eseguito in modalità utente e prima che il sistema generi altri eventi di debug per il nuovo processo.
La struttura DEBUG_EVENT contiene una struttura CREATE_PROCESS_DEBUG_INFO. Questa struttura include un handle per il nuovo processo, un handle per il file di immagine del processo, un handle per il thread iniziale del processo e altre informazioni che descrivono il nuovo processo.
L'handle per il processo ha accesso PROCESS_VM_READ e PROCESS_VM_WRITE. Se un debugger ha questi tipi di accesso a un thread, può leggere e scrivere nella memoria del processo usando le funzioni ReadProcessMemory e WriteProcessMemory. Se il sistema ha segnalato in precedenza un evento EXIT_PROCESS_DEBUG_EVENT, il sistema chiude questo handle quando il debugger chiama la funzione ContinueDebugEvent.
L'handle per il file di immagine del processo ha GENERIC_READ accesso e viene aperto per la condivisione in lettura. Il debugger deve chiudere questo handle durante l'elaborazione CREATE_PROCESS_DEBUG_EVENT.
L'handle per il thread iniziale del processo ha THREAD_GET_CONTEXT, THREAD_edizione StandardT_CONTEXT e THREAD_SUSPEND_RESUME l'accesso al thread. Se un debugger dispone di questi tipi di accesso a un thread, può leggere e scrivere nei registri del thread usando le funzioni GetThreadContext e SetThreadContext e può sospendere e riprendere il thread usando le funzioni SuspendThread e ResumeThread. Se il sistema ha segnalato in precedenza un evento EXIT_PROCESS_DEBUG_EVENT, il sistema chiude questo handle quando il debugger chiama la funzione ContinueDebugEvent.
CREATE_THREAD_DEBUG_EVENT
Generato ogni volta che viene creato un nuovo thread in un processo di cui viene eseguito il debug o ogni volta che il debugger avvia il debug di un processo già attivo. Questo evento di debug viene generato prima che il nuovo thread inizi a essere eseguito in modalità utente.
La struttura DEBUG_EVENT contiene una struttura CREATE_THREAD_DEBUG_INFO. Questa struttura include un handle per il nuovo thread e l'indirizzo iniziale del thread. L'handle ha THREAD_GET_CONTEXT, THREAD_edizione StandardT_CONTEXT e THREAD_SUSPEND_RESUME l'accesso al thread. Se un debugger dispone di questi tipi di accesso a un thread, può leggere e scrivere nei registri del thread usando le funzioni GetThreadContext e SetThreadContext e può sospendere e riprendere il thread usando le funzioni SuspendThread e ResumeThread.
Se il sistema ha segnalato in precedenza un evento EXIT_THREAD_DEBUG_EVENT, il sistema chiude l'handle al nuovo thread quando il debugger chiama la funzione ContinueDebugEvent.
EXCEPTION_DEBUG_EVENT
Generato ogni volta che si verifica un'eccezione nel processo di debug. Le possibili eccezioni includono il tentativo di accedere alla memoria inaccessibile, l'esecuzione di istruzioni del punto di interruzione, il tentativo di dividere per zero o qualsiasi altra eccezione annotata in Gestione delle eccezioni strutturate.
La struttura DEBUG_EVENT contiene una struttura EXCEPTION_DEBUG_INFO. Questa struttura descrive l'eccezione che ha causato l'evento di debug.
Oltre alle condizioni di eccezione standard, durante il debug del processo della console può verificarsi un codice di eccezione aggiuntivo. Il sistema genera un codice eccezione DBG_CONTROL_C quando CTRL+C è l'input per un processo della console che gestisce i segnali CTRL+C e viene sottoposto a debug. Questo codice di eccezione non deve essere gestito dalle applicazioni. Un'applicazione non deve mai usare un gestore eccezioni per gestirlo. Viene generato solo per il vantaggio del debugger e viene usato solo quando un debugger è collegato al processo della console.
Se un processo non viene sottoposto a debug o se il debugger passa all'eccezione DBG_CONTROL_C non gestita (tramite il comando gn), viene eseguita la ricerca dell'elenco di funzioni del gestore dell'applicazione, come documentato per la funzione SetConsoleCtrlHandler.
Se il debugger gestisce l'eccezione DBG_CONTROL_C (tramite il comando gh), un'applicazione non noterà CTRL+C tranne nel codice simile al seguente.
while ((inputChar = getchar()) != EOF) ...
Pertanto, il debugger non può essere usato per arrestare l'attesa di lettura in tale codice dalla terminazione.
EXIT_PROCESS_DEBUG_EVENT
Generato ogni volta che viene chiuso l'ultimo thread in un processo di cui viene eseguito il debug. Questo evento di debug si verifica immediatamente dopo che il sistema scarica le DLL del processo e aggiorna il codice di uscita del processo.
La struttura DEBUG_EVENT contiene una struttura EXIT_PROCESS_DEBUG_INFO che specifica il codice di uscita.
Il debugger dealloca tutte le strutture interne associate al processo alla ricezione di questo evento di debug. Il sistema chiude l'handle del debugger al processo di uscita e a tutti i thread del processo. Il debugger non deve chiudere questi handle.
Non è possibile completare la parte in modalità kernel dell'arresto del processo finché il debugger che riceve questo evento chiama ContinueDebugEvent. Fino ad allora, gli handle di processo sono aperti e lo spazio degli indirizzi virtuali non viene rilasciato, in modo che il debugger possa esaminare il processo figlio. Per ricevere una notifica quando la parte in modalità kernel dell'arresto del processo è stata completata, duplicare l'handle restituito con CREATE_PROCESS_DEBUG_EVENT, chiamare ContinueDebugEvent e quindi attendere che venga segnalato l'handle del processo duplicato.
EXIT_THREAD_DEBUG_EVENT
Generato ogni volta che un thread che fa parte di un processo di cui viene eseguito il debug viene chiuso. Il sistema genera questo evento di debug immediatamente dopo l'aggiornamento del codice di uscita del thread.
La struttura DEBUG_EVENT contiene una struttura EXIT_THREAD_DEBUG_INFO che specifica il codice di uscita.
Questo evento di debug non si verifica se il thread di uscita è l'ultimo thread di un processo. In questo caso, l'evento di debug EXIT_PROCESS_DEBUG_EVENT si verifica invece.
Il debugger dealloca tutte le strutture interne associate al thread alla ricezione di questo evento di debug. Il sistema chiude l'handle del debugger al thread di uscita. Il debugger non deve chiudere questo handle.
LOAD_DLL_DEBUG_EVENT
Generato ogni volta che un processo sottoposto a debug carica una DLL. Questo evento di debug si verifica quando il caricatore di sistema risolve i collegamenti a una DLL o quando il processo sottoposto a debug usa la funzione LoadLibrary. Questo evento di debug si verifica solo la prima volta che il sistema collega una DLL allo spazio di indirizzi virtuale di un processo.
La struttura DEBUG_EVENT contiene una struttura LOAD_DLL_DEBUG_INFO. Questa struttura include un handle per la DLL appena caricata, l'indirizzo di base della DLL e altre informazioni che descrivono la DLL. Il debugger deve chiudere l'handle all'handle DLL durante l'elaborazione LOAD_DLL_DEBUG_EVENT.
In genere, un debugger carica una tabella dei simboli associata alla DLL alla ricezione di questo evento di debug.
OUTPUT_DEBUG_STRING_EVENT
Generato quando un processo sottoposto a debug usa
Funzione OutputDebugString . La struttura DEBUG_EVENT contiene una struttura OUTPUT_DEBUG_STRING_INFO. Questa struttura specifica l'indirizzo, la lunghezza e il formato della stringa di debug.
UNLOAD_DLL_DEBUG_EVENT
Generato ogni volta che un processo sottoposto a debug scarica una DLL usando la funzione FreeLibrary. Questo evento di debug si verifica solo l'ultima volta che una DLL viene scaricata dallo spazio indirizzi di un processo, ovvero quando il numero di utilizzo della DLL è zero.
La struttura DEBUG_EVENT contiene una struttura UNLOAD_DLL_DEBUG_INFO. Questa struttura specifica l'indirizzo di base della DLL nello spazio indirizzi del processo che scarica la DLL.
In genere, un debugger scarica una tabella dei simboli associata alla DLL quando riceve questo evento di debug.
Quando un processo viene chiuso, il sistema scarica automaticamente le DLL del processo, ma non genera un evento di debug UNLOAD_DLL_DEBUG_EVENT.
RIP_EVENT
Generato ogni volta che un processo sottoposto a debug muore al di fuori del controllo del debugger di sistema.
La struttura DEBUG_EVENT contiene una struttura RIP_INFO. Questa struttura specifica l'errore e il tipo di errore.