最近我写个例子程序研究下某个异常情况,故意制造了个崩溃。然后分析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_symbolsymbols32wntdll.pdbF9EA7A7F41206C21D2ED4E99993A9EF41wntdll.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_SymbolSymbols32调整为F:Symbols32,执行相同命令,结果是报相同错误。
2、先删除现在c:symbols目录,然后将我原来的符号目录考到c:盘,改名为symbols。然后执行!address -summary命令,我等待奇迹的出现,结果却是:
0:000> !address -summary
No symbols for ntdll. Cannot continue.
然后我懵逼了,但至少得出这样一个结论c:symbols目录解决我了我的问题。然后继续折腾,结果在某次折腾里,我忘了修改windbg符号路径设置,但是目录下的相关符号被我移到了其他目录,也就是说F:Debug_SymbolSymbols32是空的,当调试时,ntdll.dll模块的符号文件是从微软符号服务器上拿的新的符号文件,也就是说问题的原因不在于目录而在于符号问见本身。
观察下两个符号文件:
原来的符号文件
这是新的,也是不出问题的符号文件
可以看到,这两个文件的的guid是一样的,但文件大小不一样,也就是说对应的版本还是不一样,旧的符号文件跟我系统里的ntdll其实是不匹配的。可是guid都一样,为什么不是正确的匹配版本呢。我懵逼了。
但是我们可以得出几点经验:
- windbg告诉你符号文件匹配,但是那是不一定的
- 以后遇到同样的问题,我们可以试着把原来所谓匹配的符号文件删除,然后执行同样的操作让windbg从新下载符号文件,可能会解决
其实,这种情况还会引发其他指令无法执行,比如:
- !teb
0:000> !teb
TEB at 008ea000
error InitTypeRead( TEB )... - !heap
0:000> !heap
Invalid type information
后续我会继续研究这个问题,同时希望看到此文的其他人,能帮我解答。