如何从WinDbg中的内存转储中获取线程ID?

时间:2014-02-07 03:25:58

标签: windbg

我正在尝试创建一个运行特定于线程的命令的脚本,以将每个线程的信息输出到单独的文件中。有没有办法获得我可以在命令中运行的线程ID,类似于:~${threadId} e!clrstack。 最终,我正在拍摄的是:

.foreach(tid {!threads})
{
  .logopen c:\temp\${tid}.txt;
  ~${tid}e !dumpstack;
  ~${tid}e !clrstack;
  ~${tid}e !dso;
  ~${tid}e kb 200;
  .logclose
}

这是我到目前为止所得到的:

.foreach /pS 1 /pS2 /pS3 /pS4 /pS5 /ps 3 (l {!runaway})
{
  .printf "${l}\n";
}

这个问题是它具有我正在寻找OSID的价值。看起来像<wantedID>:<OSID>。 如何分离我需要的部分或者是否有更简单的方法从内存转储中获取线程ID?

1 个答案:

答案 0 :(得分:2)

我对.foreach~e的使用感到有点困惑,因为这有点重复(只是你将~e限制在一个线程的事实不会导致嵌套循环。)

是命令

~*e .logopen /t d:\debug\log.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose

足够吗?日志文件名不具有线程ID。

关于.foreach的跳过令牌,我认为您只能使用/pS/ps一次。您的陈述相当于

.foreach /pS 5 /ps 3 (l {!runaway}) { ... }

如果线程ID真的重要

OS线程ID似乎非常重要。

直接在.foreach!threads~等任何命令上使用!runaway似乎不够灵活和可靠,我建议使用.shell find来获取!teb至少在输出方面有一定的一致性。

我将使用.shell find来获取线程ID,因为它由空格分隔,因此.foreach的输出可以用作~*e .foreach /pS 3 /ps 20 (tid {.shell -ci "!teb" find "ClientId"}) { .logopen d:\debug\logs\log${tid}.txt; !dumpstack; !clrstack; !dso; kb 200; .logclose} 的输入。

我提出的完整命令:

from pykd import *
threads = getProcessThreads()
for t in threads:
    print(hex(ptrPtr(t+0x24))[2:-1])

使用pykd作为扩展名

使用PyKd - Python extension for WinDbg,结果可以像这样实现:

创建文件 tid.py ,将其放在pykd.pyd扩展名旁边,并为其提供以下内容:

getProcessThreads()

ptrPtr()为您提供TEB的地址。在偏移量0x24处,您可以找到线程ID。 hex()读取内存地址,[2:是自我解释,:-1]删除0x头,.load pykd.pyd !py tid.py; *** Gives one thread ID per line, nice for .foreach .foreach (tid {!py tid.py}) { .logopen d:\debug\logs\log_${tid}.txt; ~~[${tid}]s; !dumpstack; !clrstack; !dso; kb 200; .logclose} 删除尾随L(不要问我为什么会有尾随L)。

在WinDbg中

{{1}}