日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Win32]一个调试器的实现(二)调试事件的处理

發布時間:2024/9/5 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Win32]一个调试器的实现(二)调试事件的处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇文章說到了調試循環的寫法,這回講一下調試器應該如何處理各種調試事件。

?

RIP_EVENT

關于這種調試事件的文檔資料非常少,即使提到也只是用“系統錯誤”或者“內部錯誤”一筆帶過。既然如此,我們也不需要對其進行什么處理,只要輸出一條信息或者干脆忽略它即可。

?

OUTPUT_DEBUG_STRING_EVENT

當被調試進程調用OutputDebugString時就會引發該類調試事件,OUTPUT_DEBUG_STRING_INFO結構體描述了關于該事件的詳細信息。在MSDN中,對該結構體各字段的解釋是:lpDebugStringData字段是字符串在被調試進程的進程空間內的地址;nDebugStringLength字段是以字符為單位的字符串的長度;fUnicode指示字符串是否Unicode編碼的。根據我個人的實驗觀察,發現只有第一個字段的解釋是對的。實際上,無論調用OutputDebugStringA還是OutputDebugStringW,字符串都會以ANSI編碼來表示。如果是調用OutputDebugStringW,那么會先將字符串轉換成ANSI編碼之后再調用OutputDebugStringA(這個過程在MSDN內有描述)。所以fUnicode的值永遠都是0,而nDebugStringLength是以字節為單位的字符串長度,而不是以字符為單位。

?

既然字符串是在被調試進程的地址空間內,我們就要使用ReadProcessMemory函數讀取這個字符串。下面的代碼展示了這個過程:

?1?void?OnOutputDebugString(const?OUTPUT_DEBUG_STRING_INFO*?pInfo)?{
?2?
?3?????BYTE*?pBuffer?=?(BYTE*)malloc(pInfo->nDebugStringLength);
?4?
?5?????SIZE_T?bytesRead;
?6?
?7?????ReadProcessMemory(
?8?????????g_hProcess,
?9?????????pInfo->lpDebugStringData,
10?????????pBuffer,?
11?????????pInfo->nDebugStringLength,
12?????????&bytesRead);
13?
14?????int?requireLen?=?MultiByteToWideChar(
15?????????CP_ACP,
16?????????MB_PRECOMPOSED,
17?????????(LPCSTR)pBuffer,
18?????????pInfo->nDebugStringLength,
19?????????NULL,
20?????????0);
21?
22?????TCHAR*?pWideStr?=?(TCHAR*)malloc(requireLen?*?sizeof(TCHAR));
23?
24?????MultiByteToWideChar(
25?????????CP_ACP,
26?????????MB_PRECOMPOSED,
27?????????(LPCSTR)pBuffer,
28?????????pInfo->nDebugStringLength,
29?????????pWideStr,
30?????????requireLen);
31?
32?????std::wcout?<<?TEXT("Debuggee?debug?string:?")?<<?pWideStr?<<??std::endl;
33?
34?????free(pWideStr);
35?????free(pBuffer);
36?}

?

g_hProcess是類型為HANDLE的全局變量。在啟動被調試進程之后就將它的句柄賦給了g_hProcess

?

LOAD_DLL_DEBUG_EVENT

加載一個DLL模塊之后引發該類調試事件,LOAD_DLL_DEBUG_INFO結構體描述了它的詳細信息。lpImageName這個字段可能會使你想在調試器中輸出DLL的文件名,然而這行不通。MSDN上的解釋是,lpImageName的值是文件名字符串在被調試進程的進程空間內的地址,但是這個值可能為NULL,即使不為NULL,通過ReadProcessMemory讀取到的內容也可能是NULL。所以,想通過這個字段獲取DLL的文件名并不可靠。

?

那么,通過hFile字段來獲取文件名如何?沒有Windows API可以直接通過文件句柄獲取文件名,想要這么做的話必須繞一個大圈子,詳細的方法請參考:http://blog.csdn.net/bodybo/archive/2006/08/28/1131346.aspx

?

實際上hFile是與dwDebugInfoFileOffsetnDebugInfoSize一起使用的,用于獲取DLL文件的調試信息。一般情況下我們不需要這么做,所以只要調用CloseHandle關閉這個句柄即可。記住!關閉這個句柄非常重要,如果不這么做的話會引起資源泄漏。

?

我的想法是,先通過EnumProcessModules枚舉被調試進程的模塊,然后通過GetModuleInformation獲取模塊的基地址,將這個基地址與LOAD_DLL_DEBUG_INFO結構體的lpBaseOfDll字段進行比較,如果相等的話就通過GetModuleFileNameEx獲取DLL的文件名。可是我在實驗這個方法的時候EnumProcessModules總是返回FALSEGetLastError返回299,這是什么原因呢?

?

這可能是因為當調試器在處理這類調試事件時,被調試進程還沒有啟動完畢,所需要的模塊還未全部加載完成,所以無法獲取它的模塊信息。

?

UNLOAD_DLL_DEBUG_EVENT

卸載一個DLL模塊的時候引發該類調試事件。一般情況下只要輸出一條信息或者忽略它即可。

?

CREATE_PROCESS_DEBUG_EVENT

創建進程之后的第一個調試事件,CREATE_PROCESS_DEBUG_INFO結構體描述了該類調試事件的詳細信息。該結構體有三個字段是句柄,分別是hFilehProcesshThread,同樣要記得使用CloseHandle關閉它們!

?

EXIT_PROCESS_DEBUG_EVENT

被調試進程結束時引發此類調試事件,EXIT_PROCESS_DEBUG_INFO結構體描述了它的詳細信息。或許你能做的只有輸出dwExitCode這個字段的值。

?

CREATE_THREAD_DEBUG_EVENT

創建一個線程之后引發此類調試事件,CREATE_THREAD_DEBUG_INFO結構體描述了它的詳細信息。同樣要記住用CloseHandle關閉hThread字段!

?

EXIT_THREAD_DEBUG_EVENT

一個線程結束之后引發此類調試事件,EXIT_THREAD_DEBUG_INFO結構體描述了它的詳細信息。對此同樣也只能輸出dwExitCode的值。

?

EXCEPTION_DEBUG_EVENT

發生異常時引發此類調試事件,EXCEPTION_DEBUG_INFO結構體描述了它的詳細信息。對這種調試事件的處理是最麻煩的,因為異常的種類非常多,對每種異常的處理也不相同。另外,此類調試事件也是實現斷點和單步執行的關鍵。

?

由于關于這類調試事件的篇幅太多,因此將其放到下一篇文章中講解。

?

示例代碼

這次的示例代碼基本上跟上次的示例代碼基本上一樣,只是添加了本文中描述的內容,改動非常有限,所以如果覺得沒必要的話就不要下載了。

http://files.cnblogs.com/zplutor/MiniDebugger2.rar

轉載于:https://www.cnblogs.com/zplutor/archive/2011/03/06/1972540.html

總結

以上是生活随笔為你收集整理的[Win32]一个调试器的实现(二)调试事件的处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。