How to get thread IDs from a memory dump in WinDbg? - windbg

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?

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}

Related

Getting the process ID from a crash dump file with PyKd

I am analyzing a lot of crash dumps with Pykd and I would like to get the process ID (PID) from the crash dump.
In WinDbg, I'd use the command | and use my brain to figure it out. Some time later, I'd come up with a command like
.foreach /pS 3 /ps 999 ( pid {|}) {.echo ${pid}}
which extracts the process ID for me.
Just a little bit smarter and I'd use a pseudo register instead:
.printf "%p", $tpid
How would I use PyKD to get the process ID from a user mode crash dump file (.dmp)?
Of course I can always do a pykd.dbgCommand(), but I'd like to use a more robust built-in way.
I have tried
pykd.getCurrentProcessId() but it returns 0.
pykd.reg("tpid") but it says "Invalid register name"
0:000> dx Debugger.Sessions.First().Processes
Debugger.Sessions.First().Processes
[0x294c] : wait.exe
0:000> .shell -ci ".echo " type f:\src\wait\pid.py
from pykd import *
print(hex(expr("#$tpid"))).shell: Process exited
0:000> !py f:\src\wait\pid.py
0x294c
0:000> |
. 0 id: 294c examine name: F:\src\wait\wait.exe
0:000>
The pseudo reguster idea was not that bad:
pykd.expr("$tpid")
gives the process ID as a number. Format it as hexadecimal if it's needed in the same format as |.
try to use pykd.getProcessSystemID
https://githomelab.ru/pykd/pykd/-/wikis/API%20Reference#function-getprocesssystemid
getCurrentProcessId has sense if you are debugging several processes and need to switch they contexts ( like | command )

Is there any equivalent command for !findstack to filter the managed code?

I found the !findstack just can be used to filter unmanaged code, however it failed to filter managed code, so is there any equivalent command for !findstack to filter the managed code ?
I don't know of a ready-to-use function like this, so I see two options here:
fiddle around with some WinDbg internal commands (which you can hardly understand half a year later)
use PyKd and write a nice script in Python
Approach a)
This may look similar to this:
~*e .foreach(word {!clrstack}) {.if ($spat("${word}", "?*RunMessageLoop?*") == 1) {.printf "Found!\n"}}
Approach b)
Put the following into a file called clrfindstack.py
from pykd import *
import sys
if len(sys.argv) == 1: # script name only
print "Please provide a search string as argument"
exit()
threads = getNumberThreads()
for thread in range(0, threads):
dbgCommand("~"+str(thread)+"s") # select the thread
stack = dbgCommand("!clrstack") # run !clrstack
if sys.argv[1] in stack: # [0] is the script name
print "Found", sys.argv[1], "in thread", thread, "(Use ~"+str(thread)+"s to select it)"
And then run it
0:000> !py c:\tmp\clrfindstack.py
Please provide a search string as argument
0:000> !py c:\tmp\clrfindstack.py RunMessageLoop
Found RunMessageLoop in thread 0 (Use ~0s to select it)
The implementation is probably not very pythonic, but does its job.

setting a breakpoint in windbg using a script

I would like to create a script in windbg that sets a breakpoint in System.Windows.Forms.Application+MarshalingControl..ctor and when that breakpoint is being hit, it just dumps the stack trace into a log file that i open.
I'm using the sos extension's !Name2EE command to get the JITTED code address, but i still don't have a way to get the exact address from what is being returned:
.block{.shell -ci "!Name2EE *!System.Windows.Forms.Application+MarshalingControl..ctor" FIND "JITTED Code Address:"}
but this returns: JITTED Code Address: 63348434
Where i would like to get only the address number itself.
Any suggestions?
Getting the jitted address
You can surround that by a .foreach which eats the words JITTED Code Address: by using /pS 3 (initial skip) and eats .shell: Process exited by /ps 3 (skip):
I tried with
0:000> .foreach /pS 3 /ps 3 (var {.shell -ci ".echo JITTED Code Address: 63348434" FIND "JITTED Code Address:"}) {.echo ${var}}
63348434
You should use
.block{.foreach /pS 3 /ps 3(var {.shell -ci "!Name2EE *!System.Windows.Forms.Application+MarshalingControl..ctor" FIND "JITTED Code Address:"}) {.echo ${var}}}
and then change .echo ${var} to whatever you like to do with the address.
Be aware of edge cases: the method may not have been jitted yet.
Managed breakpoint
I wonder a bit why you want to put a breakpoint at the jitted address and why a sosex managed breakpoint does not work for you. Have you tried !mbm and !mbp?

