Windows 除錯的第一步
August 26th, 2009
最近比較有空些,剛好老闆有要求要整理一下歷年來和蟲蟲作戰的心得,既然寫了英文版就順手哈啦一下中文的,也可以複習一下很久沒用的行列輸入法 🙂 本系列文章使用的範例程式可以從 Codeplex 下載。我使用 Codeplex 而非 SourceForge 的原因是因為我的網路連 Codeplex 快很多,本人並未替 Codeplex 背書,本系列文章也沒有微軟的背書 :p
另外呢,許多英文的專有名詞我直接就列了,因為和中文翻譯的名詞脫節有段時間,所以寫英文比較快些。好吧廢話不多說,直接從最簡單的 HelloCrash 這支程式開始。用 VC 2008 編譯並執行後這隻程式會掛掉 (截圖皆為英文版,因為我的 OS 是英文的 😀 中文的畫面就請自行用智慧人腦代換法來換文字)
把這個對話盒直接關掉,其實沒有太大的關係。Windows 仍會在它的日誌中,應用程式的部份去記錄這個 crash:
這筆記錄其實有很多重要的資訊在裡頭。在我們跳下去蒐集並分析 crash dump 之前,其實可以利用一下現成的資訊來做初步的分析。我發現很多人在學了 WinDBG 之後,就忘記其實還有更簡單的工具可以用 🙂 這個誤區其實是可以避免的。
在我們的例子裡,我們知道 crash 發生的 module 和 offset (見上圖的黃色高亮部份),這表示我們可以直接由 map 檔和組合語言列表去找出 crash 發生在哪支程式的哪一行。雖然這未必是 100% 正確 (理由在後續的文章會提到),但也是個值得參考的資訊。例子中 module 是 HelloCrash.exe,offset 0x1002,查找 map 檔可得知
Preferred load address is 00400000
…Address Publics by Value Rva+Base Lib:Object
0000:00000001 ___safe_se_handler_count 00000001
0000:00000000 ___ImageBase 004000000001:00000000 _wmain 00401000 f HelloCrash.obj
0001:00000017 @__security_check_cookie@4 00401017 f MSVCRT:secchk.obj
…
crash 的點應是落在 _wmain 函數 (offset 0x1000 to 0x1016),在函數內的 offset 為 0x2。若在 VC 的設定中有叫它產生組合語言列表 (/FAcs),就可直接找出該行:
; 9 : TCHAR* p = NULL;
00000 33 c0 xor eax, eax
; 10 : _tprintf(_T(“Hello, crash: %s\n”), *p); // deref NULL pointer
00002 0f b7 00 movzx eax, WORD PTR [eax]
這個例子太簡單,一眼就可看出是錯誤的取用指標造成 crash。這個例子主要是講述如何使用 map 檔來做初步的判斷,接下來的文章將為您展示其他找出問題點的方法,敬請期待囉 🙂