在通话堆栈中搜索

时间:2019-01-17 09:36:28

标签: multithreading windbg

我正在分析多线程C ++应用程序的内存和崩溃转储。

this VisualCommunity question中所述,我对所有不等待也不睡觉的线程感兴趣。
目前,我是通过Visual Studio(Threads窗口)通过以下方式获得答案的:
1.将所有线程复制到Excel工作表(column1),
2.将“ WaitFor”过滤的线程复制到Excel工作表(column2),
3.将“睡眠”过滤的线程也复制到Excel工作表(在第2列的底部),然后
4.使用±{MATCH(Column1_1;Column2_$1:Column2_$143;0) Excel工作表功能以获取我的结果(在#N/A上过滤这些结果)。

我想知道我是否可以在Windbg中做类似(但更容易)的事情。

目前,我可以要求完整的调用堆栈列表(使用Windbg命令~* kb)。

我可以在Windbg中做一个Search call stack吗(很可能是在~* kb命令中添加一些内容)?有扩展的可能性(如正则表达式)吗?

3 个答案:

答案 0 :(得分:4)

如果复制粘贴,命令必须在单行中删除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

答案 1 :(得分:1)

安德鲁·理查兹(Andrew Richards)的PDE扩展名添加了一个!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

无法找到所需的下载文件,但您可以通过Channel 9链接ping Andrew。他通常反应很快。

答案 2 :(得分:0)

还有!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