Question

I'm trying to create a script that runs thread specific commands to output information for each thread into a separate file. Is there a way to get thread ID that I can run in the command similar to this: ~${threadId} e!clrstack. Ultimately here is what I'm shooting for:

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

Here is what I got so far:

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

The issue with this that it has the value I'm looking for with OSID. Looks like this <wantedID>:<OSID>. How can I separate the part I need or is there an easier way to get thread ID from a memory dump?

Was it helpful?

Solution

I'm a bit confused about the use of .foreach together with ~e, because that's somehow duplicate (just the fact that you're limiting ~e to one thread doesn't result in a nested loop).

Is the command

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

sufficient for you? The log file name will not have the thread ID.

Regarding your skip tokens of .foreach, I think you can only use /pS and /ps once. Your statement is equivalent to

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

If the thread ID really matters

It seems that the OS thread IDs are really important.

As using .foreach directly on any command like !threads, ~ or !runaway seems not flexible and reliable enough, I propose to use .shell find to get at least some consistency in output.

I'll use !teb to get the thread ID, because it is separated by a space and therefore the output of .shell find can be used as input for .foreach.

The complete command I come up with:

~*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}

Using pykd as an extension

Using PyKd - Python extension for WinDbg, the result can be achieved like this:

Create a file tid.py, put it next to the pykd.pyd extension and give it the following content:

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

getProcessThreads() gives you the addresses of the TEBs. At offset 0x24 you can find the thread ID. ptrPtr() reads a memory address, hex() is self-explaining, [2: removes the 0x head and :-1] removes the trailing L (don't ask me why it has a trailing L).

In WinDbg

.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}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top