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?
Related
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 )
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.
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.
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}
I'm fairly new to Perl and have been searching the interwebs for documentation for what I'm trying to do. I'm not having any luck.
I have a program that outputs information to stdout with prompts throughout. I need to make a Perl script to pipe that information to a file.
I thought I could use Expect but there seems to be a problem with the pipe after the first prompt.
Here is the part of my code:
# Run program and compare the output to the BASE file
$cmd = "./program arg1 arg2 arg3 arg4 > $outfile";
my $exp = new Expect;
$exp->spawn($cmd);
BAIL_OUT("couldn't create expect object") if (! defined $exp);
$exp->expect(2);
$exp->send("\n");
For this case there is only a single prompt for the user to press "enter". This program is small and very fast - 2 seconds is plenty of time to reach the first prompt.
The output file only contains the first half of the information.
Does anyone have any suggestions on how I can grab the second half as well?
UPDATE:
I've verified that this works with Expect by using a simple script:
spawn ./program arg1 arg2 arg3 arg4
expect "<Return>"
send "\r"
interact
Where "< Return >" is a verbose expression that the Perl script could look for.
Note: I've tried writing my Perl script to expect "< Return >"...it makes no difference.
i.e.
$exp->expect(2, '-re', "<Return>")
Any thoughts?
UPDATE2:
Hazaah! I've found a solution to my problem...completely by accident.
So, I had a mistype in some test code I made...
$exp->expect(2);
$exp->send("\r");
$exp->expect(2);
Note the trailing expect(2)...I accidentally left that in and it worked!
So, I'm trying to understand what is happening. Unix expect does not seem work this way! It appears Expect implemented in Perl "expects" anything...not just prompts?
So, I provided expect another 2 seconds to collect stdout and I am able to get everything.
If anyone can offer some more detailed information as to what is going on here I'd love to understand what is going on.
Try sending \r instead of \n - you're trying to emulate a carriage return, not a newline, and the tty settings might not be translating them.
ALSO:
A suggestion from the Expect docs FAQ section, which seems likely given your accidental solution:
My script fails from time to time without any obvious reason. It
seems that I am sometimes loosing output from the spawned program.
You could be exiting too fast without giving the spawned program
enough time to finish. Try adding $exp->soft_close() to terminate the
program gracefully or do an expect() for 'eof'.
Alternatively, try adding a 'sleep 1' after you spawn() the program.
It could be that pty creation on your system is just slow (but this is
rather improbable if you are using the latest IO-Tty).
Standard unix/tcl expect doesn't exit in interactive mode, which could give your program enough time to finish running.
It's been a while since I've used Expect, but I'm pretty sure you need to provide something for Expect to match the prompt against:
$exp->expect( 2, 'Press enter' );
for example.