├── README.md └── findroots.py /README.md: -------------------------------------------------------------------------------- 1 | WinDbgScripts PYKD 2 | ============= 3 | 4 | The following set of scripts are meant to make your life easier when using WinDbg for tracking and troubleshooting your applications. 5 | In this repository I will be adding any scripts written in Python and meant for use with the PYKD windbg extension.. 6 | 7 | PYKD Scripts 8 | ------- 9 | 10 | These dependencies are needed to use these scripts in WinDBG. 11 | 12 | * [Python](https://www.python.org/) -- I Installed this directly into the Debugger base directory, but you can install where you would like. Just make sure the python executable is in the search path. 13 | * [PYKD](https://pykd.codeplex.com/) -- Be sure to follow the instructions as stated on the site. 14 | * [SOSEX](http://www.stevestechspot.com/SOSEXV40NowAvailable.aspx) -- This is an extension for the Windbg tools that more effectively and efficiently walks the .net Heaps and Threads 15 | 16 | Installation 17 | ----------- 18 | 19 | Download the github repository and copy the scripts into the %debuggerbasedirectory%\scripts directory 20 | 21 | Usage 22 | ----- 23 | 24 | In WinDbg: 25 | - .load pykd.pyd 26 | - !py scripts/scriptname.py 27 | 28 | Script Descriptions 29 | ----------------------- 30 | findroots.py - This script takes a Generation and Object Type Name as inputs. It will scan the given generation for the type of object you specified and return only the items that are rooted and give you a clickable link back. You can further specify a specific size also to narrow down the objects your trying to find that may still be rooted. 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /findroots.py: -------------------------------------------------------------------------------- 1 | import pykd 2 | import sys 3 | import argparse 4 | import re 5 | parser = argparse.ArgumentParser(description='Search a given generation and output rooted items for a specific type and optionally its size') 6 | parser.add_argument('gen', metavar='generation', type=int, help='GC generation to scan') 7 | parser.add_argument('type', metavar='typename', help='The typename you are scanning for roots for') 8 | parser.add_argument('--size', help="size of the object we are searching for root on") 9 | parser.add_argument("--verbose", help="increase output verbosity",action="store_true") 10 | 11 | args=parser.parse_args() 12 | 13 | 14 | pykd.dprintln ("Scanning for rooted objects in Gen={0} for type={1}".format(args.gen, args.type)) 15 | 16 | s = pykd.dbgCommand("!chain") 17 | out = "" 18 | if not("sos.dll" in s): 19 | pykd.dprintln("sos not found ...... loading sos") 20 | out = pykd.dbgCommand("!loadby sos clr") 21 | print out 22 | if not("sosex.dll" in s): 23 | pykd.dprintln("sosex not found ...... loading sosex please wait") 24 | out = pykd.dbgCommand("!load sosex") 25 | print out 26 | pykd.dprintln("Building heap index this may take a few minutes....") 27 | out = pykd.dbgCommand("!bhi") 28 | pykd.dprintln(out) 29 | 30 | 31 | command = "!dumpgen {0} -type {1}".format(args.gen, args.type) 32 | prog = re.compile('^([^\W]*)\W+([^\W]*)\W+([^\W]*)') 33 | 34 | for i in pykd.dbgCommand(command).split("\n"): 35 | out = "" 36 | if(args.type in i): 37 | m = prog.match(i) 38 | if args.verbose: 39 | print "Checking for root for address:{0} ".format(m.group(1)) 40 | if(args.size and m.group(3) == args.size): 41 | out = pykd.dbgCommand('!mroot {0}'.format(m.group(1))) 42 | elif not(args.size): 43 | out = pykd.dbgCommand('!mroot {0}'.format(m.group(1))) 44 | if out and not('No root' in out): 45 | pykd.dprintln("Root found at: {0} having size of {1}".format(m.group(1),m.group(3)), True) 46 | print out 47 | --------------------------------------------------------------------------------