在调用堆栈中搜索
Search in call stack
我正在分析多线程 C++ 应用程序的内存和故障转储。
如 this VisualCommunity question 中所述,我对所有不等待也不休眠的线程感兴趣。
目前,我使用 Visual Studio (Threads
window) 得到了答案:
1. 将所有线程复制到 Excel sheet(第 1 列),
2. 将 "WaitFor" 筛选的线程复制到 Excel sheet(第 2 列),
3. 将 "Sleep" 筛选的线程也复制到 Excel sheet,(在 column2 的底部)和
4. 使用 ±MATCH(Column1_1;Column2_:Column2_3;0)
Excel worksheet 函数来获取我的结果(在 #N/A
上过滤这些结果)。
我想知道我是否可以在 Windbg 中做类似(但更容易)的事情。
目前我可以要求完整的调用堆栈列表(使用 Windbg 命令~* kb
)。
我可以在 Windbg 中执行 Search call stack
(最有可能向 ~* kb
命令添加一些内容)吗?是否有任何扩展的可能性(如正则表达式)?
Andrew Richards 的 扩展添加了一个 !busy
命令
!busy - Equivalent of ~*knL but only displays stacks that are at least
'depth' frames deep (default depth is 1) and are not waiting for:-
~ ntdll!NtWaitFor*
~ ntdll!ZwWaitFor*
~ ntdll!NtRemoveIoCompletion
~ ntdll!ZwRemoveIoCompletion
~ ntdll!NtReplyWaitReceivePort
~ ntdll!ZwReplyWaitReceivePortEx
找到它的下载有问题,但您可以通过频道 9 link ping Andrew。他通常反应很快。
如果复制粘贴,命令必须在单行中删除 Where() 处的换行符
0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where
( ( p=>p.ToDisplayString().Contains("Wait") == true ))
命令结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( ( p=>p.ToDisplayString().Contains("Wait") == true ))
[0x9dc] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0x480] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xc4] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xae8] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0xeac] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
[0xf08] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xdd4] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0xc64] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0x89c] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[0x162c] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
再次为假条件的命令必须是单行
0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where
( ( p=>p.ToDisplayString().Contains("Wait") == false ))
结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( ( p=>p.ToDisplayString().Contains("Wait") == false ))
[0x208] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0x3ec] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0xadc] : user32!NtUserGetMessage + 0xc [Switch To]
[0x1794] : ntdll!NtDelayExecution + 0xc [Switch To]
[0xe78] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0x1164] : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]
Lieven 建议的 pde 的 !busy 输出与内置命令的输出比较,略微修改以排除 "RemoveIo" 和 "Wait" 堆栈
0:037> dx @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where(
(p=>p.ToDisplayString().Contains("Wait") != true)).Where(p=>p.ToDisplayString().
Contains("Remove") != true)
结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( (p=>p.ToDisplayString().Contains("Wait") !=
true)).Where(p=>p.ToDisplayString().Contains("Remove") != true)
[0xd78] : user32!NtUserGetMessage + 0xc [Switch To]
[0xe44] : user32!NtUserGetMessage + 0xc [Switch To]
[0x514] : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]
0:037> !busy
# 37 TID:0d78 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 1737fdd8 770ccde0 ntdll!KiFastSystemCallRet
01 1737fddc 770cce13 user32!NtUserGetMessage+0xc
xxxx
0b 1737ff24 00000000 ntdll!_RtlUserThreadStart+0x1b
50 TID:0e44 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 1fb8fa18 770ccde0 ntdll!KiFastSystemCallRet
01 1fb8fa1c 770c18d9 user32!NtUserGetMessage+0xc
xxxxxx
07 1fb8fb20 00000000 ntdll!_RtlUserThreadStart+0x1b
53 TID:0514 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 144cf778 7780f20f ntdll!DbgBreakPoint
01 144cf7a8 7748ed6c ntdll!DbgUiRemoteBreakin+0x3c
xxxxxxx
05 144cf848 00000000 ntdll!_RtlUserThreadStart+0x1b
Threads: 3 of 54
Frames : 1
Command: knL
Mode : Basic
还有 !findstack
命令。不幸的是,它需要一个符号作为参数,因此通配符或部分名称将不起作用。
示例:
0:001> !findstack wow64cpu!WaitForMultipleObjects32
Thread 001, 1 frame(s) match
* 01 0000000006c0eb10 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b
Thread 003, 1 frame(s) match
* 01 000000000bb3ebf0 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b
我正在分析多线程 C++ 应用程序的内存和故障转储。
如 this VisualCommunity question 中所述,我对所有不等待也不休眠的线程感兴趣。
目前,我使用 Visual Studio (Threads
window) 得到了答案:
1. 将所有线程复制到 Excel sheet(第 1 列),
2. 将 "WaitFor" 筛选的线程复制到 Excel sheet(第 2 列),
3. 将 "Sleep" 筛选的线程也复制到 Excel sheet,(在 column2 的底部)和
4. 使用 ±MATCH(Column1_1;Column2_:Column2_3;0)
Excel worksheet 函数来获取我的结果(在 #N/A
上过滤这些结果)。
我想知道我是否可以在 Windbg 中做类似(但更容易)的事情。
目前我可以要求完整的调用堆栈列表(使用 Windbg 命令~* kb
)。
我可以在 Windbg 中执行 Search call stack
(最有可能向 ~* kb
命令添加一些内容)吗?是否有任何扩展的可能性(如正则表达式)?
Andrew Richards 的 !busy
命令
!busy - Equivalent of ~*knL but only displays stacks that are at least
'depth' frames deep (default depth is 1) and are not waiting for:-
~ ntdll!NtWaitFor*
~ ntdll!ZwWaitFor*
~ ntdll!NtRemoveIoCompletion
~ ntdll!ZwRemoveIoCompletion
~ ntdll!NtReplyWaitReceivePort
~ ntdll!ZwReplyWaitReceivePortEx
找到它的下载有问题,但您可以通过频道 9 link ping Andrew。他通常反应很快。
如果复制粘贴,命令必须在单行中删除 Where() 处的换行符
0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where
( ( p=>p.ToDisplayString().Contains("Wait") == true ))
命令结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( ( p=>p.ToDisplayString().Contains("Wait") == true ))
[0x9dc] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0x480] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xc4] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xae8] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0xeac] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
[0xf08] : ntdll!NtWaitForMultipleObjects + 0xc [Switch To]
[0xdd4] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0xc64] : ntdll!NtWaitForSingleObject + 0xc [Switch To]
[0x89c] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
[0x162c] : ntdll!NtWaitForKeyedEvent + 0xc [Switch To]
再次为假条件的命令必须是单行
0:057> dx -r1 @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where
( ( p=>p.ToDisplayString().Contains("Wait") == false ))
结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( ( p=>p.ToDisplayString().Contains("Wait") == false ))
[0x208] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0x3ec] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0xadc] : user32!NtUserGetMessage + 0xc [Switch To]
[0x1794] : ntdll!NtDelayExecution + 0xc [Switch To]
[0xe78] : ntdll!NtRemoveIoCompletion + 0xc [Switch To]
[0x1164] : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]
Lieven 建议的 pde 的 !busy 输出与内置命令的输出比较,略微修改以排除 "RemoveIo" 和 "Wait" 堆栈
0:037> dx @$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).Where(
(p=>p.ToDisplayString().Contains("Wait") != true)).Where(p=>p.ToDisplayString().
Contains("Remove") != true)
结果
@$curprocess.Threads.Select(p=>p.Stack).Select(p=>p.Frames).Select(t=>t[1]).
Where( (p=>p.ToDisplayString().Contains("Wait") !=
true)).Where(p=>p.ToDisplayString().Contains("Remove") != true)
[0xd78] : user32!NtUserGetMessage + 0xc [Switch To]
[0xe44] : user32!NtUserGetMessage + 0xc [Switch To]
[0x514] : ntdll!DbgUiRemoteBreakin + 0x3c [Switch To]
0:037> !busy
# 37 TID:0d78 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 1737fdd8 770ccde0 ntdll!KiFastSystemCallRet
01 1737fddc 770cce13 user32!NtUserGetMessage+0xc
xxxx
0b 1737ff24 00000000 ntdll!_RtlUserThreadStart+0x1b
50 TID:0e44 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 1fb8fa18 770ccde0 ntdll!KiFastSystemCallRet
01 1fb8fa1c 770c18d9 user32!NtUserGetMessage+0xc
xxxxxx
07 1fb8fb20 00000000 ntdll!_RtlUserThreadStart+0x1b
53 TID:0514 kb kbn kbnL kn knL kpn kPn
# ChildEBP RetAddr
00 144cf778 7780f20f ntdll!DbgBreakPoint
01 144cf7a8 7748ed6c ntdll!DbgUiRemoteBreakin+0x3c
xxxxxxx
05 144cf848 00000000 ntdll!_RtlUserThreadStart+0x1b
Threads: 3 of 54
Frames : 1
Command: knL
Mode : Basic
还有 !findstack
命令。不幸的是,它需要一个符号作为参数,因此通配符或部分名称将不起作用。
示例:
0:001> !findstack wow64cpu!WaitForMultipleObjects32
Thread 001, 1 frame(s) match
* 01 0000000006c0eb10 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b
Thread 003, 1 frame(s) match
* 01 000000000bb3ebf0 0000000073e0d286 wow64cpu!WaitForMultipleObjects32+0x3b