The version of SOS does not match the version of CLR you are debugging
和 PDB symbol for clr.dll not loaded
解決WinDbg調試Dump文件不同環境mscordacwks.dll版本問題
程序發生了崩潰,我抓了一個mini Dump,Mini dump 有一個優點就是非常的小。比full dump 要小很多。
0:020> .loadby sos clr //首先加載sos 0:020> !threads The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1008 SOS Version: 4.0.30319.1022 0:020> .cordll -ve -u -l CLRDLL: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscordacwks.dll:4.0.30319.1022 f:8 doesn't match desired version 4.0.30319.1008 f:8 CLRDLL: Loaded DLL c:\symbols\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll\517A18FF965000\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll CLR DLL status: Loaded DLL c:\symbols\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll\517A18FF965000\mscordacwks_AMD64_AMD64_4.0.30319.1008.dll
還有一種錯誤:
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
The version of SOS does not match the version of CLR you are debugging. Please
load the matching version of SOS for the version of CLR you are debugging.
CLR Version: 4.0.30319.1026
SOS Version: 4.0.30319.34209
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
2) the file mscordacwks.dll that matches your version of clr.dll is
in the version directory or on the symbol path
3) or, if you are debugging a dump file, verify that the file
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
4) you are debugging on supported cross platform architecture as
the dump file. For example, an ARM dump file must be debugged
on an X86 or an ARM machine; an AMD64 dump file must be
debugged on an AMD64 machine.
.cordll –ve –u –l (小寫的L ) 這個命令是控制調試和控制CLR的命令,-ve是顯示詳細信息,-u 卸載模塊,-l (小寫的L) 是加載模塊,上面這個命令就是卸載CLR 調試模塊,然后再加載CLR調試模塊,並顯示詳細信息。
這個命令提示我的mscordacwks.dll 版本不對。然后有提示從 C:\symbols 加載了 mscordacwks_<arch>_<arch>_<version>.dll 這個文件。
我windbg的符號文件路徑的設置是:
srv*c:\symbols*http://msdl.microsoft.com/download/symbols
通過windbg的快捷鍵 Ctrl+S 可以設置符號文件的路徑。
雖然看似上面的mscodacwks.dll 加載了,但是運行命令還是報錯:
0:033> !clrstack The version of SOS does not match the version of CLR you are debugging. Please load the matching version of SOS for the version of CLR you are debugging. CLR Version: 4.0.30319.1008 SOS Version: 4.0.30319.1022 OS Thread Id: 0x6e54 (33) Child SP IP Call Site 000000000540a968 000007fefaab8e4f [PrestubMethodFrame: 000000000540a968] Unknown MethodDesc (Module 000007ff00a613b0, mdToken 060000aa) 000000000540a9d0 000007ff00b829fd Unknown MethodDesc (Module 000007ff00a613b0, mdToken 06000096)
CLR.dll 是一個原生C++ Win32 Native code 編寫的托管代碼運行時,它是托管代碼的運行環境,它從我們.net編寫的生成的dll中抽取IL中間代碼和元數據,通過JIT即時編譯來生成內存中的原生native Code. Windbg是一個針對原生Native code 的調試器。那在原生調試器和托管代碼世界之間,我們需要一座“橋梁”這就是SOS.dll。但是CLR的內部數據結構可能是要不斷變化的,這時如果有一個針對調試器的一個抽象層就非常重要,調試器通過一個抽象層來訪問CLR的內部數據結構。mscordacwks.dll 就是這樣一個抽象層 ( Data-Access-Component (DAC) ),它實現了讓調試器SOS.dll 以比較穩定的接口來訪問CLR內部不斷的數據結構的目的。但CLR和SOS.dll 以及 mscordacwkd.dll 還是耦合的非常緊密的,以至乎 他們的版本必須一致才可以正常工作。
一般,我們的機器上安裝好.net 運行時后,都有 clr.dll ,sos.dll 和mscordacwk.dll 三個版本一致的dll。
一般在調試dump文件才會出現這類不匹配的錯誤。因為如果是調試一個活生生的進程,調試器能自動的從.net Framework的安裝目錄來找到正確的mscordacwks.dll。
可以嘗試
!sym noisy //顯示詳細信息
.symfix+ c:\symbols //強制下載symbols
.reload /f; // Force reloading symbols 強制加載符號文件
.cordll -ve -u –l //重新加載調試DLL,這是加載DLL,不是符號
上面的命令試了后也可能不起作用。
遇到這種問題,你需要到抓取dump文件的機器上,把 mscordacwks.dll 和Sos.dll 拷貝下來,如果是別人傳給你dump,則最好讓他將這3個文件一起拷貝給你。拿到DLL后,確認版本正確后,改為類似一下的名字:
mscordacwks_AMD64_AMD64_4.0.30319.1008.dll
AMD64 這個字符串對應的是CPU架構信息,因為AMD公司先做出64位架構,Intel公司雖然也有自己的64位架構,但好像沒有流行開,他還是沿用了AMD兼容的64位。而這個AMD64的遺留名字就一直使用下來了。
文件重命名后,可以放到windbg的exe目錄下,與windbg.exe 同一個目錄,也可以放到一個指定的目錄下。
然后運行:
.cordll -u -ve -lp c:\clr1008 // C盤有個clr1008文件夾,我從那里加載調試DLL,-lp 指定目錄
.cordll -ve -u –l //從默認路徑加載調試DLL。
如果遇到如下錯誤:
CLR DLL status: ERROR: Unable to load DLL mscordacwks_AMD64_x86_4.0.30319.1008.dll,
或者
CLRDLL: ERROR: DLL C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscordacwks.dll init failure, Win32 error 0n87
CLR DLL status: ERROR: DLL C:\Windows\Microsoft.NET\Framework\ v4.0.30319\mscordacwks.dll init failure, Win32 error 0n87
說明 32位、64位這個搞錯了。
你可能抓了一個32位進程的dump。64位系統上的任務管理器中,32位進程的名字類似:w3wp.exe*32,后面帶一個 *32 字樣,它們是運行在WoW64模式下的。同時你用了一個64位的windbg調試器在嘗試調試這個dump。Dump分析必須32、64嚴格區分開,64位系統抓64位進程dump,用64位windbg來分析。64位系統抓32位進程dump,用32位windbg來分析。
還有 第三種方法,自己去獲取匹配版本的關鍵dll。 Mscordacwk 全名是指Ms-core-Data-Access-Component (DAC) -Work.dll,是sos 訪問clr數據需要的一個核心dll。
用“sos 4.0.30319.1008 ” 去網上搜索找到對應的 微軟補丁包:
例如,我找到了這樣一個網站: http://www.mskbfiles.com/sos.dll.php, (前面的網址有點舊了,2016年09月12日更新:http://dll-rehab.com/search?q=sos, http://filelog.net/file/SOS.dll )
我要的版本他這里列出來了:
“
Sos.dll version 4.0.30319.1008:
- 2835393 MS13-052: Description of the security update for the .NET Framework 4 on Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008, Windows 7, and Windows Server 2008 R2: July 9, 2013 Q2835393 KB2835393
”
點擊這個鏈接進去,找到“下載信息”
“
下載信息
此更新可從 Microsoft 下載中心下載:
http://www.microsoft.com/zh-cn/download/details.aspx?id=39418, 點擊這個鏈接去下載補丁文件
”
我的dump文件是運行在X64系統上的,那我就下載了“NDP40-KB2835393-x64.exe”。
下載這個文件,它是一個子解壓的exe文件,可以用 WinRAR 或 7-Zip 打開,打開后在目錄里找到 *.msp 結尾的文件,右鍵菜單繼續打開,然后找到 *.cab文件,選中 *.cab 文件,通過右鍵菜單繼續打開,查找里面的 sos_dll_amd64,mscordacwks_dll_am64,clr_dll_amd64文件,把他們導出到普通文件夾下,重新命名為 sos.dll,mscordacwks.dll,clr.dll,然后查看版本是不是 4.0.30319.1008。如果不是這個版本繼續在 *cab 里面找dll,應該是能找到正確的文件版本。
我就通過這種方法找到了對應 我需要的三個正確版本的dll文件。把他們放在一個clr1008的文件夾下,然后把clr1008 放與windbg.exe 同一級的目錄下。這樣加載敲命令就方便多了。
我已經將文件版本保存好后,我重新加載sos.dll
0:033> .load clr1008\sos.dll 0:033> .chain Extension DLL search Path: D:\Users\Downloads\windbg\WINXP;.... //環境變量的 PATH 值 Extension DLL chain: clr1008\sos.dll: image 4.0.30319.1008, API 1.0.0, built Fri Apr 26 14:21:22 2013 [path: D:\Users \Downloads\windbg\clr1008\sos.dll] C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos: [path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll] [path: D:\Users \Downloads\windbg\dbghelp.dll] ....
我現在有2個sos.dll, 我需要把默認路徑下的卸載掉
0:033> .unload C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos Unloading C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos extension DLL 0:033> .setdll clr1008\sos.dll
這兩個命令的作用是1)卸載dll,2)設置默認dll。
然后加載調試DLL:
0:020> .cordll -u -ve -lp clr1008
CLRDLL: Loaded DLL clr1008\mscordacwks.dll
CLR DLL status: Loaded DLL clr1008\mscordacwks.dll
如果無法正確加載PDB文件,就無法正確的顯示堆棧Stack信息,問題:
0:024> !clrstack PDB symbol for clr.dll not loaded OS Thread Id: 0x8158 (24) Unable to walk the managed stack. The current thread is likely not a managed thread. You can run !threads to get a list of managed threads in 0:024> kb //stack 信息無法正確顯示 RetAddr : Args to Child : Call Site 000007fe`f9b1c841 : 00000000`77359b6e ... : clr+0x1fde45 00000000`77359b6e : 00000000`00000000 ... : clr+0x1c841 000007fe`f9cfba57 : 00000000`02340850 ... : ntdll!RtlLookupFunctionTable+0xaa 00000000`02340850 : 00000001`0000001f ...: clr+0x1fba57 0:024> .exepath+ clr1008 //+ 是表示附加 Executable image search path is: clr1008 Expanded Executable image search path is: clr1008 0:024> .reload //必須Reload .............. 0:024> kb //之后的堆棧信息已經能正確顯示了 RetAddr : Args to Child : Call Site 000007fe`f9cfba57 : 00000000`02340850 ... : clr!SVR::gc_heap::mark_object_simple1+0xbd6 000007fe`f9cf9aa9 : 00000000`02340850 ... : clr!SVR::gc_heap::mark_object_simple+0x4d7 000007fe`f9b8cf6e : 00000001`c0e4fbc8 ... : clr!SVR::GCHeap::Promote+0x161 000007fe`f9b8ec95 : 00000000`0475dd90 ... : clr!GcEnumObject+0x37 000007fe`f9b8e585 : ffffffff`00000000 ... : clr!GcInfoDecoder::EnumerateLiveSlots+0x5dd
必須保證exepath指向正確的路徑,默認指向的是.net Framework的安裝目錄,但我現在需要的是1008版本的clr.dl路徑,所以需要將exepath 額外加上一個路徑。
If you are debugging a minidump, you need to make sure that your executable
path is pointing to clr.dll as well.
在沒有將clr1008目錄下的clr.dll 加載到exepath時,下面的輸出是這樣的:
0:000> !EEVersion 4.0.30319.1022 free Workstation mode SOS Version: 4.0.30319.1022 retail build 0:000> lmv m clr start end module name 000007fe`f77f0000 000007fe`f8155000 clr (pdb symbols) c:\symbols\clr.pdb\14AD6AF3D1B64799A5908CBBBA0E9C482\clr.pdb Loaded symbol image file: clr.dll Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Image name: clr.dll Timestamp: Wed Jan 08 14:28:31 2014 (52CCF00F) CheckSum: 0096784D ImageSize: 00965000 File version: 4.0.30319.1022 Product version: 4.0.30319.1022 File flags: 8 (Mask 3F) Private File OS: 4 Unknown Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Microsoft® .NET Framework InternalName: clr.dll OriginalFilename: clr.dll ProductVersion: 4.0.30319.1022 FileVersion: 4.0.30319.1022 (RTMGDR.030319-1000)
在將clr1008目錄下的clr.dll 附加到 exepath后,命令輸出如下:
0:020> lmv m clr start end module name 000007fe`f9b00000 000007fe`fa465000 clr (pdb symbols) c:\symbols\clr.pdb\118B3CCCBA4A4A709B496CFB294BF5162\clr.pdb Loaded symbol image file: clr.dll Mapped memory image file: clr1008\clr.dll Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Image name: clr.dll Timestamp: Fri Apr 26 14:04:47 2013 (517A18FF) CheckSum: 0095CE19 ImageSize: 00965000 File version: 4.0.30319.1008 Product version: 4.0.30319.1008 File flags: 8 (Mask 3F) Private File OS: 4 Unknown Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Microsoft® .NET Framework InternalName: clr.dll OriginalFilename: clr.dll ProductVersion: 4.0.30319.1008 FileVersion: 4.0.30319.1008 (RTMGDR.030319-1000)
可以看到 pdb 符號文件已經有了,而且有了一個Mapped memory image file: clr1008\clr.dll 這一項。而且我的symbol path下緩存的clr.pdb文件也已經對應到正確的版本了。
額外的:
lm 可以檢查你的.net 程序是否運行在 .net 4或.net 2,還是混合着 4.0 和 2.0, 就是通過 查看輸出內容是否 包含 clr, mscorwk, mscorsrv 這些模塊,4.0 的核心dll 是clr.dll。2.0 的核心dll是 mscorwks.dll 或者mscorsrv.dll。下面只有clr 模塊,說明只工作在.net 4.0下。
0:000> lm start end module name …… 00000000`77530000 00000000`7764f000 kernel32 (pdb symbols) 00000000`77650000 00000000`7774a000 user32 (pdb symbols) 00000000`77750000 00000000`778f9000 ntdll (export symbols) 000007fe`f24e0000 000007fe`f2653000 clrjit (pdb symbols) 000007fe`f77f0000 000007fe`f8155000 clr (pdb symbols)
在這里補充一點:這篇文章是將windbg如何去正確加載 sos.dll,同時有可能需要去正確加載 clr.dll 這個exe 可執行路徑。如果使用DebugDiag這類自動化工具,因為自動化工具沒有可以配置去哪個路徑加載exe可執行路徑。需要在環境變量里設置這些參數:
_NT_EXECUTABLE_IMAGE_PATH = c:\clr1008
例如我這里就設置了這樣一個環境變量,讓DebugDiag 啟動分析時,知道去這里找正確的clr版本。參見:http://msdn.microsoft.com/en-us/library/windows/hardware/hh439335(v=vs.85).aspx
參考資料:
http://stackoverflow.com/questions/23636764/clr-dll-exception-causes-the-iis-crashed
http://voneinem-windbg.blogspot.com/2007/10/failed-to-load-data-access-dll.html