分析 dump 文件崩溃栈信息
发布于 2022-09-20
Windows 上常见的几个分析 dump 文件崩溃栈信息的方法有以下几种。
windbg 和 cdb
我们可以给 windbg 或者 cdb 传递命令行参数来分析 dump 文件。
首先是 windbg。windbg 功能很强大,但是我们想自动化的批量分析 dump 文件,使用它则是很笨拙。因为微软符号仓库的原因,windbg 分析 dump 文件的时候,会下载 dump 文件里所包含所有模块的调试符号信息文件,这个过程可能耗时几分钟甚至几十分钟。
一个加速 windbg 分析 dump 速度的办法是通过环境变量 _NT_SYMBOL_PROXY
设置一个快速的网络代理,加快符号文件的下载。但是因其内部下载调试符号文件是串行的,所以其速度仍然不够快。
cdb 的功能与 windbg 类似, cdb 是个命令行工具。
breakpad
Google 的 breakpad 项目里包含了一个 processor 工具,它也可以分析 dump 文件。
processor 使用的调试符号文件不是 Windows 上的 pdb 格式,而是通过工具把 pdb 格式转换成 sym 文本格式的调试符号文件。processor 的优点是可以跨平台,它不仅可以分析 windows 平台,可以分析 linux 和 mac 平台生成的崩溃 dump 文件。它的缺点则是如果仅在 windows 平台使用它,维护符号仓库略有些麻烦,不仅需要转换符号文件格式,依赖到的微软符号,也需要自己下载。
processor 分析一个 dump 文件非常快,几秒之内就可以完成。
dbgeng
dbgeng 提供了接口从 dump 文件获得崩溃栈信息,也支持符号仓库,但是依赖到的微软符号,也需要自己下载。
dbghelp
dbghelp 可以使用 StackWalk64 来读取进程里某个线程的调用栈信息,实际上它也是可以应用到 dump 文件中的。
BOOL IMAGEAPI StackWalk64(
[in] DWORD MachineType,
[in] HANDLE hProcess,
[in] HANDLE hThread,
[in, out] LPSTACKFRAME64 StackFrame,
[in, out] PVOID ContextRecord,
[in, optional] PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
[in, optional] PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
[in, optional] PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
[in, optional] PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
StackWalk64 读取 dump 文件的崩溃栈信息实现比较复杂,需要自己处理实现 ReadMemoryRoutine
、FunctionTableAccessRoutine
、GetModuleBaseRoutine
、TranslateAddress
几个函数,几乎没有资料可以参考。
在 github 上有个 DbgHelpUtils 项目,对其有实现。
stack_tracer
最近写了一个分析 dump 文件崩溃栈信息的工具 stack_tracer。它是调用 dbgeng、dbghelp 和 DIA 接口实现的,有以下优点:
- 支持使用符号仓库
- 分析速度快,在不下载微软符号的情况下,可以在几秒之内分析出崩溃栈信息
- 支持自动并行下载微软符号,速度相比 windbg 提高几十倍
- 支持微软符号网络代理,进一步加快符号下载速度
它首先通过 dbghelp 获得 dump 文件里所有模块的信息,然后检查本地符号仓库是否已经存在这些模块对应的符号文件,并通过 DIA 库校验是否符号是否匹配。对那些符号仓库缺失的符号,通过网络去 https://msdl.microsoft.com/download/symbols 微软符号仓库并行下载。准备好符号之后,再通过 dbgeng 接口去获得 dump 文件崩溃栈信息。
它支持的命令行参数如下:
- --dump-file-path,指定 dump 文件的路径
- --symbol-path,可选,指定符号仓库的路径
- --proxy,可选,指定网络代理,用于下载微软符号,如
--proxy=socks5://127.0.0.1:8806
运行的效果如下图所示: