windbg调试学习笔记(三)

3.3 异常与事件

在调试器语境中,事件是一个基本概念,Windbg是事件驱动的。Windows操作系统的调试子系统,是“事件”的发生源。调试器的所有操作,都是因事件而动,因事件被处理而中继。Windows定义了9类调试事件,异常是其中一类(ID为1)。所以异常和事件,这二者是前者包含于后者的关系。

系统对各种异常和调试事件进行了分类,执行sx命令可以列出针对当前调试目标的异常或非异常事件的处理。下面是一个片段:


0:009> sx

  ct - Create thread - ignore

  et - Exit thread - ignore

 cpr - Create process - ignore

 epr - Exit process - break

  ld - Load module - break

       (only break for livekd.exe)

  ud - Unload module - ignore

 ser - System error - ignore

 ibp - Initial breakpoint - break

 iml - Initial module load - ignore

 out - Debuggee output - output

 

  av - Access violation - break - not handled

asrt - Assertion failure -break - not handled

 aph - Application hang - break - not handled

 bpe - Break instruction exception - break

bpec - Break instructionexception continue - handled

  eh - C++ EH exception - second-chance break -not handled

 clr - CLR exception - second-chance break -not handled

clrn - CLR notificationexception - second-chance break - handled

 cce - Control-Break exception - break

  cc - Control-Break exception continue -handled

 cce - Control-C exception - break

  cc - Control-C exception continue - handled

  dm - Data misaligned - break - not handled

dbce - Debugger commandexception - ignore - handled

  gp - Guard page violation - break - nothandled

  ii - Illegal instruction - second-chancebreak - not handled

  ip - In-page I/O error - break - not handled

  dz - Integer divide-by-zero - break - nothandled

 iov - Integer overflow - break - not handled

  ch - Invalid handle - break

  hc - Invalid handle continue - not handled

 lsq - Invalid lock sequence - break - not handled

 isc - Invalid system call - break - nothandled

  3c - Port disconnected - second-chance break- not handled

 svh - Service hang - break - not handled

 sse - Single step exception - break

ssec - Single stepexception continue - handled

 sbo - Security check failure or stack bufferoverrun - break - not handled

 sov - Stack overflow - break - not handled

  vs - Verifier stop - break - not handled

vcpp - Visual C++ exception- ignore - handled

 wkd - Wake debugger - break - not handled

 rto - Windows Runtime Originate Error -second-chance break - not handled

 rtt - Windows Runtime Transform Error -second-chance break - not handled

 wob - WOW64 breakpoint - break - handled

 wos - WOW64 single step exception - break -handled

 

   * - Other exception - second-chance break -not handled

可以看到这几个调试事件,当发生进程退出(Exit Process)和初始化断点(Initial breakpoint)事件的时候,调试器应当被中断(Break)。模块加载(Load Modual)以及有调试输出(Debuggen Output)时,需要输出相关信息;其他的都被忽略掉,不做处理(Ignore)。     我们分析一下前两个事件。使用调试器调试记事本进程时,不管是用.attach挂载方式还是.create创建方式,在调试器正式侵入记事本进程前,都会有一个中断(Initial breakpoint异常);调试开始后运行一段时间,在外面将记事本关闭,又会发生一个中断(Exit Process异常)。

可以通过Debug|Event Filters…打开事件设置对话框。这个对话框中列出了全部调试事件,用户可分别对它们进行设置。

           这个对话框列出了对于当前调试会话可用的全部调试事件。针对每个调试事件,可设置其属性。右列Execution和Continue两组单选键,分别表示事件的中断属性中继属性。右列Argument按钮可设置调试事件执行参数(上图中Load Module事件有一个Kernel32.dll参数,即当Kernel32.dll模块被加载时,调试器将被中断),Commands按钮可设置事件两轮机会发生时的执行命令。

更细致的内容,本章无力铺陈,请读者参阅《Windows 高级调试》(Mario & Daniel 2009 机械工业出版社)第三章,及《软件调试》(张银奎 2008 电子工业出版社)第9、30章相关内容。 

sxr:

      此命令将当前所有对调试事件的设置,恢复到调试器的默认设置。最后一个字母r表示Reset。

