[0.3.x] refactored : stkwalk script

git-svn-id: https://pykd.svn.codeplex.com/svn@88179 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2014-04-30 16:42:19 +00:00 committed by Mikhail I. Izmestev
parent bd19263aed
commit d922dbe8da

View File

@ -1,4 +1,5 @@
import pykd
from pykd import * from pykd import *
from optparse import OptionParser from optparse import OptionParser
from fnmatch import fnmatch from fnmatch import fnmatch
@ -6,6 +7,21 @@ import traceback
import sys import sys
nt = None nt = None
EPROCESS = None
ETHREAD = None
def setupGlobalObject():
global nt, EPROCESS, ETHREAD
try:
nt = module("nt")
EPROCESS = nt.type("_EPROCESS")
ETHREAD = nt.type("_ETHREAD")
except DbgException:
dprintln("check symbol paths")
class PrintOptions: class PrintOptions:
def __init__(self): def __init__(self):
@ -15,129 +31,59 @@ class PrintOptions:
self.showIP = True self.showIP = True
self.showSP = True self.showSP = True
self.showUnique = False self.showUnique = False
self.combineWow64 = True
def applayThreadFilter(thread,threadFilter,moduleFilter,funcFilter,printopt,stackHashes): self.showCpu = True
filterMatch = False
if not moduleFilter and not funcFilter and not threadFilter:
if printopt.showUnique == False:
return True
else:
filterMatch = True
if threadFilter and threadFilter( thread.Tcb, thread.Cid.UniqueThread ):
if printopt.showUnique == False:
return True
else:
filterMatch = True
try:
setImplicitThread(thread)
stk = getStack()
strStack = ""
for frame in stk:
m = module( frame.instructionOffset )
if filterMatch == False and moduleFilter and moduleFilter( m, m.name() ):
filterMatch = True
if printopt.showUnique == False:
return True
sym = m.findSymbol( frame.instructionOffset, showDisplacement = False )
if filterMatch == False and funcFilter and funcFilter( sym ):
filterMatch = True
if printopt.showUnique == False:
return True
if printopt.showUnique == True:
strStack += sym
if is64bitSystem():
processorMode = getProcessorMode()
try:
setProcessorMode("X86")
dbgCommand( ".reload /user" )
stk = getStackWow64()
for frame in stk:
m = module( frame.instructionOffset )
if filterMatch == False and moduleFilter and moduleFilter( m, m.name() ):
filterMatch = True
if printopt.showUnique == False:
return True
sym = m.findSymbol( frame.instructionOffset, showDisplacement = False )
if filterMatch == False and funcFilter and funcFilter( sym ):
filterMatch = True
if printopt.showUnique == False:
return True
if printopt.showUnique == True:
strStack += sym
except BaseException:
pass
setProcessorMode(processorMode)
if printopt.showUnique == False or filterMatch == False:
return filterMatch
hashStack = hash( strStack )
if hashStack in stackHashes:
return False
stackHashes.add( hashStack )
return True
except BaseException:
pass
return False
def printFrame(frame, printopt): def printFrame(frame, printopt):
str = ""
if printopt.showCpu:
str += frame.cpuType + "\t"
if printopt.showIP: if printopt.showIP:
dprint( "%016x\t" % frame.instructionOffset ) str += "%016x\t" % frame.instructionOffset
if printopt.showSP: if printopt.showSP:
dprint( "%016x\t" % frame.stackOffset ) str += "%016x\t" % frame.stackOffset
dprintln( findSymbol( frame.instructionOffset ) ) str += findSymbol( frame.instructionOffset )
dprintln(str)
def printThread(process,thread,printopt): def getModule(offset):
try: try:
setImplicitThread(thread) return module(offset)
except DbgException:
pass
return None
stk = getStack() def getStackHash(stk):
hashStr = ""
for frame in stk:
hashStr += str(frame.instructionOffset)
return hash(hashStr)
dprintln( "Thread %x, Process: %s (%x)" % ( thread, loadCStr( process.ImageFileName ), process ) ) def getStackModules(stk):
for frame in stk: modules = []
printFrame(frame, printopt) for frame in stk:
m = getModule(frame.instructionOffset)
if m and not ( m in modules ):
modules.append( m )
return modules
if is64bitSystem(): def getStackSymbols(stk):
processorMode = getProcessorMode() symbols = []
try: for frame in stk:
setProcessorMode("X86") sym = findSymbol( frame.instructionOffset, showDisplacement = False )
stk = getStackWow64() if sym and not ( sym in symbols ):
dprintln("\nWOW64 stack") symbols.append(sym)
for frame in stk: return symbols
printFrame(frame, printopt)
except BaseException:
pass
setProcessorMode(processorMode)
dprintln("")
except BaseException:
if not printopt.ignoreNotActiveThread:
dprintln( "Thread %x, Process: %s" % ( thread, loadCStr( process.ImageFileName ) ) )
dprintln( "Failed to switch into thread context\n")
dprintln("")
def printThread(thread, process):
dprintln("")
dprintln( "Thread %x, Process: %s (%x)" % ( thread, loadCStr( process.ImageFileName ), process ) )
def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,printopt): def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,printopt):
@ -147,32 +93,93 @@ def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,prin
if processFilter and not processFilter(process, process.UniqueProcessId, processName ): if processFilter and not processFilter(process, process.UniqueProcessId, processName ):
return return
try: dprintln( "Process %x" % process )
#setCurrentProcess(process) dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) )
dbgCommand(".process /p %x" % process ) dprintln( "" )
try:
dbgCommand(".process /p /r %x" % process )
dbgCommand( ".reload /user" ) dbgCommand( ".reload /user" )
threadLst = nt.typedVarList(process.ThreadListHead, "_ETHREAD", "ThreadListEntry.Flink") threadLst = typedVarList(process.ThreadListHead, ETHREAD, "ThreadListEntry.Flink")
filteredThreadLst = []
stackHashes = set() stackHashes = set()
for thread in threadLst: for thread in threadLst:
if applayThreadFilter( thread, threadFilter, moduleFilter, funcFilter, printopt, stackHashes ):
filteredThreadLst.append( thread )
if filteredThreadLst == []: if threadFilter and not threadFilter( thread.Tcb, thread.Cid.UniqueThread ):
return continue
dprintln( "Process %x" % process ) setCurrentThread( thread )
dprintln( "Name: %s Pid: %#x" % ( processName, process.UniqueProcessId ) )
dprintln( "" )
for thread in filteredThreadLst: stkNative = getStack()
printThread(process,thread, printopt) stkWow64 = []
if printopt.showWow64stack == True:
try:
switchCPUMode();
try:
stkWow64 = getStack()
except MemoryException:
pass
switchCPUMode();
except DbgException:
pass
stk = []
for frame in stkNative:
mod = getModule(frame.instructionOffset)
if mod and printopt.combineWow64 and stkWow64:
if mod.name() == "wow64cpu":
break
frame.cpuType = str(getCPUMode())
stk.append(frame)
for frame in stkWow64:
frame.cpuType = "WOW64"
stk.append(frame)
if printopt.showUnique:
stackHash= getStackHash(stk)
if stackHash in stackHashes:
continue
stackHashes.add( stackHash )
if moduleFilter:
if not [ m for m in getStackModules(stk) if moduleFilter( m, m.name() ) ]:
continue
if funcFilter:
match = False
for sym in getStackSymbols(stk):
if funcFilter(sym) or ( len( sym.split('!', 1) ) == 2 and funcFilter( sym.split('!', 1)[1] ) ):
match = True
break
if not match:
continue
printThread( thread, process )
for frame in stk:
printFrame(frame, printopt)
except DbgException:
except BaseException:
if not printopt.ignoreNotActiveProcess: if not printopt.ignoreNotActiveProcess:
dprintln( "Process %x" % process ) dprintln( "Process %x" % process )
dprintln( "Name: %s" % processName ) dprintln( "Name: %s" % processName )
dprintln( "Failed to switch into process context\n") dprintln( "Failed to switch into process context\n")
@ -180,14 +187,11 @@ def printProcess(process,processFilter,threadFilter,moduleFilter,funcFilter,prin
def main(): def main():
dprintln("Stack walker. ver 1.0")
if not isKernelDebugging(): dprintln("Stack walker. ver 1.1")
dprintln("This script is only for kernel debugging")
return
global nt if not hasattr(pykd, "__version__") or not fnmatch( pykd.__version__, "0.3.*"):
nt = module("nt") dprintln ( "pykd has incompatible version" )
parser = OptionParser() parser = OptionParser()
parser.add_option("-p", "--process", dest="processfilter", parser.add_option("-p", "--process", dest="processfilter",
@ -195,14 +199,28 @@ def main():
parser.add_option("-m", "--module", dest="modulefilter", parser.add_option("-m", "--module", dest="modulefilter",
help="module filter: boolean expression with python syntax" ) help="module filter: boolean expression with python syntax" )
parser.add_option("-f", "--function", dest="funcfilter", parser.add_option("-f", "--function", dest="funcfilter",
help="function filter: boolean expression with python syntax" ) help="function filter: boolean expression with python syntax" )
parser.add_option("-t", "--thread", dest="threadfilter", parser.add_option("-t", "--thread", dest="threadfilter",
help="thread filter: boolean expresion with python syntax" ) help="thread filter: boolean expresion with python syntax" )
parser.add_option("-u", "--unique", action="store_true", dest="uniquestack", parser.add_option("-u", "--unique", action="store_true", dest="uniquestack",
help="show only unique stacks" ) help="show only unique stacks" )
parser.add_option("-d", "--dump", dest="dumpname",
help="open crach dump" )
parser.add_option("-w", "--wow64", dest="wow64",
help="show WOW64 stacks")
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
if not isWindbgExt():
initialize()
loadDump( options.dumpname )
if not isKernelDebugging():
dprintln("This script is only for kernel debugging")
return
setupGlobalObject()
processFilter = None processFilter = None
moduleFilter = None moduleFilter = None
funcFilter = None funcFilter = None
@ -223,16 +241,14 @@ def main():
printopt = PrintOptions() printopt = PrintOptions()
printopt.showUnique = True if options.uniquestack else False printopt.showUnique = True if options.uniquestack else False
currentProcess = getCurrentProcess() if options.wow64 != None:
currentThread = getImplicitThread() printopt.showWow64stack = options.wow64.lower() == 'true'
processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink") processLst = nt.typedVarList( nt.PsActiveProcessHead, "_EPROCESS", "ActiveProcessLinks.Flink")
for process in processLst: for process in processLst:
printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt ) printProcess( process, processFilter, threadFilter, moduleFilter, funcFilter, printopt )
setCurrentProcess(currentProcess)
setImplicitThread(currentThread)
if __name__ == "__main__": if __name__ == "__main__":
main() main()