获取其调用堆栈中包含某个.NET函数的线程?

时间:2015-07-15 17:43:59

标签: windbg crash-dumps sosex

我有一个包含73个线程的用户模式转储。其中一些是管理的,其中一些是原生的。 我想找到托管线程,哪个调用栈包含一个托管函数。

我在调试器中加载了 SOSEX 扩展名。

现在我执行~*e !mk转储所有托管线程,然后手动浏览它们,寻找我需要的东西 - 太长而且无聊。

有更好的方法吗?

1 个答案:

答案 0 :(得分:5)

相关命令

!findstack <module> 2来查找堆栈上有特定模块的线程,但是恕我直言它只适用于本机调用堆栈和模块,而不适用于方法。

然后有!uniqstack可能有助于缩小线程,以防许多线程具有相同的callstack。它也是一个本地命令。

丑陋的内置解决方案

在这种情况下我做的是一个丑陋的解决方法,但我还没有找到更好的东西:

.shell -ci "!clrstack" find "Class.Method("

当然,您可以将其与~*e结合使用,为所有线程执行此操作。

~*e ? $tid;.shell -ci "!clrstack" find "Program.Main("

PyKd脚本

如果您不介意安装其他WinDbg扩展程序,我建议使用PyKd以获得更方便,更安静的解决方案。在WinDbg目录中创建文件findstack.py(或者可能是WinDbg的工作目录,不太确定,否则使用完整路径)和内容

from pykd import * 
if "Class.Method(" in dbgCommand("!clrstack"):
    print(hex(expr("$tid")))

在WinDbg中,运行如下脚本:

.load E:\path to\x86\pykd.pyd
*** Actually it's a DLL and I prefer renaming it
*** .load E:\path to\x86\pykd.dll
~*e !py findstack.py

当然,你可以参数化脚本,例如像

from pykd import *
import sys
if (len(sys.argv) < 4):
    print "find <command> <search term> <success command>."
    quit()

if sys.argv[2] in dbgCommand(sys.argv[1]):
    print(dbgCommand(sys.argv[3]))

然后用参数

调用它
~*e !py find.py "!clrstack" "Program.Main(" "? $tid"