sx{e|d|n|i}:

      这4个命令分别代表了图8-38中Execution组(中断属性)中的四个按钮,即Enable、Disable、Output、Ignore。Enable是开启中断,Disable是禁止事件中断(但对于异常,只禁止第一轮机会,第二轮机会到来时仍会中断到调试器),Output是禁止中断但会输出相关信息,Ignore表示完全忽略这个事件(对于异常,Output和Ignore两选项使得两轮机会都不会中断到调试器)。

sx{e|d|n|i} -h:

      上述命令如果带上-h选项,就不是设置中断属性,而是设置中继属性了。对应了图8-38中的Continue组。其中sxe –h表示Handled,se{d|n|i} –h都表示Not Handled。

      下面继续介绍异常、事件相关的其他调试命令:

.lastevent:

显示最近发生的一个调试事件,往往是导致中断发生的那个。下图显示的是一个很典型的初始化断点引发的中断事件。

.exr:

      此命令显示一个异常记录的详细内容,传入一个异常记录地址:

§  .exr 记录地址

如果仅仅为了显示最近的一条异常记录,可以用-1代替异常记录地址:

§  .exr -1

由于异常是事件的一种,所以使用.exr -1命令得到的异常,可能和使用.lastevent命令获取的事件(其实是异常),是同一个。但二者显示的信息各有侧重点。请对照图8-39看下面,同样的初始化断点异常,使用.exr命令时所显示的信息:

0:009> .lastevent

Last event: 4f0.1538: Breakinstruction exception - code 80000003 (first chance)

  debugger time: Fri Aug 23 16:58:02.995 2013(UTC + 8:00)

还有一个类似的命令:!cppexr,他分析并显示一个C++异常信息。

.bugcheck:

此命令不带参数。在内核环境下,显示当前bug check的详细信息;可用于活动调试或者crash dump调试环境中。用户环境不可用。见下图:

0:009> .exr -1

ExceptionAddress:0000000077090530 (ntdll!DbgBreakPoint)

   ExceptionCode: 80000003 (Break instructionexception)

  ExceptionFlags: 00000000

NumberParameters: 1

   Parameter[0]: 0000000000000000 

!analyze:  

此命令分析当前最近的异常事件(如果在进行dump分析,则是bug check),并显示分析结果。这个异常事件,就是上面.lastevent命令对应的事件。

§  -v:显示异常的详细信息,这个选项在调试错误的时候,最有用。

§  -f:f是force的缩写。强制将任何事件都当作异常来分析,即使仅仅是普通的断点事件。将因此多输出一些内容。

§  -hang:这个选项很有用,对于遇到死锁的情况,它会分析原因。在内核环境中,它分析内核锁和DPC栈;在用户环境中,它分析线程的调用栈。用户环境中,调试器只会对当前线程进行分析,所以一定要将线程环境切换到最可能引起问题的那个线程中去,才有帮助。这个参数非常有用,当真的遇到死锁时,它可以救命(另一个分析死锁的有效命令是!locks)。

§   -show bug-check-代码 [参数]:在内核环境下,显示指定的bug check的详细信息。

!error:

此命令和VC里面内置的errlook工具类似(请有兴趣的读者使用作者编写的免费软件e-look,它比errlook功能更好且易于使用)。用来根据错误码,查看对应的可读错误信息。微软系统中常用的全局错误码有两套,一套是Win32错误码,通过函数GetLastError()获得的值;另一套是NTSTATUS值。!error命令对这二者都能支持。区别的方法,若错误码后面无参数1,则为win32错误码;否则就是NTSTATUS错误码。

           比如,获取错误码为2的Win32错误信息,可用:!error 2

           获取错误码为2的NTSTATUS错误信息,可用:!error 2 1 

!gle:

此命令是Get Last Error的缩写。它调用Win32接口函数GetLastError()取得线程的错误值,并打印分析结果。如果带有-all选项,则针对当前进程的所有线程(内核环境下为所有用户线程)执行GetLastError()操作;否则仅针对当前线程。

gh/gn:这两个命令是g命令的扩展。

            gh是go with Exception handled的缩写,意思是:把异常标识为已处理而并继续执行程序;注意这里面的措辞,仅仅把异常“标识为”已处理,而并非真的被处理了。gh的作用在于,当遇到某个可以忽略的非致命异常时,将它先放过一边,而继续执行程序。

            而gn是go with Exception nothandled的缩写,意思是,对异常不进行任何处理,而继续执行程序。这时候,程序自己的异常处理模块将有机会处理异常。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金士顿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值