符号文件(symbol)
符号文件(win 下为扩展名.pdb文件)包含大量调试用的信息,这些信息程序运行的时候不需要,但是在调试或者调查崩溃问题时非常有用,符号文件中主要包括:
- 全局变量
- 局部变量
- 函数名及它的入口地址
- 框架指针省略(Frame Pointer Omission)信息
- 代码的行数
如果没有符号文件,则最多只能从dump中看出模块名+偏移,如果有符号文件,则可以精确定位到崩溃行。
公有符号和私有符号(public symbol/ private symbol)
公有符号中只包含函数名和全局变量:
私有符号中包含全部信息。
如果只有公有符号,则只能看到 函数名+偏移,如果是私有符号,则可以看到完整的行号。
windows提供的符号是公有符号:http://msdl.microsoft.com/download/symbols, 需要设置符号服务器
如何设置符号文件的路径?
D:\MyLcoalSymbol;srv*D:\SymbolCache*https://msdl.microsoft.com/download/symbols
设好后 .reload
如何手动产生dump
1. 从微软网站下载工具Procdump https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump
Procdump -ma PID/ProcessName
Procdump -ma -s 5 -n 3 PID (-s是second, -n是数量)
Procdump –ma -n 3 -s 5 -c 80 ProcessName ( -c是cpu占用超过80%)
Procdump -ma -n 10 -e 1 -f NotFound w3wp.exe (设置进程如果产生某种异常则生成dump)
2.在任务管理器中手动生成:
常用命令介绍
- 自动分析: !analyze -v
- .excr 切换到崩溃的堆栈上下文
- k/kb/kp 查看堆栈详细信息, kd以raw style查看堆栈信息
- !threads 显示所有的线程堆栈 ( ~*)
- ~ThreadID 切换到某个线程 (~5s :进到5号线程堆栈里面(要加s !))
- !address -summary 查看内存概况
- !heap 0 检查所有的堆内存的概况,
- !heap -stat -h heapAddress 查看某个堆的详细信息
- !heap -flt r MinSize MaxSize 查看某个大小范围内的所有堆信息
- u/uf 反汇编代码
- d, da, db, dc, dd, dD, df, dp, dq, du, dw 以不同格式查看内存
- dt 格式化查看某数据结构
- r 查看当前所有寄存器的值
- dv 查看当前所有局部变量的名称和值
常用扩展库Mex
下载地址:https://www.microsoft.com/en-us/download/details.aspx?id=53304
- 先load进去: .load D:\Mex\x64\mex.dll
- 在指定的内存范围内搜索字符串:
!mex.strings
!mex.grep
!grep 'Feishu' !strings 00000223b6c00000 00000223b6cff000
- !mex.us
- !mex.t
- !mex.runaway2 -v(-a)查看占用cpu高的线程
一个小例子
-
下载该dump对应的符号文件, .reload
-
发现报个错,提示符号文件的时间戳不匹配,但是由于符号文件下载的是正确的,所以需要 .symopt + 0x40, 让windbg忽略二进制文件和pdb文件的时戳差异
-
.ecxr 切换到出问题的堆栈上下文,kb查看堆栈:
- 最后一条是thread::join,翻到这个的源代码:
- 用uf命令反汇编join:
- Join + 0x10 是 mov eax, dword ptr [esi + 4], 接下来是test,那可以基本确定出错的是joinable()访问类成员变量出错 ( MOV EAX, dword ptr [ESI + xxh] 这种一般是在访问类的某个成员变量)
这里需要访问thread类的成员变量_Thr,那有可能是此时这个thread已经被释放掉了,所以调用这个joinable出异常,由于this指针是用ecx寄存器保存,用r命令查看所有寄存器的值:(dt -b this 同样可以)
- 用 !address 00340066 查看这个内存的状态:
- 可以看出这个this指针的确是处于被释放的状态,再结合这个问题的log,就定位出是用lamda委托时,捕获了this指针,但这个this指针被销毁后这个lamda才被执行,所以crash。