windbg调试笔记

操作系统的调试符号路径:

SRV*D:\symbols*http://msdl.microsoft.com/download/symbols;D:\MyAppSymbol

D:\symbols--标识本地保存下载后的符号路径

http://msdl.microsoft.com/download/symbols--微软提供的操作系统符号下载路径

D:\MyAppSymbol--表示自己编译产生的符号文件路径。

符号之间用分号隔开。

 

一:利用堆栈来发现信息:
kb --显示堆栈信息,从堆栈信息可以看出调用函数的返回地址,函数参数信息。
kn --n这个参数是用来显示frame number的。

通过上述参数信息,如果是调试临界区死锁可以使用一下命令:
!cs [参数地址] -- 该命令可以看到拥护该临界区的id号(owning thread:***)
~~[***] --该命令通过获取到的id号(owning thread:***)来转换成线程TID。
然后调试说获取到的TID,用上述类似的方法步骤查看该TID在等待那个临界区,这个临界区由那个线程所拥有

获取参数中的内容,比如MessageBox函数的第一个参数。
da 第一个参数的内存地址

.frame /number/ -- 定位到某个frame number上
x -- 显示当前frame相匹配的符号信息
dt /变量/ -- 格式化显示资料信息

二:dds命令[打印内存地址上的二进制值,同时自动搜索二进制值对应的符号]
dds ebp -- 查看当前stack中保存了那些函数地址,就可以检查ebp指向的内存。

还有如何打印出com vtable函数信息:
0:000>x ole32!OpaqueDataInfo::'vftable'
7768265c ole32!OpaqueDataInfo::'vftable' = <no type information>
77682680 ole32!OpaqueDataInfo::'vftable' = <no type information>

0:000>dds 7768265c
7768265c 77778245 ole32!ServerLocationInfo::QueryInterface

三:查看当前执行的指令
u eip

四:内存相关调试
pageHeap启动与否,在memory窗口中看到的信息不一样
pageHeap启动:>pageHeap /enable mytext.exe /full
检查启动情况:>pageHeap
pageHeap无法保证发现所有潜在问题,工作原理就是保证分配的单元数目是4kb的整数倍。

五:三种常见的问题[句柄泄漏,死锁,线程争用]
句柄泄漏:观察handle增长情况,增长handle的类型,是什么时候创建的。
          !handle, !handle /handle number/
死锁: 往往是在waitForSingleObject或者是EnterCriticalSection上不返回。
      1:kb -- 获取参数信息
      2:!cs 参数 --获取owningThreadID
      3:~~[ThreadId] -- 转换成TID
      4:切换线程用上述方法查看用户临界区的线程
      若 3 出现以下错误:
      0:001>~~[0x000014c4]
                          ^Illegal thread error in '~~[0x000014c4]'
      可以使用application verifier工具勾选Lock,运行,捕获异常。

线程争用:


性能问题:[解决该问题的关键是找到出现瓶颈的地方]
1:CPU的利用率是关键。
  CPU利用率高的几种情况:
  第一:程序出现了死循环,
  第二:如果CPU利用率一直很高,且响应时间随负荷增加而变长,当负荷下降后性能又恢复正常。
        解决的办法是升级硬件或者增加服务节点。
  第三:(待续)
       

对于出现Assess Viloation异常分析的经验。

对于发生Access Viloation异常,打出的堆栈一般有这么几种比较重要的信息显示:__except_handle4(***), __except_handle3(***), __CxxUnhandleExceptionHandle(***)。

一般来说就这三种形式。

利用

kp.--函数参数信息

kv.--参数值信息

kn.--栈帧信息编号

你就可以看到很重要的信息,注意struct _EXCEPTION_RECORD*, struct _CONTEXT*这两个结构参数。而对于_C**UnhandlerExceptionHandle是由一个

Struct Exception_Pointer 结构体,该结构体定义如下:

Struct Exception_Pointer

{

PEXCEPTION_RECORD pRecord;//里面又包含如exceptionCode, exceptionFlag等等。

PCONTEXT pContext; //这个也是一个结构体

}

所以对于_CXXUnhandlerExceptionHandler,就需要先使用dd命令来获取Exception_Pointer包含的两个数据成员的地址。

获取完这两个地址,我们就可以通过.exr和.cxr命令来参看具体发生了什么异常,发生异常时上下文信息情况。这个时候幸运时,可以看到发生crash时的源代码,

有时候还不会有很大的帮助。

还可以继续尝试在此上下文信息运行kn命令,有时会有意想不到的信息出现,也许这就是你需要的信息。

如果kn运行后,有堆栈出现,你还需要获取进一步的信息。

可以再次尝试使用 “.frame 编号”(不包括双引号)和  “x”,查看当前栈帧局部变量情况。同时最好打开watch窗口。

如果上述方法均不行,你还可以通过查看发生该问题的线程及日志来跟踪调查。运行ALT+9快捷键,将黑体加粗的线程对应的数字从16进制转换层十进制,就是线程号。

根据获取的线程号,来查看对应的日志。

 

2:WARNING: Unable to verify timestamp for ××.dll

      ERROR: Module load cdompleted but symbols could not be loaded for **.dll

     看到类似以上信息是要格外注意,如果加载不正确的信息,后面所有的命令都是很难说明问题的。这是windbg的根本,所以发布版本的时候一定要保存好自己的源代码及符

      号文件。

    利用 "lm v" 命令(不包含双引号)来查看发生dump捕获下来模块信息。利用显示的信息来与你加载符号的文件信息进行核对,看时间戳是否一致,如果不一致,那就找到对应

    的模块才做接下去的工作。

   "lm v"是查看所有加载模块的具体信息,时间较长,如果需要参看某一模块信息,可以使用扩展命令“!lmi 模块名”。

 

3:利用windbg参看发生dump发生的时间。

     打开Dump文件:你会看到Debug session time:***这样的信息,这就是发生dump的时刻信息。有了这个信息,你查看日志就有更加方便。

 

 



      
      
      
     






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值