最近我寫個例子程序研究下某個異常情況,故意制造了個崩潰。然后分析dmp文件。
當我執行!address -summary命令想觀察下進程當前內存情況時,去報如下錯誤:
0:000> !address -summary
No symbols for ntdll. Cannot continue.
這意思是沒有ntdll.dll模塊的符號,不可能啊,因為有明顯的證據證明該模塊符號文件已經加載且匹配,如下:
1、比如我們從線程棧可以佐證
05 00affa24 7799662d 008e7000 808b6aa4 00000000 kernel32!BaseThreadInitThunk+0x19 (FPO: [Non-Fpo])
06 00affa80 779965fd ffffffff 779b51e4 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [SEH])
07 00affa90 00000000 00da1091 008e7000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])
只有加載了對應符號文件,才能看到這個正確的函數名。
2、執行!chksym ntdll
0:000> !chksym ntdll
ntdll.dll
Timestamp: 6071CF9D
SizeOfImage: 19C000
pdb: wntdll.pdb
pdb sig: F9EA7A7F-4120-6C21-D2ED-4E99993A9EF4
age: 1
Loaded pdb is f:\debug_symbol\symbols32\wntdll.pdb\F9EA7A7F41206C21D2ED4E99993A9EF41\wntdll.pdb
wntdll.pdb
pdb sig: F9EA7A7F-4120-6C21-D2ED-4E99993A9EF4
age: 1
MATCH: wntdll.pdb and ntdll.dll
這條指令很明確的告訴我,不僅僅加載了,且是匹配的
可是為什么會報“No symbols for ntdll. Cannot continue.”
在網上查了很多資料都沒有什么幫助,后來在某篇文章上看到:該作者遇到了符號的其他問題,他得出結論說windbg的系統模塊符號文件路徑要設置為c:\symbols就解決了他面臨的問題。
我想,我姑且也這樣試試,於是我將我的符號路徑改成如下:
然后,結果真的可以了,!address -summary命令正確執行和輸出了。這是真的嗎,真的是因為路徑問題,真的是要c:\symbols嗎?
根據我個人的經驗,不太相信這個結論。我做了如下的驗證步驟:
1、我注意到我原來的目錄是兩層的,會不會是因為這個原因呢,我將我原來的目錄F:\Debug_Symbol\Symbols32調整為F:\Symbols32,執行相同命令,結果是報相同錯誤。
2、先刪除現在c:\symbols目錄,然后將我原來的符號目錄考到c:盤,改名為symbols。然后執行!address -summary命令,我等待奇跡的出現,結果卻是:
0:000> !address -summary
No symbols for ntdll. Cannot continue.
然后我懵逼了,但至少得出這樣一個結論c:\symbols目錄解決我了我的問題。然后繼續折騰,結果在某次折騰里,我忘了修改windbg符號路徑設置,但是目錄下的相關符號被我移到了其他目錄,也就是說F:\Debug_Symbol\Symbols32是空的,當調試時,ntdll.dll模塊的符號文件是從微軟符號服務器上拿的新的符號文件,也就是說問題的原因不在於目錄而在於符號問見本身。
觀察下兩個符號文件:
原來的符號文件
這是新的,也是不出問題的符號文件
可以看到,這兩個文件的的guid是一樣的,但文件大小不一樣,也就是說對應的版本還是不一樣,舊的符號文件跟我系統里的ntdll其實是不匹配的。可是guid都一樣,為什么不是正確的匹配版本呢。我懵逼了。
但是我們可以得出幾點經驗:
- windbg告訴你符號文件匹配,但是那是不一定的
- 以后遇到同樣的問題,我們可以試着把原來所謂匹配的符號文件刪除,然后執行同樣的操作讓windbg從新下載符號文件,可能會解決
其實,這種情況還會引發其他指令無法執行,比如:
- !teb
0:000> !teb
TEB at 008ea000
error InitTypeRead( TEB )... - !heap
0:000> !heap
Invalid type information
后續我會繼續研究這個問題,同時希望看到此文的其他人,能幫我解答。