一步一个坑——WinDbg调试.NET程序

发表于:2017-10-16 10:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:sweetjian    来源:51Testing软件测试网采编

  引言
  第一次用WinDbg来排查问题,花了很多时间踩坑,记录一下希望对后面的同学有些帮助。
  客户现场软件出现偶发性的界面卡死现象一直找不出原因,就想着让客户用任务管理器生成了一个dump文件发给我,我再用WinDbg看一下现线程堆栈。
  找篇教程,按步骤一步一步来,应该挺简单吧。我想。
  WinDbg软件版本选择
  官方版本不“绿色”,最开始从第三方下了一个《WinDbg中文版(32位/64位)6.12独立版》v6.12.2.663
  结果不管怎么尝试,加载CLRDLL的时候都提示
  0:000>.cordll-u-ve-l
  CLRDLLstatus:Noloadattempts
  由于没经验,一直怀疑是不是自己哪里没有配置正确、操作有问题、敲键盘的姿势不对?。做了很多尝试,才意识到会不会下载的版本有问题,于是赶紧去官网下载(DebuggingToolsforWindows(WinDbg,KD,CDB,NTSD))v6.3.9600.17298。果然!新的版本不会再出现这个提示!有人说这是软件BUG。。。一口老血。。。
  注:WinDbg历史版本
  32位vs64位该用哪个版本的WinDbg
  下载的WinDbg有32和64位两个版本,该用哪个版本呢?我们可以参考这位园友的回答(一句话总结Windbg32位版本和64位版本的选择)
  他说:只有在实时用户态调试,并且调试器也在同一台64位机器上的情况下必须用64位的调试工具集。
  那么我们调试dump,选择WinDbgx86应该没错了。
  按套路来
  因为一直失败,更换N种套路后,保留这一种:
  1.设置符号地址
  菜单|File|SymbolFilePath|设置符号地址srv*c:\symbolspub*http://msdl.microsoft.com/download/symbols(如果你还有本地符号,点击Browse...选择路径)
  2.打开dump文件
  菜单|File|OpenCrashDump...|选择dump文件路径打开dump文件
  3.加载SOS
  0:000>.cordll-ve-u-l
  CLRDLL:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscordacwks.dll:2.0.50727.8762f:0
  doesn'tmatchdesiredversion2.0.50727.5485f:0
  CLRDLL:Unabletofindmscordacwks_x86_x86_2.0.50727.5485.dllbymscorwkssearch
  CLRDLL:Unabletofind'mscordacwks_x86_x86_2.0.50727.5485.dll'onthepath
  CLRDLL:Unabletogetversioninfofor'c:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll',Win32error0n87
  CannotAutomaticallyloadSOS
  CLRDLL:ERROR:UnabletoloadDLLmscordacwks_x86_x86_2.0.50727.5485.dll,Win32error0n87
  CLRDLLstatus:ERROR:UnabletoloadDLLmscordacwks_x86_x86_2.0.50727.5485.dll,Win32error0n87
  诶,出错了,从日志可以看出缺少c:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll文件。
  这个文件从哪来?
  1)客户计算机:NET2.0x86在C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727路径下的mscordacwks.dll,其他版本类似;
  2)从网络下载:这里有好心人已经打包了:Mscordacwks/SOSdebuggingarchive;
  把下载的文件重命名一下放到c:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll路径下,这个路径就是前面设置的符号地址的存储路径。一定要确保版本完全一致,再加载一次就OK了。
  加载成功后提示类似:
  0:000>.cordll-u-ve-l
  CLRDLL:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscordacwks.dll:2.0.50727.8762f:0
  doesn'tmatchdesiredversion2.0.50727.5485f:0
  CLRDLL:Unabletofindmscordacwks_x86_x86_2.0.50727.5485.dllbymscorwkssearch
  CLRDLL:Unabletofind'mscordacwks_x86_x86_2.0.50727.5485.dll'onthepath
  CLRDLL:Unabletogetversioninfofor'c:\symbolspub\mscorwks.dll\53A121FA5ae000\SOS_x86_x86_2.0.50727.5485.dll',Win32error0n87
  CannotAutomaticallyloadSOS
  CLRDLL:LoadedDLLc:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll
  CLRDLLstatus:LoadedDLLc:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll
  如果一切正常,这时候输入!threads就可以看到托管线程了。
  0:000:x86>!threads
  ThreadCount:22
  UnstartedThread:0
  BackgroundThread:20
  PendingThread:0
  DeadThread:1
  HostedRuntime:no
  PreEmptiveGCAllocLock
  IDOSIDThreadOBJStateGCContextDomainCountAPTException
  017c0000000000077d1d06020Enabled0000000000000000:00000000000000000000000000778c200STA
  22260000000000078bfe0b220Enabled0000000000000000:00000000000000000000000000778c200MTA(Finalizer)
  54fd000000000007ec5a880a220Enabled0000000000000000:00000000000000000000000000778c200MTA(ThreadpoolCompletionPort)
  balabala...
  好事多磨
  没有坑是不可能滴,我电脑上却提示:
  0:000>!threads
  FailedtoloaddataaccessDLL,0x80004005
  Verifythat1)youhavearecentbuildofthedebugger(6.2.14ornewer)
  2)thefilemscordacwks.dllthatmatchesyourversionofmscorwks.dllis
  intheversiondirectory
  3)or,ifyouaredebuggingadumpfile,verifythatthefile
  mscordacwks_<arch>_<arch>_<version>.dllisonyoursymbolpath.
  4)youaredebuggingonthesamearchitectureasthedumpfile.
  Forexample,anIA64dumpfilemustbedebuggedonanIA64
  machine.
  Youcanalsorunthedebuggercommand.cordlltocontrolthedebugger's
  loadofmscordacwks.dll..cordll-ve-u-lwilldoaverbosereload.
  Ifthatsucceeds,theSOScommandshouldworkonretry.
  Ifyouaredebuggingaminidump,youneedtomakesurethatyourexecutable
  pathispointingtomscorwks.dllaswell.
  再用.cordll和.chain检查一下SOS的加载情况
  0:000>.cordll
  CLRDLLstatus:LoadedDLLc:\symbolspub\mscorwks.dll\53A121FA5ae000\mscordacwks_x86_x86_2.0.50727.5485.dll
  0:000>.chain
  ExtensionDLLsearchPath:
  balabala。。。
  ExtensionDLLchain:
  C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos:image2.0.50727.8762,API1.0.0,builtWedApr0511:41:392017
  [path:C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll]
  balabala。。。
  可以看到sos正常加载了啊,难道没有?哪里还有问题?。。。这里我又卡了很久没有头绪。。。
  Google半天才意识到,会不会是抓的dump有问题,再查,才发现有人建议用64位任务管理器抓64位进程的dump,32位任务管理器抓32位进程的dump。我去,又是一口老血。。。
  64位系统怎么抓dump
  我们以抓32位进程的dump为例,先打开32位任务管理器(C:\Windows\SysWOW64\taskmgr.exe)
  确保taskmgr.exe后面有一个*32,表示这是一个32位程序跑在64位系统上,叫做wow64模式。
  然后右键你的目标进程,点击“创建转储文件”,成功后会提示dmp文件存储路径。
  也就是说,你的目标进程有*32,taskmgr也要有*32,如果没有则都必须没有。
  另外:推荐抓dump工具:ProcDump小巧又强大,里面也是区分一个32位版本和一个64位版本。
  正确的dump抓下来,再按照前面的方法正常情况就可以开始分析了。
  再接再励
  那是不是64位任务管理器抓32位进程的dump就没用了呢?等现场抓下一个dump不知道要等到什么时候。继续Google,终于找到关键字DebuggingWOW64
  然后找到这篇文章Debugginga64-bitdumpofa32-bitmanagedprocess
  简单说,就是前面步骤做完后,通过下面两条指令切换到32bit模式
  0:000>.loadwow64exts
  0:000>!sw
  Switchedto32bitmode
  切换32bit模式后后!clrstack可以执行,却看不到正确的堆栈信息
  0:000:x86>!clrstack
  OSThreadId:0x7c0(0)
  Failedtostartstackwalk:80070057
  Google无果。不过还好,可以用其他指令指令替代它,比如!dumpstack-ee
  0:000:x86>!dumpstack-ee
  OSThreadId:0x7c0(0)
  TEBinformationisnotavailablesoastacksizeof0xFFFFisassumed
  Currentframe:
  ChildEBPRetAddrCaller,Callee
  002dca686a27d6b4(MethodDesc0x69e47600+0x70System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(System.Data.OleDb.tagDBPARAMS,System.ObjectByRef))
  002dca886a27d6b4(MethodDesc0x69e47600+0x70System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(System.Data.OleDb.tagDBPARAMS,System.ObjectByRef))
  002dcab46a27d519(MethodDesc0x69e475e4+0xbdSystem.Data.OleDb.OleDbCommand.ExecuteCommandText(System.ObjectByRef))
  002dcaf06a27d437(MethodDesc0x69e475d8+0x3bSystem.Data.OleDb.OleDbCommand.ExecuteCommand(System.Data.CommandBehavior,System.ObjectByRef))
  002dcb006a27d192(MethodDesc0x69e475cc+0xa2System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(System.Data.CommandBehavior,System.String))
  ..balabala...
  至此,我想看的线程堆栈信息终于出来了~~~额,WTF,又是万恶的ACCESS惹的祸!再吐一口血,卒。。。
  总结一下
  最好从官方下载程序(即便它不是绿色版,即便它还和其他程序绑定:-()
  用64位任务管理器(或调试器)生成64位进程的dump,用32位任务管理器(或调试器)生成32位进程的dump!
  加载SOS最容易出问题的一点就是:一定要保证加载的SOS模块要与客户现场的程序版本保持一致!
  最后,最重要的一点:不要用ACCESS、CCESS、CESS、ESS、SS、S~~~
  客户:ACCESS好用的,好伐,快给我起来干活。
  我我:。。。让我再死会儿~
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号