!analyze -v
概述
- 用于 自动分析当前异常或崩溃的根本原因,并输出详细的诊断信息
- 它是调试程序崩溃、蓝屏(
BSOD
)或未处理异常的首选工具
功能
- 分析当前异常类型(如访问违规、除零错误等),定位触发异常的代码位置
- 提供异常上下文、调用栈、寄存器状态、可能原因及建议操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
0:000> !analyze -v ******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* Event is not an exception - analysis may be incorrect KEY_VALUES_STRING: 1 Key : Analysis.CPU.mSec Value: 2421 Key : Analysis.DebugAnalysisProvider.CPP Value: Create: 8007007e on DESKTOP-NRIG174 Key : Analysis.DebugData Value: CreateObject Key : Analysis.DebugModel Value: CreateObject Key : Analysis.Elapsed.mSec Value: 8609 Key : Analysis.Init.CPU.mSec Value: 168437 Key : Analysis.Init.Elapsed.mSec Value: 15272213 Key : Analysis.Memory.CommitPeak.Mb Value: 154 Key : Analysis.System Value: CreateObject Key : Timeline.OS.Boot.DeltaSec Value: 25313 Key : Timeline.Process.Start.DeltaSec Value: 2903 Key : WER.OS.Branch Value: vb_release Key : WER.OS.Timestamp Value: 2019-12-06T14:06:00Z Key : WER.OS.Version Value: 10.0.19041.1 ADDITIONAL_XML: 1 OS_BUILD_LAYERS: 1 NTGLOBALFLAG: 2000000 PROCESS_BAM_CURRENT_THROTTLED: 0 PROCESS_BAM_PREVIOUS_THROTTLED: 0 APPLICATION_VERIFIER_FLAGS: 0 APPLICATION_VERIFIER_LOADED: 1 EXCEPTION_RECORD: (.exr -1) Last event was not an exception FAULTING_THREAD: 00006f64 PROCESS_NAME: aet_breakpad_test.exe STACK_TEXT: 00000000`0014fab0 00007ff6`8b44db55 : 00007ff6`8b634be0 00007ff6`8b42d36b 00000000`00000002 00007ff6`8b4431a4 : aet_breakpad_test!Crash+0x23 00000000`0014fc00 00007ff6`8b4d2619 : 00000000`00000000 00007ff6`8b576588 00000000`00000000 00007ff6`8b4d326d : aet_breakpad_test!main+0xd5 00000000`0014fe10 00007ff6`8b4d24c2 : 00007ff6`8b5de000 00007ff6`8b5de818 00000000`00000000 00000000`00000000 : aet_breakpad_test!invoke_main+0x39 00000000`0014fe60 00007ff6`8b4d237e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main_seh+0x132 00000000`0014fed0 00007ff6`8b4d26ae : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main+0xe 00000000`0014ff00 00007ffe`fa5f7374 : 00000000`002b3000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!mainCRTStartup+0xe 00000000`0014ff30 00007ffe`fc37cc91 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14 00000000`0014ff60 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21 FAULTING_SOURCE_LINE: Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp FAULTING_SOURCE_FILE: Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp FAULTING_SOURCE_LINE_NUMBER: 35 FAULTING_SOURCE_CODE: 31: 32: void Crash() { 33: int x = 99; 34: > 35: throw std::runtime_error("Intentional Crash!"); 36: } 37: 38: void (*fn_crash)() = nullptr; 39: int g_test = 666; 40: SYMBOL_NAME: aet_breakpad_test!Crash+23 MODULE_NAME: aet_breakpad_test IMAGE_NAME: aet_breakpad_test.exe STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ; dt ntdll!LdrpFailureData ; ~0s ; .cxr ; kb FAILURE_BUCKET_ID: APPLICATION_FAULT_AVRF_0_aet_breakpad_test.exe!Crash EXCEPTION_CODE_STR: 0 OS_VERSION: 10.0.19041.1 BUILDLAB_STR: vb_release OSPLATFORM_TYPE: x64 OSNAME: Windows 10 FAILURE_ID_HASH: {daac01dd-533f-db3b-c287-cf936d0b8ea2} Followup: MachineOwner --------- |
!exchain
概述
- 用于 显示当前线程的异常处理链,即结构化异常处理(
SEH
)的链表。它能帮助开发者快速定位异常处理流程中的关键节点,尤其在调试崩溃、访问违规等问题时非常有用
作用
- 展示当前线程的异常处理器(
EXCEPTION_REGISTRATION_RECORD
)链表 - 当异常未被捕获时,操作系统会沿异常链依次调用处理函数,
!exchain
可追踪此过程
1 2 3 4 5 6 7 8 |
0:000> !exchain 8 stack frames, scanning for handlers... Frame 0x01: aet_breakpad_test!main+0xd5 (00007ff6`8b44db55) ehandler aet_breakpad_test!ILT+13985(__GSHandlerCheck_EH4) (00007ff6`8b4306a6) Frame 0x03: aet_breakpad_test!__scrt_common_main_seh+0x132 (00007ff6`8b4d24c2) ehandler aet_breakpad_test!ILT+905(__C_specific_handler) (00007ff6`8b42d38e) Frame 0x07: ntdll!RtlUserThreadStart+0x21 (00007ffe`fc37cc91) ehandler ntdll!_C_specific_handler (00007ffe`fc3bcdb0) |
.exr -1
概述
- 用于 显示当前线程最近一次异常记录(
Exception Record
)的详细信息 - 是调试崩溃、访问违规等异常的核心工具之一
功能
- 展示异常类型、触发地址、参数等关键信息
参数
-1
:显示当前线程的 最新异常记录**(最近一次未处理的异常)0
:显示第一个异常记录(多异常场景)1
:显示第二个异常记录,依此类推
1 2 3 4 5 6 7 8 9 |
0:000> .exr -1 ExceptionAddress: 00007ffef9e4b699 (KERNELBASE!RaiseException+0x0000000000000069) ExceptionCode: e06d7363 (C++ EH exception) ExceptionFlags: 00000001 NumberParameters: 4 Parameter[0]: 0000000019930520 Parameter[1]: 000000000014fbb8 Parameter[2]: 00007ff68b631750 Parameter[3]: 00007ff68b360000 |
.ecxr
概述
- 用于 恢复并显示当前线程的异常上下文(
Exception Context
)- 当程序崩溃或触发异常时,调试器可能无法直接展示异常发生时的完整状态(如寄存器、堆栈等)
- 而
.ecxr
能还原异常触发瞬间的上下文信息,帮助开发者准确分析问题根源
功能
- 加载异常发生时的寄存器状态(
rip
、rsp
等)和堆栈信息 - 自动输出异常地址、寄存器值及调用栈
1 2 3 4 5 6 7 8 9 10 11 |
0:000> .ecxr rax=0000000001c18cb8 rbx=0000000000000000 rcx=0000000000000008 rdx=0000000000000008 rsi=00007ff68b5e1941 rdi=000000000014fcd1 rip=00007ffef9e4b699 rsp=000000000014f940 rbp=000000000014fad0 r8=00007ffed99d29fd r9=0000000001c01000 r10=0000000001c00000 r11=0000000001c01000 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206 KERNELBASE!RaiseException+0x69: 00007ffe`f9e4b699 0f1f440000 nop dword ptr [rax+rax] |
.frame
概述
- 用于 切换当前栈帧(
Stack Frame
)的上下文,使开发者能够查看不同调用层级的局部变量、参数和寄存器状态- 通过切换栈帧,可以逐层分析函数调用链中的问题
功能
- 指定当前调试的栈帧层级(如
0
为最内层,1
为上一层) - 结合
dv
或dt
命令显示当前栈帧的局部变量 - 显示该栈帧对应的寄存器和堆栈信息
k
系列-查看栈
概述
- 用于 分析和显示调用栈(
Call Stack
),是调试崩溃、死锁、逻辑错误的核心工具
k
- 显示当前线程的调用栈
1 2 3 4 5 6 7 8 9 |
0:000> k # Child-SP RetAddr Call Site 00 00000000`0014fc00 00007ff6`8b4d2619 aet_breakpad_test!main+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00000000`0014fe10 00007ff6`8b4d24c2 aet_breakpad_test!invoke_main+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00000000`0014fe60 00007ff6`8b4d237e aet_breakpad_test!__scrt_common_main_seh+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00000000`0014fed0 00007ff6`8b4d26ae aet_breakpad_test!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00000000`0014ff00 00007ffe`fa5f7374 aet_breakpad_test!mainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 05 00000000`0014ff30 00007ffe`fc37cc91 KERNEL32!BaseThreadInitThunk+0x14 06 00000000`0014ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21 |
kb
- 显示调用栈及 前三个参数(适用于快速查看函数参数值)
1 2 3 4 5 6 7 8 9 |
0:000> kb # RetAddr : Args to Child : Call Site 00 00007ff6`8b4d2619 : 00000000`00000000 00007ff6`8b576588 00000000`00000000 00007ff6`8b4d326d : aet_breakpad_test!main+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00007ff6`8b4d24c2 : 00007ff6`8b5de000 00007ff6`8b5de818 00000000`00000000 00000000`00000000 : aet_breakpad_test!invoke_main+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00007ff6`8b4d237e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main_seh+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00007ff6`8b4d26ae : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00007ffe`fa5f7374 : 00000000`002b3000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!mainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 05 00007ffe`fc37cc91 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14 06 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21 |
kp
- 显示调用栈及 完整参数列表和类型(需符号支持)
1 2 3 4 5 6 7 8 9 10 |
0:000> kp # Child-SP RetAddr Call Site 00 00000000`0014fc00 00007ff6`8b4d2619 aet_breakpad_test!main(void)+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00000000`0014fe10 00007ff6`8b4d24c2 aet_breakpad_test!invoke_main(void)+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00000000`0014fe60 00007ff6`8b4d237e aet_breakpad_test!__scrt_common_main_seh(void)+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00000000`0014fed0 00007ff6`8b4d26ae aet_breakpad_test!__scrt_common_main(void)+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00000000`0014ff00 00007ffe`fa5f7374 aet_breakpad_test!mainCRTStartup(void * __formal = 0x00000000`002b3000)+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 05 00000000`0014ff30 00007ffe`fc37cc91 KERNEL32!BaseThreadInitThunk+0x14 06 00000000`0014ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21 |
kn
- 显示调用栈并 添加帧编号(便于后续操作,如
.frame
)
1 2 3 4 5 6 7 8 9 |
0:000> kn # Child-SP RetAddr Call Site 00 00000000`0014fc00 00007ff6`8b4d2619 aet_breakpad_test!main+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00000000`0014fe10 00007ff6`8b4d24c2 aet_breakpad_test!invoke_main+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00000000`0014fe60 00007ff6`8b4d237e aet_breakpad_test!__scrt_common_main_seh+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00000000`0014fed0 00007ff6`8b4d26ae aet_breakpad_test!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00000000`0014ff00 00007ffe`fa5f7374 aet_breakpad_test!mainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 05 00000000`0014ff30 00007ffe`fc37cc91 KERNEL32!BaseThreadInitThunk+0x14 06 00000000`0014ff60 00000000`00000000 ntdll!RtlUserThreadStart+0x21 |
kv
- 显示调用栈及 寄存器和帧指针信息(适用于低级调试)
1 2 3 4 5 6 7 8 9 |
0:000> kv # Child-SP RetAddr : Args to Child : Call Site 00 00000000`0014fc00 00007ff6`8b4d2619 : 00000000`00000000 00007ff6`8b576588 00000000`00000000 00007ff6`8b4d326d : aet_breakpad_test!main+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00000000`0014fe10 00007ff6`8b4d24c2 : 00007ff6`8b5de000 00007ff6`8b5de818 00000000`00000000 00000000`00000000 : aet_breakpad_test!invoke_main+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00000000`0014fe60 00007ff6`8b4d237e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main_seh+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00000000`0014fed0 00007ff6`8b4d26ae : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00000000`0014ff00 00007ffe`fa5f7374 : 00000000`002b3000 00000000`00000000 00000000`00000000 00000000`00000000 : aet_breakpad_test!mainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 05 00000000`0014ff30 00007ffe`fc37cc91 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14 06 00000000`0014ff60 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21 |
切换到指定栈帧
1 2 |
.frame 1 // 切换到第1帧 dv /i // 显示局部变量 |
显示完整调用栈
1 |
k 100 // 显示最多 100 帧 |
过滤调用栈
- 结合
.shell
过滤特定模块:
1 |
.shell -ci "k" findstr /i "my_module" |
1 2 3 4 5 6 7 |
0:000> .shell -ci "k" findstr /i "aet_breakpad_test" 00 00000000`0014fc00 00007ff6`8b4d2619 aet_breakpad_test!main+0x98 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 54] 01 00000000`0014fe10 00007ff6`8b4d24c2 aet_breakpad_test!invoke_main+0x39 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 02 00000000`0014fe60 00007ff6`8b4d237e aet_breakpad_test!__scrt_common_main_seh+0x132 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 03 00000000`0014fed0 00007ff6`8b4d26ae aet_breakpad_test!__scrt_common_main+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 04 00000000`0014ff00 00007ffe`fa5f7374 aet_breakpad_test!mainCRTStartup+0xe [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] .shell: Process exited |
d
系列-查看内存
概述
- 显示给定范围的内存内容
db
- 以 字节(
Byte
)形式显示内存,并尝试将每个字节解析为ASCII
字符 - 非打印字符(如
0x00
、0xFF
)会显示为.
或其他符号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
0:000> dv cca = 0x00007ff6`4c0d1880 "it's me." caa = char [9] "ready..." test = "hello" sttt = struct MyStruct a = 0n0 0:000> db 0x00007ff6`4c0d1880 00007ff6`4c0d1880 69 74 27 73 20 6d 65 2e-00 00 00 00 00 00 00 00 it's me......... 00007ff6`4c0d1890 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18b0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18c0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18d0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18e0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 00007ff6`4c0d18f0 00 00 00 00 00 00 00 00-72 65 61 64 79 2e 2e 2e ........ready... |
dw
- 查看 数值数据(如整数、指针、结构体字段)
- 默认以 十六进制数值 形式展示
- 仅显示数值,不解析为字符
- 由于一个
WORD
包含 两个字节,直接解析为字符可能无意义(除非数据是Unicode
字符串)
- 对于占用
2
个字节的字符(UTF-16
),需要用dc
命令解析 - 对于占用
4
个字节的字符,由于使用极少,windbg
无直接支持 - 另外,结合上面
db
的打印内容,是小端模式,详细见下面大端小端问题
1 2 3 4 5 6 7 8 9 |
0:000> dw 0x00007ff6`4c0d1880 00007ff6`4c0d1880 7469 7327 6d20 2e65 0000 0000 0000 0000 00007ff6`4c0d1890 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18a0 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18b0 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18c0 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18d0 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18e0 0000 0000 0000 0000 0000 0000 0000 0000 00007ff6`4c0d18f0 0000 0000 0000 0000 6572 6461 2e79 2e2e |
dd
- 查看 数值数据(如整数、指针、结构体字段)
- 分析指针或地址
- 检查结构体字段
- 调试数值型数据
1 2 3 4 5 6 7 8 9 |
0:000> dd 0x00007ff6`4c0d1880 00007ff6`4c0d1880 73277469 2e656d20 00000000 00000000 00007ff6`4c0d1890 00000000 00000000 00000000 00000000 00007ff6`4c0d18a0 00000000 00000000 00000000 00000000 00007ff6`4c0d18b0 00000000 00000000 00000000 00000000 00007ff6`4c0d18c0 00000000 00000000 00000000 00000000 00007ff6`4c0d18d0 00000000 00000000 00000000 00000000 00007ff6`4c0d18e0 00000000 00000000 00000000 00000000 00007ff6`4c0d18f0 00000000 00000000 64616572 2e2e2e79 |
- 示例:查看结构体
- 和
dq
对比发现,dd
是4
个字节来显示,dq
是8
个字节来显示
- 和
1 2 3 4 5 6 7 8 |
struct MyStruct { int a; int b; }; MyStruct sttt; sttt.a = 1; sttt.b = 2; |
1 2 3 4 5 6 7 8 9 |
0:000> dd sttt 00000000`0014fca8 00000001 00000002 cccccccc cccccccc 00000000`0014fcb8 cccccccc cccccccc cccccccc cccccccc 00000000`0014fcc8 4c0d1880 00007ff6 cccccccc cccccccc 00000000`0014fcd8 cccccccc cccccccc cccccccc cccccccc 00000000`0014fce8 64616572 2e2e2e79 cccccc00 cccccccc 00000000`0014fcf8 cccccccc cccccccc cccccccc cccccccc 00000000`0014fd08 cccccccc cccccccc cccccccc cccccccc 00000000`0014fd18 cccccccc cccccccc cccccccc cccccccc |
dq
- 查看 数值数据(如整数、指针、结构体字段)
- 分析指针或地址
- 检查结构体字段
- 调试数值型数据
1 2 3 4 5 6 7 8 9 |
0:000> dq 0x00007ff6`4c0d1880 00007ff6`4c0d1880 2e656d20`73277469 00000000`00000000 00007ff6`4c0d1890 00000000`00000000 00000000`00000000 00007ff6`4c0d18a0 00000000`00000000 00000000`00000000 00007ff6`4c0d18b0 00000000`00000000 00000000`00000000 00007ff6`4c0d18c0 00000000`00000000 00000000`00000000 00007ff6`4c0d18d0 00000000`00000000 00000000`00000000 00007ff6`4c0d18e0 00000000`00000000 00000000`00000000 00007ff6`4c0d18f0 00000000`00000000 2e2e2e79`64616572 |
- 示例:查看结构体
- 小端
1 2 3 4 5 6 7 8 |
struct MyStruct { int a; int b; }; MyStruct sttt; sttt.a = 1; sttt.b = 2; |
1 2 3 4 5 6 7 8 9 |
0:000> dq sttt 00000000`0014fca8 00000002`00000001 cccccccc`cccccccc 00000000`0014fcb8 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fcc8 00007ff6`4c0d1880 cccccccc`cccccccc 00000000`0014fcd8 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fce8 2e2e2e79`64616572 cccccccc`cccccc00 00000000`0014fcf8 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fd08 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fd18 cccccccc`cccccccc cccccccc`cccccccc |
dc
- 一个专为 查看内存中的
Unicode
(多字节)字符串 设计的实用工具- 以
DWORD + ASCII
混合形式显示
- 以
- 将内存中的 每
2
字节 视为一个UTF-16
字符,并将每4
字节(即两个UTF-16
字符)组合成一个DWORD
显示
1 2 3 4 5 6 7 8 9 |
0:000> dc 0x00007ff6`1c981880 00007ff6`1c981880 73277469 2e656d20 00000000 00000000 it's me......... 00007ff6`1c981890 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818a0 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818b0 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818c0 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818d0 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818e0 00000000 00000000 00000000 00000000 ................ 00007ff6`1c9818f0 00000000 00000000 64616572 2e2e2e79 ........ready... |
du
- 用于 直接显示内存中的
Unicode
字符串(UTF-16
编码) 的工具- 它会自动解析内存中的宽字符(
wchar_t
)数据,并以可读的字符串形式输出,无需手动计算长度或处理字节序
- 它会自动解析内存中的宽字符(
- 示例:直接用显示的地址查看
1 2 3 4 5 6 7 8 9 |
0:000> dv cca = 0x00007ff6`1c981880 "it's me." caa = char [9] "ready..." test = "hello" wcc = 0x00007ff6`1c97f5b8 "我的" sttt = struct MyStruct a = 0n0 0:000> du 0x00007ff6`1c97f5b8 00007ff6`1c97f5b8 "我的" |
- 示例:通过变量名来输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
0:000> ?? & wcc wchar_t ** 0x00000000`0014fcf8 // 上面这个指针里面存了个指针,类型是wchar_t,那就先查看存的地址 0:000> dq 0x00000000`0014fcf8 00000000`0014fcf8 00007ff6`1c97f5b8 cccccccc`cccccccc 00000000`0014fd08 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fd18 cccccccc`cccccccc cccccccc`cccccccc 00000000`0014fd28 cccccccc`cccccccc 00007ff6`1c9d6b48 00000000`0014fd38 00007ff6`1c97ca40 00000000`01e85fe0 00000000`0014fd48 00000000`0014fd28 00000000`0014fd28 00000000`0014fd58 00007ff6`1c873267 00007ff6`1c97ca40 00000000`0014fd68 00000000`00000000 00000000`00000000 // 发现是00007ff6`1c97f5b8,再用du打印 0:000> du 00007ff6`1c97f5b8 00007ff6`1c97f5b8 "我的" |
da
- 用于 显示以空字符(
\0
)结尾的ASCII
字符串 的工具- 它会从指定地址开始,持续输出内存中的
ASCII
字符,直到遇到终止符\0
(0x00
)
- 它会从指定地址开始,持续输出内存中的
1 2 |
0:000> da 0x00007ff6`1c981880 00007ff6`1c981880 "it's me." |
dds
- 用于 显示内存中的
DWORD
(4
字节)数据并自动解析符号名称- 它特别适合分析指针、函数地址或全局变量,能显著提升调试效率
- 详细用法与下面的
dqs
类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
0:000> dds 00007ff6`8b634908 00007ff6`8b634908 8b42f3d2 00007ff6`8b63490c 00007ff6 00007ff6`8b634910 00000024 00007ff6`8b634914 00000000 00007ff6`8b634918 00000000 00007ff6`8b63491c 00000000 00007ff6`8b634920 00000002 00007ff6`8b634924 00000000 00007ff6`8b634928 00000000 00007ff6`8b63492c 00000000 00007ff6`8b634930 00000004 00007ff6`8b634934 00000000 00007ff6`8b634938 00000000 00007ff6`8b63493c 00000000 00007ff6`8b634940 01e83fc0 00007ff6`8b634944 00000000 00007ff6`8b634948 00000000 00007ff6`8b63494c 00000000 00007ff6`8b634950 022eefe0 00007ff6`8b634954 00000000 00007ff6`8b634958 00000000 00007ff6`8b63495c 00000000 00007ff6`8b634960 0230efc0 00007ff6`8b634964 00000000 00007ff6`8b634968 00000000 00007ff6`8b63496c 00000000 00007ff6`8b634970 022e6fd0 00007ff6`8b634974 00000000 00007ff6`8b634978 00000000 00007ff6`8b63497c 00000001 00007ff6`8b634980 022e4fd0 00007ff6`8b634984 00000000 |
dqs
- 用于显示内存中的
QWORD
(四字,8
字节)数据,并尝试将这些数值解析为符号地址- 以十六进制形式显示指定地址开始的
QWORD
数据 - 将每个
QWORD
视为一个地址,并查找对应的符号名称(如函数名、全局变量名) - 调试指针数组、虚函数表、全局变量地址等需要符号信息的场景
- 以十六进制形式显示指定地址开始的
- 示例如下:
- 显示
Crash
函数相关符号
- 显示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
0:000> x aet_breakpad_test!fn_crash 00007ff6`8b634908 aet_breakpad_test!fn_crash = 0x00007ff6`8b42f3d2 0:000> dqs 00007ff6`8b634908 00007ff6`8b634908 00007ff6`8b42f3d2 aet_breakpad_test!ILT+9165(?CrashYAXXZ) 00007ff6`8b634910 00000000`00000024 00007ff6`8b634918 00000000`00000000 00007ff6`8b634920 00000000`00000002 00007ff6`8b634928 00000000`00000000 00007ff6`8b634930 00000000`00000004 00007ff6`8b634938 00000000`00000000 00007ff6`8b634940 00000000`01e83fc0 00007ff6`8b634948 00000000`00000000 00007ff6`8b634950 00000000`022eefe0 00007ff6`8b634958 00000000`00000000 00007ff6`8b634960 00000000`0230efc0 00007ff6`8b634968 00000000`00000000 00007ff6`8b634970 00000000`022e6fd0 00007ff6`8b634978 00000001`00000000 00007ff6`8b634980 00000000`022e4fd0 |
dps
- 用于 显示内存中的指针数据并自动解析符号名称
- 以指针大小(
32
位系统为4
字节,64
位系统为8
字节)为单位显示内存数据 - 将每个指针值视为地址,并尝试解析为符号名称(如函数、全局变量)
- 根据调试目标自动选择
32
位(DWORD
)或64
位(QWORD
)解析
- 以指针大小(
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
0:000> dps 00007ff6`8b634908 00007ff6`8b634908 00007ff6`8b42f3d2 aet_breakpad_test!ILT+9165(?CrashYAXXZ) 00007ff6`8b634910 00000000`00000024 00007ff6`8b634918 00000000`00000000 00007ff6`8b634920 00000000`00000002 00007ff6`8b634928 00000000`00000000 00007ff6`8b634930 00000000`00000004 00007ff6`8b634938 00000000`00000000 00007ff6`8b634940 00000000`01e83fc0 00007ff6`8b634948 00000000`00000000 00007ff6`8b634950 00000000`022eefe0 00007ff6`8b634958 00000000`00000000 00007ff6`8b634960 00000000`0230efc0 00007ff6`8b634968 00000000`00000000 00007ff6`8b634970 00000000`022e6fd0 00007ff6`8b634978 00000001`00000000 00007ff6`8b634980 00000000`022e4fd0 |
1 2 3 4 5 6 |
0:000> dps aet_breakpad_test!fn_crash L5 00007ff6`8b634908 00007ff6`8b42f3d2 aet_breakpad_test!ILT+9165(?CrashYAXXZ) 00007ff6`8b634910 00000000`00000024 00007ff6`8b634918 00000000`00000000 00007ff6`8b634920 00000000`00000002 00007ff6`8b634928 00000000`00000000 |
dt
- 用于 显示符号的类型信息,例如结构体、联合体、类的成员布局,以及全局变量的类型
- 能够帮助开发者快速理解内存数据的结构,是调试复杂数据结构的关键工具
- 查看结构体、类、联合体的成员及其偏移量
- 根据内存地址显示某个类型实例的具体数据
- 显示嵌套结构或数组的详细信息
- 按名称模糊匹配类型或变量
1 2 3 4 |
0:000> dt MyStruct aet_breakpad_test!MyStruct +0x000 a : Int4B +0x004 b : Int4B |
1 2 3 4 5 6 7 8 9 |
0:000> dt MyStruct 00000000`0014fc88 aet_breakpad_test!MyStruct +0x000 a : 0n1 +0x004 b : 0n2 0:000> dt sttt Local var @ 0x14fc88 Type MyStruct +0x000 a : 0n1 +0x004 b : 0n2 |
1 2 3 4 5 6 7 8 |
0:000> dt -r test Local var @ 0x14fc48 Type std::basic_string<char,std::char_traits<char>,std::allocator<char> > +0x000 _Mypair : std::_Compressed_pair<std::allocator<char>,std::_String_val<std::_Simple_types<char> >,1> +0x000 _Myval2 : std::_String_val<std::_Simple_types<char> > +0x000 _Myproxy : 0x00000000`022ecfe0 std::_Container_proxy +0x008 _Bx : std::_String_val<std::_Simple_types<char> >::_Bxty +0x018 _Mysize : 5 +0x020 _Myres : 0xf |
1 2 3 4 5 |
0:000> dt /v sttt Local var [AddrFlags 90 AddrOff 0000000000000068 Reg/Val rbp (8)] @ 0x14fc88 Type MyStruct struct MyStruct, 2 elements, 0x8 bytes +0x000 a : 0n1 +0x004 b : 0n2 |
s
-搜索内存
概述
- 在内存中搜索指定的字节序列或字符串
- 它是调试内存损坏、数据查找或逆向分析的关键工具
标志
-a
- 搜索
ASCII
字符串(默认以\0
结尾)
- 搜索
-u
- 搜索
Unicode
字符串(双字节,默认以\0\0
结尾)
- 搜索
-b
- 搜索二进制字节序列(以十六进制表示)
-o
- 输出匹配项的偏移量(而非完整内存内容).
-v
- 反向搜索(显示不匹配的内容,较少用)
搜索ASCII
字符串
1 2 |
0:000> s -a 0x00000000 L?7fffffff "hello" 00000000`0014fc50 68 65 6c 6c 6f 00 00 00-00 00 00 00 00 00 00 00 hello........... |
其他相关
打印局部变量地址
- 切换到对应的帧
1 2 |
0:000> .frame 03 03 00000000`0014fc20 00007ff6`4bfc2569 aet_breakpad_test!main+0xb8 [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 53] |
- 列出局部变量
1 2 3 4 5 6 |
0:000> dv cca = 0x00007ff6`4c0d1880 "it's me." caa = char [9] "ready..." test = "hello" sttt = struct MyStruct a = 0n0 |
- 查看某个变量地址
1 2 |
0:000> ?? &a int * 0x00000000`0014fc44 |
大端小端问题
- 小端
- 低地址存低位字节
x86/x64
架构默认
- 大端
- 高地址存低位字节
- 如网络协议、某些嵌入式系统
- 按照上述
db dw
的打印,示例分析如下:- 内存中的字节顺序(来自
db
):69
→74
- 低字节
0x69
→ 高位字节0x74
- 数值 =
0x74 << 8 | 0x69 = 0x7469
- 正是
dw
显示的7469
- 内存中的字节顺序(来自
- 简单总结判断:
db
和dw
打印显示的字节顺序相反,则是小端模式db
和dw
打印显示的字节顺序相同,则是大端模式
怎么查看符号地址,如函数,局部变量,全局变量
- 使用
x
命令查看函数地址
1 2 |
0:000> x aet_breakpad_test!Crash 00007ff6`1c7e5b00 aet_breakpad_test!Crash (void) |
- 使用
x
命令或dqs
命令查看全局变量地址
1 |
x MyModule!g_GlobalVar |
1 2 |
0:000> x aet_breakpad_test!g_test 00007ff6`eb6d2058 aet_breakpad_test!g_test = <Memory access error> |
1 2 3 |
// 若变量是指针或对象: dqs MyModule!g_GlobalVar |
- 查看局部变量
1 2 3 4 |
k // 查看调用栈 .frame 0 // 切换到当前帧(默认是第0帧) dv /i /V // 显示变量名、地址和值 |
- 计算表达式地址
1 |
?? &x // 获取变量 x 的地址 |
- 使用
dv /v
查看局部变量和地址
1 2 3 4 5 6 7 |
0:000> dv /v 00000000`0014fca8 cca = 0x00007ff6`1c981880 "it's me." 00000000`0014fcc8 caa = char [9] "ready..." 00000000`0014fc48 test = "hello" 00000000`0014fcf8 wcc = 0x00007ff6`1c97f5b8 "我的" 00000000`0014fc88 sttt = struct MyStruct 00000000`0014fc24 a = 0n0 |
- 使用
dv /i /v
查看pre
表示该变量是当前函数作用域内的 私有变量(即局部变量)local
直接表明这是一个 局部变量- 其他的,如:
prm
函数参数
gbl
全局变量
1 2 3 4 5 6 7 |
0:000> dv /v /i prv local 00000000`0014fca8 cca = 0x00007ff6`1c981880 "it's me." prv local 00000000`0014fcc8 caa = char [9] "ready..." prv local 00000000`0014fc48 test = "hello" prv local 00000000`0014fcf8 wcc = 0x00007ff6`1c97f5b8 "我的" prv local 00000000`0014fc88 sttt = struct MyStruct prv local 00000000`0014fc24 a = 0n0 |
已知地址,怎么查看对应符号
- 使用
ln
1 2 3 4 5 6 7 |
0:000> ln 00007ff6`1c7e5b00 Browse module Set bu breakpoint [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 33] (00007ff6`1c7e5b00) aet_breakpad_test!Crash | (00007ff6`1c7e5b70) aet_breakpad_test!std::_String_val<std::_Simple_types<char> >::_Activate_SSO_buffer Exact matches: aet_breakpad_test!Crash (void) |
- 使用
u
进行反汇编
1 2 3 4 5 6 7 8 9 10 |
0:000> u 00007ff6`1c7e5b00 aet_breakpad_test!Crash [Q:\google_code\breakpad\src\src\client\windows\aet_test\aet_breakpad_test\aet_breakpad_test.cpp @ 33]: 00007ff6`1c7e5b00 4055 push rbp 00007ff6`1c7e5b02 57 push rdi 00007ff6`1c7e5b03 4881ec38010000 sub rsp,138h 00007ff6`1c7e5b0a 488d6c2420 lea rbp,[rsp+20h] 00007ff6`1c7e5b0f 488d0d03962000 lea rcx,[aet_breakpad_test!_NULL_IMPORT_DESCRIPTOR <PERF> (aet_breakpad_test+0x2ef119) (00007ff6`1c9ef119)] 00007ff6`1c7e5b16 e8d7cdfeff call aet_breakpad_test!ILT+22765(__CheckForDebuggerJustMyCode) (00007ff6`1c7d28f2) 00007ff6`1c7e5b1b 90 nop 00007ff6`1c7e5b1c c7450463000000 mov dword ptr [rbp+4],63h |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Windows 核心编程 _ 作业07/01
- ♥ Windows进程通信相关03/10
- ♥ Soui应用 动画二06/27
- ♥ Windows核心编程_必备知识04/27
- ♥ x86_64汇编学习记述二08/07
- ♥ Windows消息处理机制04/29