一、前言
就在去年,手頭上有個舊案子,為了與時俱進並且符合客戶的需求,在徵得老闆同意後修改了驅動的架構。為了優化網路傳輸,我將TDI client加入舊有的驅動層,但在開發過程中也因此產生了一些問題,由於狀況並不容易重現,加上除錯的過程也不是相當順利,雖然最後順利的解決,但還是值得紀錄留存。
二、問題分析
1. !analyze -v
問題初判為PFN_LIST_CORRUPT,根據官網得知,參數1可以代表不同的原因。這裡我的問題0x9A表示: 驅動試圖去釋放一個分頁,但這個分頁此時正在進行IO操作。或是說分頁被鎖在實體記憶體分頁中,在未解鎖(Unlock)的情況下,驅動試圖去釋放這個分頁,就會產生BSOD。參數2表示Page frame number. 參數4表示reference count, reference count為0才能被記憶體回收。
2. !pfn Arg2 (PFN)
查看PFN,遇到了問題,我手裡的為small dump,能得到的資訊有限,PFN看不到阿。只能再跟QA要個Complete dump繼續分析。Small dump就拿來判別問題的型態,但整體來說對問題並沒有太多的用途,畢竟連call stack都看不到什們蛛絲馬跡。
過了幾天,QA複製出了問題,要了以後再檢查看看,但映入眼簾的只有傻眼二字。這代表我輸入的指令因為符號沒有正確的載入,所以還是無法查看。
不放棄,輸入!sym
noisy,重新讀取symbols,看看問題出在哪裡。恩,看起來本地端symbol位址是沒錯的,但不知道為什們從symbol server下載的symbol並不符合這個dump所要的版本。
3. !verifier 03
現在回想之前得到的各方資訊,(1.)重現機率低,只有再移除驅動以後才會有機率發生 (2.)分頁釋放問題。重現機率低,可能是有一些異常行為沒有考慮到,所以重現問題不能用正規的方式,分頁的問題可能就是在異常的情況下未能釋放分頁,導致裝置節點(Device node)有個未釋放的記憶體,所以才會在移除驅動後發生系統崩潰。從新打開驅動驗證,除了低資源模擬以外全開,不停的測試直到藍屏再度發生。
這裡會得到和原本不一樣的bugcheck code,畢竟問題是由verifier所捕捉的。但可以知道我的驅動本身確時存在問題,參數1: 某些pool在驅動卸載的時候並沒有釋放 。參數4: 總共有一個(paged + nonpaged)未釋放。
下指令!verifier
3 (0x11) 可以得到pool的資訊,找到出問題的pool以及它的tag和配置這個pool的指令位址。看到VMdl大概已經猜到問題了,因為整個驅動程式只有幾處有使用MDL。
4. ln CallerAddress
最後下達指令ln callersAddress搭配正確的pdb,可以找到配置pool的程式碼。後來,經過確認,的確在某些網路異常下,會導致IRP沒有被正確的釋放完成,才會導致這樣的問題發生。修改程式碼以後, 經過驗證,問題也確實得到了改善。
沒有留言:
張貼留言