windbg分析崩溃dmp没有可用信息的处理

本文介绍如何通过WinDbg工具分析dmp文件来定位应用程序崩溃的原因,包括转储dmp文件、使用WinDbg打开并分析dmp文件的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、示例

这个只用作说明,因此代码简单

// TestDmp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

typedef struct _TEST_INFO_
{
	CString strAlarm;
	int nCount;

	_TEST_INFO_()
	{
		strAlarm = L"";
		nCount = 0;
	}

}TEST_INFO, *PTEST_INFO;

int _tmain(int argc, _TCHAR* argv[])
{
	PTEST_INFO pTest = NULL;
	CString strAlarm = pTest->strAlarm;

	system("pause");
	return 0;
}

分析步骤

这里主要是讲不能调试的情况(毕竟示例这么简单,调试都可不用就看出问题)

1、转储dmp文件

在进程还没有退出的情况下,在任务管理器右键进程名——创建转储文件即可

2、使用WinDbg打开dmp文件

使用WinDbg打开1中保存的dmp文件,设置一下富豪路径和源代码路径(不设置也行,测试也是可以的)

3、!analyze -v

如果出现以下问题:
在这里插入图片描述
执行以下命令切换为32位模式:
在这里插入图片描述

0:000:x86> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** The OS name list needs to be updated! Unknown Windows version: 10.0 ***
GetUrlPageData2 (WinHttp) failed: 12002.

FAULTING_IP: 
+c40
00000000 ??              ???

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 0000000000000000
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 0

CONTEXT:  0000000000000000 -- (.cxr 0x0;r)
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=00000003 edi=00000003
eip=77db32fc esp=00fdeec0 ebp=00fdf050 iopl=0         nv up ei pl nz ac pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000216
ntdll_77d40000!NtWaitForMultipleObjects+0xc:
77db32fc c21400          ret     14h

FAULTING_THREAD:  0000000000001cfc

PROCESS_NAME:  TestDmp.exe

