偵錯事件
偵錯事件是正在偵錯的進程中導致系統通知調試程式的事件。 偵錯事件包括建立進程、建立線程、載入動態連結庫 (DLL)、卸除 DLL、傳送輸出字串,以及產生例外狀況。
如果調試程式正在等候時發生偵錯事件,系統會以描述事件的資訊填入 WaitForDebugEvent 所指定的DEBUG_EVENT結構。
當系統通知調試程式偵錯事件時,它也會暫停受影響進程中的所有線程。 除非調試程式使用 ContinueDebugEvent 繼續偵錯事件,否則線程不會繼續執行。 正在偵錯進程時,可能會發生下列偵錯事件。
偵錯事件 | 描述 |
---|---|
CREATE_PROCESS_DEBUG_EVENT |
每當正在偵錯的進程中建立新進程,或每當調試程序開始偵錯已作用中的進程時,就會產生。 系統會在進程開始在使用者模式中執行之前產生這個偵錯事件,而且在系統為新進程產生任何其他偵錯事件之前。 DEBUG_EVENT 結構包含CREATE_PROCESS_DEBUG_INFO結構。 此結構包含新進程的句柄、進程的圖像檔句柄、進程初始線程的句柄,以及描述新進程的其他資訊。 進程的句柄具有PROCESS_VM_READ和PROCESS_VM_WRITE存取權。 如果調試程式具有線程的這些存取類型,則可以使用 ReadProcessMemory 和 WriteProcessMemory 函式來讀取和寫入進程的記憶體。 如果系統先前回報了EXIT_PROCESS_DEBUG_EVENT事件,當調試程式呼叫 ContinueDebugEvent 函式時,系統會關閉此句柄。 處理程式映像檔的句柄具有GENERIC_READ存取權,且已開啟以供讀取共用。 調試程序應該會在處理CREATE_PROCESS_DEBUG_EVENT時關閉此句柄。 進程初始線程的句柄具有線程的THREAD_GET_CONTEXT、THREAD_SET_CONTEXT和THREAD_SUSPEND_RESUME存取線程。 如果調試程式具有這些類型的線程存取權,則可以使用 GetThreadContext 和 SetThreadContext 函式來讀取和寫入線程的緩存器,而且可以使用 SuspendThread 和 ResumeThread 函式暫停和繼續線程。 如果系統先前回報了EXIT_PROCESS_DEBUG_EVENT事件,當調試程式呼叫 ContinueDebugEvent 函式時,系統會關閉此句柄。 |
CREATE_THREAD_DEBUG_EVENT |
每當正在偵錯的進程中建立新的線程,或每當調試程序開始偵錯已作用中的進程時,就會產生。 這個偵錯事件會在新的線程開始以使用者模式執行之前產生。 DEBUG_EVENT 結構包含CREATE_THREAD_DEBUG_INFO結構。 此結構包含新線程和線程起始位址的句柄。 句柄具有線程THREAD_GET_CONTEXT、THREAD_SET_CONTEXT和THREAD_SUSPEND_RESUME存取權。 如果調試程式具有這些類型的線程存取權,則可以使用 GetThreadContext 和 SetThreadContext 函式來讀取和寫入線程的緩存器,而且可以使用 SuspendThread 和 ResumeThread 函式暫停和繼續線程。 如果系統先前回報EXIT_THREAD_DEBUG_EVENT事件,當調試程式呼叫 ContinueDebugEvent 函式時,系統會關閉新線程的句柄。 |
EXCEPTION_DEBUG_EVENT |
每當正在偵錯的進程發生例外狀況時產生。 可能的例外狀況包括嘗試存取無法存取的記憶體、執行斷點指令、嘗試除以零,或結構化例外狀況處理中記下的任何其他例外狀況。 DEBUG_EVENT 結構包含EXCEPTION_DEBUG_INFO結構。 此結構描述造成偵錯事件的例外狀況。 除了標準例外狀況,主控台進程偵錯期間可能會發生額外的例外狀況程序代碼。 當 CTRL+C 輸入處理 CTRL+C 訊號並進行偵錯的控制台進程時,系統會產生DBG_CONTROL_C例外狀況代碼。 此例外狀況程式代碼並非由應用程式處理。 應用程式不應該使用例外狀況處理程序來處理它。 它只會針對調試程式的優點而引發,而且只有在調試程式附加至主控台進程時才使用。 如果未偵錯進程,或調試程式在未處理的DBG_CONTROL_C例外狀況上傳遞(透過 gn 命令),則會搜尋應用程式的處理程式函式清單,如 SetConsoleCtrlHandler 函式所述。 如果調試程式處理DBG_CONTROL_C例外狀況(透過 gh 命令),則應用程式不會注意到 CTRL+C,除非在類似這樣的程式代碼中。 while ((inputChar = getchar()) != EOF) ... 因此,調試程式無法用來停止這類程式代碼中的讀取等候終止。 |
EXIT_PROCESS_DEBUG_EVENT |
每當正在偵錯的進程的最後一個線程結束時產生。 此偵錯事件會在系統卸除進程的 DLL 並更新進程的結束代碼之後立即發生。 DEBUG_EVENT 結構包含指定結束代碼的EXIT_PROCESS_DEBUG_INFO結構。 調試程式會在收到這個偵錯事件時解除分配與進程相關聯的任何內部結構。 系統會關閉調試程式的句柄至結束進程和所有進程的線程。 調試程式不應該關閉這些句柄。 在收到此事件 呼叫 ContinueDebugEvent 的調試程式之前,無法完成進程關機的核心模式部分。 在此之前,進程句柄會開啟且虛擬位址空間未釋放,因此調試程式可以檢查子進程。 若要在進程關機的核心模式部分完成時收到通知,請複製傳回CREATE_PROCESS_DEBUG_EVENT的句柄、呼叫 ContinueDebugEvent,然後等候重複的進程句柄收到訊號。 |
EXIT_THREAD_DEBUG_EVENT |
每當屬於正在偵錯的進程一部分的線程結束時,就會產生。 系統會在更新線程結束代碼之後立即產生此偵錯事件。 DEBUG_EVENT 結構包含指定結束代碼的 EXIT_THREAD_DEBUG_INFO 結構。 如果結束線程是進程的最後一個線程,就不會發生這個偵錯事件。 在此情況下,會改為發生EXIT_PROCESS_DEBUG_EVENT偵錯事件。 調試程式會在收到這個偵錯事件時解除分配與線程相關聯的任何內部結構。 系統會關閉調試程式的句柄至結束的線程。 調試程式不應該關閉此句柄。 |
LOAD_DLL_DEBUG_EVENT |
每當正在偵錯的進程載入 DLL 時產生。 當系統載入器解析 DLL 的連結或偵錯的進程使用 LoadLibrary 函式時,就會發生此偵錯事件。 這個偵錯事件只會在系統第一次將 DLL 附加至進程的虛擬位址空間時發生。 DEBUG_EVENT 結構包含LOAD_DLL_DEBUG_INFO結構。 此結構包含新載入 DLL 的句柄、DLL 的基位址,以及其他描述 DLL 的資訊。 調試程式應該在處理LOAD_DLL_DEBUG_EVENT時關閉 DLL 句柄的句柄。 一般而言,調試程式會在收到這個偵錯事件時載入與 DLL 相關聯的符號數據表。 |
OUTPUT_DEBUG_STRING_EVENT |
在偵錯的進程使用時產生 OutputDebugString 函 式。 DEBUG_EVENT 結構包含OUTPUT_DEBUG_STRING_INFO結構。 這個結構會指定偵錯字串的位址、長度和格式。 |
UNLOAD_DLL_DEBUG_EVENT |
每當偵錯的進程使用 FreeLibrary 函式卸除 DLL 時產生。 這個偵錯事件只會在最後一次從進程的位址空間卸除 DLL 時發生(也就是 DLL 的使用計數為零時)。 DEBUG_EVENT 結構包含UNLOAD_DLL_DEBUG_INFO結構。 此結構會在卸除 DLL 之進程的位址空間中指定 DLL 的基位址。 一般而言,調試程式會在收到這個偵錯事件時卸除與 DLL 相關聯的符號數據表。 當進程結束時,系統會自動卸除進程的 DLL,但不會產生UNLOAD_DLL_DEBUG_EVENT偵錯事件。 |
RIP_EVENT |
每當偵錯的進程在系統調試程式的控制之外死亡時,就會產生。 DEBUG_EVENT 結構包含RIP_INFO結構。 此結構會指定錯誤和錯誤類型。 |