View rooted objects in WinDbg

I am trying to investigate what looks like a memory leak in .NET using WinDbg.
However, when I try to examine output of !dumpheap -type I see that many, if not all objects listed are "Free" objects. I'd like to filter the list to see if there any that are rooted (have references to them).
I tried the following script:
.foreach (t {!dumpheap -mt 0000000091ea94f0 -short}) { .if(!gcroot ${t}) { !mdt ${t} } }
However, it does not output anything. Is there a way to filter out the output of !dumpheap to show only rooted objects?
Free "objects"
.NET uses a heap manager to keep track of memory. This makes it possible to allocate objects smaller than 64 kB, where 64 kB is the minimum memory the OS provides.
So, .NET gets at least 64 kB and then splits that into smaller pieces. Those pieces which are unused can be understood as objects of type Free.
To get a better overview of Free objects, use !dumpheap -stat -type Free. Those Free objects don't have a root, because they are not actually objects.
But you can also see a whole lot of other objects including the sum of their sizes. Those are likely rooted.
Rooted objects
Unfortunately, commands like !gcroot don't have a boolean return value, so you need to use some tricky stuff. The basic .foreach loop is already quite good.
To get a comparable return value, we'll use the root count number, which is 1 in the following case:
0:004> !gcroot 02701078
HandleTable:
001f11ec (strong handle)
-> 02701078 System.OutOfMemoryException
Found 1 unique roots (run '!GCRoot -all' to see all roots).
Since the number can be 1, 2, 3 etc., it seems more reliable to check for !=0. Let's start like this:
.shell -ci"!gcroot ${t}" find "Found 0"
This will only keep the one line "Found 0 unique roots ...", otherwise nothing at all.
Then let's minimize the output just to keep the number by skipping the first word ("Found") using /pS 1, then processing one word and then skipping the rest (actually a maximum of 99 words) using /ps 99:
.foreach /pS 1 /ps 99(word {.shell -ci"!gcroot ${t}" find "Found 0"}) {.echo ${word}}
This will leave us with 0 only.
Next, use can use $scmp() to compare the string:
.if ($scmp("${word}","0")==0) {.echo nothing} .else {.echo something}
The whole script (formatted for readability, remove the line breaks and indentation):
.foreach (t {!dumpheap -short -mt 70c240b4}) {
.foreach /pS 1 /ps 99 (word {.shell -ci"!gcroot ${t}" find "Found 0"}) {
.if ($scmp("${word}","0")==0){
.echo nothing
} .else {
.echo something
}
}
}
In your case, replace .echo something by !mdt ${t}.
PyKd
Since above script is hard to understand and error-prone, you might want to try PyKD. Look for dbgCommand() to execute debugger commands and get the result as a string. You can then operate on that string with any Python commands, which is much easier than WinDbg built-in functions.

Windbg - How can I Dump Strings which match a given filter

One can dump all the string using the following command
!dumpheap -type System.string
How can dump or print only those string which starts or contains a specific "string"
Example. I am only intrested to view the string which contains "/my/app/request"
Use sosex instead of sos for this. It has a !strings command which allows you to filter strings using the /m:<filter> option.
Use !sosex.strings. See !sosex.help for options to filter strings based on content and/or length.
Not sure if !dumpheap supports that. You can always use .logopen to redirect the output to a file and post-process that. For a more elegant (and thus more complicated) solution, you can also use .shell to redirect the command output to a shell process for parsing. Here's an example:
http://blogs.msdn.com/b/baleixo/archive/2008/09/06/using-shell-to-search-text.aspx
You can also see the .shell documentation for more details:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff565339(v=vs.85).aspx
If you really want to go without SOSEX, then try
.foreach (string {!dumpheap -short -type System.String}) { .foreach (search {s -u ${string}+c ${string}+c+2*poi(${string}+8) "mySearchTerm"}) { du /c80 ${string}+c }}
It uses
!dumpheap to get all Strings on .NET heap
.foreach to iterate over them
s to search for a substring
.foreach again to find out if s found something
some offset calculations to get the first character (+c) of the string and the string length (+8) (multiplied by 2 to get bytes instead of characters). Those need to be adapted in case of 64 bit applications
The /c80 is just for nicer output. You could also use !do ${string} instead of du /c80 ${string}+c if you like the .NET details of the String.