今天QA發(fā)現(xiàn)在他一臺(tái)機(jī)器上啟動(dòng)我們的軟件的時(shí)會(huì)提示某個(gè)DLL(a.dll)找不到(a.dll是b.dll內(nèi)部用到的一個(gè)DLL, 我們軟件直接用的是b.dll)。
剛開始我們懷疑是不是a.dll沒有下載下來或是沒有下載完整,但是到安裝目錄下看了,a.dll在那邊,用dependency看了下,DLL的導(dǎo)出函數(shù)也都是正常的。既然DLL本身沒有問題,那就是搜索路徑的問題了,可以修改的搜索路徑一般包括當(dāng)前路徑(current directory)和DLL路徑(dll directory), 正好我們這2項(xiàng)在我們的Trace中都有記錄。通過查看Trace,發(fā)現(xiàn)dll directory在后面確實(shí)被修改成了我們另外一個(gè)軟件的路徑。
那么究竟是誰改了這個(gè)路徑? 這就需要借助Windbg了。我們知道修改DLL路徑的API是SetDllDirectory,所以我們可以通過設(shè)置API斷點(diǎn),然后查看堆棧就可以了。因?yàn)槲覀冞@個(gè)程序這里是由其他程序調(diào)用啟動(dòng)的,所以我們可以通過子進(jìn)程的方式來調(diào)試。
在QA的機(jī)器上安裝windbg, 首先將Windbg Attach到父進(jìn)程,輸入命令 .childdbg 1, 表示允許調(diào)試子進(jìn)程,然后F5,繼續(xù)運(yùn)行。接下來觸發(fā)父進(jìn)程創(chuàng)建子進(jìn)程的動(dòng)作,我們可以看到Windbg會(huì)中斷下來, 我們可以通過命令|. 查看是不是我們的目標(biāo)進(jìn)程建立起來了,接下來輸入斷點(diǎn)命令bp Kernel32!SetDllDirectoryA 和 bp Kernel32!SetDllDirectoryW, 然后F5運(yùn)行。果然很快Windbg又被中斷下來了,通過命令kv查看堆棧,我們可以看到果然有人調(diào)用SetDllDirectoryA,原來是我們的底層通訊模塊觸發(fā)的, 另外我們可以通過da poi(esp+4)查看SetDllDirectory傳入路徑的值。
那么是不是只要我們把DLL路徑改回原來的NULL,就不會(huì)有這個(gè)Bug了呢?我們可以在調(diào)用SetDllDirectory中斷時(shí),直接輸入ed esp+4 0修改傳入?yún)?shù)成0,然后F5運(yùn)行,果然后面dll的加載就都正常了。
找到原因后,接下來就是讓QA給對(duì)應(yīng)的模塊開發(fā)人員報(bào)Bug,讓他們把DLL路徑用完后改回來。
可以看到無論對(duì)于開發(fā)還是測(cè)試人員,windbg很多時(shí)候可以幫我們快速的定位問題, 如果借助符號(hào)文件,Windbg完全可以實(shí)現(xiàn)比VC IDE更強(qiáng)大的調(diào)試供功能, 并且有時(shí)候我們不需要源代碼,不需要重新編譯,直接就可以通過windbg調(diào)試和解決問題。
posted on 2012-06-26 20:33
Richard Wei 閱讀(3701)
評(píng)論(3) 編輯 收藏 引用 所屬分類:
windbg