ERROR_CODE: (NTSTATUS) 0x80000003 - {

EXCEPTION_CODE: (NTSTATUS) 0x80000003 (2147483651) - {

NTGLOBALFLAG:  0

APPLICATION_VERIFIER_FLAGS:  0

APP:  testdmp.exe

ANALYSIS_VERSION: 6.3.9600.17237 (debuggers(dbg).140716-0327) amd64fre

BUGCHECK_STR:  APPLICATION_FAULT_STATUS_BREAKPOINT_ZEROED_STACK

PRIMARY_PROBLEM_CLASS:  STATUS_BREAKPOINT

DEFAULT_BUCKET_ID:  STATUS_BREAKPOINT

LAST_CONTROL_TRANSFER:  from 0000000077bc7ef3 to 0000000077db32fc

STACK_TEXT:  
00fdeebc 77bc7ef3 00000003 00fdf0f0 00000001 ntdll_77d40000!NtWaitForMultipleObjects+0xc
00fdf050 77bc7da8 00000003 00fdf0f0 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x133
00fdf06c 77816967 00000003 00fdf0f0 00000000 KERNELBASE!WaitForMultipleObjects+0x18
00fdf118 77816598 00000000 00000000 00fdf20c kernel32!WerpReportFaultInternal+0x3b7
00fdf134 777ec299 00fdf1dc 77c7ce6b 00fdf20c kernel32!WerpReportFault+0x9d
00fdf13c 77c7ce6b 00fdf20c 00000001 20e385f0 kernel32!BasepReportFault+0x19
00fdf1dc 77de287e 00fdf20c 77db72f2 00fdf970 KERNELBASE!UnhandledExceptionFilter+0x29b
00fdf970 77da8774 ffffffff 77dca139 00000000 ntdll_77d40000!__RtlUserThreadStart+0x3a109
00fdf980 00000000 00bb161d 011da000 00000000 ntdll_77d40000!_RtlUserThreadStart+0x1b


STACK_COMMAND:  ~0s; .ecxr ; kb

FOLLOWUP_IP: 
ntdll_77d40000!NtWaitForMultipleObjects+c
77db32fc c21400          ret     14h

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  ntdll!NtWaitForMultipleObjects+c

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: ntdll_77d40000

IMAGE_NAME:  ntdll.dll

DEBUG_FLR_IMAGE_TIMESTAMP:  47d68d20

FAILURE_BUCKET_ID:  STATUS_BREAKPOINT_80000003_ntdll.dll!NtWaitForMultipleObjects

BUCKET_ID:  APPLICATION_FAULT_STATUS_BREAKPOINT_ZEROED_STACK_ntdll!NtWaitForMultipleObjects+c

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:status_breakpoint_80000003_ntdll.dll!ntwaitformultipleobjects

FAILURE_ID_HASH:  {ad4c05a5-d4e5-24d8-5d7e-ae3c60766b85}

Followup: MachineOwner
---------

运行一下~0s; .ecxr ; kb
在这里插入图片描述
好像啥也没有~~~~~

这个时候怎么办呢?没办法了吗?当然不是啦,接下来我们可以找一下有没有 KERNELBASE!UnhandledExceptionFilter 这个调用(很明显,上面第7行就是,如果没有,就执行~*kbn看看吧)

运行一下dd 00fdf20c
在这里插入图片描述
在运行一下 .exr 00fdf34c
在这里插入图片描述
再运行一下 .cxr 00fdf39c
在这里插入图片描述
这个时候就会跳转到出错的地方了
在这里插入图片描述
执行一下kbn,这个时候我们就看到了出问题的行了
在这里插入图片描述
这个时候可以打开call stack窗口,双击TestDmp!wmain+0x19
行,或者输入.frame 3,之后打开locals窗口
在这里插入图片描述
在这里插入图片描述
可知,非法使用指针了。

<think>好的,我现在需要回答用户关于如何在没有PDB文件的情况下,通过ESP寄存器使用WinDbg重建调用堆栈的问题。首先,我需要回顾一下WinDbg的基本操作和分析dump文件的步骤。根据用户提供的引用内容,特别是引用[1]和[3],分析dump文件的一般步骤包括打开dump文件、加载符号、分析异常上下文等。不过用户提到没有PDB文件,这意味着符号信息可用,这会影响堆栈的解析,因为PDB通常包含函数名和变量信息。 接下来,用户想通过ESP寄存器来重建调用堆栈。ESP(Extended Stack Pointer)寄存器在x86架构中指向当前堆栈的顶部。每个函数调用时,返回地址和局部变量会被压入堆栈,ESP会随之变化。因此,通过分析ESP的值,可能可以追踪函数调用的顺序。 首先,我需要确认在WinDbg中如何查看寄存器的值。使用`r`命令可以显示所有寄存器的当前值,包括ESP。然后,查看堆栈内存的内容,可以使用`dps`命令,它会显示指针大小的数据,并尝试解析符号。不过在没有PDB的情况下,符号解析可能不成功,只能看到地址。 用户可能需要手动分析堆栈中的返回地址。每个函数调用时,返回地址会被压入堆栈,位于EBP+4的位置(假设使用EBP帧指针)。不过如果编译器优化导致帧指针被省略(比如使用FPO优化),EBP可能不会被使用,这时只能依赖ESP的变化来推断调用链。 此时,可能需要检查堆栈中的地址,并尝试将这些地址与模块的基地址进行比较,确定它们属于哪个模块(如exe或dll)。使用`lm`命令可以列出加载的模块及其地址范围。然后,手动计算偏移量,确定函数在模块中的位置。 例如,假设ESP指向的堆栈地址是0x0012ff34,使用`dd 0x0012ff34 L4`可以查看该地址处的数据,寻找可能的返回地址。如果找到一个地址0x00401000,使用`lm`发现该地址属于主模块(基地址0x00400000),则函数偏移量为0x1000。通过反汇编`u 0x00401000`,可以查看附近的代码,推测函数调用。 此外,还可以使用`kb`或`k`命令尝试显示堆栈回溯,但如果没有符号,可能只能看到地址而非函数名。结合ESP的值和堆栈内容,手动记录每个可能的返回地址,并分析它们的模块和偏移,逐步重建调用链。 需要注意的是,这种方法需要一定的经验和耐心,因为缺乏符号信息会使得分析变得困难。可能需要结合代码逻辑、崩溃时的上下文(如异常代码、寄存器状态)来综合判断问题所在。 最后,用户可能需要参考引用[3]中的教程,了解更多关于C++异常排查的技巧,尤其是在没有符号的情况下如何利用现有信息进行调试。</think>在无PDB文件时,通过ESP寄存器重建调用堆栈需要手动分析堆栈内存和寄存器状态,具体步骤如下: --- ### **1. 加载Dump文件并检查异常上下文** - 使用`!analyze -v`命令获取异常类型和触发地址: ```bash 0:000> !analyze -v ``` 该命令会显示异常代码(如`ACCESS_VIOLATION`)、触发地址(`FAULTING_IP`)以及关键寄存器状态[^1]。 --- ### **2. 查看当前寄存器状态** - 通过`r`命令获取ESP寄存器的值: ```bash 0:000> r eax=00000001 ebx=0012ff3c ecx=00000000 edx=00000000 esi=00000000 edi=0012ff34 eip=00401000 esp=0012fecc ebp=0012ff34 iopl=0 nv up ei pl zr na po nc ``` 记录`esp`的值(例如`0x0012fecc`)。 --- ### **3. 分析堆栈内存** - 使用`dps`命令从ESP地址开始遍历堆栈,寻找可能的返回地址: ```bash 0:000> dps esp 0012fecc 0040105a ; 可能是函数返回地址 0012fed0 77c3e0b4 ; 系统DLL地址(如ntdll.dll) 0012fed4 0012ff34 ; 局部变量或参数 ``` 若地址在可执行模块范围内(如`0x0040105a`),则可能是用户代码的返回地址。 --- ### **4. 定位函数模块** - 使用`lm`命令列出已加载模块: ```bash 0:000> lm start end module name 00400000 0040f000 MyApp (deferred) ; 用户程序 77c10000 77c68000 ntdll (deferred) ; 系统DLL ``` 判断返回地址所属模块(例如`0x0040105a`属于`MyApp.exe`)。 --- ### **5. 反汇编关键地址** - 对可疑地址(如`0x0040105a`)使用`u`命令反汇编: ```bash 0:000> u 0040105a MyApp!SomeFunction+0x1a: 0040105a 8b4508 mov eax,dword ptr [ebp+8] 0040105d 83c404 add esp,4 ``` 通过反汇编代码推测函数名和调用关系。 --- ### **6. 重建调用链** 结合ESP指向的堆栈数据和反汇编结果,手动构建调用链: ``` ESP+0x00: 返回地址1 -> MyApp!FunctionA+0x10 ESP+0x04: 返回地址2 -> MyApp!FunctionB+0x20 ESP+0x08: 返回地址3 -> ntdll!RtlDispatchException ``` 每个返回地址对应一次函数调用。 --- ### **注意事项** - **帧指针优化(FPO)**:若编译器启用了FPO,EBP可能不用于帧指针,需依赖ESP偏移推算参数和返回地址。 - **系统调用识别**:地址在系统DLL范围内(如`ntdll.dll`)时,可结合公开符号库(`srv*`)解析函数名[^2]。 - **堆栈对齐**:x86架构中,参数通常按4字节对齐压栈,可通过`dd esp Ln`查看具体内容。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值